Esempio n. 1
0
static int get_sci_portaddr(struct sci *sci, int *argcp, char ***argvp,
			    bool port_only, bool optional)
{
	int argc = *argcp;
	char **argv = *argvp;
	int ret;
	bool p = false, a = false, s = false;

	while (argc > 0) {
		if (strcmp(*argv, "sci") == 0) {
			if (p)
				invarg("expected address", *argv);
			if (a)
				invarg("expected port", *argv);
			NEXT_ARG();
			ret = get_sci(&sci->sci, *argv);
			if (ret)
				invarg("expected sci", *argv);
			s = true;
		} else if (strcmp(*argv, "port") == 0) {
			NEXT_ARG();
			ret = get_port(&sci->port, *argv);
			if (ret)
				invarg("expected port", *argv);
			if (sci->port == 0)
				invarg("expected port != 0", *argv);
			p = true;
		} else if (strcmp(*argv, "address") == 0) {
			NEXT_ARG();
			ret = ll_addr_a2n(sci->abuf, sizeof(sci->abuf), *argv);
			if (ret < 0)
				invarg("expected lladdr", *argv);
			a = true;
		} else if (optional) {
			break;
		} else {
			invarg("expected sci, port, or address", *argv);
		}

		argv++; argc--;

		if (sci_complete(s, p, a, port_only))
			break;
	}

	if (!optional && !sci_complete(s, p, a, port_only))
		return -1;

	if (p && a)
		sci->sci = make_sci(sci->abuf, sci->port);

	*argvp = argv;
	*argcp = argc;

	return p || a || s;
}
Esempio n. 2
0
static int multiaddr_modify(int cmd, int argc, char **argv)
{
    struct ifreq ifr;
    int fd;

    memset(&ifr, 0, sizeof(ifr));

    if (cmd == RTM_NEWADDR)
        cmd = SIOCADDMULTI;
    else
        cmd = SIOCDELMULTI;

    while (argc > 0) {
        if (strcmp(*argv, "dev") == 0) {
            NEXT_ARG();
            if (ifr.ifr_name[0])
                duparg("dev", *argv);
            strncpy(ifr.ifr_name, *argv, IFNAMSIZ);
        } else {
            if (matches(*argv, "address") == 0) {
                NEXT_ARG();
            }
            if (matches(*argv, "help") == 0)
                usage();
            if (ifr.ifr_hwaddr.sa_data[0])
                duparg("address", *argv);
            if (ll_addr_a2n(ifr.ifr_hwaddr.sa_data,
                            14, *argv) < 0) {
                fprintf(stderr, "Error: \"%s\" is not a legal ll address.\n", *argv);
                exit(1);
            }
        }
        argc--;
        argv++;
    }
    if (ifr.ifr_name[0] == 0) {
        fprintf(stderr, "Not enough information: \"dev\" is required.\n");
        exit(-1);
    }

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        perror("Cannot create socket");
        exit(1);
    }
    if (ioctl(fd, cmd, (char*)&ifr) != 0) {
        perror("ioctl");
        exit(1);
    }
    close(fd);

    exit(0);
}
Esempio n. 3
0
/* Exits on error */
static void parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr)
{
	int alen;

	memset(ifr, 0, sizeof(*ifr));
	strncpy_IFNAMSIZ(ifr->ifr_name, dev);
	ifr->ifr_hwaddr.sa_family = hatype;

	alen = hatype == 1/*ARPHRD_ETHER*/ ? 14/*ETH_HLEN*/ : 19/*INFINIBAND_HLEN*/;
	alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), alen, lla);
	if (alen < 0)
		exit(EXIT_FAILURE);
	if (alen != halen) {
		bb_error_msg_and_die("wrong address (%s) length: expected %d bytes", lla, halen);
	}
}
Esempio n. 4
0
static int parse_address(char *dev, int hatype, int halen, char *lla, struct ifreq *ifr)
{
	int alen;

	memset(ifr, 0, sizeof(*ifr));
	strcpy(ifr->ifr_name, dev);
	ifr->ifr_hwaddr.sa_family = hatype;
	alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla);
	if (alen < 0)
		return -1;
	if (alen != halen) {
		bb_error_msg("Wrong address (%s) length: expected %d bytes", lla, halen);
		return -1;
	}
	return 0;
}
Esempio n. 5
0
static int parse_address(const char *dev, int hatype, int halen, char *lla, struct ifreq *ifr)
{
	int alen;

	memset(ifr, 0, sizeof(*ifr));
	strncpy(ifr->ifr_name, dev, IFNAMSIZ);
	ifr->ifr_hwaddr.sa_family = hatype;
	alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla);
	if (alen < 0)
		return -1;
	if (alen != halen) {
		fprintf(stderr, "Wrong address (%s) length: expected %d bytes\n", lla, halen);
		return -1;
	}
	return 0; 
}
Esempio n. 6
0
static int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type)
{
	int argc = *argc_p;
	char **argv = *argv_p;

	if (argc <= 0)
		return -1;

	if (type == TINT)
		return get_integer((int *)val, *argv, 0);

	if (type == TU32)
		return get_u32(val, *argv, 0);

	if (type == TIPV4) {
		inet_prefix addr;

		if (get_prefix_1(&addr, *argv, AF_INET))
			return -1;

		*val = addr.data[0];
		return 0;
	}

	if (type == TIPV6) {
		inet_prefix addr;

		if (get_prefix_1(&addr, *argv, AF_INET6))
			return -1;

		memcpy(val, addr.data, addr.bytelen);

		return 0;
	}

	if (type == TMAC) {
#define MAC_ALEN 6
		int ret = ll_addr_a2n((char *)val, MAC_ALEN, *argv);

		if (ret == MAC_ALEN)
			return 0;
	}

	return -1;
}
Esempio n. 7
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;
}
Esempio n. 8
0
/* Return value becomes exitcode. It's okay to not return at all */
static int do_add_or_delete(char **argv, const unsigned rtm)
{
	static const char keywords[] ALIGN1 =
		"link\0""name\0""type\0""dev\0""address\0";
	enum {
		ARG_link,
		ARG_name,
		ARG_type,
		ARG_dev,
		ARG_address,
	};
	struct rtnl_handle rth;
	struct {
		struct nlmsghdr  n;
		struct ifinfomsg i;
		char             buf[1024];
	} req;
	smalluint arg;
	char *name_str = NULL;
	char *link_str = NULL;
	char *type_str = NULL;
	char *dev_str = NULL;
	char *address_str = NULL;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_type = rtm;
	req.i.ifi_family = preferred_family;
	if (rtm == RTM_NEWLINK)
		req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;

	while (*argv) {
		arg = index_in_substrings(keywords, *argv);
		if (arg == ARG_type) {
			NEXT_ARG();
			type_str = *argv++;
			dbg("type_str:'%s'", type_str);
			break;
		}
		if (arg == ARG_link) {
			NEXT_ARG();
			link_str = *argv;
			dbg("link_str:'%s'", link_str);
		} else if (arg == ARG_name) {
			NEXT_ARG();
			name_str = *argv;
			dbg("name_str:'%s'", name_str);
		} else if (arg == ARG_address) {
			NEXT_ARG();
			address_str = *argv;
			dbg("address_str:'%s'", name_str);
		} else {
			if (arg == ARG_dev) {
				if (dev_str)
					duparg(*argv, "dev");
				NEXT_ARG();
			}
			dev_str = *argv;
			dbg("dev_str:'%s'", dev_str);
		}
		argv++;
	}
	xrtnl_open(&rth);
	ll_init_map(&rth);
	if (type_str) {
		struct rtattr *linkinfo = NLMSG_TAIL(&req.n);

		addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
		addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type_str,
				strlen(type_str));

		if (*argv) {
			struct rtattr *data = NLMSG_TAIL(&req.n);
			addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);

			if (strcmp(type_str, "vlan") == 0)
				vlan_parse_opt(argv, &req.n, sizeof(req));

			data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
		}

		linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
	}
	if (rtm != RTM_NEWLINK) {
		if (!dev_str)
			return 1; /* Need a device to delete */
		req.i.ifi_index = xll_name_to_index(dev_str);
	} else {
		if (!name_str)
			name_str = dev_str;
		if (link_str) {
			int idx = xll_name_to_index(link_str);
			addattr_l(&req.n, sizeof(req), IFLA_LINK, &idx, 4);
		}
		if (address_str) {
			unsigned char abuf[32];
			int len = ll_addr_a2n(abuf, sizeof(abuf), address_str);
			dbg("address len:%d", len);
			if (len < 0)
				return -1;
			addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, abuf, len);
		}
	}
	if (name_str) {
		const size_t name_len = strlen(name_str) + 1;
		if (name_len < 2 || name_len > IFNAMSIZ)
			invarg(name_str, "name");
		addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name_str, name_len);
	}
	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
		return 2;
	return 0;
}
Esempio n. 9
0
static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
{
	struct {
		struct nlmsghdr	n;
		struct ndmsg		ndm;
		char			buf[256];
	} req = {
		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),
		.n.nlmsg_flags = NLM_F_REQUEST | flags,
		.n.nlmsg_type = cmd,
		.ndm.ndm_family = preferred_family,
		.ndm.ndm_state = NUD_PERMANENT,
	};
	char  *dev = NULL;
	int dst_ok = 0;
	int dev_ok = 0;
	int lladdr_ok = 0;
	char *lla = NULL;
	inet_prefix dst;

	while (argc > 0) {
		if (matches(*argv, "lladdr") == 0) {
			NEXT_ARG();
			if (lladdr_ok)
				duparg("lladdr", *argv);
			lla = *argv;
			lladdr_ok = 1;
		} else if (strcmp(*argv, "nud") == 0) {
			unsigned int state;

			NEXT_ARG();
			if (nud_state_a2n(&state, *argv))
				invarg("nud state is bad", *argv);
			req.ndm.ndm_state = state;
		} else if (matches(*argv, "proxy") == 0) {
			NEXT_ARG();
			if (matches(*argv, "help") == 0)
				usage();
			if (dst_ok)
				duparg("address", *argv);
			get_addr(&dst, *argv, preferred_family);
			dst_ok = 1;
			dev_ok = 1;
			req.ndm.ndm_flags |= NTF_PROXY;
		} else if (strcmp(*argv, "router") == 0) {
			req.ndm.ndm_flags |= NTF_ROUTER;
		} else if (matches(*argv, "extern_learn") == 0) {
			req.ndm.ndm_flags |= NTF_EXT_LEARNED;
		} else if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			dev = *argv;
			dev_ok = 1;
		} else if (matches(*argv, "protocol") == 0) {
			__u32 proto;

			NEXT_ARG();
			if (rtnl_rtprot_a2n(&proto, *argv))
				invarg("\"protocol\" value is invalid\n", *argv);
			if (addattr8(&req.n, sizeof(req), NDA_PROTOCOL, proto))
				return -1;
		} else {
			if (strcmp(*argv, "to") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0) {
				NEXT_ARG();
			}
			if (dst_ok)
				duparg2("to", *argv);
			get_addr(&dst, *argv, preferred_family);
			dst_ok = 1;
		}
		argc--; argv++;
	}
	if (!dev_ok || !dst_ok || dst.family == AF_UNSPEC) {
		fprintf(stderr, "Device and destination are required arguments.\n");
		exit(-1);
	}
	req.ndm.ndm_family = dst.family;
	if (addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen) < 0)
		return -1;

	if (lla && strcmp(lla, "null")) {
		char llabuf[20];
		int l;

		l = ll_addr_a2n(llabuf, sizeof(llabuf), lla);
		if (l < 0)
			return -1;

		if (addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l) < 0)
			return -1;
	}

	ll_init_map(&rth);

	if (dev) {
		req.ndm.ndm_ifindex = ll_name_to_index(dev);
		if (!req.ndm.ndm_ifindex)
			return nodev(dev);
	}

	if (rtnl_talk(&rth, &req.n, NULL) < 0)
		exit(2);

	return 0;
}

static void print_cacheinfo(const struct nda_cacheinfo *ci)
{
	static int hz;

	if (!hz)
		hz = get_user_hz();

	if (ci->ndm_refcnt)
		print_uint(PRINT_ANY, "refcnt",
				" ref %u", ci->ndm_refcnt);

	print_uint(PRINT_ANY, "used", " used %u", ci->ndm_used / hz);
	print_uint(PRINT_ANY, "confirmed", "/%u", ci->ndm_confirmed / hz);
	print_uint(PRINT_ANY, "updated", "/%u", ci->ndm_updated / hz);
}

static void print_neigh_state(unsigned int nud)
{

	open_json_array(PRINT_JSON,
			is_json_context() ?  "state" : "");

#define PRINT_FLAG(f)						\
	if (nud & NUD_##f) {					\
		nud &= ~NUD_##f;				\
		print_string(PRINT_ANY, NULL, " %s", #f);	\
	}

	PRINT_FLAG(INCOMPLETE);
	PRINT_FLAG(REACHABLE);
	PRINT_FLAG(STALE);
	PRINT_FLAG(DELAY);
	PRINT_FLAG(PROBE);
	PRINT_FLAG(FAILED);
	PRINT_FLAG(NOARP);
	PRINT_FLAG(PERMANENT);
#undef PRINT_FLAG

	close_json_array(PRINT_JSON, NULL);
}
Esempio n. 10
0
static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
{
	struct {
		struct nlmsghdr 	n;
		struct ndmsg 		ndm;
		char   			buf[256];
	} req;
	char  *d = NULL;
	int dst_ok = 0;
	int lladdr_ok = 0;
	char * lla = NULL;
	inet_prefix dst;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
	req.n.nlmsg_type = cmd;
	req.ndm.ndm_family = preferred_family;
	req.ndm.ndm_state = NUD_PERMANENT;

	while (argc > 0) {
		if (matches(*argv, "lladdr") == 0) {
			NEXT_ARG();
			if (lladdr_ok)
				duparg("lladdr", *argv);
			lla = *argv;
			lladdr_ok = 1;
		} else if (strcmp(*argv, "nud") == 0) {
			unsigned state;
			NEXT_ARG();
			if (nud_state_a2n(&state, *argv))
				invarg("nud state is bad", *argv);
			req.ndm.ndm_state = state;
		} else if (matches(*argv, "proxy") == 0) {
			NEXT_ARG();
			if (matches(*argv, "help") == 0)
				usage();
			if (dst_ok)
				duparg("address", *argv);
			get_addr(&dst, *argv, preferred_family);
			dst_ok = 1;
			req.ndm.ndm_flags |= NTF_PROXY;
		} else if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			d = *argv;
		} else {
			if (strcmp(*argv, "to") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0) {
				NEXT_ARG();
			}
			if (dst_ok)
				duparg2("to", *argv);
			get_addr(&dst, *argv, preferred_family);
			dst_ok = 1;
		}
		argc--; argv++;
	}
	if (d == NULL || !dst_ok || dst.family == AF_UNSPEC) {
		fprintf(stderr, "Device and destination are required arguments.\n");
		exit(-1);
	}
	req.ndm.ndm_family = dst.family;
	addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen);

	if (lla && strcmp(lla, "null")) {
		char llabuf[20];
		int l;

		l = ll_addr_a2n(llabuf, sizeof(llabuf), lla);
		addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l);
	}

	ll_init_map(&rth);

	if ((req.ndm.ndm_ifindex = ll_name_to_index(d)) == 0) {
		fprintf(stderr, "Cannot find device \"%s\"\n", d);
		return -1;
	}

	if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
		exit(2);

	return 0;
}
Esempio n. 11
0
static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
			   struct iplink_req *req, int dev_index)
{
	char new_rate_api = 0, count = 0, override_legacy_rate = 0;
	struct ifla_vf_rate tivt;
	int len, argc = *argcp;
	char **argv = *argvp;
	struct rtattr *vfinfo;

	tivt.min_tx_rate = -1;
	tivt.max_tx_rate = -1;

	vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);

	while (NEXT_ARG_OK()) {
		NEXT_ARG();
		count++;
		if (!matches(*argv, "max_tx_rate")) {
			/* new API in use */
			new_rate_api = 1;
			/* override legacy rate */
			override_legacy_rate = 1;
		} else if (!matches(*argv, "min_tx_rate")) {
			/* new API in use */
			new_rate_api = 1;
		}
	}

	while (count--) {
		/* rewind arg */
		PREV_ARG();
	}

	while (NEXT_ARG_OK()) {
		NEXT_ARG();
		if (matches(*argv, "mac") == 0) {
			struct ifla_vf_mac ivm;
			NEXT_ARG();
			ivm.vf = vf;
			len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm));
		} else if (matches(*argv, "vlan") == 0) {
			struct ifla_vf_vlan ivv;
			NEXT_ARG();
			if (get_unsigned(&ivv.vlan, *argv, 0)) {
				invarg("Invalid \"vlan\" value\n", *argv);
			}
			ivv.vf = vf;
			ivv.qos = 0;
			if (NEXT_ARG_OK()) {
				NEXT_ARG();
				if (matches(*argv, "qos") == 0) {
					NEXT_ARG();
					if (get_unsigned(&ivv.qos, *argv, 0)) {
						invarg("Invalid \"qos\" value\n", *argv);
					}
				} else {
					/* rewind arg */
					PREV_ARG();
				}
			}
			addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv));
		} else if (matches(*argv, "rate") == 0) {
			struct ifla_vf_tx_rate ivt;
			NEXT_ARG();
			if (get_unsigned(&ivt.rate, *argv, 0)) {
				invarg("Invalid \"rate\" value\n", *argv);
			}
			ivt.vf = vf;
			if (!new_rate_api)
				addattr_l(&req->n, sizeof(*req),
					  IFLA_VF_TX_RATE, &ivt, sizeof(ivt));
			else if (!override_legacy_rate)
				tivt.max_tx_rate = ivt.rate;

		} else if (matches(*argv, "max_tx_rate") == 0) {
			NEXT_ARG();
			if (get_unsigned(&tivt.max_tx_rate, *argv, 0))
				invarg("Invalid \"max tx rate\" value\n",
				       *argv);
			tivt.vf = vf;

		} else if (matches(*argv, "min_tx_rate") == 0) {
			NEXT_ARG();
			if (get_unsigned(&tivt.min_tx_rate, *argv, 0))
				invarg("Invalid \"min tx rate\" value\n",
				       *argv);
			tivt.vf = vf;

		} else if (matches(*argv, "spoofchk") == 0) {
			struct ifla_vf_spoofchk ivs;
			NEXT_ARG();
			if (matches(*argv, "on") == 0)
				ivs.setting = 1;
			else if (matches(*argv, "off") == 0)
				ivs.setting = 0;
			else
				invarg("Invalid \"spoofchk\" value\n", *argv);
			ivs.vf = vf;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs));

		} else if (matches(*argv, "state") == 0) {
			struct ifla_vf_link_state ivl;
			NEXT_ARG();
			if (matches(*argv, "auto") == 0)
				ivl.link_state = IFLA_VF_LINK_STATE_AUTO;
			else if (matches(*argv, "enable") == 0)
				ivl.link_state = IFLA_VF_LINK_STATE_ENABLE;
			else if (matches(*argv, "disable") == 0)
				ivl.link_state = IFLA_VF_LINK_STATE_DISABLE;
			else
				invarg("Invalid \"state\" value\n", *argv);
			ivl.vf = vf;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl));
		} else {
			/* rewind arg */
			PREV_ARG();
			break;
		}
	}

	if (new_rate_api) {
		int tmin, tmax;

		if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) {
			ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index);
			if (tivt.min_tx_rate == -1)
				tivt.min_tx_rate = tmin;
			if (tivt.max_tx_rate == -1)
				tivt.max_tx_rate = tmax;
		}
		addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt,
			  sizeof(tivt));
	}

	if (argc == *argcp)
		incomplete_command();

	addattr_nest_end(&req->n, vfinfo);

	*argcp = argc;
	*argvp = argv;
	return 0;
}
Esempio n. 12
0
int get_addr_1(inet_prefix *addr, const char *name, int family)
{
	memset(addr, 0, sizeof(*addr));

	if (strcmp(name, "default") == 0 ||
	    strcmp(name, "all") == 0 ||
	    strcmp(name, "any") == 0) {
		if ((family == AF_DECnet) || (family == AF_MPLS))
			return -1;
		addr->family = family;
		addr->bytelen = (family == AF_INET6 ? 16 : 4);
		addr->bitlen = -1;
		return 0;
	}

	if (family == AF_PACKET) {
		int len;
		len = ll_addr_a2n((char *)&addr->data, sizeof(addr->data), name);
		if (len < 0)
			return -1;

		addr->family = AF_PACKET;
		addr->bytelen = len;
		addr->bitlen = len * 8;
		return 0;
	}

	if (strchr(name, ':')) {
		addr->family = AF_INET6;
		if (family != AF_UNSPEC && family != AF_INET6)
			return -1;
		if (inet_pton(AF_INET6, name, addr->data) <= 0)
			return -1;
		addr->bytelen = 16;
		addr->bitlen = -1;
		return 0;
	}

	if (family == AF_DECnet) {
		struct dn_naddr dna;
		addr->family = AF_DECnet;
		if (dnet_pton(AF_DECnet, name, &dna) <= 0)
			return -1;
		memcpy(addr->data, dna.a_addr, 2);
		addr->bytelen = 2;
		addr->bitlen = -1;
		return 0;
	}

	if (family == AF_MPLS) {
		int i;
		addr->family = AF_MPLS;
		if (mpls_pton(AF_MPLS, name, addr->data) <= 0)
			return -1;
		addr->bytelen = 4;
		addr->bitlen = 20;
		/* How many bytes do I need? */
		for (i = 0; i < 8; i++) {
			if (ntohl(addr->data[i]) & MPLS_LS_S_MASK) {
				addr->bytelen = (i + 1)*4;
				break;
			}
		}
		return 0;
	}

	addr->family = AF_INET;
	if (family != AF_UNSPEC && family != AF_INET)
		return -1;

	if (get_addr_ipv4((__u8 *)addr->data, name) <= 0)
		return -1;

	addr->bytelen = 4;
	addr->bitlen = -1;
	return 0;
}
Esempio n. 13
0
int main(int argc, char **argv)
{
	int opt;
	int do_list = 0;
	char *do_load = NULL;

	while ((opt = getopt(argc, argv, "h?b:lf:a:n:p:kR:B:")) != EOF) {
		switch (opt) {
	        case 'b':
			dbname = optarg;
			break;
		case 'f':
			if (do_load) {
				fprintf(stderr, "Duplicate option -f\n");
				usage();
			}
			do_load = optarg;
			break;
		case 'l':
			do_list = 1;
			break;
		case 'a':
			active_probing = atoi(optarg);
			break;
		case 'n':
			negative_timeout = atoi(optarg);
			break;
		case 'k':
			no_kernel_broadcasts = 1;
			break;
		case 'p':
			if ((poll_timeout = 1000 * strtod(optarg, NULL)) < 100) {
				fprintf(stderr,"Invalid poll timeout\n");
				exit(-1);
			}
			break;
		case 'R':
			if ((broadcast_rate = atoi(optarg)) <= 0 ||
			    (broadcast_rate = 1000/broadcast_rate) <= 0) {
				fprintf(stderr, "Invalid ARP rate\n");
				exit(-1);
			}
			break;
		case 'B':
			if ((broadcast_burst = atoi(optarg)) <= 0 ||
			    (broadcast_burst = 1000*broadcast_burst) <= 0) {
				fprintf(stderr, "Invalid ARP burst\n");
				exit(-1);
			}
			break;
		case 'h':
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argc > 0) {
		ifnum = argc;
		ifnames = argv;
		ifvec = malloc(argc*sizeof(int));
		if (!ifvec) {
			perror("malloc");
			exit(-1);
		}
	}

	if ((udp_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket");
		exit(-1);
	}

        if (ifnum) {
		int i;
		struct ifreq ifr;
		memset(&ifr, 0, sizeof(ifr));
		for (i=0; i<ifnum; i++) {
			strncpy(ifr.ifr_name, ifnames[i], IFNAMSIZ);
			if (ioctl(udp_sock, SIOCGIFINDEX, &ifr)) {
				perror("ioctl(SIOCGIFINDEX)");
				exit(-1);;
			}
			ifvec[i] = ifr.ifr_ifindex;
		}
	}

	dbase = dbopen(dbname, O_CREAT|O_RDWR, 0644, DB_HASH, NULL);
	if (dbase == NULL) {
		perror("db_open");
		exit(-1);
	}

	if (do_load) {
		char buf[128];
		FILE *fp;
		struct dbkey k;
		DBT dbkey, dbdat;

		dbkey.data = &k;
		dbkey.size = sizeof(k);

		if (strcmp(do_load, "-") == 0 || strcmp(do_load, "--") == 0) {
			fp = stdin;
		} else if ((fp = fopen(do_load, "r")) == NULL) {
			perror("fopen");
			goto do_abort;
		}

		buf[sizeof(buf)-1] = 0;
		while (fgets(buf, sizeof(buf)-1, fp)) {
			__u8 b1[6];
			char ipbuf[128];
			char macbuf[128];

			if (buf[0] == '#')
				continue;

			if (sscanf(buf, "%u%s%s", &k.iface, ipbuf, macbuf) != 3) {
				fprintf(stderr, "Wrong format of input file \"%s\"\n", do_load);
				goto do_abort;
			}
			if (strncmp(macbuf, "FAILED:", 7) == 0)
				continue;
			if (!inet_aton(ipbuf, (struct in_addr*)&k.addr)) {
				fprintf(stderr, "Invalid IP address: \"%s\"\n", ipbuf);
				goto do_abort;
			}

			if (ll_addr_a2n((char *) b1, 6, macbuf) != 6)
				goto do_abort;
			dbdat.size = 6;

			if (dbase->put(dbase, &dbkey, &dbdat, 0)) {
				perror("hash->put");
				goto do_abort;
			}
		}
		dbase->sync(dbase, 0);
		if (fp != stdin)
			fclose(fp);
	}

	if (do_list) {
		DBT dbkey, dbdat;
		printf("%-8s %-15s %s\n", "#Ifindex", "IP", "MAC");
		while (dbase->seq(dbase, &dbkey, &dbdat, R_NEXT) == 0) {
			struct dbkey *key = dbkey.data;
			if (handle_if(key->iface)) {
				if (!IS_NEG(dbdat.data)) {
					char b1[18];
					printf("%-8d %-15s %s\n",
					       key->iface,
					       inet_ntoa(*(struct in_addr*)&key->addr),
					       ll_addr_n2a(dbdat.data, 6, ARPHRD_ETHER, b1, 18));
				} else {
					printf("%-8d %-15s FAILED: %dsec ago\n",
					       key->iface,
					       inet_ntoa(*(struct in_addr*)&key->addr),
					       NEG_AGE(dbdat.data));
				}
			}
		}
	}

	if (do_load || do_list)
		goto out;

	pset[0].fd = socket(PF_PACKET, SOCK_DGRAM, 0);
	if (pset[0].fd < 0) {
		perror("socket");
		exit(-1);
	}

	if (1) {
		struct sockaddr_ll sll;
		memset(&sll, 0, sizeof(sll));
		sll.sll_family = AF_PACKET;
		sll.sll_protocol = htons(ETH_P_ARP);
		sll.sll_ifindex = (ifnum == 1 ? ifvec[0] : 0);
		if (bind(pset[0].fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) {
			perror("bind");
			goto do_abort;
		}
	}

	if (rtnl_open(&rth, RTMGRP_NEIGH) < 0) {
		perror("rtnl_open");
		goto do_abort;
	}
	pset[1].fd = rth.fd;

	load_initial_table();

	if (daemon(0, 0)) {
		perror("arpd: daemon");
		goto do_abort;
	}

	openlog("arpd", LOG_PID | LOG_CONS, LOG_DAEMON);
	catch_signal(SIGINT, sig_exit);
	catch_signal(SIGTERM, sig_exit);
	catch_signal(SIGHUP, sig_sync);
	catch_signal(SIGUSR1, sig_stats);

#define EVENTS (POLLIN|POLLPRI|POLLERR|POLLHUP)
	pset[0].events = EVENTS;
	pset[0].revents = 0;
	pset[1].events = EVENTS;
	pset[1].revents = 0;

	sigsetjmp(env, 1);

	for (;;) {
		in_poll = 1;

		if (do_exit)
			break;
		if (do_sync) {
			in_poll = 0;
			dbase->sync(dbase, 0);
			do_sync = 0;
			in_poll = 1;
		}
		if (do_stats)
			send_stats();
		if (poll(pset, 2, poll_timeout) > 0) {
			in_poll = 0;
			if (pset[0].revents&EVENTS)
				get_arp_pkt();
			if (pset[1].revents&EVENTS)
				get_kern_msg();
		} else {
			do_sync = 1;
		}
	}

	undo_sysctl_adjustments();
out:
	dbase->close(dbase);
	exit(0);

do_abort:
	dbase->close(dbase);
	exit(-1);
}
Esempio n. 14
0
static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
			   struct iplink_req *req)
{
	int len, argc = *argcp;
	char **argv = *argvp;
	struct rtattr *vfinfo;

	vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);

	while (NEXT_ARG_OK()) {
		NEXT_ARG();
		if (matches(*argv, "mac") == 0) {
			struct ifla_vf_mac ivm;
			NEXT_ARG();
			ivm.vf = vf;
			len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm));
		} else if (matches(*argv, "vlan") == 0) {
			struct ifla_vf_vlan ivv;
			NEXT_ARG();
			if (get_unsigned(&ivv.vlan, *argv, 0)) {
				invarg("Invalid \"vlan\" value\n", *argv);
			}
			ivv.vf = vf;
			ivv.qos = 0;
			if (NEXT_ARG_OK()) {
				NEXT_ARG();
				if (matches(*argv, "qos") == 0) {
					NEXT_ARG();
					if (get_unsigned(&ivv.qos, *argv, 0)) {
						invarg("Invalid \"qos\" value\n", *argv);
					}
				} else {
					/* rewind arg */
					PREV_ARG();
				}
			}
			addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv));
		} else if (matches(*argv, "rate") == 0) {
			struct ifla_vf_tx_rate ivt;
			NEXT_ARG();
			if (get_unsigned(&ivt.rate, *argv, 0)) {
				invarg("Invalid \"rate\" value\n", *argv);
			}
			ivt.vf = vf;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt, sizeof(ivt));
		
		} else if (matches(*argv, "spoofchk") == 0) {
			struct ifla_vf_spoofchk ivs;
			NEXT_ARG();
			if (matches(*argv, "on") == 0)
				ivs.setting = 1;
			else if (matches(*argv, "off") == 0)
				ivs.setting = 0;
			else
				invarg("Invalid \"spoofchk\" value\n", *argv);
			ivs.vf = vf;
			addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs));

		} else {
			/* rewind arg */
			PREV_ARG();
			break;
		}
	}

	if (argc == *argcp)
		incomplete_command();

	addattr_nest_end(&req->n, vfinfo);

	*argcp = argc;
	*argvp = argv;
	return 0;
}
Esempio n. 15
0
int iplink_parse(int argc, char **argv, struct iplink_req *req,
		char **name, char **type, char **link, char **dev)
{
	int ret, len;
	char abuf[32];
	int qlen = -1;
	int mtu = -1;
	int netns = -1;

	ret = argc;

	while (argc > 0) {
		if (strcmp(*argv, "up") == 0) {
			req->i.ifi_change |= IFF_UP;
			req->i.ifi_flags |= IFF_UP;
		} else if (strcmp(*argv, "down") == 0) {
			req->i.ifi_change |= IFF_UP;
			req->i.ifi_flags &= ~IFF_UP;
		} else if (strcmp(*argv, "name") == 0) {
			NEXT_ARG();
			*name = *argv;
		} else if (matches(*argv, "link") == 0) {
			NEXT_ARG();
			*link = *argv;
		} else if (matches(*argv, "address") == 0) {
			NEXT_ARG();
			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len);
		} else if (matches(*argv, "broadcast") == 0 ||
				strcmp(*argv, "brd") == 0) {
			NEXT_ARG();
			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
		} else if (matches(*argv, "txqueuelen") == 0 ||
				strcmp(*argv, "qlen") == 0 ||
				matches(*argv, "txqlen") == 0) {
			NEXT_ARG();
			if (qlen != -1)
				duparg("txqueuelen", *argv);
			if (get_integer(&qlen,  *argv, 0))
				invarg("Invalid \"txqueuelen\" value\n", *argv);
			addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
		} 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);
			addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
                } else if (strcmp(*argv, "netns") == 0) {
                        NEXT_ARG();
                        if (netns != -1)
                                duparg("netns", *argv);
                        if (get_integer(&netns, *argv, 0))
                                invarg("Invalid \"netns\" value\n", *argv);
                        addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
		} else if (strcmp(*argv, "multicast") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_MULTICAST;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_MULTICAST;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_MULTICAST;
			} else
				return on_off("multicast");
		} else if (strcmp(*argv, "allmulticast") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_ALLMULTI;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_ALLMULTI;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_ALLMULTI;
			} else
				return on_off("allmulticast");
		} else if (strcmp(*argv, "promisc") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_PROMISC;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_PROMISC;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_PROMISC;
			} else
				return on_off("promisc");
		} else if (strcmp(*argv, "trailers") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_NOTRAILERS;
			if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags |= IFF_NOTRAILERS;
			} else if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags &= ~IFF_NOTRAILERS;
			} else
				return on_off("trailers");
		} else if (strcmp(*argv, "arp") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_NOARP;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags &= ~IFF_NOARP;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags |= IFF_NOARP;
			} else
				return on_off("noarp");
#ifdef IFF_DYNAMIC
		} else if (matches(*argv, "dynamic") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_DYNAMIC;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_DYNAMIC;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_DYNAMIC;
			} else
				return on_off("dynamic");
#endif
		} else if (matches(*argv, "type") == 0) {
			NEXT_ARG();
			*type = *argv;
			argc--; argv++;
			break;
		} else if (matches(*argv, "alias") == 0) {
			NEXT_ARG();
			addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
				  *argv, strlen(*argv));
			argc--; argv++;
			break;
		} else {
			if (strcmp(*argv, "dev") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0)
				usage();
			if (*dev)
				duparg2("dev", *argv);
			*dev = *argv;
		}
		argc--; argv++;
	}

	return ret - argc;
}
Esempio n. 16
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;
}
Esempio n. 17
0
int iplink_parse(int argc, char **argv, struct iplink_req *req,
		char **name, char **type, char **link, char **dev, int *group, int *index)
{
	int ret, len;
	char abuf[32];
	int qlen = -1;
	int mtu = -1;
	int netns = -1;
	int vf = -1;
	int numtxqueues = -1;
	int numrxqueues = -1;
	int dev_index = 0;

	*group = -1;
	ret = argc;

	while (argc > 0) {
		if (strcmp(*argv, "up") == 0) {
			req->i.ifi_change |= IFF_UP;
			req->i.ifi_flags |= IFF_UP;
		} else if (strcmp(*argv, "down") == 0) {
			req->i.ifi_change |= IFF_UP;
			req->i.ifi_flags &= ~IFF_UP;
		} else if (strcmp(*argv, "name") == 0) {
			NEXT_ARG();
			*name = *argv;
		} else if (strcmp(*argv, "index") == 0) {
			NEXT_ARG();
			*index = atoi(*argv);
		} else if (matches(*argv, "link") == 0) {
			NEXT_ARG();
			*link = *argv;
		} else if (matches(*argv, "address") == 0) {
			NEXT_ARG();
			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len);
		} else if (matches(*argv, "broadcast") == 0 ||
				strcmp(*argv, "brd") == 0) {
			NEXT_ARG();
			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
		} else if (matches(*argv, "txqueuelen") == 0 ||
				strcmp(*argv, "qlen") == 0 ||
				matches(*argv, "txqlen") == 0) {
			NEXT_ARG();
			if (qlen != -1)
				duparg("txqueuelen", *argv);
			if (get_integer(&qlen,  *argv, 0))
				invarg("Invalid \"txqueuelen\" value\n", *argv);
			addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
		} 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);
			addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
		} else if (strcmp(*argv, "netns") == 0) {
			NEXT_ARG();
			if (netns != -1)
				duparg("netns", *argv);
			if ((netns = get_netns_fd(*argv)) >= 0)
				addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4);
			else if (get_integer(&netns, *argv, 0) == 0)
				addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
			else
				invarg("Invalid \"netns\" value\n", *argv);
		} else if (strcmp(*argv, "multicast") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_MULTICAST;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_MULTICAST;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_MULTICAST;
			} else
				return on_off("multicast", *argv);
		} else if (strcmp(*argv, "allmulticast") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_ALLMULTI;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_ALLMULTI;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_ALLMULTI;
			} else
				return on_off("allmulticast", *argv);
		} else if (strcmp(*argv, "promisc") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_PROMISC;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_PROMISC;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_PROMISC;
			} else
				return on_off("promisc", *argv);
		} else if (strcmp(*argv, "trailers") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_NOTRAILERS;
			if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags |= IFF_NOTRAILERS;
			} else if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags &= ~IFF_NOTRAILERS;
			} else
				return on_off("trailers", *argv);
		} else if (strcmp(*argv, "arp") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_NOARP;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags &= ~IFF_NOARP;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags |= IFF_NOARP;
			} else
				return on_off("noarp", *argv);
		} else if (strcmp(*argv, "vf") == 0) {
			struct rtattr *vflist;
			NEXT_ARG();
			if (get_integer(&vf,  *argv, 0)) {
				invarg("Invalid \"vf\" value\n", *argv);
			}
			vflist = addattr_nest(&req->n, sizeof(*req),
					      IFLA_VFINFO_LIST);
			if (dev_index == 0)
				missarg("dev");

			len = iplink_parse_vf(vf, &argc, &argv, req, dev_index);
			if (len < 0)
				return -1;
			addattr_nest_end(&req->n, vflist);
		} else if (matches(*argv, "master") == 0) {
			int ifindex;
			NEXT_ARG();
			ifindex = ll_name_to_index(*argv);
			if (!ifindex)
				invarg("Device does not exist\n", *argv);
			addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
				  &ifindex, 4);
		} else if (matches(*argv, "nomaster") == 0) {
			int ifindex = 0;
			addattr_l(&req->n, sizeof(*req), IFLA_MASTER,
				  &ifindex, 4);
		} else if (matches(*argv, "dynamic") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_DYNAMIC;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_DYNAMIC;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_DYNAMIC;
			} else
				return on_off("dynamic", *argv);
		} else if (matches(*argv, "type") == 0) {
			NEXT_ARG();
			*type = *argv;
			argc--; argv++;
			break;
		} else if (matches(*argv, "alias") == 0) {
			NEXT_ARG();
			addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
				  *argv, strlen(*argv));
			argc--; argv++;
			break;
		} else if (strcmp(*argv, "group") == 0) {
			NEXT_ARG();
			if (*group != -1)
				duparg("group", *argv);
			if (rtnl_group_a2n(group, *argv))
				invarg("Invalid \"group\" value\n", *argv);
		} else if (strcmp(*argv, "mode") == 0) {
			int mode;
			NEXT_ARG();
			mode = get_link_mode(*argv);
			if (mode < 0)
				invarg("Invalid link mode\n", *argv);
			addattr8(&req->n, sizeof(*req), IFLA_LINKMODE, mode);
		} else if (strcmp(*argv, "state") == 0) {
			int state;
			NEXT_ARG();
			state = get_operstate(*argv);
			if (state < 0)
				invarg("Invalid operstate\n", *argv);

			addattr8(&req->n, sizeof(*req), IFLA_OPERSTATE, state);
		} else if (matches(*argv, "numtxqueues") == 0) {
			NEXT_ARG();
			if (numtxqueues != -1)
				duparg("numtxqueues", *argv);
			if (get_integer(&numtxqueues, *argv, 0))
				invarg("Invalid \"numtxqueues\" value\n", *argv);
			addattr_l(&req->n, sizeof(*req), IFLA_NUM_TX_QUEUES,
				  &numtxqueues, 4);
		} else if (matches(*argv, "numrxqueues") == 0) {
			NEXT_ARG();
			if (numrxqueues != -1)
				duparg("numrxqueues", *argv);
			if (get_integer(&numrxqueues, *argv, 0))
				invarg("Invalid \"numrxqueues\" value\n", *argv);
			addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES,
				  &numrxqueues, 4);
		} else {
			if (strcmp(*argv, "dev") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0)
				usage();
			if (*dev)
				duparg2("dev", *argv);
			*dev = *argv;
			dev_index = ll_name_to_index(*dev);
			if (dev_index == 0)
				invarg("Unknown device", *argv);
		}
		argc--; argv++;
	}

	return ret - argc;
}
int iplink_parse(int argc, char **argv, struct iplink_req *req,
		char **name, char **type, char **link, char **dev)
{
	int ret, len;
	char abuf[32];
	int qlen = -1;
	int mtu = -1;
	int netns = -1;
	int vf = -1;

	ret = argc;

	while (argc > 0) {
		if (strcmp(*argv, "up") == 0) {
			req->i.ifi_change |= IFF_UP;
			req->i.ifi_flags |= IFF_UP;
		} else if (strcmp(*argv, "down") == 0) {
			req->i.ifi_change |= IFF_UP;
			req->i.ifi_flags &= ~IFF_UP;
		} else if (strcmp(*argv, "name") == 0) {
			NEXT_ARG();
			*name = *argv;
		} else if (matches(*argv, "link") == 0) {
			NEXT_ARG();
			*link = *argv;
		} else if (matches(*argv, "address") == 0) {
			NEXT_ARG();
			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len);
		} else if (matches(*argv, "broadcast") == 0 ||
				strcmp(*argv, "brd") == 0) {
			NEXT_ARG();
			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
			if (len < 0)
				return -1;
			addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
		} else if (matches(*argv, "txqueuelen") == 0 ||
				strcmp(*argv, "qlen") == 0 ||
				matches(*argv, "txqlen") == 0) {
			NEXT_ARG();
			if (qlen != -1)
				duparg("txqueuelen", *argv);
			if (get_integer(&qlen,  *argv, 0))
				invarg("Invalid \"txqueuelen\" value\n", *argv);
			addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
		} 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);
			addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
                } else if (strcmp(*argv, "netns") == 0) {
                        NEXT_ARG();
                        if (netns != -1)
                                duparg("netns", *argv);
                        if (get_integer(&netns, *argv, 0))
                                invarg("Invalid \"netns\" value\n", *argv);
                        addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4);
		} else if (strcmp(*argv, "multicast") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_MULTICAST;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_MULTICAST;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_MULTICAST;
			} else
				return on_off("multicast");
		} else if (strcmp(*argv, "allmulticast") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_ALLMULTI;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_ALLMULTI;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_ALLMULTI;
			} else
				return on_off("allmulticast");
		} else if (strcmp(*argv, "multipath") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_NOMULTIPATH;
			req->i.ifi_change |= IFF_MPBACKUP;
			req->i.ifi_change |= IFF_MPHANDOVER;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags &= ~IFF_NOMULTIPATH;
				req->i.ifi_flags &= ~IFF_MPBACKUP;
				req->i.ifi_flags &= ~IFF_MPHANDOVER;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags |= IFF_NOMULTIPATH;
			} else if (strcmp(*argv, "backup") == 0) {
				req->i.ifi_flags &= ~IFF_NOMULTIPATH;
				req->i.ifi_flags |= IFF_MPBACKUP;
			} else if (strcmp(*argv, "handover") == 0) {
				req->i.ifi_flags &= ~IFF_NOMULTIPATH;
				req->i.ifi_flags |= IFF_MPHANDOVER;
			} else {
				fprintf(stderr, "Error: argument of \"multipath\" must be"
						"\"on\", \"off\", \"backup\" or \"handover\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "promisc") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_PROMISC;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_PROMISC;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_PROMISC;
			} else
				return on_off("promisc");
		} else if (strcmp(*argv, "trailers") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_NOTRAILERS;
			if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags |= IFF_NOTRAILERS;
			} else if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags &= ~IFF_NOTRAILERS;
			} else
				return on_off("trailers");
		} else if (strcmp(*argv, "arp") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_NOARP;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags &= ~IFF_NOARP;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags |= IFF_NOARP;
			} else
				return on_off("noarp");
		} else if (strcmp(*argv, "vf") == 0) {
			struct rtattr *vflist;
			NEXT_ARG();
			if (get_integer(&vf,  *argv, 0)) {
				invarg("Invalid \"vf\" value\n", *argv);
			}
			vflist = addattr_nest(&req->n, sizeof(*req),
					      IFLA_VFINFO_LIST);
			len = iplink_parse_vf(vf, &argc, &argv, req);
			if (len < 0)
				return -1;
			addattr_nest_end(&req->n, vflist);
#ifdef IFF_DYNAMIC
		} else if (matches(*argv, "dynamic") == 0) {
			NEXT_ARG();
			req->i.ifi_change |= IFF_DYNAMIC;
			if (strcmp(*argv, "on") == 0) {
				req->i.ifi_flags |= IFF_DYNAMIC;
			} else if (strcmp(*argv, "off") == 0) {
				req->i.ifi_flags &= ~IFF_DYNAMIC;
			} else
				return on_off("dynamic");
#endif
		} else if (matches(*argv, "type") == 0) {
			NEXT_ARG();
			*type = *argv;
			argc--; argv++;
			break;
		} else if (matches(*argv, "alias") == 0) {
			NEXT_ARG();
			addattr_l(&req->n, sizeof(*req), IFLA_IFALIAS,
				  *argv, strlen(*argv));
			argc--; argv++;
			break;
		} else {
			if (strcmp(*argv, "dev") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0)
				usage();
			if (*dev)
				duparg2("dev", *argv);
			*dev = *argv;
		}
		argc--; argv++;
	}

	return ret - argc;
}