void ebt_parse_ip6_address(char *address, struct in6_addr *addr, struct in6_addr *msk) { struct in6_addr *tmp_addr; char buf[256]; char *p; int i; int err; strncpy(buf, address, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; if ((p = strrchr(buf, '/')) != NULL) { *p = '\0'; tmp_addr = parse_ip6_mask(p + 1); } else tmp_addr = parse_ip6_mask(NULL); in6addrcpy(msk, tmp_addr); if (!memcmp(msk, &in6addr_any, sizeof(in6addr_any))) strcpy(buf, "::"); if ((err=inet_pton(AF_INET6, buf, addr)) < 1) { ebt_print_error("Invalid IPv6 Address '%s' specified", buf); return; } for (i = 0; i < 4; i++) addr->s6_addr32[i] &= msk->s6_addr32[i]; }
static int policy_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct ip6t_policy_info *info = (void *)(*match)->data; struct ip6t_policy_elem *e = &info->pol[info->len]; struct in6_addr *addr = NULL, mask; unsigned int naddr = 0; int mode; check_inverse(optarg, &invert, &optind, 0); switch (c) { case '1': if (info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT)) exit_error(PARAMETER_PROBLEM, "policy match: double --dir option"); if (invert) exit_error(PARAMETER_PROBLEM, "policy match: can't invert --dir option"); info->flags |= parse_direction(argv[optind-1]); break; case '2': if (invert) exit_error(PARAMETER_PROBLEM, "policy match: can't invert --policy option"); info->flags |= parse_policy(argv[optind-1]); break; case '3': if (info->flags & IP6T_POLICY_MATCH_STRICT) exit_error(PARAMETER_PROBLEM, "policy match: double --strict option"); if (invert) exit_error(PARAMETER_PROBLEM, "policy match: can't invert --strict option"); info->flags |= IP6T_POLICY_MATCH_STRICT; break; case '4': if (e->match.reqid) exit_error(PARAMETER_PROBLEM, "policy match: double --reqid option"); e->match.reqid = 1; e->invert.reqid = invert; e->reqid = strtol(argv[optind-1], NULL, 10); break; case '5': if (e->match.spi) exit_error(PARAMETER_PROBLEM, "policy match: double --spi option"); e->match.spi = 1; e->invert.spi = invert; e->spi = strtol(argv[optind-1], NULL, 0x10); break; case '6': if (e->match.saddr) exit_error(PARAMETER_PROBLEM, "policy match: double --tunnel-src option"); parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr); if (naddr > 1) exit_error(PARAMETER_PROBLEM, "policy match: name resolves to multiple IPs"); e->match.saddr = 1; e->invert.saddr = invert; in6addrcpy(&e->saddr.a6, addr); in6addrcpy(&e->smask.a6, &mask); break; case '7': if (e->match.daddr) exit_error(PARAMETER_PROBLEM, "policy match: double --tunnel-dst option"); parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr); if (naddr > 1) exit_error(PARAMETER_PROBLEM, "policy match: name resolves to multiple IPs"); e->match.daddr = 1; e->invert.daddr = invert; in6addrcpy(&e->daddr.a6, addr); in6addrcpy(&e->dmask.a6, &mask); break; case '8': if (e->match.proto) exit_error(PARAMETER_PROBLEM, "policy match: double --proto option"); e->proto = parse_protocol(argv[optind-1]); if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP && e->proto != IPPROTO_COMP) exit_error(PARAMETER_PROBLEM, "policy match: protocol must ah/esp/ipcomp"); e->match.proto = 1; e->invert.proto = invert; break; case '9': if (e->match.mode) exit_error(PARAMETER_PROBLEM, "policy match: double --mode option"); mode = parse_mode(argv[optind-1]); e->match.mode = 1; e->invert.mode = invert; e->mode = mode; break; case 'a': if (invert) exit_error(PARAMETER_PROBLEM, "policy match: can't invert --next option"); if (++info->len == IP6T_POLICY_MAX_ELEM) exit_error(PARAMETER_PROBLEM, "policy match: maximum policy depth reached"); break; default: return 0; } policy_info = info; return 1; }