int reply_ca(struct sk_buff *skb_2, struct genl_info *info) { struct sk_buff *skb; void *msg_head; int ret; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) printk("reply_ca %d\n", info->snd_pid); #else printk("reply_ca %d\n", info->snd_portid); #endif if (!info) goto out; skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) goto out; msg_head = genlmsg_put(skb, 0, info->snd_seq, &ca_family, 0, CMD_ASK_CA_SIZE); if (!msg_head) { goto out; } ret = nla_put_u32(skb, ATTR_CA_SIZE, devices_counter); if (ret) goto out; genlmsg_end(skb, msg_head); #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) ret = genlmsg_unicast(&init_net, skb, info->snd_pid ); #else ret = genlmsg_unicast(&init_net, skb, info->snd_portid ); #endif if (ret) goto out; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) processPid = info->snd_pid; #else processPid = info->snd_portid; #endif return 0; out: printk("dvbsoftwareca: reply_ca error\n"); return 0; }
static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) { struct sk_buff *msg; void *hdr; int ret = -ENOBUFS; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) { ret = -ENOMEM; goto out; } hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &l2tp_nl_family, 0, L2TP_CMD_NOOP); if (IS_ERR(hdr)) { ret = PTR_ERR(hdr); goto err_out; } genlmsg_end(msg, hdr); return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid); err_out: nlmsg_free(msg); out: return ret; }
static int handle_cmd(struct sk_buff *skb, struct genl_info *info) { struct sk_buff *rep_buf; struct nlmsghdr *rep_nlh; struct nlmsghdr *req_nlh = info->nlhdr; struct tipc_genlmsghdr *req_userhdr = info->userhdr; int hdr_space = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN); u16 cmd; if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN))) cmd = TIPC_CMD_NOT_NET_ADMIN; else cmd = req_userhdr->cmd; rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd, nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), hdr_space); if (rep_buf) { skb_push(rep_buf, hdr_space); rep_nlh = nlmsg_hdr(rep_buf); memcpy(rep_nlh, req_nlh, hdr_space); rep_nlh->nlmsg_len = rep_buf->len; genlmsg_unicast(&init_net, rep_buf, NETLINK_CB(skb).portid); } return 0; }
int netlink_send_cw(unsigned char ca_num, ca_descr_t *ca_descr) { struct sk_buff *skb; void *msg_head; int ret; skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) goto out; msg_head = genlmsg_put(skb, 0, 0, &ca_family, 0, CMD_SET_CW); if (!msg_head) { goto out; } ret = nla_put_u16(skb, ATTR_CA_NUM, ca_num); if (ret) goto out; ret = nla_put(skb, ATTR_CA_DESCR, sizeof(ca_descr_t), ca_descr); if (ret) goto out; genlmsg_end(skb, msg_head); ret = genlmsg_unicast(&init_net, skb, processPid ); if (ret) goto out; return 0; out: printk("dvbsoftwareca: send_cw error\n"); return 0; }
int genl_exec(genl_exec_func_t func, void *data) { int ret; mutex_lock(&genl_exec_lock); init_completion(&done); skb_get(genlmsg_skb); genlmsg_put(genlmsg_skb, 0, 0, &genl_exec_family, NLM_F_REQUEST, GENL_EXEC_RUN); genl_exec_function = func; genl_exec_data = data; /* There is no need to send msg to current namespace. */ ret = genlmsg_unicast(&init_net, genlmsg_skb, 0); if (!ret) { wait_for_completion(&done); ret = genl_exec_function_ret; } else { pr_err("genl_exec send error %d\n", ret); } /* Wait for genetlink to kfree skb. */ while (skb_shared(genlmsg_skb)) cpu_relax(); genlmsg_skb->data = genlmsg_skb->head; skb_reset_tail_pointer(genlmsg_skb); mutex_unlock(&genl_exec_lock); return ret; }
char stp_dbg_nl_send( char * aucMsg, unsigned char cmd ) { struct sk_buff *skb = NULL; void *msg_head = NULL; int rc = -1; int i; if(num_bind_process == 0) { /* no listening process */ STP_DBG_ERR_FUNC("%s(): the process is not invoked\n", __func__); return 0; } for(i = 0 ; i < num_bind_process ; i++) { skb = genlmsg_new(2048, GFP_KERNEL); if(skb) { msg_head = genlmsg_put(skb, 0, stp_dbg_seqnum++, &stp_dbg_gnl_family, 0, cmd); if(msg_head == NULL) { nlmsg_free(skb); STP_DBG_ERR_FUNC("%s(): genlmsg_put fail...\n", __func__); return -1; } rc = nla_put_string(skb, STP_DBG_ATTR_MSG, aucMsg); if(rc != 0) { nlmsg_free(skb); STP_DBG_ERR_FUNC("%s(): nla_put_string fail...\n", __func__); return -1; } /* finalize the message */ genlmsg_end(skb, msg_head); /* sending message */ rc = genlmsg_unicast(&init_net, skb, bind_pid[i]); if(rc != 0) { STP_DBG_ERR_FUNC("%s(): genlmsg_unicast fail...\n", __func__); return -1; } } else { STP_DBG_ERR_FUNC("%s(): genlmsg_new fail...\n", __func__); return -1; } } return 0; }
int kg2_genl_system_is_resumed(void) { int ret = 0; void * hdr; struct sk_buff * msg; msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (msg == NULL) { return -ENOMEM; } // Create Generic Netlink message header hdr = genlmsg_put(msg, g_daemon_pid, 0, &kg2_genl_family, NLM_F_REQUEST, KG2_GENL_EVT_SYSTEM_IS_RESUMED); if (hdr == NULL) { ret = -EMSGSIZE; goto err; } // Finalize the message genlmsg_end(msg, hdr); // Send the message ret = genlmsg_unicast(&init_net, msg, g_daemon_pid); return ret; err: nlmsg_free(msg); return ret; }
static int l2tp_nl_cmd_session_get(struct sk_buff *skb, struct genl_info *info) { struct l2tp_session *session; struct sk_buff *msg; int ret; session = l2tp_nl_session_find(info); if (session == NULL) { ret = -ENODEV; goto out; } msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) { ret = -ENOMEM; goto out; } ret = l2tp_nl_session_send(msg, info->snd_pid, info->snd_seq, 0, session); if (ret < 0) goto err_out; return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid); err_out: nlmsg_free(msg); out: return ret; }
static int send_data(struct sk_buff *skb) { struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); void *data = genlmsg_data(genlhdr); genlmsg_end(skb, data); return genlmsg_unicast(&init_net, skb, listener_nlportid); }
/* * @pid:用户进行id @data:发送数据缓冲区 @data_len:缓冲区长度 */ static int genlnet_msg_send(int pid, char *data, uint32_t data_len) { char buf[MAX_STR_LEN]; void *msg; int ret; size_t size; struct sk_buff *skb; struct genlmsghdr *genlhdr; void *reply; memcpy(buf, data, data_len); size = nla_total_size(data_len) + nla_total_size(0); skb = genlmsg_new(size, GFP_KERNEL); if (skb == NULL) { printk("%s %d\n", __func__, __LINE__); return -1; } msg = genlmsg_put(skb, 0, 0, &genlnet_family, 0, MSG_CMD_NOTIFY); if (msg == NULL) { printk("%s %d\n", __func__, __LINE__); goto err; } ret = nla_put(skb, MSG_CMD, data_len, data); if (ret < 0) { printk("%s %d, ret = %d\n", __func__, __LINE__, ret); goto err; } genlhdr = nlmsg_data(nlmsg_hdr(skb)); reply = genlmsg_data(genlhdr); ret = genlmsg_end(skb, reply); if (ret < 0) { printk("%s %d, ret = %d\n", __func__, __LINE__, ret); goto err; } ret = genlmsg_unicast(&init_net, skb, pid); if (ret < 0) { printk("%s %d, ret = %d\n", __func__, __LINE__, ret); goto err; } return 0; err: //nlmsg_free(skb); return -1; }
static int send_data(struct sk_buff *skb) { struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); void *data = genlmsg_data(genlhdr); int rv; rv = genlmsg_end(skb, data); if (rv < 0) { nlmsg_free(skb); return rv; } return genlmsg_unicast(&init_net, skb, listener_nlpid); }
/*----------------------------------------------------------------------------*/ static BOOLEAN glResetSendMessage( char * aucMsg, u8 cmd ) { struct sk_buff *skb = NULL; void *msg_head = NULL; int rc = -1; int i; if(num_bind_process == 0) { /* no listening process */ return FALSE; } for(i = 0 ; i < num_bind_process ; i++) { skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if(skb) { msg_head = genlmsg_put(skb, 0, mtk_wifi_seqnum++, &mtk_wifi_gnl_family, 0, cmd); if(msg_head == NULL) { nlmsg_free(skb); return FALSE; } rc = nla_put_string(skb, MTK_WIFI_ATTR_MSG, aucMsg); if(rc != 0) { nlmsg_free(skb); return FALSE; } /* finalize the message */ genlmsg_end(skb, msg_head); /* sending message */ rc = genlmsg_unicast(&init_net, skb, bind_pid[i]); if(rc != 0) { return FALSE; } } else { return FALSE; } } return TRUE; }
static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info) { int err; int len; struct tipc_nl_compat_msg msg; struct nlmsghdr *req_nlh; struct nlmsghdr *rep_nlh; struct tipc_genlmsghdr *req_userhdr = info->userhdr; struct net *net = genl_info_net(info); memset(&msg, 0, sizeof(msg)); req_nlh = (struct nlmsghdr *)skb->data; msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN; msg.cmd = req_userhdr->cmd; msg.dst_sk = info->dst_sk; if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) { msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN); err = -EACCES; goto send; } len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN); if (TLV_GET_LEN(msg.req) && !TLV_OK(msg.req, len)) { msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); err = -EOPNOTSUPP; goto send; } err = tipc_nl_compat_handle(&msg); if (err == -EOPNOTSUPP) msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); else if (err == -EINVAL) msg.rep = tipc_get_err_tlv(TIPC_CFG_TLV_ERROR); send: if (!msg.rep) return err; len = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN); skb_push(msg.rep, len); rep_nlh = nlmsg_hdr(msg.rep); memcpy(rep_nlh, info->nlhdr, len); rep_nlh->nlmsg_len = msg.rep->len; genlmsg_unicast(net, msg.rep, NETLINK_CB(skb).portid); return err; }
static int l2tp_nl_cmd_tunnel_get(struct sk_buff *skb, struct genl_info *info) { struct l2tp_tunnel *tunnel; struct sk_buff *msg; u32 tunnel_id; int ret = -ENOBUFS; struct net *net = genl_info_net(info); if (!info->attrs[L2TP_ATTR_CONN_ID]) { ret = -EINVAL; goto err; } tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { ret = -ENOMEM; goto err; } tunnel = l2tp_tunnel_get(net, tunnel_id); if (!tunnel) { ret = -ENODEV; goto err_nlmsg; } ret = l2tp_nl_tunnel_send(msg, info->snd_portid, info->snd_seq, NLM_F_ACK, tunnel, L2TP_CMD_TUNNEL_GET); if (ret < 0) goto err_nlmsg_tunnel; l2tp_tunnel_dec_refcount(tunnel); return genlmsg_unicast(net, msg, info->snd_portid); err_nlmsg_tunnel: l2tp_tunnel_dec_refcount(tunnel); err_nlmsg: nlmsg_free(msg); err: return ret; }
static int l2tp_nl_cmd_tunnel_get(struct sk_buff *skb, struct genl_info *info) { struct l2tp_tunnel *tunnel; struct sk_buff *msg; u32 tunnel_id; int ret = -ENOBUFS; struct net *net = genl_info_net(info); if (!info->attrs[L2TP_ATTR_CONN_ID]) { ret = -EINVAL; goto out; } tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); tunnel = l2tp_tunnel_find(net, tunnel_id); if (tunnel == NULL) { ret = -ENODEV; goto out; } msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) { ret = -ENOMEM; goto out; } ret = l2tp_nl_tunnel_send(msg, info->snd_pid, info->snd_seq, NLM_F_ACK, tunnel); if (ret < 0) goto err_out; return genlmsg_unicast(net, msg, info->snd_pid); err_out: nlmsg_free(msg); out: return ret; }
/** * netlbl_unlabel_list - Handle a LIST message * @skb: the NETLINK buffer * @info: the Generic NETLINK info block * * Description: * Process a user generated LIST message and respond with the current status. * Returns zero on success, negative values on failure. * */ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) { int ret_val = -EINVAL; struct sk_buff *ans_skb; void *data; ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (ans_skb == NULL) goto list_failure; data = netlbl_netlink_hdr_put(ans_skb, info->snd_pid, info->snd_seq, netlbl_unlabel_gnl_family.id, 0, NLBL_UNLABEL_C_LIST); if (data == NULL) { ret_val = -ENOMEM; goto list_failure; } rcu_read_lock(); ret_val = nla_put_u8(ans_skb, NLBL_UNLABEL_A_ACPTFLG, netlabel_unlabel_acceptflg); rcu_read_unlock(); if (ret_val != 0) goto list_failure; genlmsg_end(ans_skb, data); ret_val = genlmsg_unicast(ans_skb, info->snd_pid); if (ret_val != 0) goto list_failure; return 0; list_failure: kfree(ans_skb); return ret_val; }
static int l2tp_nl_cmd_session_get(struct sk_buff *skb, struct genl_info *info) { struct l2tp_session *session; struct sk_buff *msg; int ret; session = l2tp_nl_session_get(info); if (session == NULL) { ret = -ENODEV; goto err; } msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) { ret = -ENOMEM; goto err_ref; } ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq, 0, session, L2TP_CMD_SESSION_GET); if (ret < 0) goto err_ref_msg; ret = genlmsg_unicast(genl_info_net(info), msg, info->snd_portid); l2tp_session_dec_refcount(session); return ret; err_ref_msg: nlmsg_free(msg); err_ref: l2tp_session_dec_refcount(session); err: return ret; }
/* HSR_C_GET_NODE_STATUS lets userspace query the internal HSR node table * about the status of a specific node in the network, defined by its MAC * address. * * Input: hsr ifindex, node mac address * Output: hsr ifindex, node mac address (copied from request), * age of latest frame from node over slave 1, slave 2 [ms] */ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) { /* For receiving */ struct nlattr *na; struct net_device *hsr_dev; /* For sending */ struct sk_buff *skb_out; void *msg_head; struct hsr_priv *hsr; struct hsr_port *port; unsigned char hsr_node_addr_b[ETH_ALEN]; int hsr_node_if1_age; u16 hsr_node_if1_seq; int hsr_node_if2_age; u16 hsr_node_if2_seq; int addr_b_ifindex; int res; if (!info) goto invalid; na = info->attrs[HSR_A_IFINDEX]; if (!na) goto invalid; na = info->attrs[HSR_A_NODE_ADDR]; if (!na) goto invalid; hsr_dev = __dev_get_by_index(genl_info_net(info), nla_get_u32(info->attrs[HSR_A_IFINDEX])); if (!hsr_dev) goto invalid; if (!is_hsr_master(hsr_dev)) goto invalid; /* Send reply */ skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb_out) { res = -ENOMEM; goto fail; } msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid, info->snd_seq, &hsr_genl_family, 0, HSR_C_SET_NODE_STATUS); if (!msg_head) { res = -ENOMEM; goto nla_put_failure; } res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex); if (res < 0) goto nla_put_failure; hsr = netdev_priv(hsr_dev); res = hsr_get_node_data(hsr, (unsigned char *) nla_data(info->attrs[HSR_A_NODE_ADDR]), hsr_node_addr_b, &addr_b_ifindex, &hsr_node_if1_age, &hsr_node_if1_seq, &hsr_node_if2_age, &hsr_node_if2_seq); if (res < 0) goto nla_put_failure; res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, nla_data(info->attrs[HSR_A_NODE_ADDR])); if (res < 0) goto nla_put_failure; if (addr_b_ifindex > -1) { res = nla_put(skb_out, HSR_A_NODE_ADDR_B, ETH_ALEN, hsr_node_addr_b); if (res < 0) goto nla_put_failure; res = nla_put_u32(skb_out, HSR_A_ADDR_B_IFINDEX, addr_b_ifindex); if (res < 0) goto nla_put_failure; } res = nla_put_u32(skb_out, HSR_A_IF1_AGE, hsr_node_if1_age); if (res < 0) goto nla_put_failure; res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq); if (res < 0) goto nla_put_failure; rcu_read_lock(); port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); if (port) res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX, port->dev->ifindex); rcu_read_unlock(); if (res < 0) goto nla_put_failure; res = nla_put_u32(skb_out, HSR_A_IF2_AGE, hsr_node_if2_age); if (res < 0) goto nla_put_failure; res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq); if (res < 0) goto nla_put_failure; rcu_read_lock(); port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); if (port) res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX, port->dev->ifindex); rcu_read_unlock(); if (res < 0) goto nla_put_failure; genlmsg_end(skb_out, msg_head); genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid); return 0; invalid: netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL); return 0; nla_put_failure: kfree_skb(skb_out); /* Fall through */ fail: return res; }
int kg2_genl_set_output_timing(AVC_CMD_TIMING_PARAM * timing) { int ret = 0; void * hdr; struct sk_buff * msg; msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (msg == NULL) { return -ENOMEM; } // Create Generic Netlink message header hdr = genlmsg_put(msg, g_daemon_pid, 0, &kg2_genl_family, NLM_F_REQUEST, KG2_GENL_CMD_SET_OUTPUT_TIMING); if (hdr == NULL) { ret = -EMSGSIZE; goto err; } // Add a KG2_GENL_ATTR_MSG attribute ret = nla_put_u16(msg, KG2_GENL_ATTR_HTOTAL, timing->HTotal); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u16(msg, KG2_GENL_ATTR_HACTIVE, timing->HActive); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u16(msg, KG2_GENL_ATTR_HFRONTPORCH, timing->HFrontPorch); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u8(msg, KG2_GENL_ATTR_HSYNCWIDTH, timing->HSyncWidth); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u32(msg, KG2_GENL_ATTR_HPOLARITY, timing->HPolarity); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u16(msg, KG2_GENL_ATTR_VTOTAL, timing->VTotal); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u16(msg, KG2_GENL_ATTR_VACTIVE, timing->VActive); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u16(msg, KG2_GENL_ATTR_VFRONTPORCH, timing->VFrontPorch); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u8(msg, KG2_GENL_ATTR_VSYNCWIDTH, timing->VSyncWidth); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u32(msg, KG2_GENL_ATTR_VPOLARITY, timing->VPolarity); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u32(msg, KG2_GENL_ATTR_ASPRATIO, timing->AspRatio); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u8(msg, KG2_GENL_ATTR_ISPROGRESSIVE, timing->IsProgressive); if (ret) { ret = -ENOBUFS; goto err; } ret = nla_put_u16(msg, KG2_GENL_ATTR_REFRATE, timing->RefRate); if (ret) { ret = -ENOBUFS; goto err; } // Finalize the message genlmsg_end(msg, hdr); // Send the message ret = genlmsg_unicast(&init_net, msg, g_daemon_pid); return ret; err: nlmsg_free(msg); return ret; }
int demo_cmd(struct sk_buff *skb_2, struct genl_info *info) { struct nlattr *na; struct sk_buff *skb; int rc = 0; void *msg_head; char *attr_str; u16 attr_u16; struct attr_custom cp; printk("got demo_cmd\n"); if (info == NULL) { goto out; } na = info->attrs[DEMO_ATTR1_STRING]; if (na) { attr_str = (char *)nla_data(na); if (attr_str == NULL) { printk("error while receiving data\n"); } else { printk("attr1: %s\n", attr_str); } } else { printk("no attr1\n"); } na = info->attrs[DEMO_ATTR2_UINT16]; if (na) { attr_u16 = nla_get_u16(na); printk("attr2: %x\n", attr_u16); } else { printk("no attr2\n"); } /* send message back */ /* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE */ skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (skb == NULL) { goto out; } /* create the message */ msg_head = genlmsg_put(skb, 0, info->snd_seq + 1, &demo_gnl_family, 0, DEMO_CMD); if (msg_head == NULL) { rc = -ENOMEM; goto out; } rc |= nla_put_string(skb, DEMO_ATTR1_STRING,"world"); rc |= nla_put_u16(skb, DEMO_ATTR2_UINT16, 0x1f); cp.a = 1; cp.b = 2; cp.c = 3.0; cp.d = 4.0; rc |= nla_put(skb, DEMO_ATTR3_CUSTOM, sizeof(struct attr_custom), &cp); if (rc != 0) { goto out; } /* finalize the message */ genlmsg_end(skb, msg_head); /* send the message back */ rc = genlmsg_unicast(&init_net, skb, info->snd_portid); if (rc != 0) { goto out; } return 0; out: printk("an error occured\n"); return -1; }
static int queue_userspace_packet(int dp_ifindex, struct sk_buff *skb, const struct dp_upcall_info *upcall_info) { struct ovs_header *upcall; struct sk_buff *nskb = NULL; struct sk_buff *user_skb; /* to be queued to userspace */ struct nlattr *nla; unsigned int len; int err; if (vlan_tx_tag_present(skb)) { nskb = skb_clone(skb, GFP_ATOMIC); if (!nskb) return -ENOMEM; nskb = __vlan_put_tag(nskb, vlan_tx_tag_get(nskb)); if (!nskb) return -ENOMEM; nskb->vlan_tci = 0; skb = nskb; } if (nla_attr_size(skb->len) > USHRT_MAX) { err = -EFBIG; goto out; } len = sizeof(struct ovs_header); len += nla_total_size(skb->len); len += nla_total_size(FLOW_BUFSIZE); if (upcall_info->cmd == OVS_PACKET_CMD_ACTION) len += nla_total_size(8); user_skb = genlmsg_new(len, GFP_ATOMIC); if (!user_skb) { err = -ENOMEM; goto out; } upcall = genlmsg_put(user_skb, 0, 0, &dp_packet_genl_family, 0, upcall_info->cmd); upcall->dp_ifindex = dp_ifindex; nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); ovs_flow_to_nlattrs(upcall_info->key, user_skb); nla_nest_end(user_skb, nla); if (upcall_info->userdata) nla_put_u64(user_skb, OVS_PACKET_ATTR_USERDATA, nla_get_u64(upcall_info->userdata)); nla = __nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, skb->len); skb_copy_and_csum_dev(skb, nla_data(nla)); err = genlmsg_unicast(&init_net, user_skb, upcall_info->pid); out: kfree_skb(nskb); return err; }
s32 wl_genl_send_msg( struct net_device *ndev, u32 event_type, u8 *buf, u16 len, u8 *subhdr, u16 subhdr_len) { int ret = 0; struct sk_buff *skb; void *msg; u32 attr_type = 0; bcm_event_hdr_t *hdr = NULL; int mcast = 1; /* By default sent as mutlicast type */ int pid = 0; u8 *ptr = NULL, *p = NULL; u32 tot_len = sizeof(bcm_event_hdr_t) + subhdr_len + len; u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; WL_DBG(("Enter \n")); /* Decide between STRING event and Data event */ if (event_type == 0) attr_type = BCM_GENL_ATTR_STRING; else attr_type = BCM_GENL_ATTR_MSG; skb = genlmsg_new(NLMSG_GOODSIZE, kflags); if (skb == NULL) { ret = -ENOMEM; goto out; } msg = genlmsg_put(skb, 0, 0, &wl_genl_family, 0, BCM_GENL_CMD_MSG); if (msg == NULL) { ret = -ENOMEM; goto out; } if (attr_type == BCM_GENL_ATTR_STRING) { /* Add a BCM_GENL_MSG attribute. Since it is specified as a string. * make sure it is null terminated */ if (subhdr || subhdr_len) { WL_ERR(("No sub hdr support for the ATTR STRING type \n")); ret = -EINVAL; goto out; } ret = nla_put_string(skb, BCM_GENL_ATTR_STRING, buf); if (ret != 0) { WL_ERR(("nla_put_string failed\n")); goto out; } } else { /* ATTR_MSG */ /* Create a single buffer for all */ p = ptr = kzalloc(tot_len, kflags); if (!ptr) { ret = -ENOMEM; WL_ERR(("ENOMEM!!\n")); goto out; } /* Include the bcm event header */ hdr = (bcm_event_hdr_t *)ptr; hdr->event_type = wl_event_to_bcm_event(event_type); hdr->len = len + subhdr_len; ptr += sizeof(bcm_event_hdr_t); /* Copy subhdr (if any) */ if (subhdr && subhdr_len) { memcpy(ptr, subhdr, subhdr_len); ptr += subhdr_len; } /* Copy the data */ if (buf && len) { memcpy(ptr, buf, len); } ret = nla_put(skb, BCM_GENL_ATTR_MSG, tot_len, p); if (ret != 0) { WL_ERR(("nla_put_string failed\n")); goto out; } } if (mcast) { int err = 0; /* finalize the message */ genlmsg_end(skb, msg); /* NETLINK_CB(skb).dst_group = 1; */ if ((err = genlmsg_multicast(skb, 0, wl_genl_mcast.id, GFP_ATOMIC)) < 0) WL_ERR(("genlmsg_multicast for attr(%d) failed. Error:%d \n", attr_type, err)); else WL_DBG(("Multicast msg sent successfully. attr_type:%d len:%d \n", attr_type, tot_len)); } else { NETLINK_CB(skb).dst_group = 0; /* Not in multicast group */ /* finalize the message */ genlmsg_end(skb, msg); /* send the message back */ if (genlmsg_unicast(&init_net, skb, pid) < 0) WL_ERR(("genlmsg_unicast failed\n")); } out: if (p) kfree(p); if (ret) nlmsg_free(skb); return ret; }
/* Get a list of MacAddressA of all nodes known to this node (including self). */ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) { /* For receiving */ struct nlattr *na; struct net_device *hsr_dev; /* For sending */ struct sk_buff *skb_out; void *msg_head; struct hsr_priv *hsr; void *pos; unsigned char addr[ETH_ALEN]; int res; if (!info) goto invalid; na = info->attrs[HSR_A_IFINDEX]; if (!na) goto invalid; hsr_dev = __dev_get_by_index(genl_info_net(info), nla_get_u32(info->attrs[HSR_A_IFINDEX])); if (!hsr_dev) goto invalid; if (!is_hsr_master(hsr_dev)) goto invalid; /* Send reply */ skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb_out) { res = -ENOMEM; goto fail; } msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid, info->snd_seq, &hsr_genl_family, 0, HSR_C_SET_NODE_LIST); if (!msg_head) { res = -ENOMEM; goto nla_put_failure; } res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex); if (res < 0) goto nla_put_failure; hsr = netdev_priv(hsr_dev); rcu_read_lock(); pos = hsr_get_next_node(hsr, NULL, addr); while (pos) { res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr); if (res < 0) { rcu_read_unlock(); goto nla_put_failure; } pos = hsr_get_next_node(hsr, pos, addr); } rcu_read_unlock(); genlmsg_end(skb_out, msg_head); genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid); return 0; invalid: netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL); return 0; nla_put_failure: kfree_skb(skb_out); /* Fall through */ fail: return res; }
/* an echo command, receives a message, prints it and sends another message back */ int doc_exmpl_echo(struct sk_buff *skb_2, struct genl_info *info) { struct nlattr *na; struct sk_buff *skb; int rc; void *msg_head; char * mydata; if (info == NULL) goto out; /*for each attribute there is an index in info->attrs which points to a nlattr structure *in this structure the data is given */ na = info->attrs[DOC_EXMPL_A_MSG]; if (na) { mydata = (char *)nla_data(na); if (mydata == NULL) printk("error while receiving data\n"); else printk("received: %s\n", mydata); } else printk("no info->attrs %i\n", DOC_EXMPL_A_MSG); /* send a message back*/ /* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE*/ skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (skb == NULL) goto out; /* create the message headers */ /* arguments of genlmsg_put: struct sk_buff *, int (sending) pid, int sequence number, struct genl_family *, int flags, u8 command index (why do we need this?) */ msg_head = genlmsg_put(skb, 0, info->snd_seq+1, &doc_exmpl_gnl_family, 0, DOC_EXMPL_C_ECHO); if (msg_head == NULL) { rc = -ENOMEM; goto out; } /* add a DOC_EXMPL_A_MSG attribute (actual value to be sent) */ rc = nla_put_string(skb, DOC_EXMPL_A_MSG, "hello world from kernel space"); if (rc != 0) goto out; /* finalize the message */ genlmsg_end(skb, msg_head); /* send the message back */ rc = genlmsg_unicast(&init_net, skb,info->snd_pid ); if (rc != 0) goto out; return 0; out: printk("an error occured in doc_exmpl_echo:\n"); return 0; }