static int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { struct m_pedit_sel sel = {}; int argc = *argc_p; char **argv = *argv_p; int ok = 0, iok = 0; struct rtattr *tail; while (argc > 0) { if (pedit_debug > 1) fprintf(stderr, "while pedit (%d:%s)\n", argc, *argv); if (matches(*argv, "pedit") == 0) { NEXT_ARG(); ok++; if (matches(*argv, "ex") == 0) { if (ok > 1) { fprintf(stderr, "'ex' must be before first 'munge'\n"); explain(); return -1; } sel.extended = true; NEXT_ARG(); } continue; } else if (matches(*argv, "help") == 0) { usage(); } else if (matches(*argv, "munge") == 0) { if (!ok) { fprintf(stderr, "Bad pedit construct (%s)\n", *argv); explain(); return -1; } NEXT_ARG(); if (parse_munge(&argc, &argv, &sel)) { fprintf(stderr, "Bad pedit construct (%s)\n", *argv); explain(); return -1; } ok++; } else { break; } } if (!ok) { explain(); return -1; } parse_action_control_dflt(&argc, &argv, &sel.sel.action, false, TC_ACT_OK); if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&sel.sel.index, *argv, 10)) { fprintf(stderr, "Pedit: Illegal \"index\"\n"); return -1; } argc--; argv++; iok++; } } tail = addattr_nest(n, MAX_MSG, tca_id); if (!sel.extended) { addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS, &sel, sizeof(sel.sel) + sel.sel.nkeys * sizeof(struct tc_pedit_key)); } else { addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS_EX, &sel, sizeof(sel.sel) + sel.sel.nkeys * sizeof(struct tc_pedit_key)); pedit_keys_ex_addattr(&sel, n); } addattr_nest_end(n, tail); *argc_p = argc; *argv_p = argv; return 0; }
static int parse_connmark(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { struct tc_connmark sel = {}; char **argv = *argv_p; int argc = *argc_p; int ok = 0; struct rtattr *tail; while (argc > 0) { if (matches(*argv, "connmark") == 0) { ok = 1; argc--; argv++; } else if (matches(*argv, "help") == 0) { usage(); } else { break; } } if (!ok) { explain(); return -1; } if (argc) { if (matches(*argv, "zone") == 0) { NEXT_ARG(); if (get_u16(&sel.zone, *argv, 10)) { fprintf(stderr, "simple: Illegal \"index\"\n"); return -1; } argc--; argv++; } } parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_PIPE); if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&sel.index, *argv, 10)) { fprintf(stderr, "simple: Illegal \"index\"\n"); return -1; } argc--; argv++; } } tail = addattr_nest(n, MAX_MSG, tca_id); addattr_l(n, MAX_MSG, TCA_CONNMARK_PARMS, &sel, sizeof(sel)); addattr_nest_end(n, tail); *argc_p = argc; *argv_p = argv; return 0; }
static int parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { int argc = *argc_p; char **argv = *argv_p; int ok = 0; struct rtattr *tail; unsigned int tmp; __u16 queue_mapping, ptype; __u32 flags = 0, priority, mark; struct tc_skbedit sel = { 0 }; if (matches(*argv, "skbedit") != 0) return -1; NEXT_ARG(); while (argc > 0) { if (matches(*argv, "queue_mapping") == 0) { flags |= SKBEDIT_F_QUEUE_MAPPING; NEXT_ARG(); if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) { fprintf(stderr, "Illegal queue_mapping\n"); return -1; } queue_mapping = tmp; ok++; } else if (matches(*argv, "priority") == 0) { flags |= SKBEDIT_F_PRIORITY; NEXT_ARG(); if (get_tc_classid(&priority, *argv)) { fprintf(stderr, "Illegal priority\n"); return -1; } ok++; } else if (matches(*argv, "mark") == 0) { flags |= SKBEDIT_F_MARK; NEXT_ARG(); if (get_u32(&mark, *argv, 0)) { fprintf(stderr, "Illegal mark\n"); return -1; } ok++; } else if (matches(*argv, "ptype") == 0) { NEXT_ARG(); if (matches(*argv, "host") == 0) { ptype = PACKET_HOST; } else if (matches(*argv, "broadcast") == 0) { ptype = PACKET_BROADCAST; } else if (matches(*argv, "multicast") == 0) { ptype = PACKET_MULTICAST; } else if (matches(*argv, "otherhost") == 0) { ptype = PACKET_OTHERHOST; } else { fprintf(stderr, "Illegal ptype (%s)\n", *argv); return -1; } flags |= SKBEDIT_F_PTYPE; ok++; } else if (matches(*argv, "help") == 0) { usage(); } else { break; } argc--; argv++; } parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_PIPE); if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&sel.index, *argv, 10)) { fprintf(stderr, "Pedit: Illegal \"index\"\n"); return -1; } argc--; argv++; ok++; } } if (!ok) { explain(); return -1; } tail = addattr_nest(n, MAX_MSG, tca_id); addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel)); if (flags & SKBEDIT_F_QUEUE_MAPPING) addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING, &queue_mapping, sizeof(queue_mapping)); if (flags & SKBEDIT_F_PRIORITY) addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY, &priority, sizeof(priority)); if (flags & SKBEDIT_F_MARK) addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK, &mark, sizeof(mark)); if (flags & SKBEDIT_F_PTYPE) addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE, &ptype, sizeof(ptype)); addattr_nest_end(n, tail); *argc_p = argc; *argv_p = argv; return 0; }
static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { int argc = *argc_p; char **argv = *argv_p; int ok = 0; struct tc_ife p = { 0 }; struct rtattr *tail; struct rtattr *tail2; char dbuf[ETH_ALEN]; char sbuf[ETH_ALEN]; __u16 ife_type = 0; int user_type = 0; __u32 ife_prio = 0; __u32 ife_prio_v = 0; __u32 ife_mark = 0; __u32 ife_mark_v = 0; __u16 ife_tcindex = 0; __u16 ife_tcindex_v = 0; char *daddr = NULL; char *saddr = NULL; if (argc <= 0) return -1; while (argc > 0) { if (matches(*argv, "ife") == 0) { NEXT_ARG(); continue; } else if (matches(*argv, "decode") == 0) { p.flags = IFE_DECODE; /* readability aid */ ok++; } else if (matches(*argv, "encode") == 0) { p.flags = IFE_ENCODE; ok++; } else if (matches(*argv, "allow") == 0) { NEXT_ARG(); if (matches(*argv, "mark") == 0) { ife_mark = IFE_META_SKBMARK; } else if (matches(*argv, "prio") == 0) { ife_prio = IFE_META_PRIO; } else if (matches(*argv, "tcindex") == 0) { ife_prio = IFE_META_TCINDEX; } else { fprintf(stderr, "Illegal meta define <%s>\n", *argv); return -1; } } else if (matches(*argv, "use") == 0) { NEXT_ARG(); if (matches(*argv, "mark") == 0) { NEXT_ARG(); if (get_u32(&ife_mark_v, *argv, 0)) invarg("ife mark val is invalid", *argv); } else if (matches(*argv, "prio") == 0) { NEXT_ARG(); if (get_u32(&ife_prio_v, *argv, 0)) invarg("ife prio val is invalid", *argv); } else if (matches(*argv, "tcindex") == 0) { NEXT_ARG(); if (get_u16(&ife_tcindex_v, *argv, 0)) invarg("ife tcindex val is invalid", *argv); } else { fprintf(stderr, "Illegal meta use type <%s>\n", *argv); return -1; } } else if (matches(*argv, "type") == 0) { NEXT_ARG(); if (get_u16(&ife_type, *argv, 0)) invarg("ife type is invalid", *argv); fprintf(stderr, "IFE type 0x%04X\n", ife_type); user_type = 1; } else if (matches(*argv, "dst") == 0) { NEXT_ARG(); daddr = *argv; if (sscanf(daddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", dbuf, dbuf + 1, dbuf + 2, dbuf + 3, dbuf + 4, dbuf + 5) != 6) { fprintf(stderr, "Invalid mac address %s\n", daddr); } fprintf(stderr, "dst MAC address <%s>\n", daddr); } else if (matches(*argv, "src") == 0) { NEXT_ARG(); saddr = *argv; if (sscanf(saddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", sbuf, sbuf + 1, sbuf + 2, sbuf + 3, sbuf + 4, sbuf + 5) != 6) { fprintf(stderr, "Invalid mac address %s\n", saddr); } fprintf(stderr, "src MAC address <%s>\n", saddr); } else if (matches(*argv, "help") == 0) { ife_usage(); } else { break; } argc--; argv++; } parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE); if (argc) { if (matches(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&p.index, *argv, 0)) { fprintf(stderr, "ife: Illegal \"index\"\n"); return -1; } ok++; argc--; argv++; } } if (!ok) { fprintf(stderr, "IFE requires decode/encode specified\n"); ife_usage(); } tail = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, tca_id, NULL, 0); addattr_l(n, MAX_MSG, TCA_IFE_PARMS, &p, sizeof(p)); if (!(p.flags & IFE_ENCODE)) goto skip_encode; if (daddr) addattr_l(n, MAX_MSG, TCA_IFE_DMAC, dbuf, ETH_ALEN); if (user_type) addattr_l(n, MAX_MSG, TCA_IFE_TYPE, &ife_type, 2); else fprintf(stderr, "IFE type 0x%04X\n", ETH_P_IFE); if (saddr) addattr_l(n, MAX_MSG, TCA_IFE_SMAC, sbuf, ETH_ALEN); tail2 = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, TCA_IFE_METALST, NULL, 0); if (ife_mark || ife_mark_v) { if (ife_mark_v) addattr_l(n, MAX_MSG, IFE_META_SKBMARK, &ife_mark_v, 4); else addattr_l(n, MAX_MSG, IFE_META_SKBMARK, NULL, 0); } if (ife_prio || ife_prio_v) { if (ife_prio_v) addattr_l(n, MAX_MSG, IFE_META_PRIO, &ife_prio_v, 4); else addattr_l(n, MAX_MSG, IFE_META_PRIO, NULL, 0); } if (ife_tcindex || ife_tcindex_v) { if (ife_tcindex_v) addattr_l(n, MAX_MSG, IFE_META_TCINDEX, &ife_tcindex_v, 2); else addattr_l(n, MAX_MSG, IFE_META_TCINDEX, NULL, 0); } tail2->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail2; skip_encode: tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; *argc_p = argc; *argv_p = argv; return 0; }