int addr_pton_cidr(const char *p, struct xaddr *n, u_int *l) { struct xaddr tmp; long unsigned int masklen = -1; char addrbuf[64], *mp, *cp; /* Don't modify argument */ if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) > sizeof(addrbuf)) return (-1); if ((mp = strchr(addrbuf, '/')) != NULL) { *mp = '\0'; mp++; masklen = strtoul(mp, &cp, 10); if (*mp == '\0' || *cp != '\0' || masklen > 128) return (-1); } if (addr_pton(addrbuf, &tmp) == -1) return (-1); if (mp == NULL) masklen = addr_unicast_masklen(tmp.af); if (masklen_valid(tmp.af, masklen) == -1) return (-1); if (n != NULL) memcpy(n, &tmp, sizeof(*n)); if (l != NULL) *l = masklen; return (0); }
/* * Calculate a netmask of length 'l' for address family 'af' and * store it in 'n'. * Returns 0 on success, -1 on failure. */ static int addr_netmask(int af, u_int l, struct xaddr *n) { int i; if (masklen_valid(af, l) != 0 || n == NULL) return -1; memset(n, '\0', sizeof(*n)); switch (af) { case AF_INET: n->af = AF_INET; n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); return 0; case AF_INET6: n->af = AF_INET6; for (i = 0; i < 4 && l >= 32; i++, l -= 32) n->addr32[i] = 0xffffffffU; if (i < 4 && l != 0) n->addr32[i] = htonl((0xffffffff << (32 - l)) & 0xffffffff); return 0; default: return -1; } }
int addr_netmask(int af, u_int l, struct xaddr *n) { int i; if (masklen_valid(af, l) != 0 || n == NULL) return (-1); memset(n, '\0', sizeof(*n)); switch (af) { case AF_INET: n->af = AF_INET; n->v4.s_addr = (l == 32) ? 0xffffffffUL : htonl(~(0xffffffffUL >> l)); return (0); case AF_INET6: n->af = AF_INET6; for (i = 0; i < 4 && l >= 32; i++, l -= 32) n->addr32[i] = 0xffffffffU; if (i < 4 && l != 0) n->addr32[i] = htonl(~(0xffffffffU >> l)); return (0); default: return (-1); } }