Blame view

lib/kobject_uevent.c 10.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * kernel userspace event delivery
   *
   * Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
   * Copyright (C) 2004 Novell, Inc.  All rights reserved.
   * Copyright (C) 2004 IBM, Inc. All rights reserved.
   *
   * Licensed under the GNU GPL v2.
   *
   * Authors:
   *	Robert Love		<rml@novell.com>
   *	Kay Sievers		<kay.sievers@vrfy.org>
   *	Arjan van de Ven	<arjanv@redhat.com>
   *	Greg Kroah-Hartman	<greg@kroah.com>
   */
  
  #include <linux/spinlock.h>
2d38f9a4f   Denis V. Lunev   [NETNS]: Do no in...
18
19
  #include <linux/string.h>
  #include <linux/kobject.h>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
20
21
  #include <linux/export.h>
  #include <linux/kmod.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
22
  #include <linux/slab.h>
417daa1e8   Eric W. Biederman   hotplug: netns aw...
23
  #include <linux/user_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
  #include <linux/socket.h>
  #include <linux/skbuff.h>
  #include <linux/netlink.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include <net/sock.h>
07e98962f   Eric W. Biederman   kobject: Send hot...
28
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30

cd030c4cb   Cornelia Huck   kobject: fix link...
31
  u64 uevent_seqnum;
6a8d8abb6   Kay Sievers   Driver core: add ...
32
  char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
07e98962f   Eric W. Biederman   kobject: Send hot...
33
34
35
36
37
38
  #ifdef CONFIG_NET
  struct uevent_sock {
  	struct list_head list;
  	struct sock *sk;
  };
  static LIST_HEAD(uevent_sock_list);
cd030c4cb   Cornelia Huck   kobject: fix link...
39
  #endif
7b60a18da   Andrew Vagin   uevent: send even...
40
41
  /* This lock protects uevent_seqnum and uevent_sock_list */
  static DEFINE_MUTEX(uevent_sock_mutex);
5c5daf657   Kay Sievers   Driver core: excl...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  /* the strings here must match the enum in include/linux/kobject.h */
  static const char *kobject_actions[] = {
  	[KOBJ_ADD] =		"add",
  	[KOBJ_REMOVE] =		"remove",
  	[KOBJ_CHANGE] =		"change",
  	[KOBJ_MOVE] =		"move",
  	[KOBJ_ONLINE] =		"online",
  	[KOBJ_OFFLINE] =	"offline",
  };
  
  /**
   * kobject_action_type - translate action string to numeric type
   *
   * @buf: buffer containing the action string, newline is ignored
   * @len: length of buffer
   * @type: pointer to the location to store the action type
   *
   * Returns 0 if the action string was recognized.
   */
  int kobject_action_type(const char *buf, size_t count,
  			enum kobject_action *type)
  {
  	enum kobject_action action;
  	int ret = -EINVAL;
a9edadbf7   Mark Lord   fix uevent action...
66
67
  	if (count && (buf[count-1] == '
  ' || buf[count-1] == '\0'))
5c5daf657   Kay Sievers   Driver core: excl...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  		count--;
  
  	if (!count)
  		goto out;
  
  	for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) {
  		if (strncmp(kobject_actions[action], buf, count) != 0)
  			continue;
  		if (kobject_actions[action][count] != '\0')
  			continue;
  		*type = action;
  		ret = 0;
  		break;
  	}
  out:
  	return ret;
  }
c84212860   Andrew Morton   lib/kobject_ueven...
85
  #ifdef CONFIG_NET
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
  {
  	struct kobject *kobj = data;
  	const struct kobj_ns_type_operations *ops;
  
  	ops = kobj_ns_ops(kobj);
  	if (ops) {
  		const void *sock_ns, *ns;
  		ns = kobj->ktype->namespace(kobj);
  		sock_ns = ops->netlink_ns(dsk);
  		return sock_ns != ns;
  	}
  
  	return 0;
  }
c84212860   Andrew Morton   lib/kobject_ueven...
101
  #endif
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
102

417daa1e8   Eric W. Biederman   hotplug: netns aw...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  static int kobj_usermode_filter(struct kobject *kobj)
  {
  	const struct kobj_ns_type_operations *ops;
  
  	ops = kobj_ns_ops(kobj);
  	if (ops) {
  		const void *init_ns, *ns;
  		ns = kobj->ktype->namespace(kobj);
  		init_ns = ops->initial_ns();
  		return ns != init_ns;
  	}
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  /**
8a82472f8   Cornelia Huck   driver core: Intr...
118
   * kobject_uevent_env - send an uevent with environmental data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
   *
ccd490a3c   Kay Sievers   Driver core: kern...
120
   * @action: action that is happening
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
   * @kobj: struct kobject that the action is happening to
8a82472f8   Cornelia Huck   driver core: Intr...
122
   * @envp_ext: pointer to environmental data
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
123
   *
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
124
   * Returns 0 if kobject_uevent_env() is completed with success or the
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
125
   * corresponding error when it fails.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
127
  int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
7eff2e7a8   Kay Sievers   Driver core: chan...
128
  		       char *envp_ext[])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  {
7eff2e7a8   Kay Sievers   Driver core: chan...
130
131
  	struct kobj_uevent_env *env;
  	const char *action_string = kobject_actions[action];
5f123fbd8   Kay Sievers   [PATCH] merge kob...
132
133
134
135
  	const char *devpath = NULL;
  	const char *subsystem;
  	struct kobject *top_kobj;
  	struct kset *kset;
9cd43611c   Emese Revfy   kobject: Constify...
136
  	const struct kset_uevent_ops *uevent_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  	int i = 0;
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
138
  	int retval = 0;
07e98962f   Eric W. Biederman   kobject: Send hot...
139
140
141
  #ifdef CONFIG_NET
  	struct uevent_sock *ue_sk;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142

9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
143
144
  	pr_debug("kobject: '%s' (%p): %s
  ",
810304db7   Harvey Harrison   lib: replace rema...
145
  		 kobject_name(kobj), kobj, __func__);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
146

5f123fbd8   Kay Sievers   [PATCH] merge kob...
147
148
  	/* search the kset we belong to */
  	top_kobj = kobj;
ccd490a3c   Kay Sievers   Driver core: kern...
149
  	while (!top_kobj->kset && top_kobj->parent)
14193fb91   John Anthony Kazos Jr   Kobject: kobject_...
150
  		top_kobj = top_kobj->parent;
ccd490a3c   Kay Sievers   Driver core: kern...
151

542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
152
  	if (!top_kobj->kset) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
153
154
155
  		pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
  			 "without kset!
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
156
  			 __func__);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
157
158
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159

5f123fbd8   Kay Sievers   [PATCH] merge kob...
160
  	kset = top_kobj->kset;
312c004d3   Kay Sievers   [PATCH] driver co...
161
  	uevent_ops = kset->uevent_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162

f67f129e5   Ming Lei   Driver core: impl...
163
164
165
166
167
168
169
170
  	/* skip the event, if uevent_suppress is set*/
  	if (kobj->uevent_suppress) {
  		pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
  				 "caused the event to drop!
  ",
  				 kobject_name(kobj), kobj, __func__);
  		return 0;
  	}
7eff2e7a8   Kay Sievers   Driver core: chan...
171
  	/* skip the event, if the filter returns zero. */
312c004d3   Kay Sievers   [PATCH] driver co...
172
  	if (uevent_ops && uevent_ops->filter)
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
173
  		if (!uevent_ops->filter(kset, kobj)) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
174
175
176
  			pr_debug("kobject: '%s' (%p): %s: filter function "
  				 "caused the event to drop!
  ",
810304db7   Harvey Harrison   lib: replace rema...
177
  				 kobject_name(kobj), kobj, __func__);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
178
179
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180

864062457   Kay Sievers   driver core: fix ...
181
182
183
184
185
186
  	/* originating subsystem */
  	if (uevent_ops && uevent_ops->name)
  		subsystem = uevent_ops->name(kset, kobj);
  	else
  		subsystem = kobject_name(&kset->kobj);
  	if (!subsystem) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
187
188
189
  		pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
  			 "event to drop!
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
190
  			 __func__);
864062457   Kay Sievers   driver core: fix ...
191
192
  		return 0;
  	}
7eff2e7a8   Kay Sievers   Driver core: chan...
193
194
195
  	/* environment buffer */
  	env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
  	if (!env)
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
196
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

5f123fbd8   Kay Sievers   [PATCH] merge kob...
198
199
  	/* complete object path */
  	devpath = kobject_get_path(kobj, GFP_KERNEL);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
200
201
  	if (!devpath) {
  		retval = -ENOENT;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
202
  		goto exit;
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
203
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204

5f123fbd8   Kay Sievers   [PATCH] merge kob...
205
  	/* default keys */
7eff2e7a8   Kay Sievers   Driver core: chan...
206
207
208
209
210
211
212
213
214
215
216
217
218
  	retval = add_uevent_var(env, "ACTION=%s", action_string);
  	if (retval)
  		goto exit;
  	retval = add_uevent_var(env, "DEVPATH=%s", devpath);
  	if (retval)
  		goto exit;
  	retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
  	if (retval)
  		goto exit;
  
  	/* keys passed in from the caller */
  	if (envp_ext) {
  		for (i = 0; envp_ext[i]; i++) {
c65b9145f   Tejun Heo   uevent: don't pas...
219
  			retval = add_uevent_var(env, "%s", envp_ext[i]);
7eff2e7a8   Kay Sievers   Driver core: chan...
220
221
222
223
  			if (retval)
  				goto exit;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224

5f123fbd8   Kay Sievers   [PATCH] merge kob...
225
  	/* let the kset specific function add its stuff */
312c004d3   Kay Sievers   [PATCH] driver co...
226
  	if (uevent_ops && uevent_ops->uevent) {
7eff2e7a8   Kay Sievers   Driver core: chan...
227
  		retval = uevent_ops->uevent(kset, kobj, env);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  		if (retval) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
229
230
231
  			pr_debug("kobject: '%s' (%p): %s: uevent() returned "
  				 "%d
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
232
  				 __func__, retval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
  			goto exit;
  		}
  	}
0f4dafc05   Kay Sievers   Kobject: auto-cle...
236
237
238
239
240
241
242
243
244
245
  	/*
  	 * Mark "add" and "remove" events in the object to ensure proper
  	 * events to userspace during automatic cleanup. If the object did
  	 * send an "add" event, "remove" will automatically generated by
  	 * the core, if not already done by the caller.
  	 */
  	if (action == KOBJ_ADD)
  		kobj->state_add_uevent_sent = 1;
  	else if (action == KOBJ_REMOVE)
  		kobj->state_remove_uevent_sent = 1;
7b60a18da   Andrew Vagin   uevent: send even...
246
  	mutex_lock(&uevent_sock_mutex);
7eff2e7a8   Kay Sievers   Driver core: chan...
247
  	/* we will send an event, so request a new sequence number */
7b60a18da   Andrew Vagin   uevent: send even...
248
249
250
  	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
  	if (retval) {
  		mutex_unlock(&uevent_sock_mutex);
7eff2e7a8   Kay Sievers   Driver core: chan...
251
  		goto exit;
7b60a18da   Andrew Vagin   uevent: send even...
252
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
254
  #if defined(CONFIG_NET)
5f123fbd8   Kay Sievers   [PATCH] merge kob...
255
  	/* send netlink message */
07e98962f   Eric W. Biederman   kobject: Send hot...
256
257
  	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
  		struct sock *uevent_sock = ue_sk->sk;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
258
259
  		struct sk_buff *skb;
  		size_t len;
74099b18b   Kay Sievers   driver-core: skip...
260
261
  		if (!netlink_has_listeners(uevent_sock, 1))
  			continue;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
262
263
  		/* allocate message with the maximum possible size */
  		len = strlen(action_string) + strlen(devpath) + 2;
7eff2e7a8   Kay Sievers   Driver core: chan...
264
  		skb = alloc_skb(len + env->buflen, GFP_KERNEL);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
265
  		if (skb) {
7eff2e7a8   Kay Sievers   Driver core: chan...
266
  			char *scratch;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
267
268
269
270
271
  			/* add header */
  			scratch = skb_put(skb, len);
  			sprintf(scratch, "%s@%s", action_string, devpath);
  
  			/* copy keys to our continuous event payload buffer */
7eff2e7a8   Kay Sievers   Driver core: chan...
272
273
  			for (i = 0; i < env->envp_idx; i++) {
  				len = strlen(env->envp[i]) + 1;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
274
  				scratch = skb_put(skb, len);
7eff2e7a8   Kay Sievers   Driver core: chan...
275
  				strcpy(scratch, env->envp[i]);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
276
277
278
  			}
  
  			NETLINK_CB(skb).dst_group = 1;
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
279
280
281
282
  			retval = netlink_broadcast_filtered(uevent_sock, skb,
  							    0, 1, GFP_KERNEL,
  							    kobj_bcast_filter,
  							    kobj);
ff491a733   Pablo Neira Ayuso   netlink: change r...
283
  			/* ENOBUFS should be handled in userspace */
ebf4127cd   Milan Broz   kobj_uevent: Igno...
284
  			if (retval == -ENOBUFS || retval == -ESRCH)
ff491a733   Pablo Neira Ayuso   netlink: change r...
285
  				retval = 0;
e0d7bf5d5   Ming Lei   kobject: return t...
286
287
  		} else
  			retval = -ENOMEM;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
288
  	}
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
289
  #endif
7b60a18da   Andrew Vagin   uevent: send even...
290
  	mutex_unlock(&uevent_sock_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291

5f123fbd8   Kay Sievers   [PATCH] merge kob...
292
  	/* call uevent_helper, usually only enabled during early boot */
417daa1e8   Eric W. Biederman   hotplug: netns aw...
293
  	if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
5f123fbd8   Kay Sievers   [PATCH] merge kob...
294
  		char *argv [3];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295

312c004d3   Kay Sievers   [PATCH] driver co...
296
  		argv [0] = uevent_helper;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
297
298
  		argv [1] = (char *)subsystem;
  		argv [2] = NULL;
7eff2e7a8   Kay Sievers   Driver core: chan...
299
300
301
  		retval = add_uevent_var(env, "HOME=/");
  		if (retval)
  			goto exit;
e374a2bfe   Greg Kroah-Hartman   Kobject: fix codi...
302
303
  		retval = add_uevent_var(env,
  					"PATH=/sbin:/bin:/usr/sbin:/usr/bin");
7eff2e7a8   Kay Sievers   Driver core: chan...
304
305
  		if (retval)
  			goto exit;
0ad1d6f37   Wang Chen   kobject: Transmit...
306
  		retval = call_usermodehelper(argv[0], argv,
05f54c13c   Hugh Dickins   Revert "kobject: ...
307
  					     env->envp, UMH_WAIT_EXEC);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
308
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
  
  exit:
5f123fbd8   Kay Sievers   [PATCH] merge kob...
311
  	kfree(devpath);
7eff2e7a8   Kay Sievers   Driver core: chan...
312
  	kfree(env);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
313
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
  }
8a82472f8   Cornelia Huck   driver core: Intr...
315
316
317
  EXPORT_SYMBOL_GPL(kobject_uevent_env);
  
  /**
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
318
   * kobject_uevent - notify userspace by sending an uevent
8a82472f8   Cornelia Huck   driver core: Intr...
319
   *
ccd490a3c   Kay Sievers   Driver core: kern...
320
   * @action: action that is happening
8a82472f8   Cornelia Huck   driver core: Intr...
321
   * @kobj: struct kobject that the action is happening to
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
322
323
324
   *
   * Returns 0 if kobject_uevent() is completed with success or the
   * corresponding error when it fails.
8a82472f8   Cornelia Huck   driver core: Intr...
325
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
326
  int kobject_uevent(struct kobject *kobj, enum kobject_action action)
8a82472f8   Cornelia Huck   driver core: Intr...
327
  {
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
328
  	return kobject_uevent_env(kobj, action, NULL);
8a82472f8   Cornelia Huck   driver core: Intr...
329
  }
312c004d3   Kay Sievers   [PATCH] driver co...
330
  EXPORT_SYMBOL_GPL(kobject_uevent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
332
  
  /**
7eff2e7a8   Kay Sievers   Driver core: chan...
333
334
335
   * add_uevent_var - add key value string to the environment buffer
   * @env: environment buffer structure
   * @format: printf format for the key=value pair
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
339
   *
   * Returns 0 if environment variable was added successfully or -ENOMEM
   * if no space was available.
   */
7eff2e7a8   Kay Sievers   Driver core: chan...
340
  int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  {
  	va_list args;
7eff2e7a8   Kay Sievers   Driver core: chan...
343
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344

7eff2e7a8   Kay Sievers   Driver core: chan...
345
  	if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
346
347
  		WARN(1, KERN_ERR "add_uevent_var: too many keys
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
349
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
  
  	va_start(args, format);
7eff2e7a8   Kay Sievers   Driver core: chan...
352
353
354
  	len = vsnprintf(&env->buf[env->buflen],
  			sizeof(env->buf) - env->buflen,
  			format, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
  	va_end(args);
7eff2e7a8   Kay Sievers   Driver core: chan...
356
  	if (len >= (sizeof(env->buf) - env->buflen)) {
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
357
358
  		WARN(1, KERN_ERR "add_uevent_var: buffer size too small
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
360
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361

7eff2e7a8   Kay Sievers   Driver core: chan...
362
363
  	env->envp[env->envp_idx++] = &env->buf[env->buflen];
  	env->buflen += len + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
  	return 0;
  }
312c004d3   Kay Sievers   [PATCH] driver co...
366
  EXPORT_SYMBOL_GPL(add_uevent_var);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367

4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
368
  #if defined(CONFIG_NET)
07e98962f   Eric W. Biederman   kobject: Send hot...
369
  static int uevent_net_init(struct net *net)
5f123fbd8   Kay Sievers   [PATCH] merge kob...
370
  {
07e98962f   Eric W. Biederman   kobject: Send hot...
371
  	struct uevent_sock *ue_sk;
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
372
373
374
  	struct netlink_kernel_cfg cfg = {
  		.groups	= 1,
  	};
07e98962f   Eric W. Biederman   kobject: Send hot...
375
376
377
378
379
380
  
  	ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
  	if (!ue_sk)
  		return -ENOMEM;
  
  	ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
381
  					  THIS_MODULE, &cfg);
07e98962f   Eric W. Biederman   kobject: Send hot...
382
  	if (!ue_sk->sk) {
5f123fbd8   Kay Sievers   [PATCH] merge kob...
383
384
385
  		printk(KERN_ERR
  		       "kobject_uevent: unable to create netlink socket!
  ");
743db2d90   Dan Carpenter   kobject: free mem...
386
  		kfree(ue_sk);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
387
388
  		return -ENODEV;
  	}
07e98962f   Eric W. Biederman   kobject: Send hot...
389
390
391
  	mutex_lock(&uevent_sock_mutex);
  	list_add_tail(&ue_sk->list, &uevent_sock_list);
  	mutex_unlock(&uevent_sock_mutex);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
392
393
  	return 0;
  }
07e98962f   Eric W. Biederman   kobject: Send hot...
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
  static void uevent_net_exit(struct net *net)
  {
  	struct uevent_sock *ue_sk;
  
  	mutex_lock(&uevent_sock_mutex);
  	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
  		if (sock_net(ue_sk->sk) == net)
  			goto found;
  	}
  	mutex_unlock(&uevent_sock_mutex);
  	return;
  
  found:
  	list_del(&ue_sk->list);
  	mutex_unlock(&uevent_sock_mutex);
  
  	netlink_kernel_release(ue_sk->sk);
  	kfree(ue_sk);
  }
  
  static struct pernet_operations uevent_net_ops = {
  	.init	= uevent_net_init,
  	.exit	= uevent_net_exit,
  };
  
  static int __init kobject_uevent_init(void)
  {
  	netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV);
  	return register_pernet_subsys(&uevent_net_ops);
  }
5f123fbd8   Kay Sievers   [PATCH] merge kob...
424
  postcore_initcall(kobject_uevent_init);
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
425
  #endif