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; }
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; }
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; }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
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; }
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); }
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; }
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; }
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; }
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); }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
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; } }