int nfc_genl_device_added(struct nfc_dev *dev) { struct sk_buff *msg; void *hdr; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_EVENT_DEVICE_ADDED); if (!hdr) goto free_msg; NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)); NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols); NLA_PUT_U8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up); genlmsg_end(msg, hdr); genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); return 0; nla_put_failure: genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -EMSGSIZE; }
int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol) { struct sk_buff *msg; void *hdr; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_EVENT_TM_ACTIVATED); if (!hdr) goto free_msg; if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) goto nla_put_failure; if (nla_put_u32(msg, NFC_ATTR_TM_PROTOCOLS, protocol)) goto nla_put_failure; genlmsg_end(msg, hdr); genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL); return 0; nla_put_failure: genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -EMSGSIZE; }
int nfc_genl_device_removed(struct nfc_dev *dev) { struct sk_buff *msg; void *hdr; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_EVENT_DEVICE_REMOVED); if (!hdr) goto free_msg; if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) goto nla_put_failure; genlmsg_end(msg, hdr); genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL); return 0; nla_put_failure: genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -EMSGSIZE; }
int nfc_genl_dep_link_down_event(struct nfc_dev *dev) { struct sk_buff *msg; void *hdr; pr_debug("DEP link is down\n"); msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_CMD_DEP_LINK_DOWN); if (!hdr) goto free_msg; NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx); genlmsg_end(msg, hdr); genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC); return 0; nla_put_failure: genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -EMSGSIZE; }
int nfc_genl_device_added(struct nfc_dev *dev) { struct sk_buff *msg; void *hdr; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_EVENT_DEVICE_ADDED); if (!hdr) goto free_msg; if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up)) goto nla_put_failure; genlmsg_end(msg, hdr); genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL); return 0; nla_put_failure: genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -EMSGSIZE; }
int nfc_genl_targets_found(struct nfc_dev *dev) { struct sk_buff *msg; void *hdr; dev->genl_data.poll_req_portid = 0; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_EVENT_TARGETS_FOUND); if (!hdr) goto free_msg; if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) goto nla_put_failure; genlmsg_end(msg, hdr); return genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC); nla_put_failure: genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -EMSGSIZE; }
int nfc_genl_device_added(struct nfc_dev *dev) { struct sk_buff *msg; void *hdr; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_EVENT_DEVICE_ADDED); if (!hdr) goto free_msg; if (nfc_genl_setup_device_added(dev, msg)) goto nla_put_failure; genlmsg_end(msg, hdr); genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL); return 0; nla_put_failure: free_msg: nlmsg_free(msg); return -EMSGSIZE; }
/* 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(); }
int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx) { struct sk_buff *msg; void *hdr; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_EVENT_TARGET_LOST); if (!hdr) goto free_msg; if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || nla_put_u32(msg, NFC_ATTR_TARGET_INDEX, target_idx)) goto nla_put_failure; genlmsg_end(msg, hdr); genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL); return 0; nla_put_failure: genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -EMSGSIZE; }
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); }
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); }
int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group) { /* XXX: nlh is right at the start of msg */ void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); if (genlmsg_end(msg, hdr) < 0) goto out; return genlmsg_multicast(msg, 0, group, GFP_ATOMIC); out: nlmsg_free(msg); return -ENOBUFS; }
int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) { struct device *dev = wimax_dev_to_dev(wimax_dev); void *msg = skb->data; size_t size = skb->len; might_sleep(); d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size); d_dump(2, dev, msg, size); genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); d_printf(1, dev, "CTX: genl multicast done\n"); return 0; }
int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group) { struct nlmsghdr *nlh = nlmsg_hdr(msg); void *hdr = genlmsg_data(nlmsg_data(nlh)); if (genlmsg_end(msg, hdr) < 0) goto out; return genlmsg_multicast(&nl802154_family, msg, 0, group, GFP_ATOMIC); out: nlmsg_free(msg); return -ENOBUFS; }
static int ieee802154_nl_finish(struct sk_buff *msg) { /* XXX: nlh is right at the start of msg */ void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); if (!genlmsg_end(msg, hdr)) goto out; return genlmsg_multicast(msg, 0, ieee802154_coord_mcgrp.id, GFP_ATOMIC); out: nlmsg_free(msg); return -ENOBUFS; }
static struct sk_buff *brc_send_command(struct sk_buff *request, struct nlattr **attrs) { unsigned long int flags; struct sk_buff *reply; int error; mutex_lock(&brc_serial); /* Increment sequence number first, so that we ignore any replies * to stale requests. */ spin_lock_irqsave(&brc_lock, flags); nlmsg_hdr(request)->nlmsg_seq = ++brc_seq; INIT_COMPLETION(brc_done); spin_unlock_irqrestore(&brc_lock, flags); nlmsg_end(request, nlmsg_hdr(request)); /* Send message. */ error = genlmsg_multicast(request, 0, brc_mc_group.id, GFP_KERNEL); if (error < 0) goto error; /* Wait for reply. */ error = -ETIMEDOUT; if (!wait_for_completion_timeout(&brc_done, BRC_TIMEOUT)) { pr_warn("timed out waiting for userspace\n"); goto error; } /* Grab reply. */ spin_lock_irqsave(&brc_lock, flags); reply = brc_reply; brc_reply = NULL; spin_unlock_irqrestore(&brc_lock, flags); mutex_unlock(&brc_serial); /* Re-parse message. Can't fail, since it parsed correctly once * already. */ error = nlmsg_parse(nlmsg_hdr(reply), GENL_HDRLEN, attrs, BRC_GENL_A_MAX, brc_genl_policy); WARN_ON(error); return reply; error: mutex_unlock(&brc_serial); return ERR_PTR(error); }
/** * wimax_msg_send - Send a pre-allocated message to user space * * @wimax_dev: WiMAX device descriptor * * @skb: &struct sk_buff returned by wimax_msg_alloc(). Note the * ownership of @skb is transferred to this function. * * Returns: 0 if ok, < 0 errno code on error * * Description: * * Sends a free-form message that was preallocated with * wimax_msg_alloc() and filled up. * * Assumes that once you pass an skb to this function for sending, it * owns it and will release it when done (on success). * * 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. */ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) { int result; struct device *dev = wimax_dev->net_dev->dev.parent; void *msg = skb->data; size_t size = skb->len; might_sleep(); d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size); d_dump(2, dev, msg, size); result = genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); d_printf(1, dev, "CTX: genl multicast result %d\n", result); if (result == -ESRCH) /* Nobody connected, ignore it */ result = 0; /* btw, the skb is freed already */ return result; }
/* * Send a Report State Change message (as created with _alloc). * * @report_skb: as returned by wimax_gnl_re_state_change_alloc() * @header: as returned by wimax_gnl_re_state_change_alloc() * * Returns: 0 if ok, < 0 errno code on error. * * If the message is NULL, pretend it didn't happen. */ static int wimax_gnl_re_state_change_send( struct wimax_dev *wimax_dev, struct sk_buff *report_skb, void *header) { int result = 0; struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n", wimax_dev, report_skb); if (report_skb == NULL) { result = -ENOMEM; goto out; } genlmsg_end(report_skb, header); genlmsg_multicast(&wimax_gnl_family, report_skb, 0, 0, GFP_KERNEL); out: d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n", wimax_dev, report_skb, result); return result; }
int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, u8 comm_mode, u8 rf_mode) { struct sk_buff *msg; void *hdr; pr_debug("DEP link is up\n"); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!msg) return -ENOMEM; hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, NFC_CMD_DEP_LINK_UP); if (!hdr) goto free_msg; if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) goto nla_put_failure; if (rf_mode == NFC_RF_INITIATOR && nla_put_u32(msg, NFC_ATTR_TARGET_INDEX, target_idx)) goto nla_put_failure; if (nla_put_u8(msg, NFC_ATTR_COMM_MODE, comm_mode) || nla_put_u8(msg, NFC_ATTR_RF_MODE, rf_mode)) goto nla_put_failure; genlmsg_end(msg, hdr); dev->dep_link_up = true; genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC); return 0; nla_put_failure: genlmsg_cancel(msg, hdr); free_msg: nlmsg_free(msg); return -EMSGSIZE; }
/* 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(); }
/* * Send a Report State Change message (as created with _alloc). * * @report_skb: as returned by wimax_gnl_re_state_change_alloc() * @header: as returned by wimax_gnl_re_state_change_alloc() * * Returns: 0 if ok, < 0 errno code on error. * * If the message is NULL, pretend it didn't happen. */ static int wimax_gnl_re_state_change_send( struct wimax_dev *wimax_dev, struct sk_buff *report_skb, void *header) { int result = 0; struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n", wimax_dev, report_skb); if (report_skb == NULL) goto out; genlmsg_end(report_skb, header); result = genlmsg_multicast(report_skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); if (result == -ESRCH) /* Nobody connected, ignore it */ result = 0; /* btw, the skb is freed already */ if (result < 0) { dev_err(dev, "RE_STCH: Error sending: %d\n", result); nlmsg_free(report_skb); } out: d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n", wimax_dev, report_skb, result); return result; }
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; }
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; } }
/* 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); }