static int icmpv6_nlattr_to_tuple(struct nlattr *tb[], struct nf_conntrack_tuple *tuple) { if (!tb[CTA_PROTO_ICMPV6_TYPE] || !tb[CTA_PROTO_ICMPV6_CODE] || !tb[CTA_PROTO_ICMPV6_ID]) return -EINVAL; tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]); tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]); tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMPV6_ID]); if (tuple->dst.u.icmp.type < 128 || tuple->dst.u.icmp.type - 128 >= sizeof(invmap) || !invmap[tuple->dst.u.icmp.type - 128]) return -EINVAL; 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]); 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 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; }
/* Set/clear or port flags based on attribute */ static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[], int attrtype, unsigned long mask) { if (tb[attrtype]) { u8 flag = nla_get_u8(tb[attrtype]); if (flag) p->flags |= mask; else p->flags &= ~mask; } }
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 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; u8 page; 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]); if (info->attrs[IEEE802154_ATTR_PAGE]) page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); else page = 0; if (addr.short_addr == IEEE802154_ADDR_BROADCAST) { ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); dev_put(dev); return -EINVAL; } ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, bcn_ord, sf_ord, pan_coord, blx, coord_realign); dev_put(dev); return ret; }
static void ipgre_netlink_parms(struct nlattr *data[], struct nlattr *tb[], struct ip_tunnel_parm *parms) { memset(parms, 0, sizeof(*parms)); parms->iph.protocol = IPPROTO_GRE; if (!data) return; if (data[IFLA_GRE_LINK]) parms->link = nla_get_u32(data[IFLA_GRE_LINK]); if (data[IFLA_GRE_IFLAGS]) parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); if (data[IFLA_GRE_OFLAGS]) parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); if (data[IFLA_GRE_IKEY]) parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); if (data[IFLA_GRE_OKEY]) parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); if (data[IFLA_GRE_LOCAL]) parms->iph.saddr = nla_get_be32(data[IFLA_GRE_LOCAL]); if (data[IFLA_GRE_REMOTE]) parms->iph.daddr = nla_get_be32(data[IFLA_GRE_REMOTE]); if (data[IFLA_GRE_TTL]) parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); if (data[IFLA_GRE_TOS]) parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) parms->iph.frag_off = htons(IP_DF); }
//scan netlink messages are nested (and may even be multipart) (see nl80211.c line 2591: nl80211_send_bss) int CNL80211::parseNlScanResult(nl_msg * msg) { struct nlattr * attr_buffer[NL80211_ATTR_MAX + 1]; struct nlmsghdr * msg_hdr = nlmsg_hdr(msg); struct genlmsghdr * msg_header = (struct genlmsghdr *) nlmsg_data(msg_hdr); struct nlattr * bss_buffer[NL80211_BSS_MAX + 1]; //bss = basic service set ScanResult scanresult; //This is the struct to check the validity of the attributes. See enum nl80211_bss struct nla_policy bss_policy[NL80211_BSS_MAX + 1]; bss_policy[NL80211_BSS_TSF].type = NLA_U64; bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32; bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16; bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32; bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8; if (msg_hdr->nlmsg_flags & NLM_F_MULTI) qDebug() << "netlink: Mutlipart message"; //Parse the complete message nla_parse(attr_buffer, NL80211_ATTR_MAX, genlmsg_attrdata(msg_header, 0), genlmsg_attrlen(msg_header, 0), NULL); if (!attr_buffer[NL80211_ATTR_BSS]) { //Check if BSS return NL_SKIP; } //Parse the nested attributes. this is where the scan results are if (nla_parse_nested(bss_buffer, NL80211_BSS_MAX, attr_buffer[NL80211_ATTR_BSS], bss_policy)) { return NL_SKIP; } if (!bss_buffer[NL80211_BSS_BSSID]) return NL_SKIP; scanresult.bssid = libnutcommon::MacAddress((ether_addr*)(bss_buffer[NL80211_BSS_BSSID])); scanresult.signal.bssid = scanresult.bssid; if (bss_buffer[NL80211_BSS_FREQUENCY]) scanresult.freq = nla_get_u32(bss_buffer[NL80211_BSS_FREQUENCY]); if (bss_buffer[NL80211_BSS_SIGNAL_MBM]) { scanresult.signal.type = WSR_RCPI; scanresult.signal.quality.value = nla_get_u32(bss_buffer[NL80211_BSS_SIGNAL_MBM])/100; } if (bss_buffer[NL80211_BSS_SIGNAL_UNSPEC]) { scanresult.signal.type = WSR_UNKNOWN; scanresult.signal.quality.value = nla_get_u8(bss_buffer[NL80211_BSS_SIGNAL_UNSPEC]); } // if (bss_buffer[NL80211_BSS_INFORMATION_ELEMENTS]) // print_ies(nla_data(bss_buffer[NL80211_BSS_INFORMATION_ELEMENTS]), // nla_len(bss_buffer[NL80211_BSS_INFORMATION_ELEMENTS]), // params->unknown, params->type); m_scanResults.push_back(scanresult); return NL_SKIP; }
/* * Change state of port (ie from forwarding to blocking etc) * Used by spanning tree in user space. */ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct net *net = sock_net(skb->sk); struct ifinfomsg *ifm; struct nlattr *protinfo; struct net_device *dev; struct net_bridge_port *p; u8 new_state; if (nlmsg_len(nlh) < sizeof(*ifm)) return -EINVAL; ifm = nlmsg_data(nlh); if (ifm->ifi_family != AF_BRIDGE) return -EPFNOSUPPORT; protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO); if (!protinfo || nla_len(protinfo) < sizeof(u8)) return -EINVAL; new_state = nla_get_u8(protinfo); if (new_state > BR_STATE_BLOCKING) return -EINVAL; dev = __dev_get_by_index(net, ifm->ifi_index); if (!dev) return -ENODEV; p = br_port_get_rtnl(dev); if (!p) return -EINVAL; /* if kernel STP is running, don't allow changes */ if (p->br->stp_enabled == BR_KERNEL_STP) return -EBUSY; if (!netif_running(dev) || (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)) return -ENETDOWN; p->state = new_state; br_log_state(p); spin_lock_bh(&p->br->lock); br_port_state_selection(p->br); spin_unlock_bh(&p->br->lock); br_ifinfo_notify(RTM_NEWLINK, p); 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 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 tunnel_key_copy_geneve_opt(const struct nlattr *nla, void *dst, int dst_len, struct netlink_ext_ack *extack) { struct nlattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1]; int err, data_len, opt_len; u8 *data; err = nla_parse_nested(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, nla, geneve_opt_policy, extack); if (err < 0) return err; if (!tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS] || !tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE] || !tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]) { NL_SET_ERR_MSG(extack, "Missing tunnel key geneve option class, type or data"); return -EINVAL; } data = nla_data(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]); data_len = nla_len(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]); if (data_len < 4) { NL_SET_ERR_MSG(extack, "Tunnel key geneve option data is less than 4 bytes long"); return -ERANGE; } if (data_len % 4) { NL_SET_ERR_MSG(extack, "Tunnel key geneve option data is not a multiple of 4 bytes long"); return -ERANGE; } opt_len = sizeof(struct geneve_opt) + data_len; if (dst) { struct geneve_opt *opt = dst; WARN_ON(dst_len < opt_len); opt->opt_class = nla_get_be16(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS]); opt->type = nla_get_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE]); opt->length = data_len / 4; /* length is in units of 4 bytes */ opt->r1 = 0; opt->r2 = 0; opt->r3 = 0; memcpy(opt + 1, data, data_len); } return opt_len; }
static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) { struct nlattr *attr = cda[CTA_PROTOINFO_DCCP]; struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1]; int err; if (!attr) return 0; err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr, dccp_nla_policy); if (err < 0) return err; if (!tb[CTA_PROTOINFO_DCCP_STATE] || nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) return -EINVAL; write_lock_bh(&dccp_lock); ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); write_unlock_bh(&dccp_lock); return 0; }
static int ipip_tunnel_validate(struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { u8 proto; if (!data || !data[IFLA_IPTUN_PROTO]) return 0; proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); if (proto != IPPROTO_IPIP && proto != IPPROTO_MPLS && proto != 0) return -EINVAL; return 0; }
static iz_res_t scan_response(struct iz_cmd *cmd, struct genlmsghdr *ghdr, struct nlattr **attrs) { uint8_t status, type; int i; uint8_t edl[27]; if (!attrs[IEEE802154_ATTR_DEV_INDEX] || !attrs[IEEE802154_ATTR_STATUS] || !attrs[IEEE802154_ATTR_SCAN_TYPE]) return IZ_STOP_ERR; status = nla_get_u8(attrs[IEEE802154_ATTR_STATUS]); if (status != 0) printf("Scan failed: %02x\n", status); type = nla_get_u8(attrs[IEEE802154_ATTR_SCAN_TYPE]); switch (type) { case IEEE802154_MAC_SCAN_ED: if (!attrs[IEEE802154_ATTR_ED_LIST]) return IZ_STOP_ERR; nla_memcpy(edl, attrs[IEEE802154_ATTR_ED_LIST], 27); printf("ED Scan results:\n"); for (i = 0; i < 27; i++) printf(" Ch%2d --- ED = %02x\n", i, edl[i]); return IZ_STOP_OK; case IEEE802154_MAC_SCAN_ACTIVE: printf("Started active (beacons) scan...\n"); return IZ_CONT_OK; default: printf("Unsupported scan type: %d\n", type); break; } return IZ_STOP_OK; }
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 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 nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) { struct nlattr *attr = cda[CTA_PROTOINFO_DCCP]; struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1]; int err; if (!attr) return 0; err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr, dccp_nla_policy); if (err < 0) return err; if (!tb[CTA_PROTOINFO_DCCP_STATE] || !tb[CTA_PROTOINFO_DCCP_ROLE] || nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) > CT_DCCP_ROLE_MAX || nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) { return -EINVAL; } spin_lock_bh(&ct->lock); ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) { ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT; ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER; } else { ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER; ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT; } if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) { ct->proto.dccp.handshake_seq = be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ])); } spin_unlock_bh(&ct->lock); return 0; }
static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) { struct net_device *dev; int ret = -EOPNOTSUPP; u8 type; u32 channels; u8 duration; u8 page; if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] || !info->attrs[IEEE802154_ATTR_CHANNELS] || !info->attrs[IEEE802154_ATTR_DURATION]) return -EINVAL; dev = ieee802154_nl_get_dev(info); if (!dev) return -ENODEV; if (!ieee802154_mlme_ops(dev)->scan_req) goto out; type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]); channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]); duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]); if (info->attrs[IEEE802154_ATTR_PAGE]) page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); else page = 0; ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page, duration); out: dev_put(dev); return ret; }
static iz_res_t set_response(struct iz_cmd *cmd, struct genlmsghdr *ghdr, struct nlattr **attrs) { uint8_t status; if (!attrs[IEEE802154_ATTR_STATUS]) return IZ_STOP_ERR; status = nla_get_u8(attrs[IEEE802154_ATTR_STATUS]); if (status != 0) { printf("Operation Failed. Check channel and PAN ID\n"); return IZ_STOP_ERR; } return IZ_STOP_OK; }
static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) { int buf_len, ret, len; struct sk_buff *skb; void *buf; u8 answer = 0; wl1271_debug(DEBUG_TESTMODE, "testmode cmd test"); if (!tb[WL1271_TM_ATTR_DATA]) return -EINVAL; buf = nla_data(tb[WL1271_TM_ATTR_DATA]); buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]); if (tb[WL1271_TM_ATTR_ANSWER]) answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]); if (buf_len > sizeof(struct wl1271_command)) return -EMSGSIZE; mutex_lock(&wl->mutex); ret = wl1271_cmd_test(wl, buf, buf_len, answer); mutex_unlock(&wl->mutex); if (ret < 0) { wl1271_warning("testmode cmd test failed: %d", ret); return ret; } if (answer) { len = nla_total_size(buf_len); skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); if (!skb) return -ENOMEM; NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf); ret = cfg80211_testmode_reply(skb); if (ret < 0) return ret; } return 0; nla_put_failure: kfree_skb(skb); return -EMSGSIZE; }
/** * netlbl_unlabel_accept - Handle an ACCEPT message * @skb: the NETLINK buffer * @info: the Generic NETLINK info block * * Description: * Process a user generated ACCEPT message and set the accept flag accordingly. * Returns zero on success, negative values on failure. * */ static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) { u8 value; struct netlbl_audit audit_info; if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) { value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]); if (value == 1 || value == 0) { netlbl_netlink_auditinfo(skb, &audit_info); netlbl_unlabel_acceptflg_set(value, &audit_info); return 0; } } return -EINVAL; }
/* handler for SET messages via NETLINK */ int ipctl_set(struct sk_buff *skb, struct genl_info *info) { /* message handling code goes here; return 0 on success, negative * values on failure */ int property = nla_get_u32(info->attrs[IPCTL_ATTR_PROPERTY]); int ifIndex = nla_get_u32(info->attrs[IPCTL_ATTR_IFINDEX]); int value = nla_get_u8(info->attrs[IPCTL_ATTR_VALUE]); pr_debug("ipctl: set p=%d i=%d v=%d\n", property, ifIndex, value); if (property == IPCTL_PROPERTY_PROXYARP) return ipctl_set_proxyarp_by_ifindex(ifIndex, value); return 0; }
static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr) { struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1]; int err; err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr, ct_protoinfo_tcp_policy); if (err < 0) return err; if (tb[CTA_PROTOINFO_TCP_STATE]) nfnl_ct_set_tcp_state(ct, nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE])); return 0; }
static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb, u32 pid, u32 seq, u16 flags) { int ret = -EINVAL; u8 value; if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate) return ret; value = nla_get_u8(tb[DCB_ATTR_STATE]); ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value), RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE, pid, seq, flags); return ret; }
static int ixgbe_dcb_slink_spd(struct sk_buff *skb, struct genl_info *info) { struct net_device *netdev = NULL; struct ixgbe_adapter *adapter = NULL; int ret = -EINVAL; u8 value; if (!info->attrs[DCB_A_IFNAME] || !info->attrs[DCB_A_LINK_SPD]) goto err; netdev = dev_get_by_name(&init_net, nla_data(info->attrs[DCB_A_IFNAME])); if (!netdev) goto err; ret = ixgbe_dcb_check_adapter(netdev); if (ret) goto err_out; else adapter = netdev_priv(netdev); value = nla_get_u8(info->attrs[DCB_A_LINK_SPD]); if (value > 9) { DPRINTK(DRV, ERR, "Value is not 0 thru 9, it is %d.\n", value); } else { if (!adapter->dcb_set_bitmap && ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg, adapter->ring_feature[RING_F_DCB].indices)) { ret = -EINVAL; goto err_out; } adapter->temp_dcb_cfg.link_speed = value; adapter->dcb_set_bitmap |= BIT_LINKSPEED; } ret = ixgbe_nl_reply(0, DCB_C_SLINK_SPD, DCB_A_LINK_SPD, info); if (ret) goto err_out; err_out: dev_put(netdev); err: return ret; }
/* * Change state of port (ie from forwarding to blocking etc) * Used by spanning tree in user space. */ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct ifinfomsg *ifm; struct nlattr *protinfo; struct net_device *dev; struct net_bridge_port *p; u8 new_state; if (nlmsg_len(nlh) < sizeof(*ifm)) return -EINVAL; ifm = nlmsg_data(nlh); if (ifm->ifi_family != AF_BRIDGE) return -EPFNOSUPPORT; protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO); if (!protinfo || nla_len(protinfo) < sizeof(u8)) return -EINVAL; new_state = nla_get_u8(protinfo); if (new_state > BR_STATE_BLOCKING) return -EINVAL; dev = __if_dev_get_by_index(ifm->ifi_index); if (!dev) return -ENODEV; p = dev->br_port; if (!p) return -EINVAL; /* if kernel STP is running, don't allow changes */ if (p->br->stp_enabled) return -EBUSY; if (!if_dev_admin_up(dev) || (!if_dev_running(dev) && new_state != BR_STATE_DISABLED)) return -ENETDOWN; p->state = new_state; br_log_state(p); return 0; }
static int save_attribute_handler(struct nl_msg *msg, void *arg) { struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); const char *name = "N/A"; struct wprobe_attribute *attr; int type = 0; struct wprobe_attr_cb *cb = arg; nla_parse(tb, WPROBE_ATTR_LAST, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), attribute_policy); if (tb[WPROBE_ATTR_NAME]) name = nla_data(tb[WPROBE_ATTR_NAME]); attr = malloc(sizeof(struct wprobe_attribute) + strlen(name) + 1); if (!attr) return -1; memset(attr, 0, sizeof(struct wprobe_attribute)); if (tb[WPROBE_ATTR_ID]) attr->id = nla_get_u32(tb[WPROBE_ATTR_ID]); if (tb[WPROBE_ATTR_MAC] && cb->addr) memcpy(cb->addr, nla_data(tb[WPROBE_ATTR_MAC]), 6); if (tb[WPROBE_ATTR_FLAGS]) attr->flags = nla_get_u32(tb[WPROBE_ATTR_FLAGS]); if (tb[WPROBE_ATTR_TYPE]) type = nla_get_u8(tb[WPROBE_ATTR_TYPE]); if ((type < WPROBE_VAL_STRING) || (type > WPROBE_VAL_U64)) type = 0; attr->type = type; strcpy(attr->name, name); INIT_LIST_HEAD(&attr->list); list_add(&attr->list, cb->list); return 0; }
/* * This function handles the user application switch ucode ownership. * * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and * decide who the current owner of the uCode * * If the current owner is OWNERSHIP_TM, then the only host command * can deliver to uCode is from testmode, all the other host commands * will dropped. * * default driver is the owner of uCode in normal operational mode * * @hw: ieee80211_hw object that represents the device * @tb: gnl message fields from the user space */ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) { struct iwl_priv *priv = hw->priv; u8 owner; if (!tb[IWL_TM_ATTR_UCODE_OWNER]) { IWL_DEBUG_INFO(priv, "Error finding ucode owner\n"); return -ENOMSG; } owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) priv->shrd->ucode_owner = owner; else { IWL_DEBUG_INFO(priv, "Invalid owner\n"); return -EINVAL; } return 0; }
static int nfc_netlink_event_adapter(struct genlmsghdr *gnlh, bool add) { struct nlattr *attrs[NFC_ATTR_MAX + 1]; uint32_t idx; DBG(""); nla_parse(attrs, NFC_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (!attrs[NFC_ATTR_DEVICE_INDEX]) { near_error("Missing device index"); return -ENODEV; } idx = nla_get_u32(attrs[NFC_ATTR_DEVICE_INDEX]); if (add && (!attrs[NFC_ATTR_DEVICE_NAME] || !attrs[NFC_ATTR_PROTOCOLS])) { near_error("Missing attributes"); return -EINVAL; } if (add) { char *name; uint32_t protocols; bool powered; name = nla_get_string(attrs[NFC_ATTR_DEVICE_NAME]); protocols = nla_get_u32(attrs[NFC_ATTR_PROTOCOLS]); if (!attrs[NFC_ATTR_DEVICE_POWERED]) powered = false; else powered = nla_get_u8(attrs[NFC_ATTR_DEVICE_POWERED]); return __near_manager_adapter_add(idx, name, protocols, powered); } else { __near_manager_adapter_remove(idx); } return 0; }