int xfrm_encap_type_parse(__u16 *type, int *argcp, char ***argvp) { int argc = *argcp; char **argv = *argvp; if (strcmp(*argv, "espinudp-nonike") == 0) *type = 1; else if (strcmp(*argv, "espinudp") == 0) *type = 2; else invarg("ENCAP-TYPE value is invalid", *argv); *argcp = argc; *argvp = argv; return 0; }
static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u16 queue_id; while (argc > 0) { if (matches(*argv, "queue_id") == 0) { NEXT_ARG(); if (get_u16(&queue_id, *argv, 0)) invarg("queue_id is invalid", *argv); addattr16(n, 1024, IFLA_BOND_SLAVE_QUEUE_ID, queue_id); } argc--, argv++; } return 0; }
static int xfrm_policy_ptype_parse(__u8 *ptype, int *argcp, char ***argvp) { int argc = *argcp; char **argv = *argvp; if (strcmp(*argv, "main") == 0) *ptype = XFRM_POLICY_TYPE_MAIN; else if (strcmp(*argv, "sub") == 0) *ptype = XFRM_POLICY_TYPE_SUB; else invarg("PTYPE value is invalid", *argv); *argcp = argc; *argvp = argv; return 0; }
/* Return value becomes exitcode. It's okay to not return at all */ int FAST_FUNC do_iplink(char **argv) { static const char keywords[] ALIGN1 = "add\0""delete\0""set\0""show\0""lst\0""list\0"; if (*argv) { int key = index_in_substrings(keywords, *argv); if (key < 0) /* invalid argument */ invarg(*argv, applet_name); argv++; if (key <= 1) /* add/delete */ return do_add_or_delete(argv, key ? RTM_DELLINK : RTM_NEWLINK); if (key == 2) /* set */ return do_set(argv); } /* show, lst, list */ return ipaddr_list_link(argv); }
static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp) { int argc = *argcp; char **argv = *argvp; int len = strlen(*argv); if (len > 2 && strncmp(*argv, "0x", 2) == 0) { __u8 val = 0; if (get_u8(&val, *argv, 16)) invarg("FLAG value is invalid", *argv); *flags = val; } else { while (1) { if (strcmp(*argv, "noecn") == 0) *flags |= XFRM_STATE_NOECN; else if (strcmp(*argv, "decap-dscp") == 0) *flags |= XFRM_STATE_DECAP_DSCP; else if (strcmp(*argv, "nopmtudisc") == 0) *flags |= XFRM_STATE_NOPMTUDISC; else if (strcmp(*argv, "wildrecv") == 0) *flags |= XFRM_STATE_WILDRECV; else if (strcmp(*argv, "icmp") == 0) *flags |= XFRM_STATE_ICMP; else if (strcmp(*argv, "af-unspec") == 0) *flags |= XFRM_STATE_AF_UNSPEC; else if (strcmp(*argv, "align4") == 0) *flags |= XFRM_STATE_ALIGN4; else if (strcmp(*argv, "esn") == 0) *flags |= XFRM_STATE_ESN; else { PREV_ARG(); /* back track */ break; } if (!NEXT_ARG_OK()) break; NEXT_ARG(); } } *argcp = argc; *argvp = argv; return 0; }
int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) { struct rtattr *nest; int argc = *argcp; char **argv = *argvp; __u16 type; NEXT_ARG(); type = read_encap_type(*argv); if (!type) invarg("\"encap type\" value is invalid\n", *argv); NEXT_ARG(); if (argc <= 1) { fprintf(stderr, "Error: unexpected end of line after \"encap\"\n"); exit(-1); } nest = rta_nest(rta, 1024, RTA_ENCAP); switch (type) { case LWTUNNEL_ENCAP_MPLS: parse_encap_mpls(rta, len, &argc, &argv); break; case LWTUNNEL_ENCAP_IP: parse_encap_ip(rta, len, &argc, &argv); break; case LWTUNNEL_ENCAP_ILA: parse_encap_ila(rta, len, &argc, &argv); break; case LWTUNNEL_ENCAP_IP6: parse_encap_ip6(rta, len, &argc, &argv); break; default: fprintf(stderr, "Error: unsupported encap type\n"); break; } rta_nest_end(rta, nest); rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); *argcp = argc; *argvp = argv; return 0; }
static int parse_encap_ila(struct rtattr *rta, size_t len, int *argcp, char ***argvp) { __u64 locator; int argc = *argcp; char **argv = *argvp; if (get_addr64(&locator, *argv) < 0) { fprintf(stderr, "Bad locator: %s\n", *argv); exit(1); } argc--; argv++; rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator); while (argc > 0) { if (strcmp(*argv, "csum-mode") == 0) { __u8 csum_mode; NEXT_ARG(); csum_mode = ila_csum_name2mode(*argv); if (csum_mode < 0) invarg("\"csum-mode\" value is invalid\n", *argv); rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE, csum_mode); argc--; argv++; } else { break; } } /* argv is currently the first unparsed argument, * but the lwt_parse_encap() caller will move to the next, * so step back */ *argcp = argc + 1; *argvp = argv - 1; return 0; }
static int xfrm_policy_dir_parse(__u8 *dir, int *argcp, char ***argvp) { int argc = *argcp; char **argv = *argvp; if (strcmp(*argv, "in") == 0) *dir = XFRM_POLICY_IN; else if (strcmp(*argv, "out") == 0) *dir = XFRM_POLICY_OUT; else if (strcmp(*argv, "fwd") == 0) *dir = XFRM_POLICY_FWD; else invarg("\"DIR\" is invalid", *argv); *argcp = argc; *argvp = argv; return 0; }
static bool get_sa(int *argcp, char ***argvp, __u8 *an) { int argc = *argcp; char **argv = *argvp; int ret; if (argc <= 0 || strcmp(*argv, "sa") != 0) return false; NEXT_ARG(); ret = get_an(an, *argv); if (ret) invarg("expected an { 0..3 }", *argv); argc--; argv++; *argvp = argv; *argcp = argc; return true; }
/* Return value becomes exitcode. It's okay to not return at all */ int FAST_FUNC do_iptunnel(char **argv) { static const char keywords[] ALIGN1 = "add\0""change\0""delete\0""show\0""list\0""lst\0"; enum { ARG_add = 0, ARG_change, ARG_del, ARG_show, ARG_list, ARG_lst }; if (*argv) { int key = index_in_substrings(keywords, *argv); if (key < 0) invarg(*argv, applet_name); argv++; if (key == ARG_add) return do_add(SIOCADDTUNNEL, argv); if (key == ARG_change) return do_add(SIOCCHGTUNNEL, argv); if (key == ARG_del) return do_del(argv); } return do_show(argv); }
int bridge_parse_xstats(struct link_util *lu, int argc, char **argv) { while (argc > 0) { if (strcmp(*argv, "igmp") == 0 || strcmp(*argv, "mcast") == 0) { xstats_print_attr = BRIDGE_XSTATS_MCAST; } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); filter_index = ll_name_to_index(*argv); if (!filter_index) return nodev(*argv); } else if (strcmp(*argv, "help") == 0) { bridge_print_xstats_help(lu, stdout); exit(0); } else { invarg("unknown attribute", *argv); } argc--; argv++; } return 0; }
int do_seg6(int argc, char **argv) { if (argc < 1 || matches(*argv, "help") == 0) usage(); memset(&opts, 0, sizeof(opts)); if (matches(*argv, "hmac") == 0) { NEXT_ARG(); if (matches(*argv, "show") == 0) { opts.cmd = SEG6_CMD_DUMPHMAC; } else if (matches(*argv, "set") == 0) { NEXT_ARG(); if (get_u32(&opts.keyid, *argv, 0) || opts.keyid == 0) invarg("hmac KEYID value is invalid", *argv); NEXT_ARG(); if (strcmp(*argv, "sha1") == 0) { opts.alg_id = SEG6_HMAC_ALGO_SHA1; } else if (strcmp(*argv, "sha256") == 0) { opts.alg_id = SEG6_HMAC_ALGO_SHA256; } else { invarg("hmac ALGO value is invalid", *argv); } opts.cmd = SEG6_CMD_SETHMAC; opts.pass = getpass(HMAC_KEY_PROMPT); } else { invarg("unknown", *argv); } } else if (matches(*argv, "tunsrc") == 0) { NEXT_ARG(); if (matches(*argv, "show") == 0) { opts.cmd = SEG6_CMD_GET_TUNSRC; } else if (matches(*argv, "set") == 0) { NEXT_ARG(); opts.cmd = SEG6_CMD_SET_TUNSRC; if (!inet_get_addr(*argv, NULL, &opts.addr)) invarg("tunsrc ADDRESS value is invalid", *argv); } else { invarg("unknown", *argv); } } else { invarg("unknown", *argv); } return seg6_do_cmd(); }
int mpls_tunnel_modify(int cmd, int argc, char **argv) { unsigned int key = -2; struct ifreq ifr; int err; int fd; memset(&ifr, 0, sizeof(ifr)); while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); strncpy(ifr.ifr_name, *argv, IFNAMSIZ); } else if (strcmp(*argv, "nhlfe") == 0) { NEXT_ARG(); if (get_unsigned(&key, *argv, 0)) invarg(*argv, "invalid NHLFE key"); ifr.ifr_ifru.ifru_ivalue = key; } else { usage(); } argc--; argv++; } if (!strlen(ifr.ifr_name)) { fprintf(stderr, "You must specify a interface name\n"); //exit(1); return 1; } fd = socket(AF_INET, SOCK_DGRAM, 0); err = ioctl(fd, cmd, &ifr); if (err) perror("ioctl"); return 0; }
static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp) { int argc = *argcp; char **argv = *argvp; int len = strlen(*argv); if (len > 2 && strncmp(*argv, "0x", 2) == 0) { __u8 val = 0; if (get_u8(&val, *argv, 16)) invarg("\"FLAG\" is invalid", *argv); *flags = val; } else { while (1) { if (strcmp(*argv, "noecn") == 0) *flags |= XFRM_STATE_NOECN; else if (strcmp(*argv, "decap-dscp") == 0) *flags |= XFRM_STATE_DECAP_DSCP; else if (strcmp(*argv, "wildrecv") == 0) *flags |= XFRM_STATE_WILDRECV; else { PREV_ARG(); /* back track */ break; } if (!NEXT_ARG_OK()) break; NEXT_ARG(); } } filter.state_flags_mask = XFRM_FILTER_MASK_FULL; *argcp = argc; *argvp = argv; return 0; }
int xfrm_mode_parse(__u8 *mode, int *argcp, char ***argvp) { int argc = *argcp; char **argv = *argvp; if (matches(*argv, "transport") == 0) *mode = XFRM_MODE_TRANSPORT; else if (matches(*argv, "tunnel") == 0) *mode = XFRM_MODE_TUNNEL; else if (matches(*argv, "ro") == 0) *mode = XFRM_MODE_ROUTEOPTIMIZATION; else if (matches(*argv, "in_trigger") == 0) *mode = XFRM_MODE_IN_TRIGGER; else if (matches(*argv, "beet") == 0) *mode = XFRM_MODE_BEET; else invarg("\"MODE\" is invalid", *argv); *argcp = argc; *argvp = argv; return 0; }
static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u16 queue_id; while (argc > 0) { if (matches(*argv, "queue_id") == 0) { NEXT_ARG(); if (get_u16(&queue_id, *argv, 0)) invarg("queue_id is invalid", *argv); addattr16(n, 1024, IFLA_BOND_SLAVE_QUEUE_ID, queue_id); } else { if (matches(*argv, "help") != 0) fprintf(stderr, "bond_slave: unknown option \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } return 0; }
/* Return value becomes exitcode. It's okay to not return at all */ static int ipaddr_modify(int cmd, int argc, char **argv) { static const char option[] ALIGN1 = "peer\0""remote\0""broadcast\0""brd\0" "anycast\0""scope\0""dev\0""label\0""local\0"; struct rtnl_handle rth; struct { struct nlmsghdr n; struct ifaddrmsg ifa; char buf[256]; } req; char *d = NULL; char *l = NULL; inet_prefix lcl; inet_prefix peer; int local_len = 0; int peer_len = 0; int brd_len = 0; int any_len = 0; bool scoped = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = cmd; req.ifa.ifa_family = preferred_family; while (argc > 0) { const int option_num = index_in_strings(option, *argv); switch (option_num) { case 0: /* peer */ case 1: /* remote */ NEXT_ARG(); if (peer_len) { duparg("peer", *argv); } get_prefix(&peer, *argv, req.ifa.ifa_family); peer_len = peer.bytelen; if (req.ifa.ifa_family == AF_UNSPEC) { req.ifa.ifa_family = peer.family; } addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen); req.ifa.ifa_prefixlen = peer.bitlen; break; case 2: /* broadcast */ case 3: /* brd */ { inet_prefix addr; NEXT_ARG(); if (brd_len) { duparg("broadcast", *argv); } if (LONE_CHAR(*argv, '+')) { brd_len = -1; } else if (LONE_DASH(*argv)) { brd_len = -2; } else { get_addr(&addr, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = addr.family; addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen); brd_len = addr.bytelen; } break; } case 4: /* anycast */ { inet_prefix addr; NEXT_ARG(); if (any_len) { duparg("anycast", *argv); } get_addr(&addr, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) { req.ifa.ifa_family = addr.family; } addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen); any_len = addr.bytelen; break; } case 5: /* scope */ { uint32_t scope = 0; NEXT_ARG(); if (rtnl_rtscope_a2n(&scope, *argv)) { invarg(*argv, "scope"); } req.ifa.ifa_scope = scope; scoped = 1; break; } case 6: /* dev */ NEXT_ARG(); d = *argv; break; case 7: /* label */ NEXT_ARG(); l = *argv; addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1); break; case 8: /* local */ NEXT_ARG(); default: if (local_len) { duparg2("local", *argv); } get_prefix(&lcl, *argv, req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) { req.ifa.ifa_family = lcl.family; } addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen); local_len = lcl.bytelen; } argc--; argv++; } if (d == NULL) { bb_error_msg(bb_msg_requires_arg,"\"dev\""); return -1; } if (l && strncmp(d, l, strlen(d)) != 0) { bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l); } if (peer_len == 0 && local_len && cmd != RTM_DELADDR) { peer = lcl; addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen); } if (req.ifa.ifa_prefixlen == 0) req.ifa.ifa_prefixlen = lcl.bitlen; if (brd_len < 0 && cmd != RTM_DELADDR) { inet_prefix brd; int i; if (req.ifa.ifa_family != AF_INET) { bb_error_msg_and_die("broadcast can be set only for IPv4 addresses"); } brd = peer; if (brd.bitlen <= 30) { for (i=31; i>=brd.bitlen; i--) { if (brd_len == -1) brd.data[0] |= htonl(1<<(31-i)); else brd.data[0] &= ~htonl(1<<(31-i)); } addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen); brd_len = brd.bytelen; } } if (!scoped && cmd != RTM_DELADDR) req.ifa.ifa_scope = default_scope(&lcl); xrtnl_open(&rth); ll_init_map(&rth); req.ifa.ifa_index = xll_name_to_index(d); if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2; return 0; }
static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) { int count = 0; char medium[IFNAMSIZ]; int isatap = 0; memset(p, 0, sizeof(*p)); memset(&medium, 0, sizeof(medium)); p->iph.version = 4; p->iph.ihl = 5; #ifndef IP_DF #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ #endif p->iph.frag_off = htons(IP_DF); while (argc > 0) { if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPIP; } else if (strcmp(*argv, "gre") == 0 || strcmp(*argv, "gre/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_GRE; } else if (strcmp(*argv, "sit") == 0 || strcmp(*argv, "ipv6/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPV6; } else if (strcmp(*argv, "isatap") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { fprintf(stderr, "You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPV6; isatap++; } else if (strcmp(*argv, "vti") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { fprintf(stderr, "You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPIP; p->i_flags |= VTI_ISVTI; } else { fprintf(stderr,"Unknown tunnel mode \"%s\"\n", *argv); exit(-1); } } else if (strcmp(*argv, "key") == 0) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->i_key = p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } p->i_key = p->o_key = htonl(uval); } } else if (strcmp(*argv, "ikey") == 0) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; if (strchr(*argv, '.')) p->i_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } p->i_key = htonl(uval); } } else if (strcmp(*argv, "okey") == 0) { unsigned uval; NEXT_ARG(); p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } p->o_key = htonl(uval); } } else if (strcmp(*argv, "seq") == 0) { p->i_flags |= GRE_SEQ; p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "iseq") == 0) { p->i_flags |= GRE_SEQ; } else if (strcmp(*argv, "oseq") == 0) { p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "csum") == 0) { p->i_flags |= GRE_CSUM; p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "icsum") == 0) { p->i_flags |= GRE_CSUM; } else if (strcmp(*argv, "ocsum") == 0) { p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "nopmtudisc") == 0) { p->iph.frag_off = 0; } else if (strcmp(*argv, "pmtudisc") == 0) { p->iph.frag_off = htons(IP_DF); } else if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.daddr = get_addr32(*argv); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.saddr = get_addr32(*argv); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); strncpy(medium, *argv, IFNAMSIZ-1); } else if (strcmp(*argv, "ttl") == 0 || strcmp(*argv, "hoplimit") == 0) { unsigned uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL\n", *argv); if (uval > 255) invarg("TTL must be <=255\n", *argv); p->iph.ttl = uval; } } else if (strcmp(*argv, "tos") == 0 || strcmp(*argv, "tclass") == 0 || matches(*argv, "dsfield") == 0) { char *dsfield; __u32 uval; NEXT_ARG(); dsfield = *argv; strsep(&dsfield, "/"); if (strcmp(*argv, "inherit") != 0) { dsfield = *argv; p->iph.tos = 0; } else p->iph.tos = 1; if (dsfield) { if (rtnl_dsfield_a2n(&uval, dsfield)) invarg("bad TOS value", *argv); p->iph.tos |= uval; } } else { if (strcmp(*argv, "name") == 0) { NEXT_ARG(); } else if (matches(*argv, "help") == 0) usage(); if (p->name[0]) duparg2("name", *argv); strncpy(p->name, *argv, IFNAMSIZ); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (tnl_get_ioctl(*argv, &old_p)) return -1; *p = old_p; } } count++; argc--; argv++; } if (p->iph.protocol == 0) { if (memcmp(p->name, "gre", 3) == 0) p->iph.protocol = IPPROTO_GRE; else if (memcmp(p->name, "ipip", 4) == 0) p->iph.protocol = IPPROTO_IPIP; else if (memcmp(p->name, "sit", 3) == 0) p->iph.protocol = IPPROTO_IPV6; else if (memcmp(p->name, "isatap", 6) == 0) { p->iph.protocol = IPPROTO_IPV6; isatap++; } else if (memcmp(p->name, "vti", 3) == 0) { p->iph.protocol = IPPROTO_IPIP; p->i_flags |= VTI_ISVTI; } } if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { if (!(p->i_flags & VTI_ISVTI) && (p->iph.protocol != IPPROTO_GRE)) { fprintf(stderr, "Keys are not allowed with ipip and sit tunnels\n"); return -1; } } if (medium[0]) { p->link = if_nametoindex(medium); if (p->link == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", medium); return -1; } } if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->i_key = p->iph.daddr; p->i_flags |= GRE_KEY; } if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->o_key = p->iph.daddr; p->o_flags |= GRE_KEY; } if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) { fprintf(stderr, "A broadcast tunnel requires a source address\n"); return -1; } if (isatap) p->i_flags |= SIT_ISATAP; return 0; }
/* Return value becomes exitcode. It's okay to not return at all */ int ipaddr_list_or_flush(int argc, char **argv, int flush) { static const char option[] ALIGN1 = "to\0""scope\0""up\0""label\0""dev\0"; struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *l; struct rtnl_handle rth; char *filter_dev = NULL; int no_link = 0; ipaddr_reset_filter(oneline); filter.showqueue = 1; if (filter.family == AF_UNSPEC) filter.family = preferred_family; if (flush) { if (argc <= 0) { bb_error_msg_and_die(bb_msg_requires_arg, "flush"); } if (filter.family == AF_PACKET) { bb_error_msg_and_die("cannot flush link addresses"); } } while (argc > 0) { const int option_num = index_in_strings(option, *argv); switch (option_num) { case 0: /* to */ NEXT_ARG(); get_prefix(&filter.pfx, *argv, filter.family); if (filter.family == AF_UNSPEC) { filter.family = filter.pfx.family; } break; case 1: /* scope */ { uint32_t scope = 0; NEXT_ARG(); filter.scopemask = -1; if (rtnl_rtscope_a2n(&scope, *argv)) { if (strcmp(*argv, "all") != 0) { invarg(*argv, "scope"); } scope = RT_SCOPE_NOWHERE; filter.scopemask = 0; } filter.scope = scope; break; } case 2: /* up */ filter.up = 1; break; case 3: /* label */ NEXT_ARG(); filter.label = *argv; break; case 4: /* dev */ NEXT_ARG(); default: if (filter_dev) { duparg2("dev", *argv); } filter_dev = *argv; } argv++; argc--; } xrtnl_open(&rth); xrtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK); xrtnl_dump_filter(&rth, store_nlmsg, &linfo); if (filter_dev) { filter.ifindex = xll_name_to_index(filter_dev); } if (flush) { char flushb[4096-512]; filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); filter.rth = &rth; for (;;) { xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR); filter.flushed = 0; xrtnl_dump_filter(&rth, print_addrinfo, stdout); if (filter.flushed == 0) { return 0; } if (flush_update() < 0) return 1; } } if (filter.family != AF_PACKET) { xrtnl_wilddump_request(&rth, filter.family, RTM_GETADDR); xrtnl_dump_filter(&rth, store_nlmsg, &ainfo); } if (filter.family && filter.family != AF_PACKET) { struct nlmsg_list **lp; lp=&linfo; if (filter.oneline) no_link = 1; while ((l=*lp)!=NULL) { int ok = 0; struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct nlmsg_list *a; for (a=ainfo; a; a=a->next) { struct nlmsghdr *n = &a->h; struct ifaddrmsg *ifa = NLMSG_DATA(n); if (ifa->ifa_index != ifi->ifi_index || (filter.family && filter.family != ifa->ifa_family)) continue; if ((filter.scope^ifa->ifa_scope)&filter.scopemask) continue; if ((filter.flags^ifa->ifa_flags)&filter.flagmask) continue; if (filter.pfx.family || filter.label) { struct rtattr *tb[IFA_MAX+1]; memset(tb, 0, sizeof(tb)); parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); if (!tb[IFA_LOCAL]) tb[IFA_LOCAL] = tb[IFA_ADDRESS]; if (filter.pfx.family && tb[IFA_LOCAL]) { inet_prefix dst; memset(&dst, 0, sizeof(dst)); dst.family = ifa->ifa_family; memcpy(&dst.data, RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_LOCAL])); if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bitlen)) continue; } if (filter.label) { SPRINT_BUF(b1); const char *label; if (tb[IFA_LABEL]) label = RTA_DATA(tb[IFA_LABEL]); else label = ll_idx_n2a(ifa->ifa_index, b1); if (fnmatch(filter.label, label, 0) != 0) continue; } } ok = 1; break; } if (!ok) *lp = l->next; else lp = &l->next; } } for (l = linfo; l; l = l->next) { if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { struct ifinfomsg *ifi = NLMSG_DATA(&l->h); if (filter.family != AF_PACKET) print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); } fflush(stdout); /* why? */ } return 0; }
int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) { struct qdisc_util *q = NULL; struct tc_estimator est; char d[16]; char k[16]; struct { struct nlmsghdr n; struct tcmsg t; char buf[TCA_BUF_MAX]; } req; memset(&req, 0, sizeof(req)); memset(&est, 0, sizeof(est)); memset(&d, 0, sizeof(d)); memset(&k, 0, sizeof(k)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.t.tcm_family = AF_UNSPEC; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); if (d[0]) duparg("dev", *argv); strncpy(d, *argv, sizeof(d)-1); } else if (strcmp(*argv, "handle") == 0) { __u32 handle; if (req.t.tcm_handle) duparg("handle", *argv); NEXT_ARG(); if (get_qdisc_handle(&handle, *argv)) invarg(*argv, "invalid qdisc ID"); req.t.tcm_handle = handle; } else if (strcmp(*argv, "root") == 0) { if (req.t.tcm_parent) { fprintf(stderr, "Error: \"root\" is duplicate parent ID\n"); return -1; } req.t.tcm_parent = TC_H_ROOT; #ifdef TC_H_INGRESS } else if (strcmp(*argv, "ingress") == 0) { if (req.t.tcm_parent) { fprintf(stderr, "Error: \"ingress\" is a duplicate parent ID\n"); return -1; } req.t.tcm_parent = TC_H_INGRESS; strncpy(k, "ingress", sizeof(k)-1); q = get_qdisc_kind(k); req.t.tcm_handle = 0xffff0000; argc--; argv++; break; #endif } else if (strcmp(*argv, "parent") == 0) { __u32 handle; NEXT_ARG(); if (req.t.tcm_parent) duparg("parent", *argv); if (get_tc_classid(&handle, *argv)) invarg(*argv, "invalid parent ID"); req.t.tcm_parent = handle; } else if (matches(*argv, "estimator") == 0) { if (parse_estimator(&argc, &argv, &est)) return -1; } else if (matches(*argv, "help") == 0) { usage(); } else { strncpy(k, *argv, sizeof(k)-1); q = get_qdisc_kind(k); argc--; argv++; break; } argc--; argv++; } if (k[0]) addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1); if (est.ewma_log) addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est)); if (q) { if (!q->parse_qopt) { fprintf(stderr, "qdisc '%s' does not support option parsing\n", k); return -1; } if (q->parse_qopt(q, argc, argv, &req.n)) return 1; } else { if (argc) { if (matches(*argv, "help") == 0) usage(); fprintf(stderr, "Garbage instead of arguments \"%s ...\". Try \"tc qdisc help\".\n", *argv); return -1; } } if (d[0]) { int idx; ll_init_map(&rth); if ((idx = ll_name_to_index(d)) == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", d); return 1; } req.t.tcm_ifindex = idx; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2; return 0; }
static int bridge_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u32 val; while (argc > 0) { if (matches(*argv, "forward_delay") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid forward_delay", *argv); addattr32(n, 1024, IFLA_BR_FORWARD_DELAY, val); } else if (matches(*argv, "hello_time") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid hello_time", *argv); addattr32(n, 1024, IFLA_BR_HELLO_TIME, val); } else if (matches(*argv, "max_age") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid max_age", *argv); addattr32(n, 1024, IFLA_BR_MAX_AGE, val); } else if (matches(*argv, "ageing_time") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid ageing_time", *argv); addattr32(n, 1024, IFLA_BR_AGEING_TIME, val); } else if (matches(*argv, "stp_state") == 0) { NEXT_ARG(); if (get_u32(&val, *argv, 0)) invarg("invalid stp_state", *argv); addattr32(n, 1024, IFLA_BR_STP_STATE, val); } else if (matches(*argv, "priority") == 0) { __u16 prio; NEXT_ARG(); if (get_u16(&prio, *argv, 0)) invarg("invalid priority", *argv); addattr16(n, 1024, IFLA_BR_PRIORITY, prio); } else if (matches(*argv, "vlan_filtering") == 0) { __u8 vlan_filter; NEXT_ARG(); if (get_u8(&vlan_filter, *argv, 0)) invarg("invalid vlan_filtering", *argv); addattr8(n, 1024, IFLA_BR_VLAN_FILTERING, vlan_filter); } else if (matches(*argv, "vlan_protocol") == 0) { __u16 vlan_proto; NEXT_ARG(); if (ll_proto_a2n(&vlan_proto, *argv)) invarg("invalid vlan_protocol", *argv); addattr16(n, 1024, IFLA_BR_VLAN_PROTOCOL, vlan_proto); } else if (matches(*argv, "group_fwd_mask") == 0) { __u16 fwd_mask; NEXT_ARG(); if (get_u16(&fwd_mask, *argv, 0)) invarg("invalid group_fwd_mask", *argv); addattr16(n, 1024, IFLA_BR_GROUP_FWD_MASK, fwd_mask); } else if (matches(*argv, "group_address") == 0) { char llabuf[32]; int len; NEXT_ARG(); len = ll_addr_a2n(llabuf, sizeof(llabuf), *argv); if (len < 0) return -1; addattr_l(n, 1024, IFLA_BR_GROUP_ADDR, llabuf, len); } else if (matches(*argv, "vlan_default_pvid") == 0) { __u16 default_pvid; NEXT_ARG(); if (get_u16(&default_pvid, *argv, 0)) invarg("invalid vlan_default_pvid", *argv); addattr16(n, 1024, IFLA_BR_VLAN_DEFAULT_PVID, default_pvid); } else if (matches(*argv, "mcast_router") == 0) { __u8 mcast_router; NEXT_ARG(); if (get_u8(&mcast_router, *argv, 0)) invarg("invalid mcast_router", *argv); addattr8(n, 1024, IFLA_BR_MCAST_ROUTER, mcast_router); } else if (matches(*argv, "mcast_snooping") == 0) { __u8 mcast_snoop; NEXT_ARG(); if (get_u8(&mcast_snoop, *argv, 0)) invarg("invalid mcast_snooping", *argv); addattr8(n, 1024, IFLA_BR_MCAST_SNOOPING, mcast_snoop); } else if (matches(*argv, "mcast_query_use_ifaddr") == 0) { __u8 mcast_qui; NEXT_ARG(); if (get_u8(&mcast_qui, *argv, 0)) invarg("invalid mcast_query_use_ifaddr", *argv); addattr8(n, 1024, IFLA_BR_MCAST_QUERY_USE_IFADDR, mcast_qui); } else if (matches(*argv, "mcast_querier") == 0) { __u8 mcast_querier; NEXT_ARG(); if (get_u8(&mcast_querier, *argv, 0)) invarg("invalid mcast_querier", *argv); addattr8(n, 1024, IFLA_BR_MCAST_QUERIER, mcast_querier); } else if (matches(*argv, "mcast_hash_elasticity") == 0) { __u32 mcast_hash_el; NEXT_ARG(); if (get_u32(&mcast_hash_el, *argv, 0)) invarg("invalid mcast_hash_elasticity", *argv); addattr32(n, 1024, IFLA_BR_MCAST_HASH_ELASTICITY, mcast_hash_el); } else if (matches(*argv, "mcast_hash_max") == 0) { __u32 mcast_hash_max; NEXT_ARG(); if (get_u32(&mcast_hash_max, *argv, 0)) invarg("invalid mcast_hash_max", *argv); addattr32(n, 1024, IFLA_BR_MCAST_HASH_MAX, mcast_hash_max); } else if (matches(*argv, "mcast_last_member_count") == 0) { __u32 mcast_lmc; NEXT_ARG(); if (get_u32(&mcast_lmc, *argv, 0)) invarg("invalid mcast_last_member_count", *argv); addattr32(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_CNT, mcast_lmc); } else if (matches(*argv, "mcast_startup_query_count") == 0) { __u32 mcast_sqc; NEXT_ARG(); if (get_u32(&mcast_sqc, *argv, 0)) invarg("invalid mcast_startup_query_count", *argv); addattr32(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_CNT, mcast_sqc); } else if (matches(*argv, "mcast_last_member_interval") == 0) { __u64 mcast_last_member_intvl; NEXT_ARG(); if (get_u64(&mcast_last_member_intvl, *argv, 0)) invarg("invalid mcast_last_member_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_INTVL, mcast_last_member_intvl); } else if (matches(*argv, "mcast_membership_interval") == 0) { __u64 mcast_membership_intvl; NEXT_ARG(); if (get_u64(&mcast_membership_intvl, *argv, 0)) invarg("invalid mcast_membership_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_MEMBERSHIP_INTVL, mcast_membership_intvl); } else if (matches(*argv, "mcast_querier_interval") == 0) { __u64 mcast_querier_intvl; NEXT_ARG(); if (get_u64(&mcast_querier_intvl, *argv, 0)) invarg("invalid mcast_querier_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_QUERIER_INTVL, mcast_querier_intvl); } else if (matches(*argv, "mcast_query_interval") == 0) { __u64 mcast_query_intvl; NEXT_ARG(); if (get_u64(&mcast_query_intvl, *argv, 0)) invarg("invalid mcast_query_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_QUERY_INTVL, mcast_query_intvl); } else if (!matches(*argv, "mcast_query_response_interval")) { __u64 mcast_query_resp_intvl; NEXT_ARG(); if (get_u64(&mcast_query_resp_intvl, *argv, 0)) invarg("invalid mcast_query_response_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, mcast_query_resp_intvl); } else if (!matches(*argv, "mcast_startup_query_interval")) { __u64 mcast_startup_query_intvl; NEXT_ARG(); if (get_u64(&mcast_startup_query_intvl, *argv, 0)) invarg("invalid mcast_startup_query_interval", *argv); addattr64(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, mcast_startup_query_intvl); } else if (matches(*argv, "nf_call_iptables") == 0) { __u8 nf_call_ipt; NEXT_ARG(); if (get_u8(&nf_call_ipt, *argv, 0)) invarg("invalid nf_call_iptables", *argv); addattr8(n, 1024, IFLA_BR_NF_CALL_IPTABLES, nf_call_ipt); } else if (matches(*argv, "nf_call_ip6tables") == 0) { __u8 nf_call_ip6t; NEXT_ARG(); if (get_u8(&nf_call_ip6t, *argv, 0)) invarg("invalid nf_call_ip6tables", *argv); addattr8(n, 1024, IFLA_BR_NF_CALL_IP6TABLES, nf_call_ip6t); } else if (matches(*argv, "nf_call_arptables") == 0) { __u8 nf_call_arpt; NEXT_ARG(); if (get_u8(&nf_call_arpt, *argv, 0)) invarg("invalid nf_call_arptables", *argv); addattr8(n, 1024, IFLA_BR_NF_CALL_ARPTABLES, nf_call_arpt); } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "bridge: unknown command \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } return 0; }
static int iprule_modify(int cmd, int argc, char **argv) { int table_ok = 0; struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; memset(&req, 0, sizeof(req)); req.n.nlmsg_type = cmd; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.r.rtm_family = preferred_family; req.r.rtm_protocol = RTPROT_BOOT; req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_table = 0; req.r.rtm_type = RTN_UNSPEC; req.r.rtm_flags = 0; if (cmd == RTM_NEWRULE) { req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL; req.r.rtm_type = RTN_UNICAST; } while (argc > 0) { if (strcmp(*argv, "not") == 0) { req.r.rtm_flags |= FIB_RULE_INVERT; } else if (strcmp(*argv, "from") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_src_len = dst.bitlen; addattr_l(&req.n, sizeof(req), FRA_SRC, &dst.data, dst.bytelen); } else if (strcmp(*argv, "to") == 0) { inet_prefix dst; NEXT_ARG(); get_prefix(&dst, *argv, req.r.rtm_family); req.r.rtm_dst_len = dst.bitlen; addattr_l(&req.n, sizeof(req), FRA_DST, &dst.data, dst.bytelen); } else if (matches(*argv, "preference") == 0 || matches(*argv, "order") == 0 || matches(*argv, "priority") == 0) { __u32 pref; NEXT_ARG(); if (get_u32(&pref, *argv, 0)) invarg("preference value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_PRIORITY, pref); } else if (strcmp(*argv, "tos") == 0) { __u32 tos; NEXT_ARG(); if (rtnl_dsfield_a2n(&tos, *argv)) invarg("TOS value is invalid\n", *argv); req.r.rtm_tos = tos; } else if (strcmp(*argv, "fwmark") == 0) { char *slash; __u32 fwmark, fwmask; NEXT_ARG(); if ((slash = strchr(*argv, '/')) != NULL) *slash = '\0'; if (get_u32(&fwmark, *argv, 0)) invarg("fwmark value is invalid\n", *argv); addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark); if (slash) { if (get_u32(&fwmask, slash+1, 0)) invarg("fwmask value is invalid\n", slash+1); addattr32(&req.n, sizeof(req), FRA_FWMASK, fwmask); } } else if (matches(*argv, "realms") == 0) { __u32 realm; NEXT_ARG(); if (get_rt_realms(&realm, *argv)) invarg("invalid realms\n", *argv); addattr32(&req.n, sizeof(req), FRA_FLOW, realm); } else if (matches(*argv, "table") == 0 || strcmp(*argv, "lookup") == 0) { __u32 tid; NEXT_ARG(); if (rtnl_rttable_a2n(&tid, *argv)) invarg("invalid table ID\n", *argv); if (tid < 256) req.r.rtm_table = tid; else { req.r.rtm_table = RT_TABLE_UNSPEC; addattr32(&req.n, sizeof(req), FRA_TABLE, tid); } table_ok = 1; } else if (strcmp(*argv, "dev") == 0 || strcmp(*argv, "iif") == 0) { NEXT_ARG(); addattr_l(&req.n, sizeof(req), FRA_IFNAME, *argv, strlen(*argv)+1); } else if (strcmp(*argv, "nat") == 0 || matches(*argv, "map-to") == 0) { NEXT_ARG(); fprintf(stderr, "Warning: route NAT is deprecated\n"); addattr32(&req.n, sizeof(req), RTA_GATEWAY, get_addr32(*argv)); req.r.rtm_type = RTN_NAT; } else { int type; if (strcmp(*argv, "type") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); else if (matches(*argv, "goto") == 0) { __u32 target; type = FR_ACT_GOTO; NEXT_ARG(); if (get_u32(&target, *argv, 0)) invarg("invalid target\n", *argv); addattr32(&req.n, sizeof(req), FRA_GOTO, target); } else if (matches(*argv, "nop") == 0) type = FR_ACT_NOP; else if (rtnl_rtntype_a2n(&type, *argv)) invarg("Failed to parse rule type", *argv); req.r.rtm_type = type; table_ok = 1; } argc--; argv++; } if (req.r.rtm_family == AF_UNSPEC) req.r.rtm_family = AF_INET; if (!table_ok && cmd == RTM_NEWRULE) req.r.rtm_table = RT_TABLE_MAIN; if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2; return 0; }
static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall) { char *selp = NULL; struct rtnl_handle rth; if (argc > 0) filter.use = 1; filter.xpinfo.sel.family = preferred_family; while (argc > 0) { if (strcmp(*argv, "dir") == 0) { NEXT_ARG(); xfrm_policy_dir_parse(&filter.xpinfo.dir, &argc, &argv); filter.dir_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&filter.xpinfo.index, *argv, 0)) invarg("\"INDEX\" is invalid", *argv); filter.index_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "ptype") == 0) { NEXT_ARG(); xfrm_policy_ptype_parse(&filter.ptype, &argc, &argv); filter.ptype_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "action") == 0) { NEXT_ARG(); if (strcmp(*argv, "allow") == 0) filter.xpinfo.action = XFRM_POLICY_ALLOW; else if (strcmp(*argv, "block") == 0) filter.xpinfo.action = XFRM_POLICY_BLOCK; else invarg("\"ACTION\" is invalid\n", *argv); filter.action_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "priority") == 0) { NEXT_ARG(); if (get_u32(&filter.xpinfo.priority, *argv, 0)) invarg("\"PRIORITY\" is invalid", *argv); filter.priority_mask = XFRM_FILTER_MASK_FULL; } else if (strcmp(*argv, "flag") == 0) { NEXT_ARG(); xfrm_policy_flag_parse(&filter.xpinfo.flags, &argc, &argv); filter.policy_flags_mask = XFRM_FILTER_MASK_FULL; } else { if (selp) invarg("unknown", *argv); selp = *argv; xfrm_selector_parse(&filter.xpinfo.sel, &argc, &argv); if (preferred_family == AF_UNSPEC) preferred_family = filter.xpinfo.sel.family; } argc--; argv++; } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); if (deleteall) { struct xfrm_buffer xb; char buf[NLMSG_DELETEALL_BUF_SIZE]; int i; xb.buf = buf; xb.size = sizeof(buf); xb.rth = &rth; for (i = 0; ; i++) { xb.offset = 0; xb.nlmsg_count = 0; if (show_stats > 1) fprintf(stderr, "Delete-all round = %d\n", i); if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, xfrm_policy_keep, &xb, NULL, NULL) < 0) { fprintf(stderr, "Delete-all terminated\n"); exit(1); } if (xb.nlmsg_count == 0) { if (show_stats > 1) fprintf(stderr, "Delete-all completed\n"); break; } if (rtnl_send(&rth, xb.buf, xb.offset) < 0) { perror("Failed to send delete-all request\n"); exit(1); } if (show_stats > 1) fprintf(stderr, "Delete-all nlmsg count = %d\n", xb.nlmsg_count); xb.offset = 0; xb.nlmsg_count = 0; } } else { if (rtnl_wilddump_request(&rth, preferred_family, XFRM_MSG_GETPOLICY) < 0) { perror("Cannot send dump request"); exit(1); } if (rtnl_dump_filter(&rth, xfrm_policy_print, stdout, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } } rtnl_close(&rth); exit(0); }
int main(int argc, char **argv) { char *basename; char *batch_file = NULL; basename = strrchr(argv[0], '/'); if (basename == NULL) basename = argv[0]; else basename++; while (argc > 1) { char *opt = argv[1]; if (strcmp(opt,"--") == 0) { argc--; argv++; break; } if (opt[0] != '-') break; if (opt[1] == '-') opt++; if (matches(opt, "-loops") == 0) { argc--; argv++; if (argc <= 1) usage(); max_flush_loops = atoi(argv[1]); } else if (matches(opt, "-family") == 0) { argc--; argv++; if (argc <= 1) usage(); if (strcmp(argv[1], "help") == 0) usage(); else preferred_family = read_family(argv[1]); if (preferred_family == AF_UNSPEC) invarg("invalid protocol family", argv[1]); } else if (strcmp(opt, "-4") == 0) { preferred_family = AF_INET; } else if (strcmp(opt, "-6") == 0) { preferred_family = AF_INET6; } else if (strcmp(opt, "-0") == 0) { preferred_family = AF_PACKET; } else if (strcmp(opt, "-I") == 0) { preferred_family = AF_IPX; } else if (strcmp(opt, "-D") == 0) { preferred_family = AF_DECnet; } else if (strcmp(opt, "-M") == 0) { preferred_family = AF_MPLS; } else if (strcmp(opt, "-B") == 0) { preferred_family = AF_BRIDGE; } else if (matches(opt, "-human") == 0 || matches(opt, "-human-readable") == 0) { ++human_readable; } else if (matches(opt, "-iec") == 0) { ++use_iec; } else if (matches(opt, "-stats") == 0 || matches(opt, "-statistics") == 0) { ++show_stats; } else if (matches(opt, "-details") == 0) { ++show_details; } else if (matches(opt, "-resolve") == 0) { ++resolve_hosts; } else if (matches(opt, "-oneline") == 0) { ++oneline; } else if (matches(opt, "-timestamp") == 0) { ++timestamp; } else if (matches(opt, "-tshort") == 0) { ++timestamp; ++timestamp_short; #if 0 } else if (matches(opt, "-numeric") == 0) { rtnl_names_numeric++; #endif } else if (matches(opt, "-Version") == 0) { printf("ip utility, iproute2-ss%s\n", SNAPSHOT); exit(0); } else if (matches(opt, "-force") == 0) { ++force; } else if (matches(opt, "-batch") == 0) { argc--; argv++; if (argc <= 1) usage(); batch_file = argv[1]; } else if (matches(opt, "-rcvbuf") == 0) { unsigned int size; argc--; argv++; if (argc <= 1) usage(); if (get_unsigned(&size, argv[1], 0)) { fprintf(stderr, "Invalid rcvbuf size '%s'\n", argv[1]); exit(-1); } rcvbuf = size; } else if (matches(opt, "-color") == 0) { enable_color(); } else if (matches(opt, "-help") == 0) { usage(); } else if (matches(opt, "-netns") == 0) { NEXT_ARG(); if (netns_switch(argv[1])) exit(-1); } else if (matches(opt, "-all") == 0) { do_all = true; } else { fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt); exit(-1); } argc--; argv++; } _SL_ = oneline ? "\\" : "\n" ; if (batch_file) return batch(batch_file); if (rtnl_open(&rth, 0) < 0) exit(1); if (strlen(basename) > 2) return do_cmd(basename+2, argc, argv); if (argc > 1) return do_cmd(argv[1], argc-1, argv+1); rtnl_close(&rth); usage(); }
static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) { struct rtnl_handle rth; struct { struct nlmsghdr n; struct xfrm_userpolicy_info xpinfo; char buf[RTA_BUF_SIZE]; } req; char *dirp = NULL; char *selp = NULL; char *ptypep = NULL; struct xfrm_userpolicy_type upt; char tmpls_buf[XFRM_TMPLS_BUF_SIZE]; int tmpls_len = 0; memset(&req, 0, sizeof(req)); memset(&upt, 0, sizeof(upt)); memset(&tmpls_buf, 0, sizeof(tmpls_buf)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; req.xpinfo.sel.family = preferred_family; req.xpinfo.lft.soft_byte_limit = XFRM_INF; req.xpinfo.lft.hard_byte_limit = XFRM_INF; req.xpinfo.lft.soft_packet_limit = XFRM_INF; req.xpinfo.lft.hard_packet_limit = XFRM_INF; while (argc > 0) { if (strcmp(*argv, "dir") == 0) { if (dirp) duparg("dir", *argv); dirp = *argv; NEXT_ARG(); xfrm_policy_dir_parse(&req.xpinfo.dir, &argc, &argv); } else if (strcmp(*argv, "index") == 0) { NEXT_ARG(); if (get_u32(&req.xpinfo.index, *argv, 0)) invarg("\"INDEX\" is invalid", *argv); } else if (strcmp(*argv, "ptype") == 0) { if (ptypep) duparg("ptype", *argv); ptypep = *argv; NEXT_ARG(); xfrm_policy_ptype_parse(&upt.type, &argc, &argv); } else if (strcmp(*argv, "action") == 0) { NEXT_ARG(); if (strcmp(*argv, "allow") == 0) req.xpinfo.action = XFRM_POLICY_ALLOW; else if (strcmp(*argv, "block") == 0) req.xpinfo.action = XFRM_POLICY_BLOCK; else invarg("\"action\" value is invalid\n", *argv); } else if (strcmp(*argv, "priority") == 0) { NEXT_ARG(); if (get_u32(&req.xpinfo.priority, *argv, 0)) invarg("\"PRIORITY\" is invalid", *argv); } else if (strcmp(*argv, "flag") == 0) { NEXT_ARG(); xfrm_policy_flag_parse(&req.xpinfo.flags, &argc, &argv); } else if (strcmp(*argv, "limit") == 0) { NEXT_ARG(); xfrm_lifetime_cfg_parse(&req.xpinfo.lft, &argc, &argv); } else if (strcmp(*argv, "tmpl") == 0) { struct xfrm_user_tmpl *tmpl; if (tmpls_len + sizeof(*tmpl) > sizeof(tmpls_buf)) { fprintf(stderr, "Too many tmpls: buffer overflow\n"); exit(1); } tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len); tmpl->family = preferred_family; tmpl->aalgos = (~(__u32)0); tmpl->ealgos = (~(__u32)0); tmpl->calgos = (~(__u32)0); NEXT_ARG(); xfrm_tmpl_parse(tmpl, &argc, &argv); tmpls_len += sizeof(*tmpl); } else { if (selp) duparg("unknown", *argv); selp = *argv; xfrm_selector_parse(&req.xpinfo.sel, &argc, &argv); if (preferred_family == AF_UNSPEC) preferred_family = req.xpinfo.sel.family; } argc--; argv++; } if (!dirp) { fprintf(stderr, "Not enough information: \"DIR\" is required.\n"); exit(1); } if (ptypep) { addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE, (void *)&upt, sizeof(upt)); } if (tmpls_len > 0) { addattr_l(&req.n, sizeof(req), XFRMA_TMPL, (void *)tmpls_buf, tmpls_len); } if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) exit(1); if (req.xpinfo.sel.family == AF_UNSPEC) req.xpinfo.sel.family = AF_INET; if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) exit(2); rtnl_close(&rth); return 0; }
static int bond_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u8 mode, use_carrier, primary_reselect, fail_over_mac; __u8 xmit_hash_policy, num_peer_notif, all_slaves_active; __u8 lacp_rate, ad_select, tlb_dynamic_lb; __u16 ad_user_port_key, ad_actor_sys_prio; __u32 miimon, updelay, downdelay, arp_interval, arp_validate; __u32 arp_all_targets, resend_igmp, min_links, lp_interval; __u32 packets_per_slave; unsigned ifindex; while (argc > 0) { if (matches(*argv, "mode") == 0) { NEXT_ARG(); if (get_index(mode_tbl, *argv) < 0) invarg("invalid mode", *argv); mode = get_index(mode_tbl, *argv); addattr8(n, 1024, IFLA_BOND_MODE, mode); } else if (matches(*argv, "active_slave") == 0) { NEXT_ARG(); ifindex = if_nametoindex(*argv); if (!ifindex) return -1; addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex); } else if (matches(*argv, "clear_active_slave") == 0) { addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0); } else if (matches(*argv, "miimon") == 0) { NEXT_ARG(); if (get_u32(&miimon, *argv, 0)) invarg("invalid miimon", *argv); addattr32(n, 1024, IFLA_BOND_MIIMON, miimon); } else if (matches(*argv, "updelay") == 0) { NEXT_ARG(); if (get_u32(&updelay, *argv, 0)) invarg("invalid updelay", *argv); addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay); } else if (matches(*argv, "downdelay") == 0) { NEXT_ARG(); if (get_u32(&downdelay, *argv, 0)) invarg("invalid downdelay", *argv); addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay); } else if (matches(*argv, "use_carrier") == 0) { NEXT_ARG(); if (get_u8(&use_carrier, *argv, 0)) invarg("invalid use_carrier", *argv); addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier); } else if (matches(*argv, "arp_interval") == 0) { NEXT_ARG(); if (get_u32(&arp_interval, *argv, 0)) invarg("invalid arp_interval", *argv); addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval); } else if (matches(*argv, "arp_ip_target") == 0) { struct rtattr * nest = addattr_nest(n, 1024, IFLA_BOND_ARP_IP_TARGET); if (NEXT_ARG_OK()) { NEXT_ARG(); char *targets = strdupa(*argv); char *target = strtok(targets, ","); int i; for(i = 0; target && i < BOND_MAX_ARP_TARGETS; i++) { __u32 addr = get_addr32(target); addattr32(n, 1024, i, addr); target = strtok(NULL, ","); } addattr_nest_end(n, nest); } addattr_nest_end(n, nest); } else if (matches(*argv, "arp_validate") == 0) { NEXT_ARG(); if (get_index(arp_validate_tbl, *argv) < 0) invarg("invalid arp_validate", *argv); arp_validate = get_index(arp_validate_tbl, *argv); addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate); } else if (matches(*argv, "arp_all_targets") == 0) { NEXT_ARG(); if (get_index(arp_all_targets_tbl, *argv) < 0) invarg("invalid arp_all_targets", *argv); arp_all_targets = get_index(arp_all_targets_tbl, *argv); addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets); } else if (matches(*argv, "primary") == 0) { NEXT_ARG(); ifindex = if_nametoindex(*argv); if (!ifindex) return -1; addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex); } else if (matches(*argv, "primary_reselect") == 0) { NEXT_ARG(); if (get_index(primary_reselect_tbl, *argv) < 0) invarg("invalid primary_reselect", *argv); primary_reselect = get_index(primary_reselect_tbl, *argv); addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT, primary_reselect); } else if (matches(*argv, "fail_over_mac") == 0) { NEXT_ARG(); if (get_index(fail_over_mac_tbl, *argv) < 0) invarg("invalid fail_over_mac", *argv); fail_over_mac = get_index(fail_over_mac_tbl, *argv); addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC, fail_over_mac); } else if (matches(*argv, "xmit_hash_policy") == 0) { NEXT_ARG(); if (get_index(xmit_hash_policy_tbl, *argv) < 0) invarg("invalid xmit_hash_policy", *argv); xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv); addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY, xmit_hash_policy); } else if (matches(*argv, "resend_igmp") == 0) { NEXT_ARG(); if (get_u32(&resend_igmp, *argv, 0)) invarg("invalid resend_igmp", *argv); addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp); } else if (matches(*argv, "num_grat_arp") == 0 || matches(*argv, "num_unsol_na") == 0) { NEXT_ARG(); if (get_u8(&num_peer_notif, *argv, 0)) invarg("invalid num_grat_arp|num_unsol_na", *argv); addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF, num_peer_notif); } else if (matches(*argv, "all_slaves_active") == 0) { NEXT_ARG(); if (get_u8(&all_slaves_active, *argv, 0)) invarg("invalid all_slaves_active", *argv); addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE, all_slaves_active); } else if (matches(*argv, "min_links") == 0) { NEXT_ARG(); if (get_u32(&min_links, *argv, 0)) invarg("invalid min_links", *argv); addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links); } else if (matches(*argv, "lp_interval") == 0) { NEXT_ARG(); if (get_u32(&lp_interval, *argv, 0)) invarg("invalid lp_interval", *argv); addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval); } else if (matches(*argv, "packets_per_slave") == 0) { NEXT_ARG(); if (get_u32(&packets_per_slave, *argv, 0)) invarg("invalid packets_per_slave", *argv); addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE, packets_per_slave); } else if (matches(*argv, "lacp_rate") == 0) { NEXT_ARG(); if (get_index(lacp_rate_tbl, *argv) < 0) invarg("invalid lacp_rate", *argv); lacp_rate = get_index(lacp_rate_tbl, *argv); addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate); } else if (matches(*argv, "ad_select") == 0) { NEXT_ARG(); if (get_index(ad_select_tbl, *argv) < 0) invarg("invalid ad_select", *argv); ad_select = get_index(ad_select_tbl, *argv); addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select); } else if (matches(*argv, "ad_user_port_key") == 0) { NEXT_ARG(); if (get_u16(&ad_user_port_key, *argv, 0)) invarg("invalid ad_user_port_key", *argv); addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY, ad_user_port_key); } else if (matches(*argv, "ad_actor_sys_prio") == 0) { NEXT_ARG(); if (get_u16(&ad_actor_sys_prio, *argv, 0)) invarg("invalid ad_actor_sys_prio", *argv); addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO, ad_actor_sys_prio); } else if (matches(*argv, "ad_actor_system") == 0) { int len; char abuf[32]; NEXT_ARG(); len = ll_addr_a2n(abuf, sizeof(abuf), *argv); if (len < 0) return -1; addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM, abuf, len); } else if (matches(*argv, "tlb_dynamic_lb") == 0) { NEXT_ARG(); if (get_u8(&tlb_dynamic_lb, *argv, 0)) { invarg("invalid tlb_dynamic_lb", *argv); return -1; } addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB, tlb_dynamic_lb); } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } return 0; }
static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p) { memset(p, 0, sizeof(*p)); if (argc == 0) usage(); /* Defaults */ p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT; p->l2spec_len = 4; while (argc > 0) { if (strcmp(*argv, "encap") == 0) { NEXT_ARG(); if (strcmp(*argv, "ip") == 0) { p->encap = L2TP_ENCAPTYPE_IP; } else if (strcmp(*argv, "udp") == 0) { p->encap = L2TP_ENCAPTYPE_UDP; } else { fprintf(stderr, "Unknown tunnel encapsulation \"%s\"\n", *argv); exit(-1); } } else if (strcmp(*argv, "name") == 0) { NEXT_ARG(); p->ifname = *argv; } else if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (get_addr(&p->peer_ip, *argv, AF_UNSPEC)) invarg("invalid remote address\n", *argv); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (get_addr(&p->local_ip, *argv, AF_UNSPEC)) invarg("invalid local address\n", *argv); } else if ((strcmp(*argv, "tunnel_id") == 0) || (strcmp(*argv, "tid") == 0)) { __u32 uval; NEXT_ARG(); if (get_u32(&uval, *argv, 0)) invarg("invalid ID\n", *argv); p->tunnel_id = uval; } else if ((strcmp(*argv, "peer_tunnel_id") == 0) || (strcmp(*argv, "ptid") == 0)) { __u32 uval; NEXT_ARG(); if (get_u32(&uval, *argv, 0)) invarg("invalid ID\n", *argv); p->peer_tunnel_id = uval; } else if ((strcmp(*argv, "session_id") == 0) || (strcmp(*argv, "sid") == 0)) { __u32 uval; NEXT_ARG(); if (get_u32(&uval, *argv, 0)) invarg("invalid ID\n", *argv); p->session_id = uval; } else if ((strcmp(*argv, "peer_session_id") == 0) || (strcmp(*argv, "psid") == 0)) { __u32 uval; NEXT_ARG(); if (get_u32(&uval, *argv, 0)) invarg("invalid ID\n", *argv); p->peer_session_id = uval; } else if (strcmp(*argv, "udp_sport") == 0) { __u16 uval; NEXT_ARG(); if (get_u16(&uval, *argv, 0)) invarg("invalid port\n", *argv); p->local_udp_port = uval; } else if (strcmp(*argv, "udp_dport") == 0) { __u16 uval; NEXT_ARG(); if (get_u16(&uval, *argv, 0)) invarg("invalid port\n", *argv); p->peer_udp_port = uval; } else if (strcmp(*argv, "offset") == 0) { __u8 uval; NEXT_ARG(); if (get_u8(&uval, *argv, 0)) invarg("invalid offset\n", *argv); p->offset = uval; } else if (strcmp(*argv, "peer_offset") == 0) { __u8 uval; NEXT_ARG(); if (get_u8(&uval, *argv, 0)) invarg("invalid offset\n", *argv); p->peer_offset = uval; } else if (strcmp(*argv, "cookie") == 0) { int slen; NEXT_ARG(); slen = strlen(*argv); if ((slen != 8) && (slen != 16)) invarg("cookie must be either 8 or 16 hex digits\n", *argv); p->cookie_len = slen / 2; if (hex2mem(*argv, p->cookie, p->cookie_len) < 0) invarg("cookie must be a hex string\n", *argv); } else if (strcmp(*argv, "peer_cookie") == 0) { int slen; NEXT_ARG(); slen = strlen(*argv); if ((slen != 8) && (slen != 16)) invarg("cookie must be either 8 or 16 hex digits\n", *argv); p->peer_cookie_len = slen / 2; if (hex2mem(*argv, p->peer_cookie, p->peer_cookie_len) < 0) invarg("cookie must be a hex string\n", *argv); } else if (strcmp(*argv, "l2spec_type") == 0) { NEXT_ARG(); if (strcasecmp(*argv, "default") == 0) { p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT; p->l2spec_len = 4; } else if (strcasecmp(*argv, "none") == 0) { p->l2spec_type = L2TP_L2SPECTYPE_NONE; p->l2spec_len = 0; } else { fprintf(stderr, "Unknown layer2specific header type \"%s\"\n", *argv); exit(-1); } } else if (strcmp(*argv, "tunnel") == 0) { p->tunnel = 1; } else if (strcmp(*argv, "session") == 0) { p->session = 1; } else if (matches(*argv, "help") == 0) { usage(); } else { fprintf(stderr, "Unknown command: %s\n", *argv); usage(); } argc--; argv++; } return 0; }
static int do_set(int argc, char **argv) { char *dev = NULL; __u32 mask = 0; __u32 flags = 0; int qlen = -1; int mtu = -1; char *newaddr = NULL; char *newbrd = NULL; struct ifreq ifr0, ifr1; char *newname = NULL; int htype, halen; while (argc > 0) { if (strcmp(*argv, "up") == 0) { mask |= IFF_UP; flags |= IFF_UP; } else if (strcmp(*argv, "down") == 0) { mask |= IFF_UP; flags &= ~IFF_UP; } else if (strcmp(*argv, "name") == 0) { NEXT_ARG(); newname = *argv; } else if (strcmp(*argv, "mtu") == 0) { NEXT_ARG(); if (mtu != -1) duparg("mtu", *argv); if (get_integer(&mtu, *argv, 0)) invarg("Invalid \"mtu\" value\n", *argv); } else if (strcmp(*argv, "multicast") == 0) { NEXT_ARG(); mask |= IFF_MULTICAST; if (strcmp(*argv, "on") == 0) { flags |= IFF_MULTICAST; } else if (strcmp(*argv, "off") == 0) { flags &= ~IFF_MULTICAST; } else return on_off("multicast"); } else if (strcmp(*argv, "arp") == 0) { NEXT_ARG(); mask |= IFF_NOARP; if (strcmp(*argv, "on") == 0) { flags &= ~IFF_NOARP; } else if (strcmp(*argv, "off") == 0) { flags |= IFF_NOARP; } else return on_off("noarp"); } else if (strcmp(*argv, "addr") == 0) { NEXT_ARG(); newaddr = *argv; } else { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); } if (dev) duparg2("dev", *argv); dev = *argv; } argc--; argv++; } if (!dev) { bb_error_msg("Not enough of information: \"dev\" argument is required."); exit(-1); } if (newaddr || newbrd) { halen = get_address(dev, &htype); if (halen < 0) return -1; if (newaddr) { if (parse_address(dev, htype, halen, newaddr, &ifr0) < 0) return -1; } if (newbrd) { if (parse_address(dev, htype, halen, newbrd, &ifr1) < 0) return -1; } } if (newname && strcmp(dev, newname)) { if (do_changename(dev, newname) < 0) return -1; dev = newname; } if (qlen != -1) { if (set_qlen(dev, qlen) < 0) return -1; } if (mtu != -1) { if (set_mtu(dev, mtu) < 0) return -1; } if (newaddr || newbrd) { if (newbrd) { if (set_address(&ifr1, 1) < 0) return -1; } if (newaddr) { if (set_address(&ifr0, 0) < 0) return -1; } } if (mask) return do_chflags(dev, flags, mask); return 0; }
static int gre_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct { struct nlmsghdr n; struct ifinfomsg i; char buf[1024]; } req; struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *greinfo[IFLA_GRE_MAX + 1]; __u16 iflags = 0; __u16 oflags = 0; unsigned ikey = 0; unsigned okey = 0; struct in6_addr raddr = IN6ADDR_ANY_INIT; struct in6_addr laddr = IN6ADDR_ANY_INIT; unsigned link = 0; unsigned flowinfo = 0; unsigned flags = 0; __u8 hop_limit = DEFAULT_TNL_HOP_LIMIT; __u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; int len; if (!(n->nlmsg_flags & NLM_F_CREATE)) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETLINK; req.i.ifi_family = preferred_family; req.i.ifi_index = ifi->ifi_index; if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); return -1; } len = req.n.nlmsg_len; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) goto get_failed; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); if (!tb[IFLA_LINKINFO]) goto get_failed; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); if (!linkinfo[IFLA_INFO_DATA]) goto get_failed; parse_rtattr_nested(greinfo, IFLA_GRE_MAX, linkinfo[IFLA_INFO_DATA]); if (greinfo[IFLA_GRE_IKEY]) ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]); if (greinfo[IFLA_GRE_OKEY]) okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]); if (greinfo[IFLA_GRE_IFLAGS]) iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]); if (greinfo[IFLA_GRE_OFLAGS]) oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]); if (greinfo[IFLA_GRE_LOCAL]) memcpy(&laddr, RTA_DATA(greinfo[IFLA_GRE_LOCAL]), sizeof(laddr)); if (greinfo[IFLA_GRE_REMOTE]) memcpy(&raddr, RTA_DATA(greinfo[IFLA_GRE_REMOTE]), sizeof(raddr)); if (greinfo[IFLA_GRE_TTL]) hop_limit = rta_getattr_u8(greinfo[IFLA_GRE_TTL]); if (greinfo[IFLA_GRE_LINK]) link = rta_getattr_u32(greinfo[IFLA_GRE_LINK]); if (greinfo[IFLA_GRE_ENCAP_LIMIT]) encap_limit = rta_getattr_u8(greinfo[IFLA_GRE_ENCAP_LIMIT]); if (greinfo[IFLA_GRE_FLOWINFO]) flowinfo = rta_getattr_u32(greinfo[IFLA_GRE_FLOWINFO]); if (greinfo[IFLA_GRE_FLAGS]) flags = rta_getattr_u32(greinfo[IFLA_GRE_FLAGS]); } while (argc > 0) { if (!matches(*argv, "key")) { unsigned uval; NEXT_ARG(); iflags |= GRE_KEY; oflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0) < 0) { fprintf(stderr, "Invalid value for \"key\"\n"); exit(-1); } uval = htonl(uval); } ikey = okey = uval; } else if (!matches(*argv, "ikey")) { unsigned uval; NEXT_ARG(); iflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"ikey\"\n"); exit(-1); } uval = htonl(uval); } ikey = uval; } else if (!matches(*argv, "okey")) { unsigned uval; NEXT_ARG(); oflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"okey\"\n"); exit(-1); } uval = htonl(uval); } okey = uval; } else if (!matches(*argv, "seq")) { iflags |= GRE_SEQ; oflags |= GRE_SEQ; } else if (!matches(*argv, "iseq")) { iflags |= GRE_SEQ; } else if (!matches(*argv, "oseq")) { oflags |= GRE_SEQ; } else if (!matches(*argv, "csum")) { iflags |= GRE_CSUM; oflags |= GRE_CSUM; } else if (!matches(*argv, "icsum")) { iflags |= GRE_CSUM; } else if (!matches(*argv, "ocsum")) { oflags |= GRE_CSUM; } else if (!matches(*argv, "remote")) { inet_prefix addr; NEXT_ARG(); get_prefix(&addr, *argv, preferred_family); if (addr.family == AF_UNSPEC) invarg("\"remote\" address family is AF_UNSPEC", *argv); memcpy(&raddr, &addr.data, sizeof(raddr)); } else if (!matches(*argv, "local")) { inet_prefix addr; NEXT_ARG(); get_prefix(&addr, *argv, preferred_family); if (addr.family == AF_UNSPEC) invarg("\"local\" address family is AF_UNSPEC", *argv); memcpy(&laddr, &addr.data, sizeof(laddr)); } else if (!matches(*argv, "dev")) { NEXT_ARG(); link = if_nametoindex(*argv); if (link == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", *argv); exit(-1); } } else if (!matches(*argv, "ttl") || !matches(*argv, "hoplimit")) { __u8 uval; NEXT_ARG(); if (get_u8(&uval, *argv, 0)) invarg("invalid TTL", *argv); hop_limit = uval; } else if (!matches(*argv, "tos") || !matches(*argv, "tclass") || !matches(*argv, "dsfield")) { __u8 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") == 0) flags |= IP6_TNL_F_USE_ORIG_TCLASS; else { if (get_u8(&uval, *argv, 16)) invarg("invalid TClass", *argv); flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS; flags &= ~IP6_TNL_F_USE_ORIG_TCLASS; } } else if (strcmp(*argv, "flowlabel") == 0 || strcmp(*argv, "fl") == 0) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") == 0) flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; else { if (get_u32(&uval, *argv, 16)) invarg("invalid Flowlabel", *argv); if (uval > 0xFFFFF) invarg("invalid Flowlabel", *argv); flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL; flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; } } else if (strcmp(*argv, "dscp") == 0) { NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) invarg("not inherit", *argv); flags |= IP6_TNL_F_RCV_DSCP_COPY; } else usage(); argc--; argv++; } addattr32(n, 1024, IFLA_GRE_IKEY, ikey); addattr32(n, 1024, IFLA_GRE_OKEY, okey); addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); addattr_l(n, 1024, IFLA_GRE_LOCAL, &laddr, sizeof(laddr)); addattr_l(n, 1024, IFLA_GRE_REMOTE, &raddr, sizeof(raddr)); if (link) addattr32(n, 1024, IFLA_GRE_LINK, link); addattr_l(n, 1024, IFLA_GRE_TTL, &hop_limit, 1); addattr_l(n, 1024, IFLA_GRE_ENCAP_LIMIT, &encap_limit, 1); addattr_l(n, 1024, IFLA_GRE_FLOWINFO, &flowinfo, 4); addattr_l(n, 1024, IFLA_GRE_FLAGS, &flowinfo, 4); return 0; }
static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct { struct nlmsghdr n; struct ifinfomsg i; char buf[2048]; } req; struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1]; int len; __u32 link = 0; __u32 laddr = 0; __u32 raddr = 0; __u8 ttl = 0; __u8 tos = 0; __u8 pmtudisc = 1; __u16 iflags = 0; __u8 proto = 0; struct in6_addr ip6rdprefix; __u16 ip6rdprefixlen = 0; __u32 ip6rdrelayprefix = 0; __u16 ip6rdrelayprefixlen = 0; memset(&ip6rdprefix, 0, sizeof(ip6rdprefix)); if (!(n->nlmsg_flags & NLM_F_CREATE)) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETLINK; req.i.ifi_family = preferred_family; req.i.ifi_index = ifi->ifi_index; if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); return -1; } len = req.n.nlmsg_len; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) goto get_failed; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); if (!tb[IFLA_LINKINFO]) goto get_failed; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); if (!linkinfo[IFLA_INFO_DATA]) goto get_failed; parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX, linkinfo[IFLA_INFO_DATA]); if (iptuninfo[IFLA_IPTUN_LOCAL]) laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]); if (iptuninfo[IFLA_IPTUN_REMOTE]) raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]); if (iptuninfo[IFLA_IPTUN_TTL]) ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]); if (iptuninfo[IFLA_IPTUN_TOS]) tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]); if (iptuninfo[IFLA_IPTUN_PMTUDISC]) pmtudisc = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]); if (iptuninfo[IFLA_IPTUN_FLAGS]) iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]); if (iptuninfo[IFLA_IPTUN_LINK]) link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]); if (iptuninfo[IFLA_IPTUN_PROTO]) proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]); if (iptuninfo[IFLA_IPTUN_6RD_PREFIX]) memcpy(&ip6rdprefix, RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]), sizeof(laddr)); if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]) ip6rdprefixlen = rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]); if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]) ip6rdrelayprefix = rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]); if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) ip6rdrelayprefixlen = rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); } while (argc > 0) { if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) raddr = get_addr32(*argv); else raddr = 0; } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) laddr = get_addr32(*argv); else laddr = 0; } else if (matches(*argv, "dev") == 0) { NEXT_ARG(); link = if_nametoindex(*argv); if (link == 0) invarg("\"dev\" is invalid", *argv); } else if (strcmp(*argv, "ttl") == 0 || strcmp(*argv, "hoplimit") == 0) { NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_u8(&ttl, *argv, 0)) invarg("invalid TTL\n", *argv); } else ttl = 0; } else if (strcmp(*argv, "tos") == 0 || strcmp(*argv, "tclass") == 0 || matches(*argv, "dsfield") == 0) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); tos = uval; } else tos = 1; } else if (strcmp(*argv, "nopmtudisc") == 0) { pmtudisc = 0; } else if (strcmp(*argv, "pmtudisc") == 0) { pmtudisc = 1; } else if (strcmp(lu->id, "sit") == 0 && strcmp(*argv, "isatap") == 0) { iflags |= SIT_ISATAP; } else if (strcmp(lu->id, "sit") == 0 && strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipv6/ipv4") == 0 || strcmp(*argv, "ip6ip") == 0) proto = IPPROTO_IPV6; else if (strcmp(*argv, "ipv4/ipv4") == 0 || strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip4ip4") == 0) proto = IPPROTO_IPIP; else if (strcmp(*argv, "any/ipv4") == 0 || strcmp(*argv, "any") == 0) proto = 0; else invarg("Cannot guess tunnel mode.", *argv); } else if (strcmp(*argv, "6rd-prefix") == 0) { inet_prefix prefix; NEXT_ARG(); if (get_prefix(&prefix, *argv, AF_INET6)) invarg("invalid 6rd_prefix\n", *argv); memcpy(&ip6rdprefix, prefix.data, 16); ip6rdprefixlen = prefix.bitlen; } else if (strcmp(*argv, "6rd-relay_prefix") == 0) { inet_prefix prefix; NEXT_ARG(); if (get_prefix(&prefix, *argv, AF_INET)) invarg("invalid 6rd-relay_prefix\n", *argv); memcpy(&ip6rdrelayprefix, prefix.data, 4); ip6rdrelayprefixlen = prefix.bitlen; } else if (strcmp(*argv, "6rd-reset") == 0) { inet_prefix prefix; get_prefix(&prefix, "2002::", AF_INET6); memcpy(&ip6rdprefix, prefix.data, 16); ip6rdprefixlen = 16; ip6rdrelayprefix = 0; ip6rdrelayprefixlen = 0; } else usage(strcmp(lu->id, "sit") == 0); argc--, argv++; } if (ttl && pmtudisc == 0) { fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n"); exit(-1); } addattr32(n, 1024, IFLA_IPTUN_LINK, link); addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr); addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr); addattr8(n, 1024, IFLA_IPTUN_TTL, ttl); addattr8(n, 1024, IFLA_IPTUN_TOS, tos); addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc); if (strcmp(lu->id, "sit") == 0) { addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags); addattr8(n, 1024, IFLA_IPTUN_PROTO, proto); if (ip6rdprefixlen) { addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX, &ip6rdprefix, sizeof(ip6rdprefix)); addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN, ip6rdprefixlen); addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX, ip6rdrelayprefix); addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, ip6rdrelayprefixlen); } } return 0; }