| 25 | #define V4PREFIXMAX 32 |
| 26 | |
| 27 | int |
| 28 | cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, |
| 29 | unsigned ressize) |
| 30 | { |
| 31 | struct cmdline_token_ipaddr *tk2; |
| 32 | unsigned int token_len = 0; |
| 33 | char ip_str[INET6_ADDRSTRLEN+4+1]; /* '+4' is for prefixlen (if any) */ |
| 34 | cmdline_ipaddr_t ipaddr; |
| 35 | char *prefix, *prefix_end; |
| 36 | long prefixlen = 0; |
| 37 | |
| 38 | if (res && ressize < sizeof(cmdline_ipaddr_t)) |
| 39 | return -1; |
| 40 | |
| 41 | if (!buf || !tk || ! *buf) |
| 42 | return -1; |
| 43 | |
| 44 | tk2 = (struct cmdline_token_ipaddr *)tk; |
| 45 | |
| 46 | while (!cmdline_isendoftoken(buf[token_len])) |
| 47 | token_len++; |
| 48 | |
| 49 | /* if token is too big... */ |
| 50 | if (token_len >= INET6_ADDRSTRLEN+4) |
| 51 | return -1; |
| 52 | |
| 53 | strlcpy(ip_str, buf, token_len + 1); |
| 54 | |
| 55 | /* convert the network prefix */ |
| 56 | if (tk2->ipaddr_data.flags & CMDLINE_IPADDR_NETWORK) { |
| 57 | prefix = strrchr(ip_str, '/'); |
| 58 | if (prefix == NULL) |
| 59 | return -1; |
| 60 | *prefix = '\0'; |
| 61 | prefix ++; |
| 62 | errno = 0; |
| 63 | prefixlen = strtol(prefix, &prefix_end, 10); |
| 64 | if (errno || (*prefix_end != '\0') |
| 65 | || prefixlen < 0 || prefixlen > PREFIXMAX) |
| 66 | return -1; |
| 67 | ipaddr.prefixlen = prefixlen; |
| 68 | } |
| 69 | else { |
| 70 | ipaddr.prefixlen = 0; |
| 71 | } |
| 72 | |
| 73 | /* convert the IP addr */ |
| 74 | if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V4) && |
| 75 | inet_pton(AF_INET, ip_str, &ipaddr.addr.ipv4) == 1 && |
| 76 | prefixlen <= V4PREFIXMAX) { |
| 77 | ipaddr.family = AF_INET; |
| 78 | if (res) |
| 79 | memcpy(res, &ipaddr, sizeof(ipaddr)); |
| 80 | return token_len; |
| 81 | } |
| 82 | if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V6) && |
| 83 | inet_pton(AF_INET6, ip_str, &ipaddr.addr.ipv6) == 1) { |
| 84 | ipaddr.family = AF_INET6; |