ovsdb: Synchronize comments and code in ovsdb_file_commit().
[sliver-openvswitch.git] / datapath / linux / compat / genetlink.inc
1 /* -*- c -*- */
2
3 #include <net/genetlink.h>
4 #include <linux/version.h>
5
6 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
7 #include <linux/mutex.h>
8
9 static DEFINE_MUTEX(mc_group_mutex);
10
11 int genl_register_mc_group(struct genl_family *family,
12                            struct genl_multicast_group *grp)
13 {
14         static int next_group = GENL_FIRST_MCGROUP;
15
16         mutex_lock(&mc_group_mutex);
17         grp->id = next_group;
18         grp->family = family;
19
20         if (++next_group > GENL_LAST_MCGROUP)
21                 next_group = GENL_FIRST_MCGROUP;
22         mutex_unlock(&mc_group_mutex);
23
24         return 0;
25 }
26 #endif /* kernel < 2.6.23 */
27
28 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
29 /**
30  * genl_register_family_with_ops - register a generic netlink family
31  * @family: generic netlink family
32  * @ops: operations to be registered
33  * @n_ops: number of elements to register
34  *
35  * Registers the specified family and operations from the specified table.
36  * Only one family may be registered with the same family name or identifier.
37  *
38  * The family id may equal GENL_ID_GENERATE causing an unique id to
39  * be automatically generated and assigned.
40  *
41  * Either a doit or dumpit callback must be specified for every registered
42  * operation or the function will fail. Only one operation structure per
43  * command identifier may be registered.
44  *
45  * See include/net/genetlink.h for more documenation on the operations
46  * structure.
47  *
48  * This is equivalent to calling genl_register_family() followed by
49  * genl_register_ops() for every operation entry in the table taking
50  * care to unregister the family on error path.
51  *
52  * Return 0 on success or a negative error code.
53  */
54 int genl_register_family_with_ops(struct genl_family *family,
55         struct genl_ops *ops, size_t n_ops)
56 {
57         int err, i;
58
59         err = genl_register_family(family);
60         if (err)
61                 return err;
62
63         for (i = 0; i < n_ops; ++i, ++ops) {
64                 err = genl_register_ops(family, ops);
65                 if (err)
66                         goto err_out;
67         }
68         return 0;
69 err_out:
70         genl_unregister_family(family);
71         return err;
72 }
73 #endif
74
75 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
76 /**
77  * nlmsg_notify - send a notification netlink message
78  * @sk: netlink socket to use
79  * @skb: notification message
80  * @pid: destination netlink pid for reports or 0
81  * @group: destination multicast group or 0
82  * @report: 1 to report back, 0 to disable
83  * @flags: allocation flags
84  */
85 int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid,
86                  unsigned int group, int report, gfp_t flags)
87 {
88         int err = 0;
89
90         if (group) {
91                 int exclude_pid = 0;
92
93                 if (report) {
94                         atomic_inc(&skb->users);
95                         exclude_pid = pid;
96                 }
97
98                 /* errors reported via destination sk->sk_err, but propagate
99                  * delivery errors if NETLINK_BROADCAST_ERROR flag is set */
100                 err = nlmsg_multicast(sk, skb, exclude_pid, group, flags);
101         }
102
103         if (report) {
104                 int err2;
105
106                 err2 = nlmsg_unicast(sk, skb, pid);
107                 if (!err || err == -ESRCH)
108                         err = err2;
109         }
110
111         return err;
112 }
113 #endif
114
115 /* This is analogous to rtnl_notify() but uses genl_sock instead of rtnl.
116  *
117  * This is not (yet) in any upstream kernel. */
118 void genl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
119                  struct nlmsghdr *nlh, gfp_t flags)
120 {
121 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
122         struct sock *sk = net->genl_sock;
123 #else
124         struct sock *sk = genl_sock;
125 #endif
126         int report = 0;
127
128         if (nlh)
129                 report = nlmsg_report(nlh);
130
131         nlmsg_notify(sk, skb, pid, group, report, flags);
132 }
133
134 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
135 /* This function wasn't exported before 2.6.30.  Lose! */
136 void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
137 {
138 }
139 #endif