On Wed, Nov 27, 2019 at 05:07:36AM +0100, Klemens Nanni wrote: > As I've already done with pfctl and bgpd, this is the first diff to > convert iked to a more AF agnostic address parsing. > > This diff introduces the copy_satoipa() wrapper and makes set_ipmask() > handle the -1 mask case which will be used in the future. Here's the follow up diff on top of the previous (to avoid one monster diff).
This is the minimal version without any cosmetic fixes or logical relocations to either improve the code or sync it with pfctl, bgpd, etc. I see no behaviour change in parsing various IP addresses, being host or network addresses, with various netmasks in use. More tests appreciated. Feedback? OK? --- parse.y Wed Nov 27 05:23:08 2019 +++ parse.y Wed Nov 27 06:21:50 2019 @@ -334,8 +334,7 @@ void copy_satoipa(struct ipsec_addr_wrap *, struct sockaddr *); struct ipsec_addr_wrap *host(const char *); -struct ipsec_addr_wrap *host_v6(const char *, int); -struct ipsec_addr_wrap *host_v4(const char *, int); +struct ipsec_addr_wrap *host_ip(const char *, int); struct ipsec_addr_wrap *host_dns(const char *, int); struct ipsec_addr_wrap *host_if(const char *, int); struct ipsec_addr_wrap *host_any(void); @@ -2013,82 +2012,65 @@ host(const char *s) { struct ipsec_addr_wrap *ipa = NULL; - int mask, cont = 1; - char *p, *q, *ps; + int mask = -1; + char *p, *ps; + const char *errstr; - if ((p = strrchr(s, '/')) != NULL) { - errno = 0; - mask = strtol(p + 1, &q, 0); - if (errno == ERANGE || !q || *q || mask > 128 || q == (p + 1)) - errx(1, "host: invalid netmask '%s'", p); - if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) - err(1, "%s", __func__); - strlcpy(ps, s, strlen(s) - strlen(p) + 1); - } else { - if ((ps = strdup(s)) == NULL) - err(1, "%s", __func__); - mask = -1; + if ((ps = strdup(s)) == NULL) + err(1, "%s: strdup", __func__); + + if ((p = strchr(ps, '/')) != NULL) { + mask = strtonum(p+1, 0, 128, &errstr); + if (errstr) { + fprintf(stderr, "netmask is %s: %s\n", errstr, p); + goto error; + } + p[0] = '\0'; } - /* Does interface with this name exist? */ - if (cont && (ipa = host_if(ps, mask)) != NULL) - cont = 0; + if ((ipa = host_if(ps, mask)) == NULL && + (ipa = host_ip(ps, mask)) == NULL && + (ipa = host_dns(ps, mask)) == NULL) + fprintf(stderr, "no IP address found for %s\n", s); - /* IPv4 address? */ - if (cont && (ipa = host_v4(s, mask == -1 ? 32 : mask)) != NULL) - cont = 0; - - /* IPv6 address? */ - if (cont && (ipa = host_v6(ps, mask == -1 ? 128 : mask)) != NULL) - cont = 0; - - /* dns lookup */ - if (cont && mask == -1 && (ipa = host_dns(s, mask)) != NULL) - cont = 0; +error: free(ps); - - if (ipa == NULL || cont == 1) { - fprintf(stderr, "no IP address found for %s\n", s); - return (NULL); - } return (ipa); } struct ipsec_addr_wrap * -host_v6(const char *s, int prefixlen) +host_ip(const char *s, int mask) { struct ipsec_addr_wrap *ipa = NULL; struct addrinfo hints, *res; char hbuf[NI_MAXHOST]; bzero(&hints, sizeof(struct addrinfo)); - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; if (getaddrinfo(s, NULL, &hints, &res)) return (NULL); if (res->ai_next) - err(1, "host_v6: numeric hostname expanded to multiple item"); + err(1, "%s: %s expanded to multiple item", __func__, s); ipa = calloc(1, sizeof(struct ipsec_addr_wrap)); if (ipa == NULL) err(1, "%s", __func__); ipa->af = res->ai_family; - memcpy(&ipa->address, res->ai_addr, sizeof(struct sockaddr_in6)); - if (prefixlen > 128) - prefixlen = 128; + copy_satoipa(ipa, res->ai_addr); ipa->next = NULL; ipa->tail = ipa; - set_ipmask(ipa, prefixlen); + set_ipmask(ipa, mask); if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) { errx(1, "could not get a numeric hostname"); } - if (prefixlen != 128) { + if (mask > -1) { ipa->netaddress = 1; - if (asprintf(&ipa->name, "%s/%d", hbuf, prefixlen) == -1) + if (asprintf(&ipa->name, "%s/%d", hbuf, mask) == -1) err(1, "%s", __func__); } else { if ((ipa->name = strdup(hbuf)) == NULL) @@ -2096,45 +2078,6 @@ } freeaddrinfo(res); - - return (ipa); -} - -struct ipsec_addr_wrap * -host_v4(const char *s, int mask) -{ - struct ipsec_addr_wrap *ipa = NULL; - struct sockaddr_in ina; - int bits = 32; - - bzero(&ina, sizeof(ina)); - if (strrchr(s, '/') != NULL) { - if ((bits = inet_net_pton(AF_INET, s, &ina.sin_addr, - sizeof(ina.sin_addr))) == -1) - return (NULL); - } else { - if (inet_pton(AF_INET, s, &ina.sin_addr) != 1) - return (NULL); - } - - ipa = calloc(1, sizeof(struct ipsec_addr_wrap)); - if (ipa == NULL) - err(1, "%s", __func__); - - ina.sin_family = AF_INET; - ina.sin_len = sizeof(ina); - memcpy(&ipa->address, &ina, sizeof(ina)); - - ipa->name = strdup(s); - if (ipa->name == NULL) - err(1, "%s", __func__); - ipa->af = AF_INET; - ipa->next = NULL; - ipa->tail = ipa; - - set_ipmask(ipa, bits); - if (strrchr(s, '/') != NULL) - ipa->netaddress = 1; return (ipa); }