예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
파일: netlink.c 프로젝트: avagin/linux
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;
}
예제 #8
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();
}
예제 #9
0
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;
}
예제 #10
0
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;
  }
}
예제 #11
0
파일: netlink.c 프로젝트: 020gzh/linux
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),
			&quota_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(&quota_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);
}
예제 #12
0
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),
			&quota_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);
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #15
0
파일: netlink.c 프로젝트: 7799/linux
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;
}
예제 #16
0
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;
}
예제 #17
0
파일: brcompat.c 프로젝트: carriercomm/ODS
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);
}
예제 #18
0
/**
 * 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;
}
예제 #19
0
파일: stack.c 프로젝트: 020gzh/linux
/*
 * 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;
}
예제 #20
0
파일: netlink.c 프로젝트: AllenDou/linux
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;
}
예제 #21
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();
}
예제 #22
0
/*
 * 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;
}
예제 #23
0
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;
}
예제 #24
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;
  }
}
예제 #25
0
/* 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);
}