Merge tag 'linux-watchdog-5.10-rc1' of git://www.linux-watchdog.org/linux-watchdog
[linux-2.6-microblaze.git] / drivers / net / netconsole.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  linux/drivers/net/netconsole.c
4  *
5  *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
6  *
7  *  This file contains the implementation of an IRQ-safe, crash-safe
8  *  kernel console implementation that outputs kernel messages to the
9  *  network.
10  *
11  * Modification history:
12  *
13  * 2001-09-17    started by Ingo Molnar.
14  * 2003-08-11    2.6 port by Matt Mackall
15  *               simplified options
16  *               generic card hooks
17  *               works non-modular
18  * 2003-09-07    rewritten with netpoll api
19  */
20
21 /****************************************************************
22  *
23  ****************************************************************/
24
25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26
27 #include <linux/mm.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 #include <linux/console.h>
32 #include <linux/moduleparam.h>
33 #include <linux/kernel.h>
34 #include <linux/string.h>
35 #include <linux/netpoll.h>
36 #include <linux/inet.h>
37 #include <linux/configfs.h>
38 #include <linux/etherdevice.h>
39
40 MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>");
41 MODULE_DESCRIPTION("Console driver for network interfaces");
42 MODULE_LICENSE("GPL");
43
44 #define MAX_PARAM_LENGTH        256
45 #define MAX_PRINT_CHUNK         1000
46
47 static char config[MAX_PARAM_LENGTH];
48 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
49 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
50
51 static bool oops_only = false;
52 module_param(oops_only, bool, 0600);
53 MODULE_PARM_DESC(oops_only, "Only log oops messages");
54
55 #ifndef MODULE
56 static int __init option_setup(char *opt)
57 {
58         strlcpy(config, opt, MAX_PARAM_LENGTH);
59         return 1;
60 }
61 __setup("netconsole=", option_setup);
62 #endif  /* MODULE */
63
64 /* Linked list of all configured targets */
65 static LIST_HEAD(target_list);
66
67 /* This needs to be a spinlock because write_msg() cannot sleep */
68 static DEFINE_SPINLOCK(target_list_lock);
69
70 /*
71  * Console driver for extended netconsoles.  Registered on the first use to
72  * avoid unnecessarily enabling ext message formatting.
73  */
74 static struct console netconsole_ext;
75
76 /**
77  * struct netconsole_target - Represents a configured netconsole target.
78  * @list:       Links this target into the target_list.
79  * @item:       Links us into the configfs subsystem hierarchy.
80  * @enabled:    On / off knob to enable / disable target.
81  *              Visible from userspace (read-write).
82  *              We maintain a strict 1:1 correspondence between this and
83  *              whether the corresponding netpoll is active or inactive.
84  *              Also, other parameters of a target may be modified at
85  *              runtime only when it is disabled (enabled == 0).
86  * @np:         The netpoll structure for this target.
87  *              Contains the other userspace visible parameters:
88  *              dev_name        (read-write)
89  *              local_port      (read-write)
90  *              remote_port     (read-write)
91  *              local_ip        (read-write)
92  *              remote_ip       (read-write)
93  *              local_mac       (read-only)
94  *              remote_mac      (read-write)
95  */
96 struct netconsole_target {
97         struct list_head        list;
98 #ifdef  CONFIG_NETCONSOLE_DYNAMIC
99         struct config_item      item;
100 #endif
101         bool                    enabled;
102         bool                    extended;
103         struct netpoll          np;
104 };
105
106 #ifdef  CONFIG_NETCONSOLE_DYNAMIC
107
108 static struct configfs_subsystem netconsole_subsys;
109 static DEFINE_MUTEX(dynamic_netconsole_mutex);
110
111 static int __init dynamic_netconsole_init(void)
112 {
113         config_group_init(&netconsole_subsys.su_group);
114         mutex_init(&netconsole_subsys.su_mutex);
115         return configfs_register_subsystem(&netconsole_subsys);
116 }
117
118 static void __exit dynamic_netconsole_exit(void)
119 {
120         configfs_unregister_subsystem(&netconsole_subsys);
121 }
122
123 /*
124  * Targets that were created by parsing the boot/module option string
125  * do not exist in the configfs hierarchy (and have NULL names) and will
126  * never go away, so make these a no-op for them.
127  */
128 static void netconsole_target_get(struct netconsole_target *nt)
129 {
130         if (config_item_name(&nt->item))
131                 config_item_get(&nt->item);
132 }
133
134 static void netconsole_target_put(struct netconsole_target *nt)
135 {
136         if (config_item_name(&nt->item))
137                 config_item_put(&nt->item);
138 }
139
140 #else   /* !CONFIG_NETCONSOLE_DYNAMIC */
141
142 static int __init dynamic_netconsole_init(void)
143 {
144         return 0;
145 }
146
147 static void __exit dynamic_netconsole_exit(void)
148 {
149 }
150
151 /*
152  * No danger of targets going away from under us when dynamic
153  * reconfigurability is off.
154  */
155 static void netconsole_target_get(struct netconsole_target *nt)
156 {
157 }
158
159 static void netconsole_target_put(struct netconsole_target *nt)
160 {
161 }
162
163 #endif  /* CONFIG_NETCONSOLE_DYNAMIC */
164
165 /* Allocate new target (from boot/module param) and setup netpoll for it */
166 static struct netconsole_target *alloc_param_target(char *target_config)
167 {
168         int err = -ENOMEM;
169         struct netconsole_target *nt;
170
171         /*
172          * Allocate and initialize with defaults.
173          * Note that these targets get their config_item fields zeroed-out.
174          */
175         nt = kzalloc(sizeof(*nt), GFP_KERNEL);
176         if (!nt)
177                 goto fail;
178
179         nt->np.name = "netconsole";
180         strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
181         nt->np.local_port = 6665;
182         nt->np.remote_port = 6666;
183         eth_broadcast_addr(nt->np.remote_mac);
184
185         if (*target_config == '+') {
186                 nt->extended = true;
187                 target_config++;
188         }
189
190         /* Parse parameters and setup netpoll */
191         err = netpoll_parse_options(&nt->np, target_config);
192         if (err)
193                 goto fail;
194
195         err = netpoll_setup(&nt->np);
196         if (err)
197                 goto fail;
198
199         nt->enabled = true;
200
201         return nt;
202
203 fail:
204         kfree(nt);
205         return ERR_PTR(err);
206 }
207
208 /* Cleanup netpoll for given target (from boot/module param) and free it */
209 static void free_param_target(struct netconsole_target *nt)
210 {
211         netpoll_cleanup(&nt->np);
212         kfree(nt);
213 }
214
215 #ifdef  CONFIG_NETCONSOLE_DYNAMIC
216
217 /*
218  * Our subsystem hierarchy is:
219  *
220  * /sys/kernel/config/netconsole/
221  *                              |
222  *                              <target>/
223  *                              |       enabled
224  *                              |       dev_name
225  *                              |       local_port
226  *                              |       remote_port
227  *                              |       local_ip
228  *                              |       remote_ip
229  *                              |       local_mac
230  *                              |       remote_mac
231  *                              |
232  *                              <target>/...
233  */
234
235 static struct netconsole_target *to_target(struct config_item *item)
236 {
237         return item ?
238                 container_of(item, struct netconsole_target, item) :
239                 NULL;
240 }
241
242 /*
243  * Attribute operations for netconsole_target.
244  */
245
246 static ssize_t enabled_show(struct config_item *item, char *buf)
247 {
248         return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->enabled);
249 }
250
251 static ssize_t extended_show(struct config_item *item, char *buf)
252 {
253         return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->extended);
254 }
255
256 static ssize_t dev_name_show(struct config_item *item, char *buf)
257 {
258         return snprintf(buf, PAGE_SIZE, "%s\n", to_target(item)->np.dev_name);
259 }
260
261 static ssize_t local_port_show(struct config_item *item, char *buf)
262 {
263         return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.local_port);
264 }
265
266 static ssize_t remote_port_show(struct config_item *item, char *buf)
267 {
268         return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.remote_port);
269 }
270
271 static ssize_t local_ip_show(struct config_item *item, char *buf)
272 {
273         struct netconsole_target *nt = to_target(item);
274
275         if (nt->np.ipv6)
276                 return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6);
277         else
278                 return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip);
279 }
280
281 static ssize_t remote_ip_show(struct config_item *item, char *buf)
282 {
283         struct netconsole_target *nt = to_target(item);
284
285         if (nt->np.ipv6)
286                 return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6);
287         else
288                 return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip);
289 }
290
291 static ssize_t local_mac_show(struct config_item *item, char *buf)
292 {
293         struct net_device *dev = to_target(item)->np.dev;
294         static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
295
296         return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast);
297 }
298
299 static ssize_t remote_mac_show(struct config_item *item, char *buf)
300 {
301         return snprintf(buf, PAGE_SIZE, "%pM\n", to_target(item)->np.remote_mac);
302 }
303
304 /*
305  * This one is special -- targets created through the configfs interface
306  * are not enabled (and the corresponding netpoll activated) by default.
307  * The user is expected to set the desired parameters first (which
308  * would enable him to dynamically add new netpoll targets for new
309  * network interfaces as and when they come up).
310  */
311 static ssize_t enabled_store(struct config_item *item,
312                 const char *buf, size_t count)
313 {
314         struct netconsole_target *nt = to_target(item);
315         unsigned long flags;
316         int enabled;
317         int err;
318
319         mutex_lock(&dynamic_netconsole_mutex);
320         err = kstrtoint(buf, 10, &enabled);
321         if (err < 0)
322                 goto out_unlock;
323
324         err = -EINVAL;
325         if (enabled < 0 || enabled > 1)
326                 goto out_unlock;
327         if ((bool)enabled == nt->enabled) {
328                 pr_info("network logging has already %s\n",
329                         nt->enabled ? "started" : "stopped");
330                 goto out_unlock;
331         }
332
333         if (enabled) {  /* true */
334                 if (nt->extended && !(netconsole_ext.flags & CON_ENABLED)) {
335                         netconsole_ext.flags |= CON_ENABLED;
336                         register_console(&netconsole_ext);
337                 }
338
339                 /*
340                  * Skip netpoll_parse_options() -- all the attributes are
341                  * already configured via configfs. Just print them out.
342                  */
343                 netpoll_print_options(&nt->np);
344
345                 err = netpoll_setup(&nt->np);
346                 if (err)
347                         goto out_unlock;
348
349                 pr_info("network logging started\n");
350         } else {        /* false */
351                 /* We need to disable the netconsole before cleaning it up
352                  * otherwise we might end up in write_msg() with
353                  * nt->np.dev == NULL and nt->enabled == true
354                  */
355                 spin_lock_irqsave(&target_list_lock, flags);
356                 nt->enabled = false;
357                 spin_unlock_irqrestore(&target_list_lock, flags);
358                 netpoll_cleanup(&nt->np);
359         }
360
361         nt->enabled = enabled;
362
363         mutex_unlock(&dynamic_netconsole_mutex);
364         return strnlen(buf, count);
365 out_unlock:
366         mutex_unlock(&dynamic_netconsole_mutex);
367         return err;
368 }
369
370 static ssize_t extended_store(struct config_item *item, const char *buf,
371                 size_t count)
372 {
373         struct netconsole_target *nt = to_target(item);
374         int extended;
375         int err;
376
377         mutex_lock(&dynamic_netconsole_mutex);
378         if (nt->enabled) {
379                 pr_err("target (%s) is enabled, disable to update parameters\n",
380                        config_item_name(&nt->item));
381                 err = -EINVAL;
382                 goto out_unlock;
383         }
384
385         err = kstrtoint(buf, 10, &extended);
386         if (err < 0)
387                 goto out_unlock;
388         if (extended < 0 || extended > 1) {
389                 err = -EINVAL;
390                 goto out_unlock;
391         }
392
393         nt->extended = extended;
394
395         mutex_unlock(&dynamic_netconsole_mutex);
396         return strnlen(buf, count);
397 out_unlock:
398         mutex_unlock(&dynamic_netconsole_mutex);
399         return err;
400 }
401
402 static ssize_t dev_name_store(struct config_item *item, const char *buf,
403                 size_t count)
404 {
405         struct netconsole_target *nt = to_target(item);
406         size_t len;
407
408         mutex_lock(&dynamic_netconsole_mutex);
409         if (nt->enabled) {
410                 pr_err("target (%s) is enabled, disable to update parameters\n",
411                        config_item_name(&nt->item));
412                 mutex_unlock(&dynamic_netconsole_mutex);
413                 return -EINVAL;
414         }
415
416         strlcpy(nt->np.dev_name, buf, IFNAMSIZ);
417
418         /* Get rid of possible trailing newline from echo(1) */
419         len = strnlen(nt->np.dev_name, IFNAMSIZ);
420         if (nt->np.dev_name[len - 1] == '\n')
421                 nt->np.dev_name[len - 1] = '\0';
422
423         mutex_unlock(&dynamic_netconsole_mutex);
424         return strnlen(buf, count);
425 }
426
427 static ssize_t local_port_store(struct config_item *item, const char *buf,
428                 size_t count)
429 {
430         struct netconsole_target *nt = to_target(item);
431         int rv = -EINVAL;
432
433         mutex_lock(&dynamic_netconsole_mutex);
434         if (nt->enabled) {
435                 pr_err("target (%s) is enabled, disable to update parameters\n",
436                        config_item_name(&nt->item));
437                 goto out_unlock;
438         }
439
440         rv = kstrtou16(buf, 10, &nt->np.local_port);
441         if (rv < 0)
442                 goto out_unlock;
443         mutex_unlock(&dynamic_netconsole_mutex);
444         return strnlen(buf, count);
445 out_unlock:
446         mutex_unlock(&dynamic_netconsole_mutex);
447         return rv;
448 }
449
450 static ssize_t remote_port_store(struct config_item *item,
451                 const char *buf, size_t count)
452 {
453         struct netconsole_target *nt = to_target(item);
454         int rv = -EINVAL;
455
456         mutex_lock(&dynamic_netconsole_mutex);
457         if (nt->enabled) {
458                 pr_err("target (%s) is enabled, disable to update parameters\n",
459                        config_item_name(&nt->item));
460                 goto out_unlock;
461         }
462
463         rv = kstrtou16(buf, 10, &nt->np.remote_port);
464         if (rv < 0)
465                 goto out_unlock;
466         mutex_unlock(&dynamic_netconsole_mutex);
467         return strnlen(buf, count);
468 out_unlock:
469         mutex_unlock(&dynamic_netconsole_mutex);
470         return rv;
471 }
472
473 static ssize_t local_ip_store(struct config_item *item, const char *buf,
474                 size_t count)
475 {
476         struct netconsole_target *nt = to_target(item);
477
478         mutex_lock(&dynamic_netconsole_mutex);
479         if (nt->enabled) {
480                 pr_err("target (%s) is enabled, disable to update parameters\n",
481                        config_item_name(&nt->item));
482                 goto out_unlock;
483         }
484
485         if (strnchr(buf, count, ':')) {
486                 const char *end;
487                 if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {
488                         if (*end && *end != '\n') {
489                                 pr_err("invalid IPv6 address at: <%c>\n", *end);
490                                 goto out_unlock;
491                         }
492                         nt->np.ipv6 = true;
493                 } else
494                         goto out_unlock;
495         } else {
496                 if (!nt->np.ipv6) {
497                         nt->np.local_ip.ip = in_aton(buf);
498                 } else
499                         goto out_unlock;
500         }
501
502         mutex_unlock(&dynamic_netconsole_mutex);
503         return strnlen(buf, count);
504 out_unlock:
505         mutex_unlock(&dynamic_netconsole_mutex);
506         return -EINVAL;
507 }
508
509 static ssize_t remote_ip_store(struct config_item *item, const char *buf,
510                size_t count)
511 {
512         struct netconsole_target *nt = to_target(item);
513
514         mutex_lock(&dynamic_netconsole_mutex);
515         if (nt->enabled) {
516                 pr_err("target (%s) is enabled, disable to update parameters\n",
517                        config_item_name(&nt->item));
518                 goto out_unlock;
519         }
520
521         if (strnchr(buf, count, ':')) {
522                 const char *end;
523                 if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {
524                         if (*end && *end != '\n') {
525                                 pr_err("invalid IPv6 address at: <%c>\n", *end);
526                                 goto out_unlock;
527                         }
528                         nt->np.ipv6 = true;
529                 } else
530                         goto out_unlock;
531         } else {
532                 if (!nt->np.ipv6) {
533                         nt->np.remote_ip.ip = in_aton(buf);
534                 } else
535                         goto out_unlock;
536         }
537
538         mutex_unlock(&dynamic_netconsole_mutex);
539         return strnlen(buf, count);
540 out_unlock:
541         mutex_unlock(&dynamic_netconsole_mutex);
542         return -EINVAL;
543 }
544
545 static ssize_t remote_mac_store(struct config_item *item, const char *buf,
546                 size_t count)
547 {
548         struct netconsole_target *nt = to_target(item);
549         u8 remote_mac[ETH_ALEN];
550
551         mutex_lock(&dynamic_netconsole_mutex);
552         if (nt->enabled) {
553                 pr_err("target (%s) is enabled, disable to update parameters\n",
554                        config_item_name(&nt->item));
555                 goto out_unlock;
556         }
557
558         if (!mac_pton(buf, remote_mac))
559                 goto out_unlock;
560         if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
561                 goto out_unlock;
562         memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
563
564         mutex_unlock(&dynamic_netconsole_mutex);
565         return strnlen(buf, count);
566 out_unlock:
567         mutex_unlock(&dynamic_netconsole_mutex);
568         return -EINVAL;
569 }
570
571 CONFIGFS_ATTR(, enabled);
572 CONFIGFS_ATTR(, extended);
573 CONFIGFS_ATTR(, dev_name);
574 CONFIGFS_ATTR(, local_port);
575 CONFIGFS_ATTR(, remote_port);
576 CONFIGFS_ATTR(, local_ip);
577 CONFIGFS_ATTR(, remote_ip);
578 CONFIGFS_ATTR_RO(, local_mac);
579 CONFIGFS_ATTR(, remote_mac);
580
581 static struct configfs_attribute *netconsole_target_attrs[] = {
582         &attr_enabled,
583         &attr_extended,
584         &attr_dev_name,
585         &attr_local_port,
586         &attr_remote_port,
587         &attr_local_ip,
588         &attr_remote_ip,
589         &attr_local_mac,
590         &attr_remote_mac,
591         NULL,
592 };
593
594 /*
595  * Item operations and type for netconsole_target.
596  */
597
598 static void netconsole_target_release(struct config_item *item)
599 {
600         kfree(to_target(item));
601 }
602
603 static struct configfs_item_operations netconsole_target_item_ops = {
604         .release                = netconsole_target_release,
605 };
606
607 static const struct config_item_type netconsole_target_type = {
608         .ct_attrs               = netconsole_target_attrs,
609         .ct_item_ops            = &netconsole_target_item_ops,
610         .ct_owner               = THIS_MODULE,
611 };
612
613 /*
614  * Group operations and type for netconsole_subsys.
615  */
616
617 static struct config_item *make_netconsole_target(struct config_group *group,
618                                                   const char *name)
619 {
620         unsigned long flags;
621         struct netconsole_target *nt;
622
623         /*
624          * Allocate and initialize with defaults.
625          * Target is disabled at creation (!enabled).
626          */
627         nt = kzalloc(sizeof(*nt), GFP_KERNEL);
628         if (!nt)
629                 return ERR_PTR(-ENOMEM);
630
631         nt->np.name = "netconsole";
632         strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
633         nt->np.local_port = 6665;
634         nt->np.remote_port = 6666;
635         eth_broadcast_addr(nt->np.remote_mac);
636
637         /* Initialize the config_item member */
638         config_item_init_type_name(&nt->item, name, &netconsole_target_type);
639
640         /* Adding, but it is disabled */
641         spin_lock_irqsave(&target_list_lock, flags);
642         list_add(&nt->list, &target_list);
643         spin_unlock_irqrestore(&target_list_lock, flags);
644
645         return &nt->item;
646 }
647
648 static void drop_netconsole_target(struct config_group *group,
649                                    struct config_item *item)
650 {
651         unsigned long flags;
652         struct netconsole_target *nt = to_target(item);
653
654         spin_lock_irqsave(&target_list_lock, flags);
655         list_del(&nt->list);
656         spin_unlock_irqrestore(&target_list_lock, flags);
657
658         /*
659          * The target may have never been enabled, or was manually disabled
660          * before being removed so netpoll may have already been cleaned up.
661          */
662         if (nt->enabled)
663                 netpoll_cleanup(&nt->np);
664
665         config_item_put(&nt->item);
666 }
667
668 static struct configfs_group_operations netconsole_subsys_group_ops = {
669         .make_item      = make_netconsole_target,
670         .drop_item      = drop_netconsole_target,
671 };
672
673 static const struct config_item_type netconsole_subsys_type = {
674         .ct_group_ops   = &netconsole_subsys_group_ops,
675         .ct_owner       = THIS_MODULE,
676 };
677
678 /* The netconsole configfs subsystem */
679 static struct configfs_subsystem netconsole_subsys = {
680         .su_group       = {
681                 .cg_item        = {
682                         .ci_namebuf     = "netconsole",
683                         .ci_type        = &netconsole_subsys_type,
684                 },
685         },
686 };
687
688 #endif  /* CONFIG_NETCONSOLE_DYNAMIC */
689
690 /* Handle network interface device notifications */
691 static int netconsole_netdev_event(struct notifier_block *this,
692                                    unsigned long event, void *ptr)
693 {
694         unsigned long flags;
695         struct netconsole_target *nt;
696         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
697         bool stopped = false;
698
699         if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
700               event == NETDEV_RELEASE || event == NETDEV_JOIN))
701                 goto done;
702
703         spin_lock_irqsave(&target_list_lock, flags);
704 restart:
705         list_for_each_entry(nt, &target_list, list) {
706                 netconsole_target_get(nt);
707                 if (nt->np.dev == dev) {
708                         switch (event) {
709                         case NETDEV_CHANGENAME:
710                                 strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
711                                 break;
712                         case NETDEV_RELEASE:
713                         case NETDEV_JOIN:
714                         case NETDEV_UNREGISTER:
715                                 /* rtnl_lock already held
716                                  * we might sleep in __netpoll_cleanup()
717                                  */
718                                 spin_unlock_irqrestore(&target_list_lock, flags);
719
720                                 __netpoll_cleanup(&nt->np);
721
722                                 spin_lock_irqsave(&target_list_lock, flags);
723                                 dev_put(nt->np.dev);
724                                 nt->np.dev = NULL;
725                                 nt->enabled = false;
726                                 stopped = true;
727                                 netconsole_target_put(nt);
728                                 goto restart;
729                         }
730                 }
731                 netconsole_target_put(nt);
732         }
733         spin_unlock_irqrestore(&target_list_lock, flags);
734         if (stopped) {
735                 const char *msg = "had an event";
736                 switch (event) {
737                 case NETDEV_UNREGISTER:
738                         msg = "unregistered";
739                         break;
740                 case NETDEV_RELEASE:
741                         msg = "released slaves";
742                         break;
743                 case NETDEV_JOIN:
744                         msg = "is joining a master device";
745                         break;
746                 }
747                 pr_info("network logging stopped on interface %s as it %s\n",
748                         dev->name, msg);
749         }
750
751 done:
752         return NOTIFY_DONE;
753 }
754
755 static struct notifier_block netconsole_netdev_notifier = {
756         .notifier_call  = netconsole_netdev_event,
757 };
758
759 /**
760  * send_ext_msg_udp - send extended log message to target
761  * @nt: target to send message to
762  * @msg: extended log message to send
763  * @msg_len: length of message
764  *
765  * Transfer extended log @msg to @nt.  If @msg is longer than
766  * MAX_PRINT_CHUNK, it'll be split and transmitted in multiple chunks with
767  * ncfrag header field added to identify them.
768  */
769 static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,
770                              int msg_len)
771 {
772         static char buf[MAX_PRINT_CHUNK]; /* protected by target_list_lock */
773         const char *header, *body;
774         int offset = 0;
775         int header_len, body_len;
776
777         if (msg_len <= MAX_PRINT_CHUNK) {
778                 netpoll_send_udp(&nt->np, msg, msg_len);
779                 return;
780         }
781
782         /* need to insert extra header fields, detect header and body */
783         header = msg;
784         body = memchr(msg, ';', msg_len);
785         if (WARN_ON_ONCE(!body))
786                 return;
787
788         header_len = body - header;
789         body_len = msg_len - header_len - 1;
790         body++;
791
792         /*
793          * Transfer multiple chunks with the following extra header.
794          * "ncfrag=<byte-offset>/<total-bytes>"
795          */
796         memcpy(buf, header, header_len);
797
798         while (offset < body_len) {
799                 int this_header = header_len;
800                 int this_chunk;
801
802                 this_header += scnprintf(buf + this_header,
803                                          sizeof(buf) - this_header,
804                                          ",ncfrag=%d/%d;", offset, body_len);
805
806                 this_chunk = min(body_len - offset,
807                                  MAX_PRINT_CHUNK - this_header);
808                 if (WARN_ON_ONCE(this_chunk <= 0))
809                         return;
810
811                 memcpy(buf + this_header, body + offset, this_chunk);
812
813                 netpoll_send_udp(&nt->np, buf, this_header + this_chunk);
814
815                 offset += this_chunk;
816         }
817 }
818
819 static void write_ext_msg(struct console *con, const char *msg,
820                           unsigned int len)
821 {
822         struct netconsole_target *nt;
823         unsigned long flags;
824
825         if ((oops_only && !oops_in_progress) || list_empty(&target_list))
826                 return;
827
828         spin_lock_irqsave(&target_list_lock, flags);
829         list_for_each_entry(nt, &target_list, list)
830                 if (nt->extended && nt->enabled && netif_running(nt->np.dev))
831                         send_ext_msg_udp(nt, msg, len);
832         spin_unlock_irqrestore(&target_list_lock, flags);
833 }
834
835 static void write_msg(struct console *con, const char *msg, unsigned int len)
836 {
837         int frag, left;
838         unsigned long flags;
839         struct netconsole_target *nt;
840         const char *tmp;
841
842         if (oops_only && !oops_in_progress)
843                 return;
844         /* Avoid taking lock and disabling interrupts unnecessarily */
845         if (list_empty(&target_list))
846                 return;
847
848         spin_lock_irqsave(&target_list_lock, flags);
849         list_for_each_entry(nt, &target_list, list) {
850                 if (!nt->extended && nt->enabled && netif_running(nt->np.dev)) {
851                         /*
852                          * We nest this inside the for-each-target loop above
853                          * so that we're able to get as much logging out to
854                          * at least one target if we die inside here, instead
855                          * of unnecessarily keeping all targets in lock-step.
856                          */
857                         tmp = msg;
858                         for (left = len; left;) {
859                                 frag = min(left, MAX_PRINT_CHUNK);
860                                 netpoll_send_udp(&nt->np, tmp, frag);
861                                 tmp += frag;
862                                 left -= frag;
863                         }
864                 }
865         }
866         spin_unlock_irqrestore(&target_list_lock, flags);
867 }
868
869 static struct console netconsole_ext = {
870         .name   = "netcon_ext",
871         .flags  = CON_EXTENDED, /* starts disabled, registered on first use */
872         .write  = write_ext_msg,
873 };
874
875 static struct console netconsole = {
876         .name   = "netcon",
877         .flags  = CON_ENABLED,
878         .write  = write_msg,
879 };
880
881 static int __init init_netconsole(void)
882 {
883         int err;
884         struct netconsole_target *nt, *tmp;
885         unsigned long flags;
886         char *target_config;
887         char *input = config;
888
889         if (strnlen(input, MAX_PARAM_LENGTH)) {
890                 while ((target_config = strsep(&input, ";"))) {
891                         nt = alloc_param_target(target_config);
892                         if (IS_ERR(nt)) {
893                                 err = PTR_ERR(nt);
894                                 goto fail;
895                         }
896                         /* Dump existing printks when we register */
897                         if (nt->extended)
898                                 netconsole_ext.flags |= CON_PRINTBUFFER |
899                                                         CON_ENABLED;
900                         else
901                                 netconsole.flags |= CON_PRINTBUFFER;
902
903                         spin_lock_irqsave(&target_list_lock, flags);
904                         list_add(&nt->list, &target_list);
905                         spin_unlock_irqrestore(&target_list_lock, flags);
906                 }
907         }
908
909         err = register_netdevice_notifier(&netconsole_netdev_notifier);
910         if (err)
911                 goto fail;
912
913         err = dynamic_netconsole_init();
914         if (err)
915                 goto undonotifier;
916
917         if (netconsole_ext.flags & CON_ENABLED)
918                 register_console(&netconsole_ext);
919         register_console(&netconsole);
920         pr_info("network logging started\n");
921
922         return err;
923
924 undonotifier:
925         unregister_netdevice_notifier(&netconsole_netdev_notifier);
926
927 fail:
928         pr_err("cleaning up\n");
929
930         /*
931          * Remove all targets and destroy them (only targets created
932          * from the boot/module option exist here). Skipping the list
933          * lock is safe here, and netpoll_cleanup() will sleep.
934          */
935         list_for_each_entry_safe(nt, tmp, &target_list, list) {
936                 list_del(&nt->list);
937                 free_param_target(nt);
938         }
939
940         return err;
941 }
942
943 static void __exit cleanup_netconsole(void)
944 {
945         struct netconsole_target *nt, *tmp;
946
947         unregister_console(&netconsole_ext);
948         unregister_console(&netconsole);
949         dynamic_netconsole_exit();
950         unregister_netdevice_notifier(&netconsole_netdev_notifier);
951
952         /*
953          * Targets created via configfs pin references on our module
954          * and would first be rmdir(2)'ed from userspace. We reach
955          * here only when they are already destroyed, and only those
956          * created from the boot/module option are left, so remove and
957          * destroy them. Skipping the list lock is safe here, and
958          * netpoll_cleanup() will sleep.
959          */
960         list_for_each_entry_safe(nt, tmp, &target_list, list) {
961                 list_del(&nt->list);
962                 free_param_target(nt);
963         }
964 }
965
966 /*
967  * Use late_initcall to ensure netconsole is
968  * initialized after network device driver if built-in.
969  *
970  * late_initcall() and module_init() are identical if built as module.
971  */
972 late_initcall(init_netconsole);
973 module_exit(cleanup_netconsole);