/** * 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; }
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 ; }