示例#1
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;
}
示例#2
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;
}
示例#4
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;
}
示例#5
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;
  }
}
示例#6
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);
}
示例#7
0
/**
 * 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);

}
示例#8
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);
}
/*
 * @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;
}
示例#10
0
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;
}
示例#11
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;
}
示例#12
0
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;
}
示例#13
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;
}
示例#14
0
文件: ipctlm.c 项目: oskarb/ipctl
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;
}
示例#15
0
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;
}
示例#16
0
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;
}
示例#17
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;
}
示例#18
0
文件: netl.c 项目: 0x90/pyroute2
/* 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;
}
示例#19
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();
}
示例#20
0
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;
}
示例#21
0
/* 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;
}
示例#22
0
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;
}
示例#23
0
/* 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;
}
示例#24
0
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;
}
示例#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);
}
示例#26
0
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;
}
示例#27
0
文件: gnKernel.c 项目: b3h3moth/lkm
/* 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;
}
示例#28
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;
  }
}
示例#29
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;
}