Blame view

lib/kobject_uevent.c 11.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
  #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>
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;
86d56134f   Michael Marineau   kobject: Make sup...
31
  #ifdef CONFIG_UEVENT_HELPER
6a8d8abb6   Kay Sievers   Driver core: add ...
32
  char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
86d56134f   Michael Marineau   kobject: Make sup...
33
  #endif
07e98962f   Eric W. Biederman   kobject: Send hot...
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);
cd030c4cb   Cornelia Huck   kobject: fix link...
40
  #endif
7b60a18da   Andrew Vagin   uevent: send even...
41
42
  /* This lock protects uevent_seqnum and uevent_sock_list */
  static DEFINE_MUTEX(uevent_sock_mutex);
5c5daf657   Kay Sievers   Driver core: excl...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  /* 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...
67
68
  	if (count && (buf[count-1] == '
  ' || buf[count-1] == '\0'))
5c5daf657   Kay Sievers   Driver core: excl...
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  		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...
86
  #ifdef CONFIG_NET
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
87
88
  static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
  {
82ef3d5d5   Weilong Chen   net: fix "queues"...
89
  	struct kobject *kobj = data, *ksobj;
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
90
91
92
  	const struct kobj_ns_type_operations *ops;
  
  	ops = kobj_ns_ops(kobj);
82ef3d5d5   Weilong Chen   net: fix "queues"...
93
94
95
96
97
98
99
  	if (!ops && kobj->kset) {
  		ksobj = &kobj->kset->kobj;
  		if (ksobj->parent != NULL)
  			ops = kobj_ns_ops(ksobj->parent);
  	}
  
  	if (ops && ops->netlink_ns && kobj->ktype->namespace) {
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
100
101
102
103
104
105
106
107
  		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...
108
  #endif
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
109

86d56134f   Michael Marineau   kobject: Make sup...
110
  #ifdef CONFIG_UEVENT_HELPER
417daa1e8   Eric W. Biederman   hotplug: netns aw...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  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;
  }
bcccff93a   Vladimir Davydov   kobject: don't bl...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
  {
  	int len;
  
  	len = strlcpy(&env->buf[env->buflen], subsystem,
  		      sizeof(env->buf) - env->buflen);
  	if (len >= (sizeof(env->buf) - env->buflen)) {
  		WARN(1, KERN_ERR "init_uevent_argv: buffer size too small
  ");
  		return -ENOMEM;
  	}
  
  	env->argv[0] = uevent_helper;
  	env->argv[1] = &env->buf[env->buflen];
  	env->argv[2] = NULL;
  
  	env->buflen += len + 1;
  	return 0;
  }
  
  static void cleanup_uevent_env(struct subprocess_info *info)
  {
  	kfree(info->data);
  }
86d56134f   Michael Marineau   kobject: Make sup...
149
  #endif
bcccff93a   Vladimir Davydov   kobject: don't bl...
150

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  /**
8a82472f8   Cornelia Huck   driver core: Intr...
152
   * kobject_uevent_env - send an uevent with environmental data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
   *
ccd490a3c   Kay Sievers   Driver core: kern...
154
   * @action: action that is happening
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
   * @kobj: struct kobject that the action is happening to
8a82472f8   Cornelia Huck   driver core: Intr...
156
   * @envp_ext: pointer to environmental data
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
157
   *
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
158
   * Returns 0 if kobject_uevent_env() is completed with success or the
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
159
   * corresponding error when it fails.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
161
  int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
7eff2e7a8   Kay Sievers   Driver core: chan...
162
  		       char *envp_ext[])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  {
7eff2e7a8   Kay Sievers   Driver core: chan...
164
165
  	struct kobj_uevent_env *env;
  	const char *action_string = kobject_actions[action];
5f123fbd8   Kay Sievers   [PATCH] merge kob...
166
167
168
169
  	const char *devpath = NULL;
  	const char *subsystem;
  	struct kobject *top_kobj;
  	struct kset *kset;
9cd43611c   Emese Revfy   kobject: Constify...
170
  	const struct kset_uevent_ops *uevent_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  	int i = 0;
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
172
  	int retval = 0;
07e98962f   Eric W. Biederman   kobject: Send hot...
173
174
175
  #ifdef CONFIG_NET
  	struct uevent_sock *ue_sk;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176

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

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

542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
186
  	if (!top_kobj->kset) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
187
188
189
  		pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
  			 "without kset!
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
190
  			 __func__);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
191
192
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

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

f67f129e5   Ming Lei   Driver core: impl...
197
198
199
200
201
202
203
204
  	/* 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...
205
  	/* skip the event, if the filter returns zero. */
312c004d3   Kay Sievers   [PATCH] driver co...
206
  	if (uevent_ops && uevent_ops->filter)
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
207
  		if (!uevent_ops->filter(kset, kobj)) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
208
209
210
  			pr_debug("kobject: '%s' (%p): %s: filter function "
  				 "caused the event to drop!
  ",
810304db7   Harvey Harrison   lib: replace rema...
211
  				 kobject_name(kobj), kobj, __func__);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
212
213
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

864062457   Kay Sievers   driver core: fix ...
215
216
217
218
219
220
  	/* 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...
221
222
223
  		pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
  			 "event to drop!
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
224
  			 __func__);
864062457   Kay Sievers   driver core: fix ...
225
226
  		return 0;
  	}
7eff2e7a8   Kay Sievers   Driver core: chan...
227
228
229
  	/* environment buffer */
  	env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
  	if (!env)
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
230
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231

5f123fbd8   Kay Sievers   [PATCH] merge kob...
232
233
  	/* complete object path */
  	devpath = kobject_get_path(kobj, GFP_KERNEL);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
234
235
  	if (!devpath) {
  		retval = -ENOENT;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
236
  		goto exit;
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
237
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238

5f123fbd8   Kay Sievers   [PATCH] merge kob...
239
  	/* default keys */
7eff2e7a8   Kay Sievers   Driver core: chan...
240
241
242
243
244
245
246
247
248
249
250
251
252
  	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...
253
  			retval = add_uevent_var(env, "%s", envp_ext[i]);
7eff2e7a8   Kay Sievers   Driver core: chan...
254
255
256
257
  			if (retval)
  				goto exit;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258

5f123fbd8   Kay Sievers   [PATCH] merge kob...
259
  	/* let the kset specific function add its stuff */
312c004d3   Kay Sievers   [PATCH] driver co...
260
  	if (uevent_ops && uevent_ops->uevent) {
7eff2e7a8   Kay Sievers   Driver core: chan...
261
  		retval = uevent_ops->uevent(kset, kobj, env);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  		if (retval) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
263
264
265
  			pr_debug("kobject: '%s' (%p): %s: uevent() returned "
  				 "%d
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
266
  				 __func__, retval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
  			goto exit;
  		}
  	}
0f4dafc05   Kay Sievers   Kobject: auto-cle...
270
271
272
273
274
275
276
277
278
279
  	/*
  	 * 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...
280
  	mutex_lock(&uevent_sock_mutex);
7eff2e7a8   Kay Sievers   Driver core: chan...
281
  	/* we will send an event, so request a new sequence number */
7b60a18da   Andrew Vagin   uevent: send even...
282
283
284
  	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...
285
  		goto exit;
7b60a18da   Andrew Vagin   uevent: send even...
286
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287

4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
288
  #if defined(CONFIG_NET)
5f123fbd8   Kay Sievers   [PATCH] merge kob...
289
  	/* send netlink message */
07e98962f   Eric W. Biederman   kobject: Send hot...
290
291
  	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
  		struct sock *uevent_sock = ue_sk->sk;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
292
293
  		struct sk_buff *skb;
  		size_t len;
74099b18b   Kay Sievers   driver-core: skip...
294
295
  		if (!netlink_has_listeners(uevent_sock, 1))
  			continue;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
296
297
  		/* allocate message with the maximum possible size */
  		len = strlen(action_string) + strlen(devpath) + 2;
7eff2e7a8   Kay Sievers   Driver core: chan...
298
  		skb = alloc_skb(len + env->buflen, GFP_KERNEL);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
299
  		if (skb) {
7eff2e7a8   Kay Sievers   Driver core: chan...
300
  			char *scratch;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
301
302
303
304
305
  			/* 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...
306
307
  			for (i = 0; i < env->envp_idx; i++) {
  				len = strlen(env->envp[i]) + 1;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
308
  				scratch = skb_put(skb, len);
7eff2e7a8   Kay Sievers   Driver core: chan...
309
  				strcpy(scratch, env->envp[i]);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
310
311
312
  			}
  
  			NETLINK_CB(skb).dst_group = 1;
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
313
314
315
316
  			retval = netlink_broadcast_filtered(uevent_sock, skb,
  							    0, 1, GFP_KERNEL,
  							    kobj_bcast_filter,
  							    kobj);
ff491a733   Pablo Neira Ayuso   netlink: change r...
317
  			/* ENOBUFS should be handled in userspace */
ebf4127cd   Milan Broz   kobj_uevent: Igno...
318
  			if (retval == -ENOBUFS || retval == -ESRCH)
ff491a733   Pablo Neira Ayuso   netlink: change r...
319
  				retval = 0;
e0d7bf5d5   Ming Lei   kobject: return t...
320
321
  		} else
  			retval = -ENOMEM;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
322
  	}
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
323
  #endif
7b60a18da   Andrew Vagin   uevent: send even...
324
  	mutex_unlock(&uevent_sock_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325

86d56134f   Michael Marineau   kobject: Make sup...
326
  #ifdef CONFIG_UEVENT_HELPER
5f123fbd8   Kay Sievers   [PATCH] merge kob...
327
  	/* call uevent_helper, usually only enabled during early boot */
417daa1e8   Eric W. Biederman   hotplug: netns aw...
328
  	if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
bcccff93a   Vladimir Davydov   kobject: don't bl...
329
  		struct subprocess_info *info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330

7eff2e7a8   Kay Sievers   Driver core: chan...
331
332
333
  		retval = add_uevent_var(env, "HOME=/");
  		if (retval)
  			goto exit;
e374a2bfe   Greg Kroah-Hartman   Kobject: fix codi...
334
335
  		retval = add_uevent_var(env,
  					"PATH=/sbin:/bin:/usr/sbin:/usr/bin");
7eff2e7a8   Kay Sievers   Driver core: chan...
336
337
  		if (retval)
  			goto exit;
bcccff93a   Vladimir Davydov   kobject: don't bl...
338
339
340
  		retval = init_uevent_argv(env, subsystem);
  		if (retval)
  			goto exit;
7eff2e7a8   Kay Sievers   Driver core: chan...
341

bcccff93a   Vladimir Davydov   kobject: don't bl...
342
343
344
345
346
347
348
349
  		retval = -ENOMEM;
  		info = call_usermodehelper_setup(env->argv[0], env->argv,
  						 env->envp, GFP_KERNEL,
  						 NULL, cleanup_uevent_env, env);
  		if (info) {
  			retval = call_usermodehelper_exec(info, UMH_NO_WAIT);
  			env = NULL;	/* freed by cleanup_uevent_env */
  		}
5f123fbd8   Kay Sievers   [PATCH] merge kob...
350
  	}
86d56134f   Michael Marineau   kobject: Make sup...
351
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
  
  exit:
5f123fbd8   Kay Sievers   [PATCH] merge kob...
354
  	kfree(devpath);
7eff2e7a8   Kay Sievers   Driver core: chan...
355
  	kfree(env);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
356
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  }
8a82472f8   Cornelia Huck   driver core: Intr...
358
359
360
  EXPORT_SYMBOL_GPL(kobject_uevent_env);
  
  /**
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
361
   * kobject_uevent - notify userspace by sending an uevent
8a82472f8   Cornelia Huck   driver core: Intr...
362
   *
ccd490a3c   Kay Sievers   Driver core: kern...
363
   * @action: action that is happening
8a82472f8   Cornelia Huck   driver core: Intr...
364
   * @kobj: struct kobject that the action is happening to
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
365
366
367
   *
   * Returns 0 if kobject_uevent() is completed with success or the
   * corresponding error when it fails.
8a82472f8   Cornelia Huck   driver core: Intr...
368
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
369
  int kobject_uevent(struct kobject *kobj, enum kobject_action action)
8a82472f8   Cornelia Huck   driver core: Intr...
370
  {
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
371
  	return kobject_uevent_env(kobj, action, NULL);
8a82472f8   Cornelia Huck   driver core: Intr...
372
  }
312c004d3   Kay Sievers   [PATCH] driver co...
373
  EXPORT_SYMBOL_GPL(kobject_uevent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
  
  /**
7eff2e7a8   Kay Sievers   Driver core: chan...
376
377
378
   * 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
379
380
381
382
   *
   * Returns 0 if environment variable was added successfully or -ENOMEM
   * if no space was available.
   */
7eff2e7a8   Kay Sievers   Driver core: chan...
383
  int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
  {
  	va_list args;
7eff2e7a8   Kay Sievers   Driver core: chan...
386
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387

7eff2e7a8   Kay Sievers   Driver core: chan...
388
  	if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
389
390
  		WARN(1, KERN_ERR "add_uevent_var: too many keys
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
392
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
  
  	va_start(args, format);
7eff2e7a8   Kay Sievers   Driver core: chan...
395
396
397
  	len = vsnprintf(&env->buf[env->buflen],
  			sizeof(env->buf) - env->buflen,
  			format, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
  	va_end(args);
7eff2e7a8   Kay Sievers   Driver core: chan...
399
  	if (len >= (sizeof(env->buf) - env->buflen)) {
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
400
401
  		WARN(1, KERN_ERR "add_uevent_var: buffer size too small
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
403
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404

7eff2e7a8   Kay Sievers   Driver core: chan...
405
406
  	env->envp[env->envp_idx++] = &env->buf[env->buflen];
  	env->buflen += len + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
  	return 0;
  }
312c004d3   Kay Sievers   [PATCH] driver co...
409
  EXPORT_SYMBOL_GPL(add_uevent_var);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410

4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
411
  #if defined(CONFIG_NET)
07e98962f   Eric W. Biederman   kobject: Send hot...
412
  static int uevent_net_init(struct net *net)
5f123fbd8   Kay Sievers   [PATCH] merge kob...
413
  {
07e98962f   Eric W. Biederman   kobject: Send hot...
414
  	struct uevent_sock *ue_sk;
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
415
416
  	struct netlink_kernel_cfg cfg = {
  		.groups	= 1,
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
417
  		.flags	= NL_CFG_F_NONROOT_RECV,
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
418
  	};
07e98962f   Eric W. Biederman   kobject: Send hot...
419
420
421
422
  
  	ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
  	if (!ue_sk)
  		return -ENOMEM;
9f00d9776   Pablo Neira Ayuso   netlink: hide str...
423
  	ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);
07e98962f   Eric W. Biederman   kobject: Send hot...
424
  	if (!ue_sk->sk) {
5f123fbd8   Kay Sievers   [PATCH] merge kob...
425
426
427
  		printk(KERN_ERR
  		       "kobject_uevent: unable to create netlink socket!
  ");
743db2d90   Dan Carpenter   kobject: free mem...
428
  		kfree(ue_sk);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
429
430
  		return -ENODEV;
  	}
07e98962f   Eric W. Biederman   kobject: Send hot...
431
432
433
  	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...
434
435
  	return 0;
  }
07e98962f   Eric W. Biederman   kobject: Send hot...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
  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)
  {
07e98962f   Eric W. Biederman   kobject: Send hot...
463
464
  	return register_pernet_subsys(&uevent_net_ops);
  }
5f123fbd8   Kay Sievers   [PATCH] merge kob...
465
  postcore_initcall(kobject_uevent_init);
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
466
  #endif