[NETNS]: Do no include NET related headers if CONFIG_NET is not set.
[safe/jmp/linux-2.6] / lib / kobject_uevent.c
1 /*
2  * kernel userspace event delivery
3  *
4  * Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
5  * Copyright (C) 2004 Novell, Inc.  All rights reserved.
6  * Copyright (C) 2004 IBM, Inc. All rights reserved.
7  *
8  * Licensed under the GNU GPL v2.
9  *
10  * Authors:
11  *      Robert Love             <rml@novell.com>
12  *      Kay Sievers             <kay.sievers@vrfy.org>
13  *      Arjan van de Ven        <arjanv@redhat.com>
14  *      Greg Kroah-Hartman      <greg@kroah.com>
15  */
16
17 #include <linux/spinlock.h>
18 #include <linux/string.h>
19 #include <linux/kobject.h>
20 #include <linux/module.h>
21
22 #ifdef CONFIG_NET
23 #include <linux/socket.h>
24 #include <linux/skbuff.h>
25 #include <linux/netlink.h>
26 #include <net/sock.h>
27 #endif
28
29
30 u64 uevent_seqnum;
31 char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
32 static DEFINE_SPINLOCK(sequence_lock);
33 #if defined(CONFIG_NET)
34 static struct sock *uevent_sock;
35 #endif
36
37 /* the strings here must match the enum in include/linux/kobject.h */
38 static const char *kobject_actions[] = {
39         [KOBJ_ADD] =            "add",
40         [KOBJ_REMOVE] =         "remove",
41         [KOBJ_CHANGE] =         "change",
42         [KOBJ_MOVE] =           "move",
43         [KOBJ_ONLINE] =         "online",
44         [KOBJ_OFFLINE] =        "offline",
45 };
46
47 /**
48  * kobject_action_type - translate action string to numeric type
49  *
50  * @buf: buffer containing the action string, newline is ignored
51  * @len: length of buffer
52  * @type: pointer to the location to store the action type
53  *
54  * Returns 0 if the action string was recognized.
55  */
56 int kobject_action_type(const char *buf, size_t count,
57                         enum kobject_action *type)
58 {
59         enum kobject_action action;
60         int ret = -EINVAL;
61
62         if (count && buf[count-1] == '\n')
63                 count--;
64
65         if (!count)
66                 goto out;
67
68         for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) {
69                 if (strncmp(kobject_actions[action], buf, count) != 0)
70                         continue;
71                 if (kobject_actions[action][count] != '\0')
72                         continue;
73                 *type = action;
74                 ret = 0;
75                 break;
76         }
77 out:
78         return ret;
79 }
80
81 /**
82  * kobject_uevent_env - send an uevent with environmental data
83  *
84  * @action: action that is happening
85  * @kobj: struct kobject that the action is happening to
86  * @envp_ext: pointer to environmental data
87  *
88  * Returns 0 if kobject_uevent() is completed with success or the
89  * corresponding error when it fails.
90  */
91 int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
92                        char *envp_ext[])
93 {
94         struct kobj_uevent_env *env;
95         const char *action_string = kobject_actions[action];
96         const char *devpath = NULL;
97         const char *subsystem;
98         struct kobject *top_kobj;
99         struct kset *kset;
100         struct kset_uevent_ops *uevent_ops;
101         u64 seq;
102         int i = 0;
103         int retval = 0;
104
105         pr_debug("kobject: '%s' (%p): %s\n",
106                  kobject_name(kobj), kobj, __FUNCTION__);
107
108         /* search the kset we belong to */
109         top_kobj = kobj;
110         while (!top_kobj->kset && top_kobj->parent)
111                 top_kobj = top_kobj->parent;
112
113         if (!top_kobj->kset) {
114                 pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
115                          "without kset!\n", kobject_name(kobj), kobj,
116                          __FUNCTION__);
117                 return -EINVAL;
118         }
119
120         kset = top_kobj->kset;
121         uevent_ops = kset->uevent_ops;
122
123         /* skip the event, if the filter returns zero. */
124         if (uevent_ops && uevent_ops->filter)
125                 if (!uevent_ops->filter(kset, kobj)) {
126                         pr_debug("kobject: '%s' (%p): %s: filter function "
127                                  "caused the event to drop!\n",
128                                  kobject_name(kobj), kobj, __FUNCTION__);
129                         return 0;
130                 }
131
132         /* originating subsystem */
133         if (uevent_ops && uevent_ops->name)
134                 subsystem = uevent_ops->name(kset, kobj);
135         else
136                 subsystem = kobject_name(&kset->kobj);
137         if (!subsystem) {
138                 pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
139                          "event to drop!\n", kobject_name(kobj), kobj,
140                          __FUNCTION__);
141                 return 0;
142         }
143
144         /* environment buffer */
145         env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
146         if (!env)
147                 return -ENOMEM;
148
149         /* complete object path */
150         devpath = kobject_get_path(kobj, GFP_KERNEL);
151         if (!devpath) {
152                 retval = -ENOENT;
153                 goto exit;
154         }
155
156         /* default keys */
157         retval = add_uevent_var(env, "ACTION=%s", action_string);
158         if (retval)
159                 goto exit;
160         retval = add_uevent_var(env, "DEVPATH=%s", devpath);
161         if (retval)
162                 goto exit;
163         retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
164         if (retval)
165                 goto exit;
166
167         /* keys passed in from the caller */
168         if (envp_ext) {
169                 for (i = 0; envp_ext[i]; i++) {
170                         retval = add_uevent_var(env, envp_ext[i]);
171                         if (retval)
172                                 goto exit;
173                 }
174         }
175
176         /* let the kset specific function add its stuff */
177         if (uevent_ops && uevent_ops->uevent) {
178                 retval = uevent_ops->uevent(kset, kobj, env);
179                 if (retval) {
180                         pr_debug("kobject: '%s' (%p): %s: uevent() returned "
181                                  "%d\n", kobject_name(kobj), kobj,
182                                  __FUNCTION__, retval);
183                         goto exit;
184                 }
185         }
186
187         /*
188          * Mark "add" and "remove" events in the object to ensure proper
189          * events to userspace during automatic cleanup. If the object did
190          * send an "add" event, "remove" will automatically generated by
191          * the core, if not already done by the caller.
192          */
193         if (action == KOBJ_ADD)
194                 kobj->state_add_uevent_sent = 1;
195         else if (action == KOBJ_REMOVE)
196                 kobj->state_remove_uevent_sent = 1;
197
198         /* we will send an event, so request a new sequence number */
199         spin_lock(&sequence_lock);
200         seq = ++uevent_seqnum;
201         spin_unlock(&sequence_lock);
202         retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
203         if (retval)
204                 goto exit;
205
206 #if defined(CONFIG_NET)
207         /* send netlink message */
208         if (uevent_sock) {
209                 struct sk_buff *skb;
210                 size_t len;
211
212                 /* allocate message with the maximum possible size */
213                 len = strlen(action_string) + strlen(devpath) + 2;
214                 skb = alloc_skb(len + env->buflen, GFP_KERNEL);
215                 if (skb) {
216                         char *scratch;
217
218                         /* add header */
219                         scratch = skb_put(skb, len);
220                         sprintf(scratch, "%s@%s", action_string, devpath);
221
222                         /* copy keys to our continuous event payload buffer */
223                         for (i = 0; i < env->envp_idx; i++) {
224                                 len = strlen(env->envp[i]) + 1;
225                                 scratch = skb_put(skb, len);
226                                 strcpy(scratch, env->envp[i]);
227                         }
228
229                         NETLINK_CB(skb).dst_group = 1;
230                         netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
231                 }
232         }
233 #endif
234
235         /* call uevent_helper, usually only enabled during early boot */
236         if (uevent_helper[0]) {
237                 char *argv [3];
238
239                 argv [0] = uevent_helper;
240                 argv [1] = (char *)subsystem;
241                 argv [2] = NULL;
242                 retval = add_uevent_var(env, "HOME=/");
243                 if (retval)
244                         goto exit;
245                 retval = add_uevent_var(env,
246                                         "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
247                 if (retval)
248                         goto exit;
249
250                 call_usermodehelper(argv[0], argv, env->envp, UMH_WAIT_EXEC);
251         }
252
253 exit:
254         kfree(devpath);
255         kfree(env);
256         return retval;
257 }
258 EXPORT_SYMBOL_GPL(kobject_uevent_env);
259
260 /**
261  * kobject_uevent - notify userspace by ending an uevent
262  *
263  * @action: action that is happening
264  * @kobj: struct kobject that the action is happening to
265  *
266  * Returns 0 if kobject_uevent() is completed with success or the
267  * corresponding error when it fails.
268  */
269 int kobject_uevent(struct kobject *kobj, enum kobject_action action)
270 {
271         return kobject_uevent_env(kobj, action, NULL);
272 }
273 EXPORT_SYMBOL_GPL(kobject_uevent);
274
275 /**
276  * add_uevent_var - add key value string to the environment buffer
277  * @env: environment buffer structure
278  * @format: printf format for the key=value pair
279  *
280  * Returns 0 if environment variable was added successfully or -ENOMEM
281  * if no space was available.
282  */
283 int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
284 {
285         va_list args;
286         int len;
287
288         if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
289                 printk(KERN_ERR "add_uevent_var: too many keys\n");
290                 WARN_ON(1);
291                 return -ENOMEM;
292         }
293
294         va_start(args, format);
295         len = vsnprintf(&env->buf[env->buflen],
296                         sizeof(env->buf) - env->buflen,
297                         format, args);
298         va_end(args);
299
300         if (len >= (sizeof(env->buf) - env->buflen)) {
301                 printk(KERN_ERR "add_uevent_var: buffer size too small\n");
302                 WARN_ON(1);
303                 return -ENOMEM;
304         }
305
306         env->envp[env->envp_idx++] = &env->buf[env->buflen];
307         env->buflen += len + 1;
308         return 0;
309 }
310 EXPORT_SYMBOL_GPL(add_uevent_var);
311
312 #if defined(CONFIG_NET)
313 static int __init kobject_uevent_init(void)
314 {
315         uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT,
316                                             1, NULL, NULL, THIS_MODULE);
317         if (!uevent_sock) {
318                 printk(KERN_ERR
319                        "kobject_uevent: unable to create netlink socket!\n");
320                 return -ENODEV;
321         }
322
323         return 0;
324 }
325
326 postcore_initcall(kobject_uevent_init);
327 #endif