Index: sbin/ipfw/tables.c =================================================================== --- sbin/ipfw/tables.c +++ sbin/ipfw/tables.c @@ -1168,11 +1168,14 @@ static void tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type, - uint8_t tflags) + uint8_t tflags, uint32_t vmask) { char *p, *pp; int mask, af; - struct in6_addr *paddr, tmp; + struct addrinfo hints, *res; + struct in6_addr tmp; + void *paddr; + //struct in6_addr *paddr, tmp; struct tflow_entry *tfe; uint32_t key, *pkey; uint16_t port; @@ -1182,42 +1185,47 @@ masklen = 0; af = 0; - paddr = (struct in6_addr *)&tentry->k; + paddr = &tentry->k; switch (type) { case IPFW_TABLE_ADDR: + memset(&hints, 0, sizeof(hints)); + type = IPFW_TABLE_ADDR; + + if (vmask & IPFW_VTYPE_NH4) { + masklen = 32; + af = hints.ai_family = AF_INET; + } else if (vmask & IPFW_VTYPE_NH6) { + masklen = 128; + af = hints.ai_family = AF_INET6; + } + /* Remove / if exists */ if ((p = strchr(arg, '/')) != NULL) { *p = '\0'; - mask = atoi(p + 1); + masklen = atoi(p + 1); } + if ((af == AF_INET && masklen > 32) || (af == AF_INET6 && masklen > 128)) + errx(EX_DATAERR, "bad IPv%d mask width: %s", + (af == AF_INET6 ? 6 : 4), p + 1); - if (inet_pton(AF_INET, arg, paddr) == 1) { - if (p != NULL && mask > 32) - errx(EX_DATAERR, "bad IPv4 mask width: %s", - p + 1); - - masklen = p ? mask : 32; - af = AF_INET; - } else if (inet_pton(AF_INET6, arg, paddr) == 1) { - if (IN6_IS_ADDR_V4COMPAT(paddr)) - errx(EX_DATAERR, - "Use IPv4 instead of v4-compatible"); - if (p != NULL && mask > 128) - errx(EX_DATAERR, "bad IPv6 mask width: %s", - p + 1); - - masklen = p ? mask : 128; - af = AF_INET6; - } else { - /* Assume FQDN */ - if (lookup_host(arg, (struct in_addr *)paddr) != 0) - errx(EX_NOHOST, "hostname ``%s'' unknown", arg); - - masklen = 32; - type = IPFW_TABLE_ADDR; - af = AF_INET; + if (getaddrinfo(arg, NULL, &hints, &res) != 0) + errx(EX_NOHOST, "hostname or ip ``%s'' unknown or invalid", arg); + + switch (af) { + case AF_INET: + *(struct in_addr *)paddr = ((struct sockaddr_in *)res->ai_addr)->sin_addr; + break; + case AF_INET6: + *(struct in6_addr *)paddr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; + break; } + + if (af == AF_INET6 && IN6_IS_ADDR_V4COMPAT((struct in6_addr *)paddr)) + errx(EX_DATAERR, + "Use IPv4 instead of v4-compatible"); + + freeaddrinfo(res); break; case IPFW_TABLE_INTERFACE: /* Assume interface name. Copy significant data only */ @@ -1472,7 +1480,7 @@ vmask = IPFW_VTYPE_LEGACY; } - tentry_fill_key_type(key, tent, type, tflags); + tentry_fill_key_type(key, tent, type, tflags, vmask); *ptype = type; *pvmask = vmask; @@ -1610,18 +1618,15 @@ } break; case IPFW_VTYPE_NH6: - if (strchr(n, ':') != NULL) { - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(n, NULL, &hints, &res) == 0) { - v->nh6 = ((struct sockaddr_in6 *) - res->ai_addr)->sin6_addr; - v->zoneid = ((struct sockaddr_in6 *) - res->ai_addr)->sin6_scope_id; - freeaddrinfo(res); - break; - } + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + if (getaddrinfo(n, NULL, &hints, &res) == 0) { + v->nh6 = ((struct sockaddr_in6 *) + res->ai_addr)->sin6_addr; + v->zoneid = ((struct sockaddr_in6 *) + res->ai_addr)->sin6_scope_id; + freeaddrinfo(res); + break; } etype = "ipv6"; break;