Esempio n. 1
0
static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *info)
{
	int ret = 0;
	struct l2tp_session *session;

	session = l2tp_nl_session_find(info);
	if (session == NULL) {
		ret = -ENODEV;
		goto out;
	}

	if (info->attrs[L2TP_ATTR_DEBUG])
		session->debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);

	if (info->attrs[L2TP_ATTR_DATA_SEQ])
		session->data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);

	if (info->attrs[L2TP_ATTR_RECV_SEQ])
		session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]);

	if (info->attrs[L2TP_ATTR_SEND_SEQ]) {
		session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]);
		l2tp_session_set_header_len(session, session->tunnel->version);
	}

	if (info->attrs[L2TP_ATTR_LNS_MODE])
		session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]);

	if (info->attrs[L2TP_ATTR_RECV_TIMEOUT])
		session->reorder_timeout = nla_get_msecs(info->attrs[L2TP_ATTR_RECV_TIMEOUT]);

	if (info->attrs[L2TP_ATTR_MTU])
		session->mtu = nla_get_u16(info->attrs[L2TP_ATTR_MTU]);

	if (info->attrs[L2TP_ATTR_MRU])
		session->mru = nla_get_u16(info->attrs[L2TP_ATTR_MRU]);

	ret = l2tp_session_notify(&l2tp_nl_family, info,
				  session, L2TP_CMD_SESSION_MODIFY);

out:
	return ret;
}
Esempio n. 2
0
static iz_res_t list_response(struct iz_cmd *cmd, struct genlmsghdr *ghdr, struct nlattr **attrs)
{
	char * dev_name;
	char * phy_name = NULL;
	uint32_t dev_index;
	unsigned char hw_addr[IEEE802154_ADDR_LEN];
	uint16_t short_addr;
	uint16_t pan_id;
	char * dev_type_str;

	/* Check for mandatory attributes */
	if (!attrs[IEEE802154_ATTR_DEV_NAME]     ||
	    !attrs[IEEE802154_ATTR_DEV_INDEX]    ||
	    !attrs[IEEE802154_ATTR_HW_ADDR]      ||
	    !attrs[IEEE802154_ATTR_SHORT_ADDR]   ||
	    !attrs[IEEE802154_ATTR_PAN_ID])
		return IZ_STOP_ERR;

	/* Get attribute values from the message */
	dev_name = nla_get_string(attrs[IEEE802154_ATTR_DEV_NAME]);
	dev_index = nla_get_u32(attrs[IEEE802154_ATTR_DEV_INDEX]);
	nla_memcpy(hw_addr, attrs[IEEE802154_ATTR_HW_ADDR],
		IEEE802154_ADDR_LEN);
	short_addr = nla_get_u16(attrs[IEEE802154_ATTR_SHORT_ADDR]);
	pan_id = nla_get_u16(attrs[IEEE802154_ATTR_PAN_ID]);

	if (attrs[IEEE802154_ATTR_PHY_NAME])
		phy_name = nla_get_string(attrs[IEEE802154_ATTR_PHY_NAME]);

	/* Display information about interface */
	printf("%s\n", dev_name);
	dev_type_str = "IEEE 802.15.4 MAC interface";
	printf("    link: %s\n", dev_type_str);
	if (phy_name)
		printf("    phy %s\n", phy_name);

	printf("    hw %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
			hw_addr[0], hw_addr[1], hw_addr[2], hw_addr[3],
			hw_addr[4], hw_addr[5], hw_addr[6], hw_addr[7]);
	printf(" pan 0x%04hx short 0x%04hx\n", pan_id, short_addr);

	return (cmd->flags & NLM_F_MULTI) ? IZ_CONT_OK : IZ_STOP_OK;
}
Esempio n. 3
0
static int ipvs_dests_parse_cb(struct nl_msg *msg, void *arg)
{
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
	struct nlattr *dest_attrs[IPVS_DEST_ATTR_MAX + 1];
	struct ip_vs_get_dests **dp = (struct ip_vs_get_dests **)arg;
	struct ip_vs_get_dests *d = (struct ip_vs_get_dests *)*dp;
	int i = d->num_dests;

	if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0)
		return -1;

	if (!attrs[IPVS_CMD_ATTR_DEST])
		return -1;

	if (nla_parse_nested(dest_attrs, IPVS_DEST_ATTR_MAX, attrs[IPVS_CMD_ATTR_DEST], ipvs_dest_policy))
		return -1;

	memset(&(d->entrytable[i]), 0, sizeof(d->entrytable[i]));

	if (!(dest_attrs[IPVS_DEST_ATTR_ADDR] &&
	      dest_attrs[IPVS_DEST_ATTR_PORT] &&
	      dest_attrs[IPVS_DEST_ATTR_FWD_METHOD] &&
	      dest_attrs[IPVS_DEST_ATTR_WEIGHT] &&
	      dest_attrs[IPVS_DEST_ATTR_U_THRESH] &&
	      dest_attrs[IPVS_DEST_ATTR_L_THRESH] &&
	      dest_attrs[IPVS_DEST_ATTR_ACTIVE_CONNS] &&
	      dest_attrs[IPVS_DEST_ATTR_INACT_CONNS] &&
	      dest_attrs[IPVS_DEST_ATTR_PERSIST_CONNS]))
		return -1;

	memcpy(&(d->entrytable[i].addr),
	       nla_data(dest_attrs[IPVS_DEST_ATTR_ADDR]),
	       sizeof(d->entrytable[i].addr));
	d->entrytable[i].port = nla_get_u16(dest_attrs[IPVS_DEST_ATTR_PORT]);
	d->entrytable[i].conn_flags = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_FWD_METHOD]);
	d->entrytable[i].weight = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_WEIGHT]);
	d->entrytable[i].u_threshold = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_U_THRESH]);
	d->entrytable[i].l_threshold = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_L_THRESH]);
	d->entrytable[i].activeconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_ACTIVE_CONNS]);
	d->entrytable[i].inactconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_INACT_CONNS]);
	d->entrytable[i].persistconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_PERSIST_CONNS]);
	d->entrytable[i].af = d->af;

	if (ipvs_parse_stats(&(d->entrytable[i].stats),
			     dest_attrs[IPVS_DEST_ATTR_STATS]) != 0)
		return -1;

	i++;

	d->num_dests = i;
	d = realloc(d, sizeof(*d) + sizeof(ipvs_dest_entry_t) * (d->num_dests + 1));
	*dp = d;
	return 0;
}
Esempio n. 4
0
static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
{
	struct nlattr *tb[CTA_PROTO_MAX+1];
	int err;

	err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
	if (err < 0)
		return err;

	if (!repl && tb[CTA_PROTO_NUM])
		nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM]));
	if (tb[CTA_PROTO_SRC_PORT])
		nfnl_ct_set_src_port(ct, repl,
			ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])));
	if (tb[CTA_PROTO_DST_PORT])
		nfnl_ct_set_dst_port(ct, repl,
			ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])));

	if (ct->ct_family == AF_INET) {
		if (tb[CTA_PROTO_ICMP_ID])
			nfnl_ct_set_icmp_id(ct, repl,
				ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
		if (tb[CTA_PROTO_ICMP_TYPE])
			nfnl_ct_set_icmp_type(ct, repl,
				nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
		if (tb[CTA_PROTO_ICMP_CODE])
			nfnl_ct_set_icmp_code(ct, repl,
				nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
	} else if (ct->ct_family == AF_INET6) {
		if (tb[CTA_PROTO_ICMPV6_ID])
			nfnl_ct_set_icmp_id(ct, repl,
			    ntohs(nla_get_u16(tb[CTA_PROTO_ICMPV6_ID])));
		if (tb[CTA_PROTO_ICMPV6_TYPE])
			nfnl_ct_set_icmp_type(ct, repl,
				nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]));
		if (tb[CTA_PROTO_ICMPV6_CODE])
			nfnl_ct_set_icmp_code(ct, repl,
				nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]));
	}

	return 0;
}
Esempio n. 5
0
/*
 * PANid, channel, beacon_order = 15, superframe_order = 15,
 * PAN_coordinator, battery_life_extension = 0,
 * coord_realignment = 0, security_enable = 0
*/
static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
{
    struct net_device *dev;
    struct ieee802154_addr addr;

    u8 channel, bcn_ord, sf_ord;
    int pan_coord, blx, coord_realign;
    int ret;

    if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
            !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
            !info->attrs[IEEE802154_ATTR_CHANNEL] ||
            !info->attrs[IEEE802154_ATTR_BCN_ORD] ||
            !info->attrs[IEEE802154_ATTR_SF_ORD] ||
            !info->attrs[IEEE802154_ATTR_PAN_COORD] ||
            !info->attrs[IEEE802154_ATTR_BAT_EXT] ||
            !info->attrs[IEEE802154_ATTR_COORD_REALIGN]
       )
        return -EINVAL;

    dev = ieee802154_nl_get_dev(info);
    if (!dev)
        return -ENODEV;

    addr.addr_type = IEEE802154_ADDR_SHORT;
    addr.short_addr = nla_get_u16(
                          info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
    addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);

    channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]);
    bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]);
    sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]);
    pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]);
    blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]);
    coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]);

    ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel,
            bcn_ord, sf_ord, pan_coord, blx, coord_realign);

    dev_put(dev);
    return ret;
}
Esempio n. 6
0
static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
{
	struct net *net = ovs_dp_get_net(parms->dp);
	struct nlattr *options = parms->options;
	struct vxlan_port *vxlan_port;
	struct vxlan_sock *vs;
	struct vport *vport;
	struct nlattr *a;
	u16 dst_port;
	int err;

	if (!options) {
		err = -EINVAL;
		goto error;
	}
	a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT);
	if (a && nla_len(a) == sizeof(u16)) {
		dst_port = nla_get_u16(a);
	} else {
		/* Require destination port from userspace. */
		err = -EINVAL;
		goto error;
	}

	vport = ovs_vport_alloc(sizeof(struct vxlan_port),
				&ovs_vxlan_vport_ops, parms);
	if (IS_ERR(vport))
		return vport;

	vxlan_port = vxlan_vport(vport);
	strncpy(vxlan_port->name, parms->name, IFNAMSIZ);

	a = nla_find_nested(options, OVS_TUNNEL_ATTR_EXTENSION);
	if (a) {
		err = vxlan_configure_exts(vport, a);
		if (err) {
			ovs_vport_free(vport);
			goto error;
		}
	}

	vs = vxlan_sock_add(net, htons(dst_port), vxlan_rcv, vport, true,
			    vxlan_port->exts);
	if (IS_ERR(vs)) {
		ovs_vport_free(vport);
		return (void *)vs;
	}
	vxlan_port->vs = vs;

	return vport;

error:
	return ERR_PTR(err);
}
static int nl_msg_cb(struct nl_msg* msg, void* arg)
{
	struct config *conf = arg;
	struct sockaddr_nl nla;
	struct nlmsghdr *nlh = nlmsg_hdr(msg);
	struct nlattr *attrs[NL802154_ATTR_MAX+1];

	struct genlmsghdr *gnlh = (struct genlmsghdr*) nlmsg_data(nlh);

	nla_parse(attrs, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	if (!attrs[NL802154_ATTR_SHORT_ADDR] || !attrs[NL802154_ATTR_PAN_ID])
		return NL_SKIP;

	/* We only handle short addresses right now */
	conf->short_addr = nla_get_u16(attrs[NL802154_ATTR_SHORT_ADDR]);
	conf->pan_id = nla_get_u16(attrs[NL802154_ATTR_PAN_ID]);

	return NL_SKIP;
}
Esempio n. 8
0
static int rmnet_newlink(struct net *src_net, struct net_device *dev,
			 struct nlattr *tb[], struct nlattr *data[],
			 struct netlink_ext_ack *extack)
{
	int ingress_format = RMNET_INGRESS_FORMAT_DEMUXING |
			     RMNET_INGRESS_FORMAT_DEAGGREGATION |
			     RMNET_INGRESS_FORMAT_MAP;
	int egress_format = RMNET_EGRESS_FORMAT_MUXING |
			    RMNET_EGRESS_FORMAT_MAP;
	struct net_device *real_dev;
	int mode = RMNET_EPMODE_VND;
	struct rmnet_port *port;
	int err = 0;
	u16 mux_id;

	real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
	if (!real_dev || !dev)
		return -ENODEV;

	if (!data[IFLA_VLAN_ID])
		return -EINVAL;

	mux_id = nla_get_u16(data[IFLA_VLAN_ID]);

	err = rmnet_register_real_device(real_dev);
	if (err)
		goto err0;

	port = rmnet_get_port_rtnl(real_dev);
	err = rmnet_vnd_newlink(mux_id, dev, port, real_dev);
	if (err)
		goto err1;

	err = netdev_master_upper_dev_link(dev, real_dev, NULL, NULL);
	if (err)
		goto err2;

	netdev_dbg(dev, "data format [ingress 0x%08X] [egress 0x%08X]\n",
		   ingress_format, egress_format);
	port->egress_data_format = egress_format;
	port->ingress_data_format = ingress_format;

	rmnet_set_endpoint_config(real_dev, mux_id, mode, dev);
	rmnet_set_endpoint_config(dev, mux_id, mode, real_dev);
	return 0;

err2:
	rmnet_vnd_dellink(mux_id, port);
err1:
	rmnet_unregister_real_device(real_dev, port);
err0:
	return err;
}
Esempio n. 9
0
static iz_res_t assoc_response(struct iz_cmd *cmd, struct genlmsghdr *ghdr, struct nlattr **attrs)
{
	if (!attrs[IEEE802154_ATTR_SHORT_ADDR] ||
		!attrs[IEEE802154_ATTR_STATUS] )
		return IZ_STOP_ERR;

	printf("Received short address %04hx, status %02hhx\n",
		nla_get_u16(attrs[IEEE802154_ATTR_SHORT_ADDR]),
		nla_get_u8(attrs[IEEE802154_ATTR_STATUS]));

	return IZ_STOP_OK;
}
Esempio n. 10
0
static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr,
			      struct lwtunnel_state **ts)
{
	struct ip_tunnel_info *tun_info;
	struct lwtunnel_state *new_state;
	struct nlattr *tb[IP_TUN_MAX + 1];
	int err;

	err = nla_parse_nested(tb, IP_TUN_MAX, attr, ip_tun_policy);
	if (err < 0)
		return err;

	new_state = lwtunnel_state_alloc(sizeof(*tun_info));
	if (!new_state)
		return -ENOMEM;

	new_state->type = LWTUNNEL_ENCAP_IP;

	tun_info = lwt_tun_info(new_state);

	if (tb[IP_TUN_ID])
		tun_info->key.tun_id = nla_get_u64(tb[IP_TUN_ID]);

	if (tb[IP_TUN_DST])
		tun_info->key.ipv4_dst = nla_get_be32(tb[IP_TUN_DST]);

	if (tb[IP_TUN_SRC])
		tun_info->key.ipv4_src = nla_get_be32(tb[IP_TUN_SRC]);

	if (tb[IP_TUN_TTL])
		tun_info->key.ipv4_ttl = nla_get_u8(tb[IP_TUN_TTL]);

	if (tb[IP_TUN_TOS])
		tun_info->key.ipv4_tos = nla_get_u8(tb[IP_TUN_TOS]);

	if (tb[IP_TUN_SPORT])
		tun_info->key.tp_src = nla_get_be16(tb[IP_TUN_SPORT]);

	if (tb[IP_TUN_DPORT])
		tun_info->key.tp_dst = nla_get_be16(tb[IP_TUN_DPORT]);

	if (tb[IP_TUN_FLAGS])
		tun_info->key.tun_flags = nla_get_u16(tb[IP_TUN_FLAGS]);

	tun_info->mode = IP_TUNNEL_INFO_TX;
	tun_info->options = NULL;
	tun_info->options_len = 0;

	*ts = new_state;

	return 0;
}
Esempio n. 11
0
/*
 * iwpm_register_pid_cb - Process a port mapper response to
 *                        iwpm_register_pid()
 */
int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct iwpm_nlmsg_request *nlmsg_request = NULL;
	struct nlattr *nltb[IWPM_NLA_RREG_PID_MAX];
	struct iwpm_dev_data *pm_msg;
	char *dev_name, *iwpm_name;
	u32 msg_seq;
	u8 nl_client;
	u16 iwpm_version;
	const char *msg_type = "Register Pid response";

	if (iwpm_parse_nlmsg(cb, IWPM_NLA_RREG_PID_MAX,
				resp_reg_policy, nltb, msg_type))
		return -EINVAL;

	msg_seq = nla_get_u32(nltb[IWPM_NLA_RREG_PID_SEQ]);
	nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
	if (!nlmsg_request) {
		pr_info("%s: Could not find a matching request (seq = %u)\n",
				 __func__, msg_seq);
		return -EINVAL;
	}
	pm_msg = nlmsg_request->req_buffer;
	nl_client = nlmsg_request->nl_client;
	dev_name = (char *)nla_data(nltb[IWPM_NLA_RREG_IBDEV_NAME]);
	iwpm_name = (char *)nla_data(nltb[IWPM_NLA_RREG_ULIB_NAME]);
	iwpm_version = nla_get_u16(nltb[IWPM_NLA_RREG_ULIB_VER]);

	/* check device name, ulib name and version */
	if (strcmp(pm_msg->dev_name, dev_name) ||
			strcmp(iwpm_ulib_name, iwpm_name) ||
			iwpm_version != iwpm_ulib_version) {

		pr_info("%s: Incorrect info (dev = %s name = %s version = %d)\n",
				__func__, dev_name, iwpm_name, iwpm_version);
		nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
		goto register_pid_response_exit;
	}
	iwpm_user_pid = cb->nlh->nlmsg_pid;
	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
	pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
			__func__, iwpm_user_pid);
	if (iwpm_valid_client(nl_client))
		iwpm_set_registration(nl_client, IWPM_REG_VALID);
register_pid_response_exit:
	nlmsg_request->request_done = 1;
	/* always for found nlmsg_request */
	kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
	barrier();
	wake_up(&nlmsg_request->waitq);
	return 0;
}
Esempio n. 12
0
static int l2tp_nl_cmd_session_modify(struct sk_buff *skb, struct genl_info *info)
{
	int ret = 0;
	struct l2tp_session *session;

	session = l2tp_nl_session_find(info);
	if (session == NULL) {
		ret = -ENODEV;
		goto out;
	}

	if (info->attrs[L2TP_ATTR_DEBUG])
		session->debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);

	if (info->attrs[L2TP_ATTR_DATA_SEQ])
		session->data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);

	if (info->attrs[L2TP_ATTR_RECV_SEQ])
		session->recv_seq = nla_get_u8(info->attrs[L2TP_ATTR_RECV_SEQ]);

	if (info->attrs[L2TP_ATTR_SEND_SEQ])
		session->send_seq = nla_get_u8(info->attrs[L2TP_ATTR_SEND_SEQ]);

	if (info->attrs[L2TP_ATTR_LNS_MODE])
		session->lns_mode = nla_get_u8(info->attrs[L2TP_ATTR_LNS_MODE]);

	if (info->attrs[L2TP_ATTR_RECV_TIMEOUT])
		session->reorder_timeout = nla_get_msecs(info->attrs[L2TP_ATTR_RECV_TIMEOUT]);

	if (info->attrs[L2TP_ATTR_MTU])
		session->mtu = nla_get_u16(info->attrs[L2TP_ATTR_MTU]);

	if (info->attrs[L2TP_ATTR_MRU])
		session->mru = nla_get_u16(info->attrs[L2TP_ATTR_MRU]);

out:
	return ret;
}
Esempio n. 13
0
static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
				struct nlattr *tb[], struct nlattr *data[],
				struct netlink_ext_ack *extack)
{
	struct net_device *pdev;
	struct ipoib_dev_priv *ppriv;
	u16 child_pkey;
	int err;

	if (!tb[IFLA_LINK])
		return -EINVAL;

	pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
	if (!pdev || pdev->type != ARPHRD_INFINIBAND)
		return -ENODEV;

	ppriv = ipoib_priv(pdev);

	if (test_bit(IPOIB_FLAG_SUBINTERFACE, &ppriv->flags)) {
		ipoib_warn(ppriv, "child creation disallowed for child devices\n");
		return -EINVAL;
	}

	if (!data || !data[IFLA_IPOIB_PKEY]) {
		ipoib_dbg(ppriv, "no pkey specified, using parent pkey\n");
		child_pkey  = ppriv->pkey;
	} else
		child_pkey  = nla_get_u16(data[IFLA_IPOIB_PKEY]);

	err = ipoib_intf_init(ppriv->ca, ppriv->port, dev->name, dev);
	if (err) {
		ipoib_warn(ppriv, "failed to initialize pkey device\n");
		return err;
	}

	err = __ipoib_vlan_add(ppriv, ipoib_priv(dev),
			       child_pkey, IPOIB_RTNL_CHILD);
	if (err)
		return err;

	if (data) {
		err = ipoib_changelink(dev, tb, data, extack);
		if (err) {
			unregister_netdevice(dev);
			return err;
		}
	}

	return 0;
}
Esempio n. 14
0
static int rmnet_rtnl_validate(struct nlattr *tb[], struct nlattr *data[],
			       struct netlink_ext_ack *extack)
{
	u16 mux_id;

	if (!data || !data[IFLA_VLAN_ID])
		return -EINVAL;

	mux_id = nla_get_u16(data[IFLA_VLAN_ID]);
	if (mux_id > (RMNET_MAX_LOGICAL_EP - 1))
		return -ERANGE;

	return 0;
}
Esempio n. 15
0
static int ieee802154_associate_req(struct sk_buff *skb,
                                    struct genl_info *info)
{
    struct net_device *dev;
    struct ieee802154_addr addr;
    int ret = -EINVAL;

    if (!info->attrs[IEEE802154_ATTR_CHANNEL] ||
            !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
            (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] &&
             !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) ||
            !info->attrs[IEEE802154_ATTR_CAPABILITY])
        return -EINVAL;

    dev = ieee802154_nl_get_dev(info);
    if (!dev)
        return -ENODEV;

    if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
        addr.addr_type = IEEE802154_ADDR_LONG;
        nla_memcpy(addr.hwaddr,
                   info->attrs[IEEE802154_ATTR_COORD_HW_ADDR],
                   IEEE802154_ADDR_LEN);
    } else {
        addr.addr_type = IEEE802154_ADDR_SHORT;
        addr.short_addr = nla_get_u16(
                              info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
    }
    addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);

    ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr,
            nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]),
            nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY]));

    dev_put(dev);
    return ret;
}
Esempio n. 16
0
static int vlan_validate(struct nlattr *tb[], struct nlattr *data[],
			 struct netlink_ext_ack *extack)
{
	struct ifla_vlan_flags *flags;
	u16 id;
	int err;

	if (tb[IFLA_ADDRESS]) {
		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
			return -EINVAL;
		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
			return -EADDRNOTAVAIL;
	}

	if (!data)
		return -EINVAL;

	if (data[IFLA_VLAN_PROTOCOL]) {
		switch (nla_get_be16(data[IFLA_VLAN_PROTOCOL])) {
		case htons(ETH_P_8021Q):
		case htons(ETH_P_8021AD):
			break;
		default:
			return -EPROTONOSUPPORT;
		}
	}

	if (data[IFLA_VLAN_ID]) {
		id = nla_get_u16(data[IFLA_VLAN_ID]);
		if (id >= VLAN_VID_MASK)
			return -ERANGE;
	}
	if (data[IFLA_VLAN_FLAGS]) {
		flags = nla_data(data[IFLA_VLAN_FLAGS]);
		if ((flags->flags & flags->mask) &
		    ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
		      VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP))
			return -EINVAL;
	}

	err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
	if (err < 0)
		return err;
	err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
	if (err < 0)
		return err;
	return 0;
}
Esempio n. 17
0
static struct vport *geneve_tnl_create(const struct vport_parms *parms)
{
	struct net *net = ovs_dp_get_net(parms->dp);
	struct nlattr *options = parms->options;
	struct geneve_port *geneve_port;
	struct net_device *dev;
	struct vport *vport;
	struct nlattr *a;
	u16 dst_port;
	int err;

	if (!options) {
		err = -EINVAL;
		goto error;
	}

	a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT);
	if (a && nla_len(a) == sizeof(u16)) {
		dst_port = nla_get_u16(a);
	} else {
		/* Require destination port from userspace. */
		err = -EINVAL;
		goto error;
	}

	vport = ovs_vport_alloc(sizeof(struct geneve_port),
				&ovs_geneve_vport_ops, parms);
	if (IS_ERR(vport))
		return vport;

	geneve_port = geneve_vport(vport);
	geneve_port->dst_port = dst_port;

	rtnl_lock();
	dev = geneve_dev_create_fb(net, parms->name, NET_NAME_USER, dst_port);
	if (IS_ERR(dev)) {
		rtnl_unlock();
		ovs_vport_free(vport);
		return ERR_CAST(dev);
	}

	dev_change_flags(dev, dev->flags | IFF_UP);
	rtnl_unlock();
	return vport;
error:
	return ERR_PTR(err);
}
Esempio n. 18
0
static int cb_handler(struct nl_msg * msg, void * arg)
{

  * (int*) arg = 123; // cbarg

  struct nlmsghdr * hdr = nlmsg_hdr(msg);
  struct genlmsghdr * gnlh = nlmsg_data(hdr);

  int valid =
    genlmsg_validate(hdr, 0, DEMO_ATTR_MAX, demo_gnl_policy);
  printf("valid %d %s\n", valid, valid ? "ERROR" : "OK");

  // one way
  struct nlattr * attrs[DEMO_ATTR_MAX + 1];

  if (genlmsg_parse(hdr, 0, attrs, DEMO_ATTR_MAX, demo_gnl_policy) < 0)
    {
      printf("genlsmg_parse ERROR\n");
    }

  else
    {
      printf("genlsmg_parse OK\n");
      printf("attr1 %s\n", nla_get_string(attrs[DEMO_ATTR1_STRING]));
      printf("attr2 %x\n", nla_get_u16(attrs[DEMO_ATTR2_UINT16]));
      struct attr_custom * cp = (struct attr_custom *) nla_data(attrs[DEMO_ATTR3_CUSTOM]);
      printf("attr3 %d %ld %f %lf\n", cp->a, cp->b, cp->c,cp->d);

    }

  // another way
  printf("gnlh->cmd %d\n", gnlh->cmd);	//--- DEMO_CMD_ECHO

  int remaining = genlmsg_attrlen(gnlh, 0);
  struct nlattr * attr = genlmsg_attrdata(gnlh, 0);

  while (nla_ok(attr, remaining))
    {
      printf("remaining %d\n", remaining);
      printf("attr @ %p\n", attr); // nla_get_string(attr)
      attr = nla_next(attr, &remaining);
    }

  nl_msg_dump(msg, stderr);

  return NL_STOP;
}
Esempio n. 19
0
static int ip6_tun_build_state(struct net_device *dev, struct nlattr *attr,
			       unsigned int family, const void *cfg,
			       struct lwtunnel_state **ts)
{
	struct ip_tunnel_info *tun_info;
	struct lwtunnel_state *new_state;
	struct nlattr *tb[LWTUNNEL_IP6_MAX + 1];
	int err;

	err = nla_parse_nested(tb, LWTUNNEL_IP6_MAX, attr, ip6_tun_policy);
	if (err < 0)
		return err;

	new_state = lwtunnel_state_alloc(sizeof(*tun_info));
	if (!new_state)
		return -ENOMEM;

	new_state->type = LWTUNNEL_ENCAP_IP6;

	tun_info = lwt_tun_info(new_state);

	if (tb[LWTUNNEL_IP6_ID])
		tun_info->key.tun_id = nla_get_u64(tb[LWTUNNEL_IP6_ID]);

	if (tb[LWTUNNEL_IP6_DST])
		tun_info->key.u.ipv6.dst = nla_get_in6_addr(tb[LWTUNNEL_IP6_DST]);

	if (tb[LWTUNNEL_IP6_SRC])
		tun_info->key.u.ipv6.src = nla_get_in6_addr(tb[LWTUNNEL_IP6_SRC]);

	if (tb[LWTUNNEL_IP6_HOPLIMIT])
		tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP6_HOPLIMIT]);

	if (tb[LWTUNNEL_IP6_TC])
		tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP6_TC]);

	if (tb[LWTUNNEL_IP6_FLAGS])
		tun_info->key.tun_flags = nla_get_u16(tb[LWTUNNEL_IP6_FLAGS]);

	tun_info->mode = IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6;
	tun_info->options_len = 0;

	*ts = new_state;

	return 0;
}
Esempio n. 20
0
static int bridge_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
				 void *data)
{
	struct bridge_data *bd = data;
	struct nlattr *br_attrs[IFLA_BRPORT_MAX+1];
	int err;

	/* Backwards compatibility */
	if (!nla_is_nested(attr)) {
		if (nla_len(attr) < 1)
			return -NLE_RANGE;

		bd->b_port_state = nla_get_u8(attr);
		bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;

		return 0;
	}

	if ((err = nla_parse_nested(br_attrs, IFLA_BRPORT_MAX, attr,
	     br_attrs_policy)) < 0)
		return err;

	bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS;

	if (br_attrs[IFLA_BRPORT_STATE]) {
		bd->b_port_state = nla_get_u8(br_attrs[IFLA_BRPORT_STATE]);
		bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
	}

	if (br_attrs[IFLA_BRPORT_PRIORITY]) {
		bd->b_priority = nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]);
		bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
	}

	if (br_attrs[IFLA_BRPORT_COST]) {
		bd->b_cost = nla_get_u32(br_attrs[IFLA_BRPORT_COST]);
		bd->ce_mask |= BRIDGE_ATTR_COST;
	}

	check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE);
	check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD);
	check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK);
	check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE);

	return 0;
}
Esempio n. 21
0
static struct vport *stt_tnl_create(const struct vport_parms *parms)
{
	struct net *net = ovs_dp_get_net(parms->dp);
	struct nlattr *options = parms->options;
	struct stt_port *stt_port;
	struct stt_sock *stt_sock;
	struct vport *vport;
	struct nlattr *a;
	int err;
	u16 dst_port;

	if (!options) {
		err = -EINVAL;
		goto error;
	}

	a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT);
	if (a && nla_len(a) == sizeof(u16)) {
		dst_port = nla_get_u16(a);
	} else {
		/* Require destination port from userspace. */
		err = -EINVAL;
		goto error;
	}

	vport = ovs_vport_alloc(sizeof(struct stt_port),
				&ovs_stt_vport_ops, parms);
	if (IS_ERR(vport))
		return vport;

	stt_port = stt_vport(vport);
	strncpy(stt_port->name, parms->name, IFNAMSIZ);

	stt_sock = stt_sock_add(net, htons(dst_port), stt_rcv, vport);
	if (IS_ERR(stt_sock)) {
		ovs_vport_free(vport);
		return ERR_CAST(stt_sock);
	}
	stt_port->stt_sock = stt_sock;

	return vport;
error:
	return ERR_PTR(err);
}
Esempio n. 22
0
static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
			       struct nlattr *tb[], struct nlattr *data[])
{
	struct net_device *pdev;
	struct ipoib_dev_priv *ppriv;
	u16 child_pkey;
	int err;

	if (!tb[IFLA_LINK])
		return -EINVAL;

	pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
	if (!pdev)
		return -ENODEV;

	ppriv = netdev_priv(pdev);

	if (test_bit(IPOIB_FLAG_SUBINTERFACE, &ppriv->flags)) {
		ipoib_warn(ppriv, "child creation disallowed for child devices\n");
		return -EINVAL;
	}

	if (!data || !data[IFLA_IPOIB_PKEY]) {
		ipoib_dbg(ppriv, "no pkey specified, using parent pkey\n");
		child_pkey  = ppriv->pkey;
	} else
		child_pkey  = nla_get_u16(data[IFLA_IPOIB_PKEY]);

	if (child_pkey == 0 || child_pkey == 0x8000)
		return -EINVAL;

	/*
	 * Set the full membership bit, so that we join the right
	 * broadcast group, etc.
	 */
	child_pkey |= 0x8000;

	err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD);

	if (!err && data)
		err = ipoib_changelink(dev, tb, data);
	return err;
}
Esempio n. 23
0
/*
 * iwpm_mapping_info_cb - Process a port mapper request for mapping info
 */
int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
	const char *msg_type = "Mapping Info response";
	int iwpm_pid;
	u8 nl_client;
	char *iwpm_name;
	u16 iwpm_version;
	int ret = -EINVAL;

	if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX,
				resp_mapinfo_policy, nltb, msg_type)) {
		pr_info("%s: Unable to parse nlmsg\n", __func__);
		return ret;
	}
	iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]);
	iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]);
	if (strcmp(iwpm_ulib_name, iwpm_name) ||
			iwpm_version != iwpm_ulib_version) {
		pr_info("%s: Invalid port mapper name = %s version = %d\n",
				__func__, iwpm_name, iwpm_version);
		return ret;
	}
	nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
	if (!iwpm_valid_client(nl_client)) {
		pr_info("%s: Invalid port mapper client = %d\n",
				__func__, nl_client);
		return ret;
	}
	iwpm_set_registered(nl_client, 0);
	atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
	if (!iwpm_mapinfo_available())
		return 0;
	iwpm_pid = cb->nlh->nlmsg_pid;
	pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
		 __func__, iwpm_pid);
	ret = iwpm_send_mapinfo(nl_client, iwpm_pid);
	return ret;
}
Esempio n. 24
0
static int tcf_bpf_init_from_ops(struct nlattr **tb, struct tcf_bpf_cfg *cfg)
{
	struct sock_filter *bpf_ops;
	struct sock_fprog_kern fprog_tmp;
	struct bpf_prog *fp;
	u16 bpf_size, bpf_num_ops;
	int ret;

	bpf_num_ops = nla_get_u16(tb[TCA_ACT_BPF_OPS_LEN]);
	if (bpf_num_ops	> BPF_MAXINSNS || bpf_num_ops == 0)
		return -EINVAL;

	bpf_size = bpf_num_ops * sizeof(*bpf_ops);
	if (bpf_size != nla_len(tb[TCA_ACT_BPF_OPS]))
		return -EINVAL;

	bpf_ops = kzalloc(bpf_size, GFP_KERNEL);
	if (bpf_ops == NULL)
		return -ENOMEM;

	memcpy(bpf_ops, nla_data(tb[TCA_ACT_BPF_OPS]), bpf_size);

	fprog_tmp.len = bpf_num_ops;
	fprog_tmp.filter = bpf_ops;

	ret = bpf_prog_create(&fp, &fprog_tmp);
	if (ret < 0) {
		kfree(bpf_ops);
		return ret;
	}

	cfg->bpf_ops = bpf_ops;
	cfg->bpf_num_ops = bpf_num_ops;
	cfg->filter = fp;
	cfg->is_ebpf = false;

	return 0;
}
Esempio n. 25
0
static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb,
                        u32 pid, u32 seq, u16 flags)
{
	int ret = -EINVAL;
	u16 id;
	u8 up, idtype;
	struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1];

	if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp)
		goto out;

	ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP],
	                       dcbnl_app_nest);
	if (ret)
		goto out;

	ret = -EINVAL;
	/* all must be non-null */
	if ((!app_tb[DCB_APP_ATTR_IDTYPE]) ||
	    (!app_tb[DCB_APP_ATTR_ID]) ||
	    (!app_tb[DCB_APP_ATTR_PRIORITY]))
		goto out;

	/* either by eth type or by socket number */
	idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]);
	if ((idtype != DCB_APP_IDTYPE_ETHTYPE) &&
	    (idtype != DCB_APP_IDTYPE_PORTNUM))
		goto out;

	id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]);
	up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]);

	ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up),
	                  RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP,
	                  pid, seq, flags);
out:
	return ret;
}
static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
{
	struct ifla_vlan_flags *flags;
	u16 id;
	int err;

	if (tb[IFLA_ADDRESS]) {
		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
			return -EINVAL;
		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
			return -EADDRNOTAVAIL;
	}

	if (!data)
		return -EINVAL;

	if (data[IFLA_VLAN_ID]) {
		id = nla_get_u16(data[IFLA_VLAN_ID]);
		if (id >= VLAN_VID_MASK)
			return -ERANGE;
	}
	if (data[IFLA_VLAN_FLAGS]) {
		flags = nla_data(data[IFLA_VLAN_FLAGS]);
		if ((flags->flags & flags->mask) &
		    ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
		      VLAN_FLAG_LOOSE_BINDING))
			return -EINVAL;
	}

	err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
	if (err < 0)
		return err;
	err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
	if (err < 0)
		return err;
	return 0;
}
Esempio n. 27
0
static int ieee802154_disassociate_req(struct sk_buff *skb,
		struct genl_info *info)
{
	struct net_device *dev;
	struct ieee802154_addr addr;
	int ret = -EOPNOTSUPP;

	if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] &&
		!info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) ||
	    !info->attrs[IEEE802154_ATTR_REASON])
		return -EINVAL;

	dev = ieee802154_nl_get_dev(info);
	if (!dev)
		return -ENODEV;
	if (!ieee802154_mlme_ops(dev)->disassoc_req)
		goto out;

	if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
		addr.addr_type = IEEE802154_ADDR_LONG;
		nla_memcpy(addr.hwaddr,
				info->attrs[IEEE802154_ATTR_DEST_HW_ADDR],
				IEEE802154_ADDR_LEN);
	} else {
		addr.addr_type = IEEE802154_ADDR_SHORT;
		addr.short_addr = nla_get_u16(
				info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]);
	}
	addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);

	ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr,
			nla_get_u8(info->attrs[IEEE802154_ATTR_REASON]));

out:
	dev_put(dev);
	return ret;
}
Esempio n. 28
0
static int handle_wiphy(struct netlink_config_s *nlcfg, struct nl_msg *msg, void *arg)
{
    struct nlattr *tb[NL80211_ATTR_MAX + 1];
    struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
    struct nlattr *nl_band;
    struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    struct ieee80211_band *lband;
    int rem_band;
    int bandidx = -1;

    nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
            genlmsg_attrlen(gnlh, 0), NULL);

    if (!tb[NL80211_ATTR_WIPHY_BANDS])
        return -1;

    nla_for_each_nested(nl_band, tb[NL80211_ATTR_WIPHY_BANDS], rem_band) {
        bandidx++;
        if (!nl_band)
            continue;

        nla_parse(tb_band, NL80211_BAND_ATTR_MAX,
                  nla_data(nl_band), nla_len(nl_band), NULL);

        lband = &nlcfg->bands[bandidx];
        if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET]) {
            assert(sizeof(lband->ht_cap.mcs) == nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]));
            lband->ht_cap.ht_supported = true;
            memcpy(&lband->ht_cap.mcs,
                   nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]),
                   nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]));
            lband->ht_cap.cap = nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]);
            lband->ht_cap.ampdu_factor = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]);
            lband->ht_cap.ampdu_density = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]);
        }
        /* TODO: get rates */
    }
static int vlan_parse(struct rtnl_link *link, struct nlattr *data,
		      struct nlattr *xstats)
{
	struct nlattr *tb[IFLA_VLAN_MAX+1];
	struct vlan_info *vi;
	int err;

	NL_DBG(3, "Parsing VLAN link info");

	if ((err = nla_parse_nested(tb, IFLA_VLAN_MAX, data, vlan_policy)) < 0)
		goto errout;

	if ((err = vlan_alloc(link)) < 0)
		goto errout;

	vi = link->l_info;

	if (tb[IFLA_VLAN_ID]) {
		vi->vi_vlan_id = nla_get_u16(tb[IFLA_VLAN_ID]);
		vi->vi_mask |= VLAN_HAS_ID;
	}

	if (tb[IFLA_VLAN_FLAGS]) {
		struct ifla_vlan_flags flags;
		nla_memcpy(&flags, tb[IFLA_VLAN_FLAGS], sizeof(flags));

		vi->vi_flags = flags.flags;
		vi->vi_mask |= VLAN_HAS_FLAGS;
	}

	if (tb[IFLA_VLAN_INGRESS_QOS]) {
		struct ifla_vlan_qos_mapping *map;
		struct nlattr *nla;
		int remaining;

		memset(vi->vi_ingress_qos, 0, sizeof(vi->vi_ingress_qos));

		nla_for_each_nested(nla, tb[IFLA_VLAN_INGRESS_QOS], remaining) {
			if (nla_len(nla) < sizeof(*map))
				return nl_error(EINVAL, "Malformed mapping");

			map = nla_data(nla);
			if (map->from < 0 || map->from > VLAN_PRIO_MAX) {
				return nl_error(EINVAL, "VLAN prio %d out of "
						"range", map->from);
			}

			vi->vi_ingress_qos[map->from] = map->to;
		}

		vi->vi_mask |= VLAN_HAS_INGRESS_QOS;
	}

	if (tb[IFLA_VLAN_EGRESS_QOS]) {
		struct ifla_vlan_qos_mapping *map;
		struct nlattr *nla;
		int remaining, i = 0;

		nla_for_each_nested(nla, tb[IFLA_VLAN_EGRESS_QOS], remaining) {
			if (nla_len(nla) < sizeof(*map))
				return nl_error(EINVAL, "Malformed mapping");
			i++;
		}

		/* align to have a little reserve */
		vi->vi_egress_size = (i + 32) & ~31;
		vi->vi_egress_qos = calloc(vi->vi_egress_size, sizeof(*map));
		if (vi->vi_egress_qos == NULL)
			return nl_errno(ENOMEM);

		i = 0;
		nla_for_each_nested(nla, tb[IFLA_VLAN_EGRESS_QOS], remaining) {
			map = nla_data(nla);
			NL_DBG(4, "Assigning egress qos mapping %d\n", i);
			vi->vi_egress_qos[i].vm_from = map->from;
			vi->vi_egress_qos[i++].vm_to = map->to;
		}

		vi->vi_negress = i;
		vi->vi_mask |= VLAN_HAS_EGRESS_QOS;
	}
Esempio n. 30
0
static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
		    const char **helper, bool log)
{
	struct nlattr *a;
	int rem;

	nla_for_each_nested(a, attr, rem) {
		int type = nla_type(a);
		int maxlen = ovs_ct_attr_lens[type].maxlen;
		int minlen = ovs_ct_attr_lens[type].minlen;

		if (type > OVS_CT_ATTR_MAX) {
			OVS_NLERR(log,
				  "Unknown conntrack attr (type=%d, max=%d)",
				  type, OVS_CT_ATTR_MAX);
			return -EINVAL;
		}
		if (nla_len(a) < minlen || nla_len(a) > maxlen) {
			OVS_NLERR(log,
				  "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)",
				  type, nla_len(a), maxlen);
			return -EINVAL;
		}

		switch (type) {
		case OVS_CT_ATTR_COMMIT:
			info->commit = true;
			break;
#ifdef CONFIG_NF_CONNTRACK_ZONES
		case OVS_CT_ATTR_ZONE:
			info->zone.id = nla_get_u16(a);
			break;
#endif
#ifdef CONFIG_NF_CONNTRACK_MARK
		case OVS_CT_ATTR_MARK: {
			struct md_mark *mark = nla_data(a);

			if (!mark->mask) {
				OVS_NLERR(log, "ct_mark mask cannot be 0");
				return -EINVAL;
			}
			info->mark = *mark;
			break;
		}
#endif
#ifdef CONFIG_NF_CONNTRACK_LABELS
		case OVS_CT_ATTR_LABELS: {
			struct md_labels *labels = nla_data(a);

			if (!labels_nonzero(&labels->mask)) {
				OVS_NLERR(log, "ct_labels mask cannot be 0");
				return -EINVAL;
			}
			info->labels = *labels;
			break;
		}
#endif
		case OVS_CT_ATTR_HELPER:
			*helper = nla_data(a);
			if (!memchr(*helper, '\0', nla_len(a))) {
				OVS_NLERR(log, "Invalid conntrack helper");
				return -EINVAL;
			}
			break;
		default:
			OVS_NLERR(log, "Unknown conntrack attr (%d)",
				  type);
			return -EINVAL;
		}
	}