Blame view

lib/kobject_uevent.c 10.3 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
20
  #include <linux/string.h>
  #include <linux/kobject.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
417daa1e8   Eric W. Biederman   hotplug: netns aw...
22
  #include <linux/user_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
  #include <linux/socket.h>
  #include <linux/skbuff.h>
  #include <linux/netlink.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <net/sock.h>
07e98962f   Eric W. Biederman   kobject: Send hot...
27
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

cd030c4cb   Cornelia Huck   kobject: fix link...
30
  u64 uevent_seqnum;
6a8d8abb6   Kay Sievers   Driver core: add ...
31
  char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
cd030c4cb   Cornelia Huck   kobject: fix link...
32
  static DEFINE_SPINLOCK(sequence_lock);
07e98962f   Eric W. Biederman   kobject: Send hot...
33
34
35
36
37
38
39
  #ifdef CONFIG_NET
  struct uevent_sock {
  	struct list_head list;
  	struct sock *sk;
  };
  static LIST_HEAD(uevent_sock_list);
  static DEFINE_MUTEX(uevent_sock_mutex);
cd030c4cb   Cornelia Huck   kobject: fix link...
40
  #endif
5c5daf657   Kay Sievers   Driver core: excl...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  /* 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...
65
66
  	if (count && (buf[count-1] == '
  ' || buf[count-1] == '\0'))
5c5daf657   Kay Sievers   Driver core: excl...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  		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...
84
  #ifdef CONFIG_NET
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  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...
100
  #endif
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
101

417daa1e8   Eric W. Biederman   hotplug: netns aw...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  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
116
  /**
8a82472f8   Cornelia Huck   driver core: Intr...
117
   * kobject_uevent_env - send an uevent with environmental data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
   *
ccd490a3c   Kay Sievers   Driver core: kern...
119
   * @action: action that is happening
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
   * @kobj: struct kobject that the action is happening to
8a82472f8   Cornelia Huck   driver core: Intr...
121
   * @envp_ext: pointer to environmental data
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
122
   *
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
123
   * Returns 0 if kobject_uevent_env() is completed with success or the
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
124
   * corresponding error when it fails.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
126
  int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
7eff2e7a8   Kay Sievers   Driver core: chan...
127
  		       char *envp_ext[])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  {
7eff2e7a8   Kay Sievers   Driver core: chan...
129
130
  	struct kobj_uevent_env *env;
  	const char *action_string = kobject_actions[action];
5f123fbd8   Kay Sievers   [PATCH] merge kob...
131
132
133
134
  	const char *devpath = NULL;
  	const char *subsystem;
  	struct kobject *top_kobj;
  	struct kset *kset;
9cd43611c   Emese Revfy   kobject: Constify...
135
  	const struct kset_uevent_ops *uevent_ops;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
136
  	u64 seq;
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;
7eff2e7a8   Kay Sievers   Driver core: chan...
246
  	/* we will send an event, so request a new sequence number */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  	spin_lock(&sequence_lock);
312c004d3   Kay Sievers   [PATCH] driver co...
248
  	seq = ++uevent_seqnum;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  	spin_unlock(&sequence_lock);
7eff2e7a8   Kay Sievers   Driver core: chan...
250
251
252
  	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
  	if (retval)
  		goto exit;
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
258
  	mutex_lock(&uevent_sock_mutex);
  	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
  		struct sock *uevent_sock = ue_sk->sk;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
259
260
261
262
263
  		struct sk_buff *skb;
  		size_t len;
  
  		/* 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
284
285
  			/* ENOBUFS should be handled in userspace */
  			if (retval == -ENOBUFS)
  				retval = 0;
e0d7bf5d5   Ming Lei   kobject: return t...
286
287
  		} else
  			retval = -ENOMEM;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
288
  	}
07e98962f   Eric W. Biederman   kobject: Send hot...
289
  	mutex_unlock(&uevent_sock_mutex);
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
290
  #endif
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
372
373
374
375
376
377
378
379
  	struct uevent_sock *ue_sk;
  
  	ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
  	if (!ue_sk)
  		return -ENOMEM;
  
  	ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,
  					  1, NULL, NULL, THIS_MODULE);
  	if (!ue_sk->sk) {
5f123fbd8   Kay Sievers   [PATCH] merge kob...
380
381
382
  		printk(KERN_ERR
  		       "kobject_uevent: unable to create netlink socket!
  ");
743db2d90   Dan Carpenter   kobject: free mem...
383
  		kfree(ue_sk);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
384
385
  		return -ENODEV;
  	}
07e98962f   Eric W. Biederman   kobject: Send hot...
386
387
388
  	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...
389
390
  	return 0;
  }
07e98962f   Eric W. Biederman   kobject: Send hot...
391
392
393
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
  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...
421
  postcore_initcall(kobject_uevent_init);
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
422
  #endif