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; }
/* This is called when we haven't heard from the node with MAC address addr for * some time (just before the node is removed from the node table/list). */ void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN]) { struct sk_buff *skb; void *msg_head; struct hsr_port *master; int res; skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb) goto fail; msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0, HSR_C_NODE_DOWN); if (!msg_head) goto nla_put_failure; res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr); if (res < 0) goto nla_put_failure; genlmsg_end(skb, msg_head); genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC); return; nla_put_failure: kfree_skb(skb); fail: rcu_read_lock(); master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); netdev_warn(master->dev, "Could not send HSR node down\n"); rcu_read_unlock(); }
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; }
void ptp_work_send_rtc_change(struct work_struct *work) { struct ptp_device *ptp = container_of(work, struct ptp_device, work_send_rtc_change); struct sk_buff *skb; uint8_t commandByte; void *msgHead; int returnValue = 0; skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if(skb == NULL) return; /* Decide which command byte to send with the message based upon the lock state */ if(ptp->rtcLockState == PTP_RTC_LOCKED) { commandByte = PTP_EVENTS_C_RTC_LOCK; } else { commandByte = PTP_EVENTS_C_RTC_UNLOCK; } /* Create the message headers */ msgHead = genlmsg_put(skb, 0, ptp->netlinkSequence++, &ptp_events_genl_family, 0, commandByte); if(msgHead == NULL) { returnValue = -ENOMEM; goto rtc_change_fail; } /* Write the PTP domain identifier to the message */ returnValue = nla_put_u8(skb, PTP_EVENTS_A_DOMAIN, ptp->properties.domainNumber); if(returnValue != 0) goto rtc_change_fail; /* Finalize the message and multicast it */ genlmsg_end(skb, msgHead); returnValue = genlmsg_multicast(skb, 0, rtc_mcast.id, GFP_ATOMIC); skb = NULL; switch(returnValue) { case 0: case -ESRCH: // Success or no process was listening, simply break break; default: // This is an actual error, print the return code printk(KERN_INFO DRIVER_NAME ": Failure delivering multicast Netlink message: %d\n", returnValue); goto rtc_change_fail; } rtc_change_fail: if (NULL != skb) { nlmsg_free(skb); skb = NULL; } }
void quota_send_warning(struct kqid qid, dev_t dev, const char warntype) { static atomic_t seq; struct sk_buff *skb; void *msg_head; int ret; int msg_size = 4 * nla_total_size(sizeof(u32)) + 2 * nla_total_size(sizeof(u64)); /* We have to allocate using GFP_NOFS as we are called from a * filesystem performing write and thus further recursion into * the fs to free some data could cause deadlocks. */ skb = genlmsg_new(msg_size, GFP_NOFS); if (!skb) { printk(KERN_ERR "VFS: Not enough memory to send quota warning.\n"); return; } msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq), "a_genl_family, 0, QUOTA_NL_C_WARNING); if (!msg_head) { printk(KERN_ERR "VFS: Cannot store netlink header in quota warning.\n"); goto err_out; } ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, qid.type); if (ret) goto attr_err_out; ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, from_kqid_munged(&init_user_ns, qid)); if (ret) goto attr_err_out; ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype); if (ret) goto attr_err_out; ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev)); if (ret) goto attr_err_out; ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev)); if (ret) goto attr_err_out; ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, from_kuid_munged(&init_user_ns, current_uid())); if (ret) goto attr_err_out; genlmsg_end(skb, msg_head); genlmsg_multicast("a_genl_family, skb, 0, 0, GFP_NOFS); return; attr_err_out: printk(KERN_ERR "VFS: Not enough space to compose quota message!\n"); err_out: kfree_skb(skb); }
/** * wimax_msg_alloc - Create a new skb for sending a message to userspace * * @wimax_dev: WiMAX device descriptor * @pipe_name: "named pipe" the message will be sent to * @msg: pointer to the message data to send * @size: size of the message to send (in bytes), including the header. * @gfp_flags: flags for memory allocation. * * Returns: %0 if ok, negative errno code on error * * Description: * * Allocates an skb that will contain the message to send to user * space over the messaging pipe and initializes it, copying the * payload. * * Once this call is done, you can deliver it with * wimax_msg_send(). * * IMPORTANT: * * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. */ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, const char *pipe_name, const void *msg, size_t size, gfp_t gfp_flags) { int result; struct device *dev = wimax_dev->net_dev->dev.parent; size_t msg_size; void *genl_msg; struct sk_buff *skb; msg_size = nla_total_size(size) + nla_total_size(sizeof(u32)) + (pipe_name ? nla_total_size(strlen(pipe_name)) : 0); result = -ENOMEM; skb = genlmsg_new(msg_size, gfp_flags); if (skb == NULL) goto error_new; genl_msg = genlmsg_put(skb, 0, 0, &wimax_gnl_family, 0, WIMAX_GNL_OP_MSG_TO_USER); if (genl_msg == NULL) { dev_err(dev, "no memory to create generic netlink message\n"); goto error_genlmsg_put; } result = nla_put_u32(skb, WIMAX_GNL_MSG_IFIDX, wimax_dev->net_dev->ifindex); if (result < 0) { dev_err(dev, "no memory to add ifindex attribute\n"); goto error_nla_put; } if (pipe_name) { result = nla_put_string(skb, WIMAX_GNL_MSG_PIPE_NAME, pipe_name); if (result < 0) { dev_err(dev, "no memory to add pipe_name attribute\n"); goto error_nla_put; } } result = nla_put(skb, WIMAX_GNL_MSG_DATA, size, msg); if (result < 0) { dev_err(dev, "no memory to add payload (msg %p size %zu) in " "attribute: %d\n", msg, size, result); goto error_nla_put; } genlmsg_end(skb, genl_msg); return skb; error_nla_put: error_genlmsg_put: error_new: nlmsg_free(skb); return ERR_PTR(result); }
void quota_send_warning(short type, unsigned int id, dev_t dev, const char warntype) { static atomic_t seq; struct sk_buff *skb; void *msg_head; int ret; int msg_size = 4 * nla_total_size(sizeof(u32)) + 2 * nla_total_size(sizeof(u64)); /* */ skb = genlmsg_new(msg_size, GFP_NOFS); if (!skb) { printk(KERN_ERR "VFS: Not enough memory to send quota warning.\n"); return; } msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq), "a_genl_family, 0, QUOTA_NL_C_WARNING); if (!msg_head) { printk(KERN_ERR "VFS: Cannot store netlink header in quota warning.\n"); goto err_out; } ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type); if (ret) goto attr_err_out; ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id); if (ret) goto attr_err_out; ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype); if (ret) goto attr_err_out; ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev)); if (ret) goto attr_err_out; ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev)); if (ret) goto attr_err_out; ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid()); if (ret) goto attr_err_out; genlmsg_end(skb, msg_head); genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS); return; attr_err_out: printk(KERN_ERR "VFS: Not enough space to compose quota message!\n"); err_out: kfree_skb(skb); }
/* * @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; }
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 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; }
int genetlink_register(void) { int ret = 0; ret = genl_register_family_with_ops(&vswitch_flow_family, vswitch_flow_ops, 1); if (ret) return ret; genl_skb = genlmsg_new(0, GFP_KERNEL); if (genl_skb == NULL) { genetlink_unregister(); } return 0; }
static int kg2_genl_get_daemon_pid(struct sk_buff * skb, struct genl_info * info) { int ret = 0; void * hdr; struct sk_buff * msg; printk(KERN_INFO "kg2: Send daemon PID to user: %u\n", info->snd_pid); if (g_daemon_pid == 0) return -EINVAL; // Allocate message msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (msg == NULL) return -ENOMEM; // Set message header hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &kg2_genl_family, 0, KG2_GENL_CMD_SET_DAEMON_PID); if (hdr == NULL) { ret = -EMSGSIZE; goto err; } // Set message payload ret = nla_put_u32(msg, KG2_GENL_ATTR_PID, g_daemon_pid); if (ret) { ret = -ENOBUFS; goto err; } // Finalize message genlmsg_end(msg, hdr); // Reply message return genlmsg_reply(msg, info); err: nlmsg_free(msg); return ret; }
static int ipctl_reply(struct sk_buff *skb, struct genl_info *info, int property, int ifIndex, int value) { struct sk_buff *skb_reply; void *msg_head; int rc = 0; pr_debug("ipctl: reply start\n"); skb_reply = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (skb_reply == NULL) goto out; msg_head = genlmsg_put(skb_reply, 0, info->snd_seq, &ipctl_gnl_family, 0, IPCTL_CMD_GET); if (msg_head == NULL) { rc = -ENOMEM; goto out; } rc = nla_put_u32(skb_reply, IPCTL_ATTR_PROPERTY, property); if (rc != 0) goto out; rc = nla_put_u32(skb_reply, IPCTL_ATTR_IFINDEX, ifIndex); if (rc != 0) goto out; rc = nla_put_u8(skb_reply, IPCTL_ATTR_VALUE, value); if (rc != 0) goto out; /* finalize the message */ genlmsg_end(skb_reply, msg_head); rc = genlmsg_reply(skb_reply , info); if (rc != 0) goto out; return 0; out: pr_warning("ipctl: Error occured in reply: %d\n", rc); return rc; }
static struct sk_buff *brc_make_request(int op, const char *bridge, const char *port) { struct sk_buff *skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) goto error; genlmsg_put(skb, 0, 0, &brc_genl_family, 0, op); if (bridge) NLA_PUT_STRING(skb, BRC_GENL_A_DP_NAME, bridge); if (port) NLA_PUT_STRING(skb, BRC_GENL_A_PORT_NAME, port); return skb; nla_put_failure: kfree_skb(skb); error: return NULL; }
static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size) { struct sk_buff *skb; void *data; skb = genlmsg_new(size, GFP_NOFS); if (!skb) return -ENOMEM; /* add the message headers */ data = genlmsg_put(skb, 0, dlm_nl_seqnum++, &family, 0, cmd); if (!data) { nlmsg_free(skb); return -EINVAL; } *skbp = skb; return 0; }
/** * Register a new generic netlink family and the ops */ int genl_exec_init(void) { int err; /*register a generic netlink family int genl_register_family_with_ops(struct genl_family *family, struct genl_ops *ops, size_t n_ops) */ err = genl_register_family_with_ops(&genl_exec_family, genl_exec_ops, ARRAY_SIZE(genl_exec_ops)); if (err) return err; /*test the family is registered successfully*/ genlmsg_skb = genlmsg_new(0, GFP_KERNEL); if (!genlmsg_skb) { genl_unregister_family(&genl_exec_family); return -ENOMEM; } return 0; }
/* hello world from the inner space */ int hello_world(struct sk_buff *request, struct genl_info *info) { struct sk_buff *reply; int rc; void *msg_head; if (info == NULL) goto out; /* send a message back*/ /* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE*/ reply = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (reply == NULL) goto out; msg_head = genlmsg_put_reply(reply, info, &exmpl_gnl_family, 0, info->genlhdr->cmd); if (msg_head == NULL) { rc = -ENOMEM; goto out; } /* add a EXMPL_MSG attribute (actual value to be sent) */ rc = nla_put_string(reply, EXMPL_MSG, "hello world from kernel space"); if (rc != 0) goto out; /* finalize the message */ genlmsg_end(reply, msg_head); /* send the message back */ rc = genlmsg_reply(reply, info); if (rc != 0) goto out; return 0; out: printk("an error occured in hello_world:\n"); return 0; }
/* This is called if for some node with MAC address addr, we only get frames * over one of the slave interfaces. This would indicate an open network ring * (i.e. a link has failed somewhere). */ void hsr_nl_ringerror(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN], struct hsr_port *port) { struct sk_buff *skb; void *msg_head; struct hsr_port *master; int res; skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb) goto fail; msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0, HSR_C_RING_ERROR); if (!msg_head) goto nla_put_failure; res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr); if (res < 0) goto nla_put_failure; res = nla_put_u32(skb, HSR_A_IFINDEX, port->dev->ifindex); if (res < 0) goto nla_put_failure; genlmsg_end(skb, msg_head); genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC); return; nla_put_failure: kfree_skb(skb); fail: rcu_read_lock(); master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); netdev_warn(master->dev, "Could not send HSR ring error message\n"); rcu_read_unlock(); }
static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); struct in6_addr *tun_src; struct sk_buff *msg; void *hdr; msg = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &seg6_genl_family, 0, SEG6_CMD_GET_TUNSRC); if (!hdr) goto free_msg; rcu_read_lock(); tun_src = rcu_dereference(seg6_pernet(net)->tun_src); if (nla_put(msg, SEG6_ATTR_DST, sizeof(struct in6_addr), tun_src)) goto nla_put_failure; rcu_read_unlock(); genlmsg_end(msg, hdr); genlmsg_reply(msg, info); return 0; nla_put_failure: rcu_read_unlock(); genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -ENOMEM; }
/* 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; }
/* 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; }
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; }
/* Method to conditionally transmit a Netlink packet containing one or more * packets of information from the status FIFO */ static int tx_netlink_status(struct aes3_rx *rx) { struct sk_buff *skb; void *msgHead; int returnValue = 0; uint32_t status; /* Make sure we have something to do */ if(rx->statusReadyAes != AES_NEW_STATUS_READY && rx->statusReadyMeter != AES_NEW_STATUS_READY) { return(returnValue); } /* We will send a packet, allocate a socket buffer */ skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if(skb == NULL) return(-ENOMEM); /* Create the message headers. AES status messages get priority. */ msgHead = genlmsg_put(skb, 0, rx->netlinkSequence++, &events_genl_family, 0, (rx->statusReadyAes == AES_NEW_STATUS_READY ? LABX_AES_EVENTS_C_AES_STATUS_PACKETS : LABX_AES_EVENTS_C_METER_STATUS_PACKETS)); if(msgHead == NULL) { returnValue = -ENOMEM; goto tx_failure; } /* Write the AES device's ID, properly translated for userspace, to identify the * message source. The full ID is required since this driver can be used encapsulated * within any number of more complex devices. */ returnValue = nla_put_u32(skb, LABX_AES_EVENTS_A_AES_DEVICE, new_encode_dev(rx->deviceNode)); if(returnValue != 0) goto tx_failure; /* AES interrupts get priority. Calling code must make sure to call us multiple * times if there are multiple statuses to send out. */ if(rx->statusReadyAes == AES_NEW_STATUS_READY) { /* Clear the AES status flag */ rx->statusReadyAes = AES_STATUS_IDLE; /* Read the AES rx status register and send it out */ status = XIo_In32(REGISTER_ADDRESS(rx, AES_RX_STREAM_STATUS_REG)); returnValue = nla_put_u32(skb, LABX_AES_EVENTS_A_AES_RX_STATUS, status); if(returnValue != 0) goto tx_failure; /* Read the AES tx status register and send it out */ status = XIo_In32(REGISTER_ADDRESS(rx, AES_TX_STREAM_STATUS_REG)); returnValue = nla_put_u32(skb, LABX_AES_EVENTS_A_AES_TX_STATUS, status); if(returnValue != 0) goto tx_failure; } else if(rx->statusReadyMeter == AES_NEW_STATUS_READY) { /* Clear the metering status flag */ rx->statusReadyMeter = AES_STATUS_IDLE; /* Read the metering rx status register and send it out */ status = XIo_In32(REGISTER_ADDRESS(rx, AES_RX_AUDIO_METER_REG)); returnValue = nla_put_u32(skb, LABX_AES_EVENTS_A_METER_RX_STATUS, status); if(returnValue != 0) goto tx_failure; /* Read the metering tx status register and send it out */ status = XIo_In32(REGISTER_ADDRESS(rx, AES_TX_AUDIO_METER_REG)); returnValue = nla_put_u32(skb, LABX_AES_EVENTS_A_METER_TX_STATUS, status); if(returnValue != 0) goto tx_failure; } /* Finalize the message and multicast it */ genlmsg_end(skb, msgHead); returnValue = genlmsg_multicast(skb, 0, labx_aes_mcast.id, GFP_ATOMIC); switch(returnValue) { case 0: case -ESRCH: /* Success or no process was listening, simply break */ break; default: /* This is an actual error, print the return code */ printk(KERN_INFO DRIVER_NAME ": Failure delivering multicast Netlink message: %d\n", returnValue); goto tx_failure; } tx_failure: return(returnValue); }
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; }
/* 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; }
void ptp_work_send_gm_change(struct work_struct *work) { struct ptp_device *ptp = container_of(work, struct ptp_device, work_send_gm_change); struct sk_buff *skb; struct nlattr *valueMap; int32_t pairIndex; uint8_t *gmIdentity; char gmIdentityString[NEW_GM_BUF_SIZE]; void *msgHead; int returnValue = 0; skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if(skb == NULL) return; /* Create the message headers */ msgHead = genlmsg_put(skb, 0, ptp->netlinkSequence++, &ptp_events_genl_family, 0, PTP_EVENTS_C_GM_CHANGE); if(msgHead == NULL) { returnValue = -ENOMEM; goto gm_change_fail; } /* Write the PTP domain identifier to the message */ returnValue = nla_put_u8(skb, PTP_EVENTS_A_DOMAIN, ptp->properties.domainNumber); if(returnValue != 0) goto gm_change_fail; /* Put a single entry into a key / value map to communicate the new Grandmaster */ valueMap = nla_nest_start(skb, PTP_EVENTS_A_VALUEMAP); if(valueMap == NULL) goto gm_change_fail; /* Place the length of the map, then the key / value strings */ nla_put_u32(skb, PTP_VALUEMAP_A_LENGTH, 1); pairIndex = PTP_VALUEMAP_A_PAIRS; /* Capture the Grandmaster identity as a string value */ gmIdentity = ptp->gmPriority->rootSystemIdentity.clockIdentity; snprintf(gmIdentityString, NEW_GM_BUF_SIZE, "%s:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", NEW_GM_KEY_STRING, gmIdentity[0], gmIdentity[1], gmIdentity[2], gmIdentity[3], gmIdentity[4], gmIdentity[5], gmIdentity[6], gmIdentity[7]); gmIdentityString[NEW_GM_BUF_SIZE-1] = 0; nla_put_string(skb, pairIndex++, gmIdentityString); /* End the value map nesting */ nla_nest_end(skb, valueMap); /* Finalize the message and multicast it */ genlmsg_end(skb, msgHead); returnValue = genlmsg_multicast(skb, 0, rtc_mcast.id, GFP_ATOMIC); skb = NULL; switch(returnValue) { case 0: // Success, simply break break; case -ESRCH: // No process was listening, auto-acknowledge the result printk(KERN_INFO DRIVER_NAME ": No process listening for netlink events; auto-acknowledging ...\n"); ack_grandmaster_change(ptp); break; default: // This is an actual error, print the return code printk(KERN_INFO DRIVER_NAME ": Failure delivering multicast Netlink message: %d\n", returnValue); goto gm_change_fail; } gm_change_fail: if (returnValue != 0) { printk(KERN_INFO DRIVER_NAME ": GM change event failure %d; auto-acknowledging ...\n", returnValue); ack_grandmaster_change(ptp); } if (NULL != skb) { nlmsg_free(skb); skb = NULL; } }
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; }