/* Function which parses command options; returns true if it ate an option */ static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct ipt_conntrack_info *sinfo = (struct ipt_conntrack_info *)(*match)->data; char *protocol = NULL; unsigned int naddrs = 0; struct in_addr *addrs = NULL; switch (c) { case '1': check_inverse(optarg, &invert, &optind, 0); parse_states(argv[optind-1], sinfo); if (invert) { sinfo->invflags |= IPT_CONNTRACK_STATE; } sinfo->flags |= IPT_CONNTRACK_STATE; break; case '2': check_inverse(optarg, &invert, &optind, 0); if(invert) sinfo->invflags |= IPT_CONNTRACK_PROTO; /* Canonicalize into lower case */ for (protocol = argv[optind-1]; *protocol; protocol++) *protocol = tolower(*protocol); protocol = argv[optind-1]; sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = parse_protocol(protocol); if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0 && (sinfo->invflags & IPT_INV_PROTO)) exit_error(PARAMETER_PROBLEM, "rule would never match protocol"); sinfo->flags |= IPT_CONNTRACK_PROTO; break; case '3': check_inverse(optarg, &invert, &optind, 0); if (invert) sinfo->invflags |= IPT_CONNTRACK_ORIGSRC; parse_hostnetworkmask(argv[optind-1], &addrs, &sinfo->sipmsk[IP_CT_DIR_ORIGINAL], &naddrs); if(naddrs > 1) exit_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); if(naddrs == 1) { sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr; } sinfo->flags |= IPT_CONNTRACK_ORIGSRC; break; case '4': check_inverse(optarg, &invert, &optind, 0); if (invert) sinfo->invflags |= IPT_CONNTRACK_ORIGDST; parse_hostnetworkmask(argv[optind-1], &addrs, &sinfo->dipmsk[IP_CT_DIR_ORIGINAL], &naddrs); if(naddrs > 1) exit_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); if(naddrs == 1) { sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr; } sinfo->flags |= IPT_CONNTRACK_ORIGDST; break; case '5': check_inverse(optarg, &invert, &optind, 0); if (invert) sinfo->invflags |= IPT_CONNTRACK_REPLSRC; parse_hostnetworkmask(argv[optind-1], &addrs, &sinfo->sipmsk[IP_CT_DIR_REPLY], &naddrs); if(naddrs > 1) exit_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); if(naddrs == 1) { sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr; } sinfo->flags |= IPT_CONNTRACK_REPLSRC; break; case '6': check_inverse(optarg, &invert, &optind, 0); if (invert) sinfo->invflags |= IPT_CONNTRACK_REPLDST; parse_hostnetworkmask(argv[optind-1], &addrs, &sinfo->dipmsk[IP_CT_DIR_REPLY], &naddrs); if(naddrs > 1) exit_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); if(naddrs == 1) { sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr; } sinfo->flags |= IPT_CONNTRACK_REPLDST; break; case '7': check_inverse(optarg, &invert, &optind, 0); parse_statuses(argv[optind-1], sinfo); if (invert) { sinfo->invflags |= IPT_CONNTRACK_STATUS; } sinfo->flags |= IPT_CONNTRACK_STATUS; break; case '8': check_inverse(optarg, &invert, &optind, 0); parse_expires(argv[optind-1], sinfo); if (invert) { sinfo->invflags |= IPT_CONNTRACK_EXPIRES; } sinfo->flags |= IPT_CONNTRACK_EXPIRES; break; default: return 0; } *flags = sinfo->flags; return 1; }
static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match) { struct ipt_owner_info *ownerinfo = (struct ipt_owner_info *)(*match)->data; switch (c) { char *end; struct passwd *pwd; struct group *grp; case '1': check_inverse(optarg, &invert, &optind, 0); if ((pwd = getpwnam(optarg))) ownerinfo->uid = pwd->pw_uid; else { ownerinfo->uid = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad OWNER UID value `%s'", optarg); } if (invert) ownerinfo->invert |= IPT_OWNER_UID; ownerinfo->match |= IPT_OWNER_UID; *flags = 1; break; case '2': check_inverse(optarg, &invert, &optind, 0); if ((grp = getgrnam(optarg))) ownerinfo->gid = grp->gr_gid; else { ownerinfo->gid = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad OWNER GID value `%s'", optarg); } if (invert) ownerinfo->invert |= IPT_OWNER_GID; ownerinfo->match |= IPT_OWNER_GID; *flags = 1; break; case '3': check_inverse(optarg, &invert, &optind, 0); ownerinfo->pid = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad OWNER PID value `%s'", optarg); if (invert) ownerinfo->invert |= IPT_OWNER_PID; ownerinfo->match |= IPT_OWNER_PID; *flags = 1; break; case '4': check_inverse(optarg, &invert, &optind, 0); ownerinfo->sid = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad OWNER SID value `%s'", optarg); if (invert) ownerinfo->invert |= IPT_OWNER_SID; ownerinfo->match |= IPT_OWNER_SID; *flags = 1; break; #ifdef IPT_OWNER_COMM case '5': check_inverse(optarg, &invert, &optind, 0); if(strlen(optarg) > sizeof(ownerinfo->comm)) exit_error(PARAMETER_PROBLEM, "OWNER CMD `%s' too long, max %u characters", optarg, (unsigned int)sizeof(ownerinfo->comm)); strncpy(ownerinfo->comm, optarg, sizeof(ownerinfo->comm)); ownerinfo->comm[sizeof(ownerinfo->comm)-1] = '\0'; if (invert) ownerinfo->invert |= IPT_OWNER_COMM; ownerinfo->match |= IPT_OWNER_COMM; *flags = 1; break; #endif default: return 0; } return 1; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ip6t_entry *entry, unsigned int *nfcache, struct ip6t_entry_match **match) { struct ip6t_frag *fraginfo = (struct ip6t_frag *)(*match)->data; switch (c) { case '1': if (*flags & IP6T_FRAG_IDS) exit_error(PARAMETER_PROBLEM, "Only one `--fragid' allowed"); check_inverse(optarg, &invert, &optind, 0); parse_frag_ids(argv[optind-1], fraginfo->ids); if (invert) fraginfo->invflags |= IP6T_FRAG_INV_IDS; fraginfo->flags |= IP6T_FRAG_IDS; *flags |= IP6T_FRAG_IDS; break; case '2': if (*flags & IP6T_FRAG_LEN) exit_error(PARAMETER_PROBLEM, "Only one `--fraglen' allowed"); check_inverse(optarg, &invert, &optind, 0); fraginfo->hdrlen = parse_frag_id(argv[optind-1], "length"); if (invert) fraginfo->invflags |= IP6T_FRAG_INV_LEN; fraginfo->flags |= IP6T_FRAG_LEN; *flags |= IP6T_FRAG_LEN; break; case '3': if (*flags & IP6T_FRAG_RES) exit_error(PARAMETER_PROBLEM, "Only one `--fragres' allowed"); fraginfo->flags |= IP6T_FRAG_RES; *flags |= IP6T_FRAG_RES; break; case '4': if (*flags & IP6T_FRAG_FST) exit_error(PARAMETER_PROBLEM, "Only one `--fragfirst' allowed"); fraginfo->flags |= IP6T_FRAG_FST; *flags |= IP6T_FRAG_FST; break; case '5': if (*flags & (IP6T_FRAG_MF|IP6T_FRAG_NMF)) exit_error(PARAMETER_PROBLEM, "Only one `--fragmore' or `--fraglast' allowed"); fraginfo->flags |= IP6T_FRAG_MF; *flags |= IP6T_FRAG_MF; break; case '6': if (*flags & (IP6T_FRAG_MF|IP6T_FRAG_NMF)) exit_error(PARAMETER_PROBLEM, "Only one `--fragmore' or `--fraglast' allowed"); fraginfo->flags |= IP6T_FRAG_NMF; *flags |= IP6T_FRAG_NMF; break; default: return 0; } return 1; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { struct ipt_trigger_info *info = (struct ipt_trigger_info *)(*target)->data; switch (c) { case '1': if (!strcasecmp(optarg, "dnat")) info->type = IPT_TRIGGER_DNAT; else if (!strcasecmp(optarg, "in")) info->type = IPT_TRIGGER_IN; else if (!strcasecmp(optarg, "out")) info->type = IPT_TRIGGER_OUT; else exit_error(PARAMETER_PROBLEM, "triggering type can only be one of `%s', '%s' '%s'", "dnat", "in", "out"); return 1; case '2': if (!strcasecmp(optarg, "tcp")) info->proto = IPPROTO_TCP; else if (!strcasecmp(optarg, "udp")) info->proto = IPPROTO_UDP; else if (!strcasecmp(optarg, "all")) info->proto = 0; else exit_error(PARAMETER_PROBLEM, "triggering protocol can only be one of `%s', '%s', '%s'", "tcp", "udp", "all"); return 1; case '3': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --triggering-port"); parse_ports(optarg, info->ports.mport); return 1; #ifdef ATP_SUPPORT_PRTT_RPROTOCOL case '4': if (!strcasecmp(optarg, "tcp")) info->rproto = IPPROTO_TCP; else if (!strcasecmp(optarg, "udp")) info->rproto = IPPROTO_UDP; else if (!strcasecmp(optarg, "all")) info->rproto = 0; else exit_error(PARAMETER_PROBLEM, "open protocol can only be one of '%s', '%s', '%s'", "tcp", "udp", "all"); return 1; case '5': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --open-port"); //parse_ports(optarg, info->ports.rport); parse_Openports(optarg, &(info->ports)); *flags |= IP_NAT_RANGE_PROTO_SPECIFIED; return 1; #else #if 0 case '4': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --open-port"); parse_ports(optarg, info->ports.rport); *flags |= IP_NAT_RANGE_PROTO_SPECIFIED; return 1; #endif #endif default: return 0; } }
static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, unsigned int *flags, struct ebt_entry_match **match) { struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)(*match)->data; char *end; long int i; switch (c) { case IP_SOURCE: check_option(flags, OPT_SOURCE); ipinfo->bitmask |= EBT_IP_SOURCE; case IP_DEST: if (c == IP_DEST) { check_option(flags, OPT_DEST); ipinfo->bitmask |= EBT_IP_DEST; } if (check_inverse(optarg)) { if (c == IP_SOURCE) ipinfo->invflags |= EBT_IP_SOURCE; else ipinfo->invflags |= EBT_IP_DEST; } if (optind > argc) print_error("Missing IP address argument"); if (c == IP_SOURCE) parse_ip_address(argv[optind - 1], &ipinfo->saddr, &ipinfo->smsk); else parse_ip_address(argv[optind - 1], &ipinfo->daddr, &ipinfo->dmsk); break; case IP_SPORT: case IP_DPORT: if (c == IP_SPORT) { check_option(flags, OPT_SPORT); ipinfo->bitmask |= EBT_IP_SPORT; if (check_inverse(optarg)) ipinfo->invflags |= EBT_IP_SPORT; } else { check_option(flags, OPT_DPORT); ipinfo->bitmask |= EBT_IP_DPORT; if (check_inverse(optarg)) ipinfo->invflags |= EBT_IP_DPORT; } if (optind > argc) print_error("Missing port argument"); if (c == IP_SPORT) parse_port_range(NULL, argv[optind - 1], ipinfo->sport); else parse_port_range(NULL, argv[optind - 1], ipinfo->dport); break; case IP_myTOS: check_option(flags, OPT_TOS); if (check_inverse(optarg)) ipinfo->invflags |= EBT_IP_TOS; if (optind > argc) print_error("Missing IP tos argument"); i = strtol(argv[optind - 1], &end, 16); if (i < 0 || i > 255 || *end != '\0') print_error("Problem with specified IP tos"); ipinfo->tos = i; ipinfo->bitmask |= EBT_IP_TOS; break; case IP_myDSCP: /* brcm */ check_option(flags, OPT_DSCP); if (check_inverse(optarg)) ipinfo->invflags |= EBT_IP_DSCP; if (optind > argc) print_error("Missing IP dscp argument"); i = strtol(argv[optind - 1], &end, 16); if (i < 0 || i > 255 || (i & 0x3) || *end != '\0') print_error("Problem with specified IP dscp"); ipinfo->dscp = i; ipinfo->bitmask |= EBT_IP_DSCP; break; case IP_PROTO: check_option(flags, OPT_PROTO); if (check_inverse(optarg)) ipinfo->invflags |= EBT_IP_PROTO; if (optind > argc) print_error("Missing IP protocol argument"); i = strtoul(argv[optind - 1], &end, 10); if (*end != '\0') { struct protoent *pe; pe = getprotobyname(argv[optind - 1]); if (pe == NULL) print_error ("Unknown specified IP protocol - %s", argv[optind - 1]); ipinfo->protocol = pe->p_proto; } else { ipinfo->protocol = (unsigned char) i; } ipinfo->bitmask |= EBT_IP_PROTO; break; default: return 0; } return 1; }
/* Function which parses command options; returns true if it ate an option */ static int hashlimit_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_hashlimit_info *r = (struct xt_hashlimit_info *)(*match)->data; unsigned int num; switch(c) { case '%': param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit", *flags & PARAM_LIMIT); if (check_inverse(argv[optind-1], &invert, &optind, 0)) break; if (!parse_rate(optarg, &r->cfg.avg)) exit_error(PARAMETER_PROBLEM, "bad rate `%s'", optarg); *flags |= PARAM_LIMIT; break; case '$': param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-burst", *flags & PARAM_BURST); if (check_inverse(argv[optind-1], &invert, &optind, 0)) break; if (string_to_number(optarg, 0, 10000, &num) == -1) exit_error(PARAMETER_PROBLEM, "bad --hashlimit-burst `%s'", optarg); r->cfg.burst = num; *flags |= PARAM_BURST; break; case '&': param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size", *flags & PARAM_SIZE); if (check_inverse(argv[optind-1], &invert, &optind, 0)) break; if (string_to_number(optarg, 0, 0xffffffff, &num) == -1) exit_error(PARAMETER_PROBLEM, "bad --hashlimit-htable-size: `%s'", optarg); r->cfg.size = num; *flags |= PARAM_SIZE; break; case '*': param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max", *flags & PARAM_MAX); if (check_inverse(argv[optind-1], &invert, &optind, 0)) break; if (string_to_number(optarg, 0, 0xffffffff, &num) == -1) exit_error(PARAMETER_PROBLEM, "bad --hashlimit-htable-max: `%s'", optarg); r->cfg.max = num; *flags |= PARAM_MAX; break; case '(': param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-htable-gcinterval", *flags & PARAM_GCINTERVAL); if (check_inverse(argv[optind-1], &invert, &optind, 0)) break; if (string_to_number(optarg, 0, 0xffffffff, &num) == -1) exit_error(PARAMETER_PROBLEM, "bad --hashlimit-htable-gcinterval: `%s'", optarg); /* FIXME: not HZ dependent!! */ r->cfg.gc_interval = num; *flags |= PARAM_GCINTERVAL; break; case ')': param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-htable-expire", *flags & PARAM_EXPIRE); if (check_inverse(argv[optind-1], &invert, &optind, 0)) break; if (string_to_number(optarg, 0, 0xffffffff, &num) == -1) exit_error(PARAMETER_PROBLEM, "bad --hashlimit-htable-expire: `%s'", optarg); /* FIXME: not HZ dependent */ r->cfg.expire = num; *flags |= PARAM_EXPIRE; break; case '_': param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-mode", *flags & PARAM_MODE); if (check_inverse(argv[optind-1], &invert, &optind, 0)) break; if (parse_mode(&r->cfg.mode, optarg) < 0) exit_error(PARAMETER_PROBLEM, "bad --hashlimit-mode: `%s'\n", optarg); *flags |= PARAM_MODE; break; case '"': param_act(P_ONLY_ONCE, "hashlimit", "--hashlimit-name", *flags & PARAM_NAME); if (check_inverse(argv[optind-1], &invert, &optind, 0)) break; if (strlen(optarg) == 0) exit_error(PARAMETER_PROBLEM, "Zero-length name?"); strncpy(r->name, optarg, sizeof(r->name)); *flags |= PARAM_NAME; break; default: return 0; } if (invert) exit_error(PARAMETER_PROBLEM, "hashlimit does not support invert"); return 1; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ip6t_entry *entry, struct ip6t_entry_target **target) { struct ip6t_log_info *loginfo = (struct ip6t_log_info *)(*target)->data; switch (c) { case '!': if (*flags & IP6T_LOG_OPT_LEVEL) exit_error(PARAMETER_PROBLEM, "Can't specify --log-level twice"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --log-level"); loginfo->level = parse_level(optarg); *flags |= IP6T_LOG_OPT_LEVEL; break; case '#': if (*flags & IP6T_LOG_OPT_PREFIX) exit_error(PARAMETER_PROBLEM, "Can't specify --log-prefix twice"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --log-prefix"); if (strlen(optarg) > sizeof(loginfo->prefix) - 1) exit_error(PARAMETER_PROBLEM, "Maximum prefix length %u for --log-prefix", sizeof(loginfo->prefix) - 1); strcpy(loginfo->prefix, optarg); *flags |= IP6T_LOG_OPT_PREFIX; break; case '1': if (*flags & IP6T_LOG_OPT_TCPSEQ) exit_error(PARAMETER_PROBLEM, "Can't specify --log-tcp-sequence " "twice"); loginfo->logflags |= IP6T_LOG_TCPSEQ; *flags |= IP6T_LOG_OPT_TCPSEQ; break; case '2': if (*flags & IP6T_LOG_OPT_TCPOPT) exit_error(PARAMETER_PROBLEM, "Can't specify --log-tcp-options twice"); loginfo->logflags |= IP6T_LOG_TCPOPT; *flags |= IP6T_LOG_OPT_TCPOPT; break; case '3': if (*flags & IP6T_LOG_OPT_IPOPT) exit_error(PARAMETER_PROBLEM, "Can't specify --log-ip-options twice"); loginfo->logflags |= IP6T_LOG_IPOPT; *flags |= IP6T_LOG_OPT_IPOPT; break; default: return 0; } return 1; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ip6t_entry *entry, unsigned int *nfcache, struct ip6t_entry_match **match) { struct ip6t_owner_info *ownerinfo = (struct ip6t_owner_info *)(*match)->data; switch (c) { char *end; struct passwd *pwd; struct group *grp; case '1': check_inverse(optarg, &invert, &optind, 0); if ((pwd = getpwnam(optarg))) ownerinfo->uid = pwd->pw_uid; else { ownerinfo->uid = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad OWNER UID value `%s'", optarg); } if (invert) ownerinfo->invert |= IP6T_OWNER_UID; ownerinfo->match |= IP6T_OWNER_UID; *flags = 1; break; case '2': check_inverse(optarg, &invert, &optind, 0); if ((grp = getgrnam(optarg))) ownerinfo->gid = grp->gr_gid; else { ownerinfo->gid = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad OWNER GID value `%s'", optarg); } if (invert) ownerinfo->invert |= IP6T_OWNER_GID; ownerinfo->match |= IP6T_OWNER_GID; *flags = 1; break; case '3': check_inverse(optarg, &invert, &optind, 0); ownerinfo->pid = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad OWNER PID value `%s'", optarg); if (invert) ownerinfo->invert |= IP6T_OWNER_PID; ownerinfo->match |= IP6T_OWNER_PID; *flags = 1; break; case '4': check_inverse(optarg, &invert, &optind, 0); ownerinfo->sid = strtoul(optarg, &end, 0); if (*end != '\0' || end == optarg) exit_error(PARAMETER_PROBLEM, "Bad OWNER SID value `%s'", optarg); if (invert) ownerinfo->invert |= IP6T_OWNER_SID; ownerinfo->match |= IP6T_OWNER_SID; *flags = 1; break; default: return 0; } return 1; }
static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, unsigned int *flags, struct ebt_entry_match **match) { struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data; long int i; char *end; uint32_t *addr; uint32_t *mask; char *maddr; char *mmask; switch (c) { case ARP_OPCODE: check_option(flags, OPT_OPCODE); if (check_inverse(optarg)) arpinfo->invflags |= EBT_ARP_OPCODE; if (optind > argc) print_error("Missing ARP opcode argument"); i = strtol(argv[optind - 1], &end, 10); if (i < 0 || i >= (0x1 << 16) || *end !='\0') { for (i = 0; i < NUMOPCODES; i++) if (!strcasecmp(opcodes[i], optarg)) break; if (i == NUMOPCODES) print_error("Problem with specified " "ARP opcode"); i++; } arpinfo->opcode = htons(i); arpinfo->bitmask |= EBT_ARP_OPCODE; break; case ARP_HTYPE: check_option(flags, OPT_HTYPE); if (check_inverse(optarg)) arpinfo->invflags |= EBT_ARP_HTYPE; if (optind > argc) print_error("Missing ARP hardware type argument"); i = strtol(argv[optind - 1], &end, 10); if (i < 0 || i >= (0x1 << 16) || *end !='\0') { if (!strcasecmp("Ethernet", argv[optind - 1])) i = 1; else print_error("Problem with specified ARP " "hardware type"); } arpinfo->htype = htons(i); arpinfo->bitmask |= EBT_ARP_HTYPE; break; case ARP_PTYPE: { uint16_t proto; check_option(flags, OPT_PTYPE); if (check_inverse(optarg)) arpinfo->invflags |= EBT_ARP_PTYPE; if (optind > argc) print_error("Missing ARP protocol type argument"); i = strtol(argv[optind - 1], &end, 16); if (i < 0 || i >= (0x1 << 16) || *end !='\0') { struct ethertypeent *ent; ent = getethertypebyname(argv[optind - 1]); if (!ent) print_error("Problem with specified ARP " "protocol type"); proto = ent->e_ethertype; } else proto = i; arpinfo->ptype = htons(proto); arpinfo->bitmask |= EBT_ARP_PTYPE; break; } case ARP_IP_S: case ARP_IP_D: if (c == ARP_IP_S) { check_option(flags, OPT_IP_S); addr = &arpinfo->saddr; mask = &arpinfo->smsk; arpinfo->bitmask |= EBT_ARP_SRC_IP; } else { check_option(flags, OPT_IP_D); addr = &arpinfo->daddr; mask = &arpinfo->dmsk; arpinfo->bitmask |= EBT_ARP_DST_IP; } if (check_inverse(optarg)) { if (c == ARP_IP_S) arpinfo->invflags |= EBT_ARP_SRC_IP; else arpinfo->invflags |= EBT_ARP_DST_IP; } if (optind > argc) print_error("Missing ARP IP address argument"); parse_ip_address(argv[optind - 1], addr, mask); break; case ARP_MAC_S: case ARP_MAC_D: if (c == ARP_MAC_S) { check_option(flags, OPT_MAC_S); maddr = arpinfo->smaddr; mmask = arpinfo->smmsk; arpinfo->bitmask |= EBT_ARP_SRC_MAC; } else { check_option(flags, OPT_MAC_D); maddr = arpinfo->dmaddr; mmask = arpinfo->dmmsk; arpinfo->bitmask |= EBT_ARP_DST_MAC; } if (check_inverse(optarg)) { if (c == ARP_MAC_S) arpinfo->invflags |= EBT_ARP_SRC_MAC; else arpinfo->invflags |= EBT_ARP_DST_MAC; } if (optind > argc) print_error("Missing ARP MAC address argument"); if (get_mac_and_mask(argv[optind - 1], maddr, mmask)) print_error("Problem with ARP MAC address argument"); break; default: return 0; } return 1; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) (*target)->data; int group_d; switch (c) { case '!': if (*flags & IPT_LOG_OPT_NLGROUP) exit_error(PARAMETER_PROBLEM, "Can't specify --ulog-nlgroup twice"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --ulog-nlgroup"); group_d = atoi(optarg); if (group_d > 32 || group_d < 1) exit_error(PARAMETER_PROBLEM, "--ulog-nlgroup has to be between 1 and 32"); loginfo->nl_group = (1 << (group_d - 1)); *flags |= IPT_LOG_OPT_NLGROUP; break; case '#': if (*flags & IPT_LOG_OPT_PREFIX) exit_error(PARAMETER_PROBLEM, "Can't specify --ulog-prefix twice"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --ulog-prefix"); if (strlen(optarg) > sizeof(loginfo->prefix) - 1) exit_error(PARAMETER_PROBLEM, "Maximum prefix length %u for --ulog-prefix", (unsigned int)(sizeof(loginfo->prefix) - 1)); strcpy(loginfo->prefix, optarg); *flags |= IPT_LOG_OPT_PREFIX; break; case 'A': if (*flags & IPT_LOG_OPT_CPRANGE) exit_error(PARAMETER_PROBLEM, "Can't specify --ulog-cprange twice"); if (atoi(optarg) < 0) exit_error(PARAMETER_PROBLEM, "Negative copy range?"); loginfo->copy_range = atoi(optarg); *flags |= IPT_LOG_OPT_CPRANGE; break; case 'B': if (*flags & IPT_LOG_OPT_QTHRESHOLD) exit_error(PARAMETER_PROBLEM, "Can't specify --ulog-qthreshold twice"); if (atoi(optarg) < 1) exit_error(PARAMETER_PROBLEM, "Negative or zero queue threshold ?"); if (atoi(optarg) > ULOG_MAX_QLEN) exit_error(PARAMETER_PROBLEM, "Maximum queue length exceeded"); loginfo->qthreshold = atoi(optarg); *flags |= IPT_LOG_OPT_QTHRESHOLD; break; } return 1; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct ipt_entry_target **target) { int portok; struct ipt_porttrigger_info *info = (struct ipt_porttrigger_info *)(*target)->data; switch (c) { case '1': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' "); if (!strcasecmp(optarg, "dnat")) info->mode= MODE_DNAT; else if (!strcasecmp(optarg, "forward_in")) info->mode= MODE_FORWARD_IN; else if (!strcasecmp(optarg, "forward_out")) info->mode= MODE_FORWARD_OUT; return 1; case '2': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' "); if (!strcasecmp(optarg, "tcp")) info->trigger_proto= IPPROTO_TCP; else if (!strcasecmp(optarg, "udp")) info->trigger_proto = IPPROTO_UDP; else if (!strcasecmp(optarg, "all") || !strcasecmp(optarg, "any")) info->trigger_proto = 0; return 1; case '3': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' "); if (!strcasecmp(optarg, "tcp")) info->forward_proto= IPPROTO_TCP; else if (!strcasecmp(optarg, "udp")) info->forward_proto = IPPROTO_UDP; else if (!strcasecmp(optarg, "all") || !strcasecmp(optarg, "any")) info->forward_proto = 0; return 1; case '4': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' "); parse_multi_ports(optarg, &info->trigger_ports); return 1; case '5': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' "); parse_multi_ports(optarg, &info->forward_ports); return 1; case '6': if (check_inverse(optarg, &invert, &optind, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' "); info->timer = atoi(optarg); return 1; default: return 0; } }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ip6t_entry *entry, unsigned int *nfcache, struct ip6t_entry_match **match) { struct ip6t_rt *rtinfo = (struct ip6t_rt *)(*match)->data; switch (c) { case '1': if (*flags & IP6T_RT_TYP) exit_error(PARAMETER_PROBLEM, "Only one `--rt-type' allowed"); check_inverse(optarg, &invert, &optind, 0); rtinfo->rt_type = parse_rt_num(argv[optind-1], "type"); if (invert) rtinfo->invflags |= IP6T_RT_INV_TYP; rtinfo->flags |= IP6T_RT_TYP; *flags |= IP6T_RT_TYP; break; case '2': if (*flags & IP6T_RT_SGS) exit_error(PARAMETER_PROBLEM, "Only one `--rt-segsleft' allowed"); check_inverse(optarg, &invert, &optind, 0); parse_rt_segsleft(argv[optind-1], rtinfo->segsleft); if (invert) rtinfo->invflags |= IP6T_RT_INV_SGS; rtinfo->flags |= IP6T_RT_SGS; *flags |= IP6T_RT_SGS; break; case '3': if (*flags & IP6T_RT_LEN) exit_error(PARAMETER_PROBLEM, "Only one `--rt-len' allowed"); check_inverse(optarg, &invert, &optind, 0); rtinfo->hdrlen = parse_rt_num(argv[optind-1], "length"); if (invert) rtinfo->invflags |= IP6T_RT_INV_LEN; rtinfo->flags |= IP6T_RT_LEN; *flags |= IP6T_RT_LEN; break; case '4': if (*flags & IP6T_RT_RES) exit_error(PARAMETER_PROBLEM, "Only one `--rt-0-res' allowed"); if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) ) exit_error(PARAMETER_PROBLEM, "`--rt-type 0' required before `--rt-0-res'"); rtinfo->flags |= IP6T_RT_RES; *flags |= IP6T_RT_RES; break; case '5': if (*flags & IP6T_RT_FST) exit_error(PARAMETER_PROBLEM, "Only one `--rt-0-addrs' allowed"); if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) ) exit_error(PARAMETER_PROBLEM, "`--rt-type 0' required before `--rt-0-addrs'"); check_inverse(optarg, &invert, &optind, 0); if (invert) exit_error(PARAMETER_PROBLEM, " '!' not allowed with `--rt-0-addrs'"); rtinfo->addrnr = parse_addresses(argv[optind-1], rtinfo->addrs); rtinfo->flags |= IP6T_RT_FST; *flags |= IP6T_RT_FST; break; case '6': if (*flags & IP6T_RT_FST_NSTRICT) exit_error(PARAMETER_PROBLEM, "Only one `--rt-0-not-strict' allowed"); if ( !(*flags & IP6T_RT_FST) ) exit_error(PARAMETER_PROBLEM, "`--rt-0-addr ...' required before `--rt-0-not-strict'"); rtinfo->flags |= IP6T_RT_FST_NSTRICT; *flags |= IP6T_RT_FST_NSTRICT; break; default: return 0; } return 1; }
/* Function which parses command options; returns true if it ate an option. */ static int tcp_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_tcp *tcpinfo = (struct xt_tcp *)(*match)->data; switch (c) { case '1': if (*flags & TCP_SRC_PORTS) exit_error(PARAMETER_PROBLEM, "Only one `--source-port' allowed"); check_inverse(optarg, &invert, &optind, 0); parse_tcp_ports(argv[optind-1], tcpinfo->spts); if (invert) tcpinfo->invflags |= XT_TCP_INV_SRCPT; *flags |= TCP_SRC_PORTS; break; case '2': if (*flags & TCP_DST_PORTS) exit_error(PARAMETER_PROBLEM, "Only one `--destination-port' allowed"); check_inverse(optarg, &invert, &optind, 0); parse_tcp_ports(argv[optind-1], tcpinfo->dpts); if (invert) tcpinfo->invflags |= XT_TCP_INV_DSTPT; *flags |= TCP_DST_PORTS; break; case '3': if (*flags & TCP_FLAGS) exit_error(PARAMETER_PROBLEM, "Only one of `--syn' or `--tcp-flags' " " allowed"); parse_tcp_flags(tcpinfo, "SYN,RST,ACK,FIN", "SYN", invert); *flags |= TCP_FLAGS; break; case '4': if (*flags & TCP_FLAGS) exit_error(PARAMETER_PROBLEM, "Only one of `--syn' or `--tcp-flags' " " allowed"); check_inverse(optarg, &invert, &optind, 0); if (!argv[optind] || argv[optind][0] == '-' || argv[optind][0] == '!') exit_error(PARAMETER_PROBLEM, "--tcp-flags requires two args."); parse_tcp_flags(tcpinfo, argv[optind-1], argv[optind], invert); optind++; *flags |= TCP_FLAGS; break; case '5': if (*flags & TCP_OPTION) exit_error(PARAMETER_PROBLEM, "Only one `--tcp-option' allowed"); check_inverse(optarg, &invert, &optind, 0); parse_tcp_option(argv[optind-1], &tcpinfo->option); if (invert) tcpinfo->invflags |= XT_TCP_INV_OPTION; *flags |= TCP_OPTION; break; default: return 0; } return 1; }
static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match) { const char *s; char *e, *p; int n; struct ipt_web_info *info; if ((c < '1') || (c > '6')) return 0; if (*flags) exit_error(PARAMETER_PROBLEM, "Multiple modes are not supported"); *flags = 1; info = (struct ipt_web_info *)(*match)->data; switch (c) { case '2': info->mode = IPT_WEB_HOST; break; case '3': info->mode = IPT_WEB_RURI; break; case '4': info->mode = IPT_WEB_PATH; break; case '5': info->mode = IPT_WEB_QUERY; break; case '6': info->mode = IPT_WEB_HORE; break; default: // IPT_WEB_HTTP return 1; } if (entry->ip.proto != IPPROTO_TCP) { exit_error(PARAMETER_PROBLEM, "web match requires -p tcp"); } check_inverse(optarg, &invert, &optind, 0); if (invert) info->invert = 1; // convert arg to text\0text\0\0 s = argv[optind - 1]; if ((p = malloc(strlen(s) + 2)) == NULL) { exit_error(PARAMETER_PROBLEM, "Not enough memory"); } e = p; while (*s) { while ((*s == ' ') || (*s == '\n') || (*s == '\t')) ++s; if (*s == 0) break; while ((*s != 0) && (*s != ' ') && (*s != '\n') && (*s != '\t')) { *e++ = *s++; } *e++ = 0; } n = (e - p); #if 0 *e = 0; e = p; while (*e) { printf("[%s]\n", e); e += strlen(e) + 1; } #endif if (n <= 1) { exit_error(PARAMETER_PROBLEM, "Text is too short"); } if (n >= IPT_WEB_MAXTEXT) { exit_error(PARAMETER_PROBLEM, "Text is too long"); } memcpy(info->text, p, n); memset(info->text + n, 0, IPT_WEB_MAXTEXT - n); // term, need to clear rest for ipt rule cmp free(p); return 1; }
static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match) { struct ipt_policy_info *info = (void *)(*match)->data; struct ipt_policy_elem *e = &info->pol[info->len]; struct in_addr *addr = NULL, mask; unsigned int naddr = 0; int mode; check_inverse(optarg, &invert, &optind, 0); switch (c) { case '1': if (info->flags & (IPT_POLICY_MATCH_IN|IPT_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 & IPT_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 |= IPT_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; e->saddr.a4 = addr[0]; e->smask.a4 = 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; e->daddr.a4 = addr[0]; e->dmask.a4 = 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 == IPT_POLICY_MAX_ELEM) exit_error(PARAMETER_PROBLEM, "policy match: maximum policy depth reached"); break; default: return 0; } policy_info = info; return 1; }
static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ip6t_entry *entry, unsigned int *nfcache, struct ip6t_entry_match **match) { struct ip6t_physdev_info *info = (struct ip6t_physdev_info*)(*match)->data; switch (c) { case '1': if (*flags & IP6T_PHYSDEV_OP_IN) goto multiple_use; check_inverse(optarg, &invert, &optind, 0); parse_interface(argv[optind-1], info->physindev, (unsigned char *)info->in_mask); if (invert) info->invert |= IP6T_PHYSDEV_OP_IN; info->bitmask |= IP6T_PHYSDEV_OP_IN; *flags |= IP6T_PHYSDEV_OP_IN; break; case '2': if (*flags & IP6T_PHYSDEV_OP_OUT) goto multiple_use; check_inverse(optarg, &invert, &optind, 0); parse_interface(argv[optind-1], info->physoutdev, (unsigned char *)info->out_mask); if (invert) info->invert |= IP6T_PHYSDEV_OP_OUT; info->bitmask |= IP6T_PHYSDEV_OP_OUT; *flags |= IP6T_PHYSDEV_OP_OUT; break; case '3': if (*flags & IP6T_PHYSDEV_OP_ISIN) goto multiple_use; check_inverse(optarg, &invert, &optind, 0); info->bitmask |= IP6T_PHYSDEV_OP_ISIN; if (invert) info->invert |= IP6T_PHYSDEV_OP_ISIN; *flags |= IP6T_PHYSDEV_OP_ISIN; break; case '4': if (*flags & IP6T_PHYSDEV_OP_ISOUT) goto multiple_use; check_inverse(optarg, &invert, &optind, 0); info->bitmask |= IP6T_PHYSDEV_OP_ISOUT; if (invert) info->invert |= IP6T_PHYSDEV_OP_ISOUT; *flags |= IP6T_PHYSDEV_OP_ISOUT; break; case '5': if (*flags & IP6T_PHYSDEV_OP_BRIDGED) goto multiple_use; check_inverse(optarg, &invert, &optind, 0); if (invert) info->invert |= IP6T_PHYSDEV_OP_BRIDGED; *flags |= IP6T_PHYSDEV_OP_BRIDGED; info->bitmask |= IP6T_PHYSDEV_OP_BRIDGED; break; default: return 0; } return 1; multiple_use: exit_error(PARAMETER_PROBLEM, "multiple use of the same physdev option is not allowed"); }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ip6t_entry *entry, struct ip6t_entry_target **target) { struct ip6t_route_target_info *route_info = (struct ip6t_route_target_info*)(*target)->data; switch (c) { case '1': if (*flags & IP6T_ROUTE_OPT_OIF) exit_error(PARAMETER_PROBLEM, "Can't specify --oif twice"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --oif"); if (strlen(optarg) > sizeof(route_info->oif) - 1) exit_error(PARAMETER_PROBLEM, "Maximum interface name length %u", sizeof(route_info->oif) - 1); strcpy(route_info->oif, optarg); *flags |= IP6T_ROUTE_OPT_OIF; break; case '2': exit_error(PARAMETER_PROBLEM, "--iif option not implemented"); break; case '3': if (*flags & IP6T_ROUTE_OPT_GW) exit_error(PARAMETER_PROBLEM, "Can't specify --gw twice"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --gw"); if (!inet_pton(AF_INET6, optarg, (struct in6_addr*)&route_info->gw)) { exit_error(PARAMETER_PROBLEM, "Invalid IPv6 address %s", optarg); } *flags |= IP6T_ROUTE_OPT_GW; break; case '4': if (*flags & IP6T_ROUTE_OPT_CONTINUE) exit_error(PARAMETER_PROBLEM, "Can't specify --continue twice"); if (*flags & IP6T_ROUTE_OPT_TEE) exit_error(PARAMETER_PROBLEM, "Can't specify --continue AND --tee"); route_info->flags |= IP6T_ROUTE_CONTINUE; *flags |= IP6T_ROUTE_OPT_CONTINUE; break; case '5': if (*flags & IP6T_ROUTE_OPT_TEE) exit_error(PARAMETER_PROBLEM, "Can't specify --tee twice"); if (*flags & IP6T_ROUTE_OPT_CONTINUE) exit_error(PARAMETER_PROBLEM, "Can't specify --tee AND --continue"); route_info->flags |= IP6T_ROUTE_TEE; *flags |= IP6T_ROUTE_OPT_TEE; break; default: return 0; } return 1; }
static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match) { struct ipt_dccp_info *einfo = (struct ipt_dccp_info *)(*match)->data; switch (c) { case '1': if (*flags & IPT_DCCP_SRC_PORTS) exit_error(PARAMETER_PROBLEM, "Only one `--source-port' allowed"); einfo->flags |= IPT_DCCP_SRC_PORTS; check_inverse(optarg, &invert, &optind, 0); parse_dccp_ports(argv[optind-1], einfo->spts); if (invert) einfo->invflags |= IPT_DCCP_SRC_PORTS; *flags |= IPT_DCCP_SRC_PORTS; break; case '2': if (*flags & IPT_DCCP_DEST_PORTS) exit_error(PARAMETER_PROBLEM, "Only one `--destination-port' allowed"); einfo->flags |= IPT_DCCP_DEST_PORTS; check_inverse(optarg, &invert, &optind, 0); parse_dccp_ports(argv[optind-1], einfo->dpts); if (invert) einfo->invflags |= IPT_DCCP_DEST_PORTS; *flags |= IPT_DCCP_DEST_PORTS; break; case '3': if (*flags & IPT_DCCP_TYPE) exit_error(PARAMETER_PROBLEM, "Only one `--dccp-types' allowed"); einfo->flags |= IPT_DCCP_TYPE; check_inverse(optarg, &invert, &optind, 0); einfo->typemask = parse_dccp_types(argv[optind-1]); if (invert) einfo->invflags |= IPT_DCCP_TYPE; *flags |= IPT_DCCP_TYPE; break; case '4': if (*flags & IPT_DCCP_OPTION) exit_error(PARAMETER_PROBLEM, "Only one `--dccp-option' allowed"); einfo->flags |= IPT_DCCP_OPTION; check_inverse(optarg, &invert, &optind, 0); einfo->option = parse_dccp_option(argv[optind-1]); if (invert) einfo->invflags |= IPT_DCCP_OPTION; *flags |= IPT_DCCP_OPTION; break; default: return 0; } return 1; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match) { struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data; switch (c) { case 201: if (*flags) exit_error(PARAMETER_PROBLEM, "recent: only one of `--set', `--rcheck' " "`--update' or `--remove' may be set"); check_inverse(optarg, &invert, &optind, 0); info->check_set |= IPT_RECENT_SET; if (invert) info->invert = 1; *flags = 1; break; case 202: if (*flags) exit_error(PARAMETER_PROBLEM, "recent: only one of `--set', `--rcheck' " "`--update' or `--remove' may be set"); check_inverse(optarg, &invert, &optind, 0); info->check_set |= IPT_RECENT_CHECK; if(invert) info->invert = 1; *flags = 1; break; case 203: if (*flags) exit_error(PARAMETER_PROBLEM, "recent: only one of `--set', `--rcheck' " "`--update' or `--remove' may be set"); check_inverse(optarg, &invert, &optind, 0); info->check_set |= IPT_RECENT_UPDATE; if (invert) info->invert = 1; *flags = 1; break; case 206: if (*flags) exit_error(PARAMETER_PROBLEM, "recent: only one of `--set', `--rcheck' " "`--update' or `--remove' may be set"); check_inverse(optarg, &invert, &optind, 0); info->check_set |= IPT_RECENT_REMOVE; if (invert) info->invert = 1; *flags = 1; break; case 204: info->seconds = atoi(optarg); break; case 205: info->hit_count = atoi(optarg); break; case 207: info->check_set |= IPT_RECENT_TTL; break; case 208: strncpy(info->name,optarg,IPT_RECENT_NAME_LEN); info->name[IPT_RECENT_NAME_LEN-1] = '\0'; break; case 209: info->side = IPT_RECENT_SOURCE; break; case 210: info->side = IPT_RECENT_DEST; break; default: return 0; } return 1; }
static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, struct xt_entry_target **target) { struct xt_nflog_info *info = (struct xt_nflog_info *)(*target)->data; int n; switch (c) { case NFLOG_GROUP: if (*flags & NFLOG_GROUP) exit_error(PARAMETER_PROBLEM, "Can't specify --nflog-group twice"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --nflog-group"); n = atoi(optarg); if (n < 1 || n > 32) exit_error(PARAMETER_PROBLEM, "--nflog-group has to be between 1 and 32"); info->group = 1 << (n - 1); break; case NFLOG_PREFIX: if (*flags & NFLOG_PREFIX) exit_error(PARAMETER_PROBLEM, "Can't specify --nflog-prefix twice"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --nflog-prefix"); n = strlen(optarg); if (n == 0) exit_error(PARAMETER_PROBLEM, "No prefix specified for --nflog-prefix"); if (n >= sizeof(info->prefix)) exit_error(PARAMETER_PROBLEM, "--nflog-prefix too long, max %Zu characters", sizeof(info->prefix) - 1); if (n != strlen(strtok(optarg, "\n"))) exit_error(PARAMETER_PROBLEM, "Newlines are not allowed in --nflog-prefix"); strcpy(info->prefix, optarg); break; case NFLOG_RANGE: if (*flags & NFLOG_RANGE) exit_error(PARAMETER_PROBLEM, "Can't specify --nflog-range twice"); n = atoi(optarg); if (n < 0) exit_error(PARAMETER_PROBLEM, "Invalid --nflog-range, must be >= 0"); info->len = n; break; case NFLOG_THRESHOLD: if (*flags & NFLOG_THRESHOLD) exit_error(PARAMETER_PROBLEM, "Can't specify --nflog-threshold twice"); n = atoi(optarg); if (n < 1) exit_error(PARAMETER_PROBLEM, "Invalid --nflog-threshold, must be >= 1"); info->threshold = n; break; default: return 0; } *flags |= c; return 1; }
/* Function which parses command options; returns true if it ate an option */ static int parse(int c, char **argv, int invert, unsigned int *flags, const struct ipt_entry *entry, unsigned int *nfcache, struct ipt_entry_match **match) { struct ipt_string_info *stringinfo = (struct ipt_string_info *)(*match)->data; switch (c) { case '1': if (*flags & FROM) exit_error(PARAMETER_PROBLEM, "Can't specify multiple --from"); stringinfo->from_offset = atoi(optarg); *flags |= FROM; stringinfo->type = 0; break; case '2': if (*flags & TO) exit_error(PARAMETER_PROBLEM, "Can't specify multiple --to"); stringinfo->to_offset = atoi(optarg); *flags |= TO; stringinfo->type = 0; break; case '3': if (*flags & ALGO) exit_error(PARAMETER_PROBLEM, "Can't specify multiple --algo"); parse_algo(optarg, stringinfo); *flags |= ALGO; stringinfo->type = 0; break; case '4': check_inverse(optarg, &invert, &optind, 0); parse_string(argv[optind-1], stringinfo); if (invert) stringinfo->invert = 1; stringinfo->patlen=strlen((char *)&stringinfo->pattern); stringinfo->type = IPT_WEBSTR_URL; break; case '5': check_inverse(optarg, &invert, &optind, 0); parse_string(argv[optind-1], stringinfo); if (invert) stringinfo->invert = 1; stringinfo->patlen=strlen((char *)&stringinfo->pattern); stringinfo->type = IPT_WEBSTR_HOST; break; case '6': check_inverse(optarg, &invert, &optind, 0); parse_string(argv[optind-1], stringinfo); if (invert) stringinfo->invert = 1; stringinfo->patlen=strlen((char *)&stringinfo->pattern); stringinfo->type = IPT_WEBSTR_CONTENT; break; default: return 0; } *flags = 1; return 1; }
int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table) { struct arptables_command_state cs; int invert = 0; unsigned int nsaddrs = 0, ndaddrs = 0; struct in_addr *saddrs = NULL, *daddrs = NULL; int c, verbose = 0; const char *chain = NULL; const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL; const char *policy = NULL, *newname = NULL; unsigned int rulenum = 0, options = 0, command = 0; const char *pcnt = NULL, *bcnt = NULL; int ret = 1; struct xtables_target *t; memset(&cs, 0, sizeof(cs)); cs.jumpto = ""; opts = original_opts; global_option_offset = 0; xtables_globals.orig_opts = original_opts; /* re-set optind to 0 in case do_command gets called * a second time */ optind = 0; for (t = xtables_targets; t; t = t->next) { t->tflags = 0; t->used = 0; } /* Suppress error messages: we may add new options if we demand-load a protocol. */ opterr = 0; while ((c = getopt_long(argc, argv, "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:l:i:vnt:m:c:", opts, NULL)) != -1) { switch (c) { /* * Command selection */ case 'A': add_command(&command, CMD_APPEND, CMD_NONE, invert); chain = optarg; break; case 'D': add_command(&command, CMD_DELETE, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') { rulenum = parse_rulenumber(argv[optind++]); command = CMD_DELETE_NUM; } break; case 'R': add_command(&command, CMD_REPLACE, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') rulenum = parse_rulenumber(argv[optind++]); else xtables_error(PARAMETER_PROBLEM, "-%c requires a rule number", cmd2char(CMD_REPLACE)); break; case 'I': add_command(&command, CMD_INSERT, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') rulenum = parse_rulenumber(argv[optind++]); else rulenum = 1; break; case 'L': add_command(&command, CMD_LIST, CMD_ZERO, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; case 'F': add_command(&command, CMD_FLUSH, CMD_NONE, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; case 'Z': add_command(&command, CMD_ZERO, CMD_LIST, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; case 'N': if (optarg && *optarg == '-') xtables_error(PARAMETER_PROBLEM, "chain name not allowed to start " "with `-'\n"); if (xtables_find_target(optarg, XTF_TRY_LOAD)) xtables_error(PARAMETER_PROBLEM, "chain name may not clash " "with target name\n"); add_command(&command, CMD_NEW_CHAIN, CMD_NONE, invert); chain = optarg; break; case 'X': add_command(&command, CMD_DELETE_CHAIN, CMD_NONE, invert); if (optarg) chain = optarg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') chain = argv[optind++]; break; case 'E': add_command(&command, CMD_RENAME_CHAIN, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') newname = argv[optind++]; else xtables_error(PARAMETER_PROBLEM, "-%c requires old-chain-name and " "new-chain-name", cmd2char(CMD_RENAME_CHAIN)); break; case 'P': add_command(&command, CMD_SET_POLICY, CMD_NONE, invert); chain = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') policy = argv[optind++]; else xtables_error(PARAMETER_PROBLEM, "-%c requires a chain and a policy", cmd2char(CMD_SET_POLICY)); break; case 'h': if (!optarg) optarg = argv[optind]; exit_printhelp(); break; case 's': check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_S_IP, &cs.fw.arp.invflags, invert); shostnetworkmask = argv[optind-1]; break; case 'd': check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_D_IP, &cs.fw.arp.invflags, invert); dhostnetworkmask = argv[optind-1]; break; case 2:/* src-mac */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_S_MAC, &cs.fw.arp.invflags, invert); if (getmac_and_mask(argv[optind - 1], cs.fw.arp.src_devaddr.addr, cs.fw.arp.src_devaddr.mask)) xtables_error(PARAMETER_PROBLEM, "Problem with specified " "source mac"); break; case 3:/* dst-mac */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_D_MAC, &cs.fw.arp.invflags, invert); if (getmac_and_mask(argv[optind - 1], cs.fw.arp.tgt_devaddr.addr, cs.fw.arp.tgt_devaddr.mask)) xtables_error(PARAMETER_PROBLEM, "Problem with specified " "destination mac"); break; case 'l':/* hardware length */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_H_LENGTH, &cs.fw.arp.invflags, invert); getlength_and_mask(argv[optind - 1], &cs.fw.arp.arhln, &cs.fw.arp.arhln_mask); if (cs.fw.arp.arhln != 6) { xtables_error(PARAMETER_PROBLEM, "Only harware address length of" " 6 is supported currently."); } break; case 8:/* protocol length */ xtables_error(PARAMETER_PROBLEM, "not supported"); /* check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_P_LENGTH, &cs.fw.arp.invflags, invert); getlength_and_mask(argv[optind - 1], &cs.fw.arp.arpln, &cs.fw.arp.arpln_mask); break; */ case 4:/* opcode */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_OPCODE, &cs.fw.arp.invflags, invert); if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arpop, &cs.fw.arp.arpop_mask, 10)) { int i; for (i = 0; i < NUMOPCODES; i++) if (!strcasecmp(opcodes[i], optarg)) break; if (i == NUMOPCODES) xtables_error(PARAMETER_PROBLEM, "Problem with specified opcode"); cs.fw.arp.arpop = htons(i+1); } break; case 5:/* h-type */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_H_TYPE, &cs.fw.arp.invflags, invert); if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arhrd, &cs.fw.arp.arhrd_mask, 16)) { if (strcasecmp(argv[optind-1], "Ethernet")) xtables_error(PARAMETER_PROBLEM, "Problem with specified hardware type"); cs.fw.arp.arhrd = htons(1); } break; case 6:/* proto-type */ check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_P_TYPE, &cs.fw.arp.invflags, invert); if (get16_and_mask(argv[optind - 1], &cs.fw.arp.arpro, &cs.fw.arp.arpro_mask, 0)) { if (strcasecmp(argv[optind-1], "ipv4")) xtables_error(PARAMETER_PROBLEM, "Problem with specified protocol type"); cs.fw.arp.arpro = htons(0x800); } break; case 'j': set_option(&options, OPT_JUMP, &cs.fw.arp.invflags, invert); cs.jumpto = parse_target(optarg); cs.target = command_jump(&cs.fw, cs.jumpto); break; case 'i': check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_VIANAMEIN, &cs.fw.arp.invflags, invert); parse_interface(argv[optind-1], cs.fw.arp.iniface, cs.fw.arp.iniface_mask); /* cs.fw.nfcache |= NFC_IP_IF_IN; */ break; case 'o': check_inverse(optarg, &invert, &optind, argc); set_option(&options, OPT_VIANAMEOUT, &cs.fw.arp.invflags, invert); parse_interface(argv[optind-1], cs.fw.arp.outiface, cs.fw.arp.outiface_mask); /* cs.fw.nfcache |= NFC_IP_IF_OUT; */ break; case 'v': if (!verbose) set_option(&options, OPT_VERBOSE, &cs.fw.arp.invflags, invert); verbose++; break; case 'm': /*{ size_t size; if (invert) exit_error(PARAMETER_PROBLEM, "unexpected ! flag before --match"); m = find_match(optarg, LOAD_MUST_SUCCEED); size = ARPT_ALIGN(sizeof(struct arpt_entry_match)) + m->size; m->m = fw_calloc(1, size); m->m->u.match_size = size; strcpy(m->m->u.user.name, m->name); m->init(m->m, &fw.nfcache); opts = merge_options(opts, m->extra_opts, &m->option_offset); }*/ break; case 'n': set_option(&options, OPT_NUMERIC, &cs.fw.arp.invflags, invert); break; case 't': if (invert) xtables_error(PARAMETER_PROBLEM, "unexpected ! flag before --table"); *table = argv[optind-1]; break; case 'V': if (invert) printf("Not %s ;-)\n", program_version); else printf("%s v%s\n", program_name, program_version); exit(0); case '0': set_option(&options, OPT_LINENUMBERS, &cs.fw.arp.invflags, invert); break; case 'M': //modprobe = optarg; break; case 'c': set_option(&options, OPT_COUNTERS, &cs.fw.arp.invflags, invert); pcnt = optarg; if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') bcnt = argv[optind++]; else xtables_error(PARAMETER_PROBLEM, "-%c requires packet and byte counter", opt2char(OPT_COUNTERS)); if (sscanf(pcnt, "%llu", &cs.fw.counters.pcnt) != 1) xtables_error(PARAMETER_PROBLEM, "-%c packet counter not numeric", opt2char(OPT_COUNTERS)); if (sscanf(bcnt, "%llu", &cs.fw.counters.bcnt) != 1) xtables_error(PARAMETER_PROBLEM, "-%c byte counter not numeric", opt2char(OPT_COUNTERS)); break; case 1: /* non option */ if (optarg[0] == '!' && optarg[1] == '\0') { if (invert) xtables_error(PARAMETER_PROBLEM, "multiple consecutive ! not" " allowed"); invert = TRUE; optarg[0] = '\0'; continue; } printf("Bad argument `%s'\n", optarg); exit_tryhelp(2); default: if (cs.target) { xtables_option_tpcall(c, argv, invert, cs.target, &cs.fw); } break; } invert = FALSE; } if (cs.target) xtables_option_tfcall(cs.target); if (optind < argc) xtables_error(PARAMETER_PROBLEM, "unknown arguments found on commandline"); if (!command) xtables_error(PARAMETER_PROBLEM, "no command specified"); if (invert) xtables_error(PARAMETER_PROBLEM, "nothing appropriate following !"); if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) { if (!(options & OPT_D_IP)) dhostnetworkmask = "0.0.0.0/0"; if (!(options & OPT_S_IP)) shostnetworkmask = "0.0.0.0/0"; } if (shostnetworkmask) parse_hostnetworkmask(shostnetworkmask, &saddrs, &(cs.fw.arp.smsk), &nsaddrs); if (dhostnetworkmask) parse_hostnetworkmask(dhostnetworkmask, &daddrs, &(cs.fw.arp.tmsk), &ndaddrs); if ((nsaddrs > 1 || ndaddrs > 1) && (cs.fw.arp.invflags & (ARPT_INV_SRCIP | ARPT_INV_TGTIP))) xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple" " source or destination IP addresses"); if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1)) xtables_error(PARAMETER_PROBLEM, "Replacement rule does not " "specify a unique address"); generic_opt_check(command, options); if (chain && strlen(chain) > ARPT_FUNCTION_MAXNAMELEN) xtables_error(PARAMETER_PROBLEM, "chain name `%s' too long (must be under %i chars)", chain, ARPT_FUNCTION_MAXNAMELEN); if (nft_init(h, xtables_arp) < 0) xtables_error(OTHER_PROBLEM, "Could not initialize nftables layer."); h->ops = nft_family_ops_lookup(h->family); if (h->ops == NULL) xtables_error(PARAMETER_PROBLEM, "Unknown family"); if (command == CMD_APPEND || command == CMD_DELETE || command == CMD_INSERT || command == CMD_REPLACE) { if (strcmp(chain, "PREROUTING") == 0 || strcmp(chain, "INPUT") == 0) { /* -o not valid with incoming packets. */ if (options & OPT_VIANAMEOUT) xtables_error(PARAMETER_PROBLEM, "Can't use -%c with %s\n", opt2char(OPT_VIANAMEOUT), chain); } if (strcmp(chain, "POSTROUTING") == 0 || strcmp(chain, "OUTPUT") == 0) { /* -i not valid with outgoing packets */ if (options & OPT_VIANAMEIN) xtables_error(PARAMETER_PROBLEM, "Can't use -%c with %s\n", opt2char(OPT_VIANAMEIN), chain); } if (!cs.target && strlen(cs.jumpto) != 0) { size_t size; cs.target = xtables_find_target(XT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED); size = sizeof(struct arpt_entry_target) + cs.target->size; cs.target->t = xtables_calloc(1, size); cs.target->t->u.target_size = size; strcpy(cs.target->t->u.user.name, cs.jumpto); } } switch (command) { case CMD_APPEND: ret = append_entry(h, chain, *table, &cs, 0, nsaddrs, saddrs, ndaddrs, daddrs, options&OPT_VERBOSE, true); break; case CMD_DELETE: ret = delete_entry(chain, *table, &cs, nsaddrs, saddrs, ndaddrs, daddrs, options&OPT_VERBOSE, h); break; case CMD_DELETE_NUM: ret = nft_rule_delete_num(h, chain, *table, rulenum - 1, verbose); break; case CMD_REPLACE: ret = replace_entry(chain, *table, &cs, rulenum - 1, saddrs, daddrs, options&OPT_VERBOSE, h); break; case CMD_INSERT: ret = append_entry(h, chain, *table, &cs, rulenum - 1, nsaddrs, saddrs, ndaddrs, daddrs, options&OPT_VERBOSE, false); break; case CMD_LIST: ret = list_entries(h, chain, *table, rulenum, options&OPT_VERBOSE, options&OPT_NUMERIC, /*options&OPT_EXPANDED*/0, options&OPT_LINENUMBERS); break; case CMD_FLUSH: ret = nft_rule_flush(h, chain, *table); break; case CMD_ZERO: ret = nft_chain_zero_counters(h, chain, *table); break; case CMD_LIST|CMD_ZERO: ret = list_entries(h, chain, *table, rulenum, options&OPT_VERBOSE, options&OPT_NUMERIC, /*options&OPT_EXPANDED*/0, options&OPT_LINENUMBERS); if (ret) ret = nft_chain_zero_counters(h, chain, *table); break; case CMD_NEW_CHAIN: ret = nft_chain_user_add(h, chain, *table); break; case CMD_DELETE_CHAIN: ret = nft_chain_user_del(h, chain, *table); break; case CMD_RENAME_CHAIN: ret = nft_chain_user_rename(h, chain, *table, newname); break; case CMD_SET_POLICY: ret = nft_chain_set(h, *table, chain, policy, NULL); if (ret < 0) xtables_error(PARAMETER_PROBLEM, "Wrong policy `%s'\n", policy); break; default: /* We should never reach this... */ exit_tryhelp(2); } /* if (verbose > 1) dump_entries(*handle);*/ return ret; }