/* * Print the ip address contained in a command. */ void print_ip6(struct buf_pr *bp, ipfw_insn_ip6 *cmd, char const *s) { struct hostent *he = NULL; int len = F_LEN((ipfw_insn *) cmd) - 1; struct in6_addr *a = &(cmd->addr6); char trad[255]; bprintf(bp, "%s%s ", cmd->o.len & F_NOT ? " not": "", s); if (cmd->o.opcode == O_IP6_SRC_ME || cmd->o.opcode == O_IP6_DST_ME) { bprintf(bp, "me6"); return; } if (cmd->o.opcode == O_IP6) { bprintf(bp, " ip6"); return; } /* * len == 4 indicates a single IP, whereas lists of 1 or more * addr/mask pairs have len = (2n+1). We convert len to n so we * use that to count the number of entries. */ for (len = len / 4; len > 0; len -= 2, a += 2) { int mb = /* mask length */ (cmd->o.opcode == O_IP6_SRC || cmd->o.opcode == O_IP6_DST) ? 128 : contigmask((uint8_t *)&(a[1]), 128); if (mb == 128 && co.do_resolv) he = gethostbyaddr((char *)a, sizeof(*a), AF_INET6); if (he != NULL) /* resolved to name */ bprintf(bp, "%s", he->h_name); else if (mb == 0) /* any */ bprintf(bp, "any"); else { /* numeric IP followed by some kind of mask */ if (inet_ntop(AF_INET6, a, trad, sizeof( trad ) ) == NULL) bprintf(bp, "Error ntop in print_ip6\n"); bprintf(bp, "%s", trad ); if (mb < 0) /* mask not contiguous */ bprintf(bp, "/%s", inet_ntop(AF_INET6, &a[1], trad, sizeof(trad))); else if (mb < 128) bprintf(bp, "/%d", mb); } if (len > 2) bprintf(bp, ","); } }
void show_to_mask(ipfw_insn *cmd, int show_or) { int mask; char *word = "to"; if (show_or) word = "or"; ipfw_insn_ip *p = (ipfw_insn_ip *)cmd; printf(" %s %s", word, inet_ntoa(p->addr)); mask = contigmask((u_char *)&(p->mask.s_addr), 32); if (mask < 32) printf("/%d", mask); }
/* * fill the addr and mask fields in the instruction as appropriate from av. * Update length as appropriate. * The following formats are allowed: * any matches any IP6. Actually returns an empty instruction. * me returns O_IP6_*_ME * * 03f1::234:123:0342 single IP6 address * 03f1::234:123:0342/24 address/masklen * 03f1::234:123:0342/ffff::ffff:ffff address/mask * 03f1::234:123:0342/24,03f1::234:123:0343/ List of address * * Set of address (as in ipv6) not supported because ipv6 address * are typically random past the initial prefix. * Return 1 on success, 0 on failure. */ static int fill_ip6(ipfw_insn_ip6 *cmd, char *av, int cblen, struct tidx *tstate) { int len = 0; struct in6_addr *d = &(cmd->addr6); /* * Needed for multiple address. * Note d[1] points to struct in6_add r mask6 of cmd */ cmd->o.len &= ~F_LEN_MASK; /* zero len */ if (strcmp(av, "any") == 0) return (1); if (strcmp(av, "me") == 0) { /* Set the data for "me" opt*/ cmd->o.len |= F_INSN_SIZE(ipfw_insn); return (1); } if (strcmp(av, "me6") == 0) { /* Set the data for "me" opt*/ cmd->o.len |= F_INSN_SIZE(ipfw_insn); return (1); } if (strncmp(av, "table(", 6) == 0) { fill_table(&cmd->o, av, O_IP_DST_LOOKUP, tstate); return (1); } av = strdup(av); while (av) { /* * After the address we can have '/' indicating a mask, * or ',' indicating another address follows. */ char *p, *q; int masklen; char md = '\0'; CHECK_LENGTH(cblen, 1 + len + 2 * F_INSN_SIZE(struct in6_addr)); if ((q = strchr(av, ',')) ) { *q = '\0'; q++; } if ((p = strchr(av, '/')) ) { md = *p; /* save the separator */ *p = '\0'; /* terminate address string */ p++; /* and skip past it */ } /* now p points to NULL, mask or next entry */ /* lookup stores address in *d as a side effect */ if (lookup_host6(av, d) != 0) { /* XXX: failed. Free memory and go */ errx(EX_DATAERR, "bad address \"%s\"", av); } /* next, look at the mask, if any */ if (md == '/' && strchr(p, ':')) { if (!inet_pton(AF_INET6, p, &d[1])) errx(EX_DATAERR, "bad mask \"%s\"", p); masklen = contigmask((uint8_t *)&(d[1]), 128); } else { masklen = (md == '/') ? atoi(p) : 128; if (masklen > 128 || masklen < 0) errx(EX_DATAERR, "bad width \"%s\''", p); else n2mask(&d[1], masklen); } APPLY_MASK(d, &d[1]) /* mask base address with mask */ av = q; /* Check this entry */ if (masklen == 0) { /* * 'any' turns the entire list into a NOP. * 'not any' never matches, so it is removed from the * list unless it is the only item, in which case we * report an error. */ if (cmd->o.len & F_NOT && av == NULL && len == 0) errx(EX_DATAERR, "not any never matches"); continue; } /* * A single IP can be stored alone */ if (masklen == 128 && av == NULL && len == 0) { len = F_INSN_SIZE(struct in6_addr); break; } /* Update length and pointer to arguments */ len += F_INSN_SIZE(struct in6_addr)*2; d += 2; } /* end while */