/**
 * nlmsg_notify - send a notification netlink message
 * @sk: netlink socket to use
 * @skb: notification message
 * @portid: destination netlink portid for reports or 0
 * @group: destination multicast group or 0
 * @report: 1 to report back, 0 to disable
 * @flags: allocation flags
 */
int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
		 unsigned int group, int report, gfp_t flags)
{
	int err = 0;

	if (group) {
		int exclude_portid = 0;

		if (report) {
			atomic_inc(&skb->users);
			exclude_portid = portid;
		}

		/* errors reported via destination sk->sk_err, but propagate
		 * delivery errors if NETLINK_BROADCAST_ERROR flag is set */
		err = nlmsg_multicast(sk, skb, exclude_portid, group, flags);
	}

	if (report) {
		int err2;

		err2 = nlmsg_unicast(sk, skb, portid);
		if (!err || err == -ESRCH)
			err = err2;
	}

	return err;
}
Example #2
0
a_status_t
acfg_net_indicate_event(struct net_device *dev, acfg_os_event_t    *event, 
							int send_iwevent)
{
    struct sk_buff *skb;
    int err;
    __acfg_event_t   fn;
#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,6,24)
    if (!net_eq(dev_net(dev), &init_net))
        return A_STATUS_FAILED  ;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,6,24)
    skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
#else
    skb = nlmsg_new(NLMSG_SPACE(ACFG_MAX_PAYLOAD));
#endif
    if (!skb)
        return A_STATUS_ENOMEM ;

    err = ev_fill_info(skb, dev, RTM_NEWLINK, event);
    if (err < 0) {
        kfree_skb(skb);
        return A_STATUS_FAILED ;
    }

    NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
#if ATOPT_ORI_ATHEROS_BUG
    NETLINK_CB(skb).portid = 0;  /* from kernel */
#else
    NETLINK_CB(skb).pid = 0;  /* from kernel */
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)    
    NETLINK_CB(skb).dst_pid = 0;  /* multicast */
#endif


    /* Send event to acfg */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)   
  	err = nlmsg_multicast(acfg_ev_sock, skb, 0, RTNLGRP_NOTIFY);
#else
    rtnl_notify(skb, &init_net, 0, RTNLGRP_NOTIFY, NULL, GFP_ATOMIC);
#endif
	if (send_iwevent) {
    /* Send iw event */
    fn = iw_events[event->id];
		if (fn != NULL) {
    fn(dev, &event->data);
		}
	}
    return A_STATUS_OK ;
}