static int tcindex_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; char *end; if (handle) { t->tcm_handle = strtoul(handle, &end, 0); if (*end) { fprintf(stderr, "Illegal filter ID\n"); return -1; } } if (!argc) return 0; tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc) { if (!strcmp(*argv, "hash")) { int hash; NEXT_ARG(); hash = strtoul(*argv, &end, 0); if (*end || !hash || hash > 0x10000) { explain(); return -1; } addattr_l(n, 4096, TCA_TCINDEX_HASH, &hash, sizeof(hash)); } else if (!strcmp(*argv,"mask")) { __u16 mask; NEXT_ARG(); mask = strtoul(*argv, &end, 0); if (*end) { explain(); return -1; } addattr_l(n, 4096, TCA_TCINDEX_MASK, &mask, sizeof(mask)); } else if (!strcmp(*argv,"shift")) { int shift; NEXT_ARG(); shift = strtoul(*argv, &end, 0); if (*end) { explain(); return -1; } addattr_l(n, 4096, TCA_TCINDEX_SHIFT, &shift, sizeof(shift)); } else if (!strcmp(*argv,"fall_through")) { int value = 1; addattr_l(n, 4096, TCA_TCINDEX_FALL_THROUGH, &value, sizeof(value)); } else if (!strcmp(*argv,"pass_on")) { int value = 0; addattr_l(n, 4096, TCA_TCINDEX_FALL_THROUGH, &value, sizeof(value)); } else if (!strcmp(*argv,"classid")) { __u32 handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, 4096, TCA_TCINDEX_CLASSID, &handle, 4); } else if (!strcmp(*argv,"police")) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_TCINDEX_POLICE, n)) { fprintf(stderr, "Illegal \"police\"\n"); return -1; } continue; } else if (!strcmp(*argv,"action")) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_TCINDEX_ACT, n)) { fprintf(stderr, "Illegal \"action\"\n"); return -1; } continue; } else { explain(); return -1; } argc--; argv++; } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct tc_police tp; struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; __u32 mask = 0; int mask_set = 0; memset(&tp, 0, sizeof(tp)); if (handle) { char *slash; if ((slash = strchr(handle, '/')) != NULL) *slash = '\0'; if (get_u32(&t->tcm_handle, handle, 0)) { fprintf(stderr, "Illegal \"handle\"\n"); return -1; } if (slash) { if (get_u32(&mask, slash+1, 0)) { fprintf(stderr, "Illegal \"handle\" mask\n"); return -1; } mask_set = 1; } } if (argc == 0) return 0; tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); if (mask_set) addattr32(n, MAX_MSG, TCA_FW_MASK, mask); while (argc > 0) { if (matches(*argv, "classid") == 0 || matches(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, 4096, TCA_FW_CLASSID, &handle, 4); } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_FW_POLICE, n)) { fprintf(stderr, "Illegal \"police\"\n"); return -1; } continue; } else if (matches(*argv, "action") == 0) { NEXT_ARG(); if (parse_action(&argc, &argv, TCA_FW_ACT, n)) { fprintf(stderr, "Illegal fw \"action\"\n"); return -1; } continue; } else if (strcmp(*argv, "indev") == 0) { char d[IFNAMSIZ+1]; memset(d, 0, sizeof (d)); argc--; argv++; if (argc < 1) { fprintf(stderr, "Illegal indev\n"); return -1; } strncpy(d, *argv, sizeof (d) - 1); addattr_l(n, MAX_MSG, TCA_FW_INDEV, d, strlen(d) + 1); } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int flow_parse_opt(struct filter_util *fu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct tc_police tp; struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; __u32 mask = ~0U, xor = 0; __u32 keys = 0, nkeys = 0; __u32 mode = FLOW_MODE_MAP; __u32 tmp; memset(&tp, 0, sizeof(tp)); if (handle) { if (get_u32(&t->tcm_handle, handle, 0)) { fprintf(stderr, "Illegal \"handle\"\n"); return -1; } } tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "map") == 0) { mode = FLOW_MODE_MAP; } else if (matches(*argv, "hash") == 0) { mode = FLOW_MODE_HASH; } else if (matches(*argv, "keys") == 0) { NEXT_ARG(); if (flow_parse_keys(&keys, &nkeys, *argv)) return -1; addattr32(n, 4096, TCA_FLOW_KEYS, keys); } else if (matches(*argv, "and") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"mask\"\n"); return -1; } transfer_bitop(&mask, &xor, tmp, 0); } else if (matches(*argv, "or") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"or\"\n"); return -1; } transfer_bitop(&mask, &xor, ~tmp, tmp); } else if (matches(*argv, "xor") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"xor\"\n"); return -1; } transfer_bitop(&mask, &xor, ~0, tmp); } else if (matches(*argv, "rshift") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"rshift\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_RSHIFT, tmp); } else if (matches(*argv, "addend") == 0) { NEXT_ARG(); if (get_addend(&tmp, *argv, keys)) { fprintf(stderr, "Illegal \"addend\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_ADDEND, tmp); } else if (matches(*argv, "divisor") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"divisor\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_DIVISOR, tmp); } else if (matches(*argv, "baseclass") == 0) { NEXT_ARG(); if (get_tc_classid(&tmp, *argv) || TC_H_MIN(tmp) == 0) { fprintf(stderr, "Illegal \"baseclass\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_BASECLASS, tmp); } else if (matches(*argv, "perturb") == 0) { NEXT_ARG(); if (get_u32(&tmp, *argv, 0)) { fprintf(stderr, "Illegal \"perturb\"\n"); return -1; } addattr32(n, 4096, TCA_FLOW_PERTURB, tmp); } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_FLOW_POLICE, n)) { fprintf(stderr, "Illegal \"police\"\n"); return -1; } continue; } else if (matches(*argv, "action") == 0) { NEXT_ARG(); if (parse_action(&argc, &argv, TCA_FLOW_ACT, n)) { fprintf(stderr, "Illegal \"action\"\n"); return -1; } continue; } else if (matches(*argv, "match") == 0) { NEXT_ARG(); if (parse_ematch(&argc, &argv, TCA_FLOW_EMATCHES, n)) { fprintf(stderr, "Illegal \"ematch\"\n"); return -1; } continue; } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argv++, argc--; } if (nkeys > 1 && mode != FLOW_MODE_HASH) { fprintf(stderr, "Invalid mode \"map\" for multiple keys\n"); return -1; } addattr32(n, 4096, TCA_FLOW_MODE, mode); if (mask != ~0 || xor != 0) { addattr32(n, 4096, TCA_FLOW_MASK, mask); addattr32(n, 4096, TCA_FLOW_XOR, xor); } tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; return 0; }
static int rsvp_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { int family = strcmp(qu->id, "rsvp") == 0 ? AF_INET : AF_INET6; struct tc_rsvp_pinfo pinfo; struct tc_police tp; struct tcmsg *t = NLMSG_DATA(n); int pinfo_ok = 0; struct rtattr *tail; memset(&pinfo, 0, sizeof(pinfo)); memset(&tp, 0, sizeof(tp)); if (handle) { if (get_u32(&t->tcm_handle, handle, 0)) { fprintf(stderr, "Illegal \"handle\"\n"); return -1; } } if (argc == 0) return 0; tail = NLMSG_TAIL(n); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "session") == 0) { inet_prefix addr; NEXT_ARG(); if (get_addr_and_pi(&argc, &argv, &addr, &pinfo, 1, family)) { fprintf(stderr, "Illegal \"session\"\n"); return -1; } addattr_l(n, 4096, TCA_RSVP_DST, &addr.data, addr.bytelen); if (pinfo.dpi.mask || pinfo.protocol) pinfo_ok++; continue; } else if (matches(*argv, "sender") == 0 || matches(*argv, "flowspec") == 0) { inet_prefix addr; NEXT_ARG(); if (get_addr_and_pi(&argc, &argv, &addr, &pinfo, 0, family)) { fprintf(stderr, "Illegal \"sender\"\n"); return -1; } addattr_l(n, 4096, TCA_RSVP_SRC, &addr.data, addr.bytelen); if (pinfo.spi.mask || pinfo.protocol) pinfo_ok++; continue; } else if (matches("ipproto", *argv) == 0) { int num; NEXT_ARG(); num = inet_proto_a2n(*argv); if (num < 0) { fprintf(stderr, "Illegal \"ipproto\"\n"); return -1; } pinfo.protocol = num; pinfo_ok++; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, 4096, TCA_RSVP_CLASSID, &handle, 4); } else if (strcmp(*argv, "tunnelid") == 0) { unsigned tid; NEXT_ARG(); if (get_unsigned(&tid, *argv, 0)) { fprintf(stderr, "Illegal \"tunnelid\"\n"); return -1; } pinfo.tunnelid = tid; pinfo_ok++; } else if (strcmp(*argv, "tunnel") == 0) { unsigned tid; NEXT_ARG(); if (get_unsigned(&tid, *argv, 0)) { fprintf(stderr, "Illegal \"tunnel\"\n"); return -1; } addattr_l(n, 4096, TCA_RSVP_CLASSID, &tid, 4); NEXT_ARG(); if (strcmp(*argv, "skip") == 0) { NEXT_ARG(); } if (get_unsigned(&tid, *argv, 0)) { fprintf(stderr, "Illegal \"skip\"\n"); return -1; } pinfo.tunnelhdr = tid; pinfo_ok++; } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_RSVP_POLICE, n)) { fprintf(stderr, "Illegal \"police\"\n"); return -1; } continue; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } if (pinfo_ok) addattr_l(n, 4096, TCA_RSVP_PINFO, &pinfo, sizeof(pinfo)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }