2 * Copyright (c) 2005-2014 Sandvine Incorporated. All rights reserved.
3 * Copyright (c) 2000 Darrell Anderson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * FreeBSD subsystem supporting netdump network dumps.
31 * A dedicated server must be running to accept client dumps.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
39 #include <sys/param.h>
42 #include <sys/endian.h>
43 #include <sys/eventhandler.h>
45 #include <sys/kernel.h>
46 #include <sys/kerneldump.h>
48 #include <sys/module.h>
51 #include <sys/protosw.h>
52 #include <sys/socket.h>
53 #include <sys/sysctl.h>
54 #include <sys/syslog.h>
55 #include <sys/systm.h>
59 #include <ddb/db_lex.h>
62 #include <net/ethernet.h>
64 #include <net/if_arp.h>
65 #include <net/if_dl.h>
66 #include <net/if_types.h>
67 #include <net/if_var.h>
68 #include <net/debugnet.h>
70 #include <netinet/in.h>
71 #include <netinet/in_systm.h>
72 #include <netinet/in_var.h>
73 #include <netinet/ip.h>
74 #include <netinet/ip_var.h>
75 #include <netinet/ip_options.h>
76 #include <netinet/udp.h>
77 #include <netinet/udp_var.h>
78 #include <netinet/netdump/netdump.h>
80 #include <machine/in_cksum.h>
81 #include <machine/pcb.h>
83 #define NETDDEBUGV(f, ...) do { \
85 printf(("%s: " f), __func__, ## __VA_ARGS__); \
88 static void netdump_cleanup(void);
89 static int netdump_configure(struct diocskerneldump_arg *,
91 static int netdump_dumper(void *priv __unused, void *virtual,
92 vm_offset_t physical __unused, off_t offset, size_t length);
93 static bool netdump_enabled(void);
94 static int netdump_enabled_sysctl(SYSCTL_HANDLER_ARGS);
95 static int netdump_ioctl(struct cdev *dev __unused, u_long cmd,
96 caddr_t addr, int flags __unused, struct thread *td);
97 static int netdump_modevent(module_t mod, int type, void *priv);
98 static int netdump_start(struct dumperinfo *di, void *key,
100 static void netdump_unconfigure(void);
102 /* Must be at least as big as the chunks dumpsys() gives us. */
103 static unsigned char nd_buf[MAXDUMPPGS * PAGE_SIZE];
104 static int dump_failed;
106 /* Configuration parameters. */
108 char ndc_iface[IFNAMSIZ];
109 union kd_ip ndc_server;
110 union kd_ip ndc_client;
111 union kd_ip ndc_gateway;
114 struct debugnet_pcb *nd_pcb;
118 #define nd_server nd_conf.ndc_server.in4
119 #define nd_client nd_conf.ndc_client.in4
120 #define nd_gateway nd_conf.ndc_gateway.in4
122 /* General dynamic settings. */
123 static struct sx nd_conf_lk;
124 SX_SYSINIT(nd_conf, &nd_conf_lk, "netdump configuration lock");
125 #define NETDUMP_WLOCK() sx_xlock(&nd_conf_lk)
126 #define NETDUMP_WUNLOCK() sx_xunlock(&nd_conf_lk)
127 #define NETDUMP_RLOCK() sx_slock(&nd_conf_lk)
128 #define NETDUMP_RUNLOCK() sx_sunlock(&nd_conf_lk)
129 #define NETDUMP_ASSERT_WLOCKED() sx_assert(&nd_conf_lk, SA_XLOCKED)
130 #define NETDUMP_ASSERT_LOCKED() sx_assert(&nd_conf_lk, SA_LOCKED)
131 static struct ifnet *nd_ifp;
132 static eventhandler_tag nd_detach_cookie;
134 FEATURE(netdump, "Netdump client support");
136 static SYSCTL_NODE(_net, OID_AUTO, netdump, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
137 "netdump parameters");
140 SYSCTL_INT(_net_netdump, OID_AUTO, debug, CTLFLAG_RWTUN,
142 "Debug message verbosity");
143 SYSCTL_PROC(_net_netdump, OID_AUTO, enabled,
144 CTLFLAG_RD | CTLTYPE_INT | CTLFLAG_MPSAFE, NULL, 0,
145 netdump_enabled_sysctl, "I",
146 "netdump configuration status");
147 static char nd_path[MAXPATHLEN];
148 SYSCTL_STRING(_net_netdump, OID_AUTO, path, CTLFLAG_RW,
149 nd_path, sizeof(nd_path),
150 "Server path for output files");
152 * The following three variables were moved to debugnet(4), but these knobs
153 * were retained as aliases.
155 SYSCTL_INT(_net_netdump, OID_AUTO, polls, CTLFLAG_RWTUN,
157 "Number of times to poll before assuming packet loss (0.5ms per poll)");
158 SYSCTL_INT(_net_netdump, OID_AUTO, retries, CTLFLAG_RWTUN,
159 &debugnet_nretries, 0,
160 "Number of retransmit attempts before giving up");
161 SYSCTL_INT(_net_netdump, OID_AUTO, arp_retries, CTLFLAG_RWTUN,
162 &debugnet_arp_nretries, 0,
163 "Number of ARP attempts before giving up");
165 static bool nd_is_enabled;
167 netdump_enabled(void)
170 NETDUMP_ASSERT_LOCKED();
171 return (nd_is_enabled);
175 netdump_set_enabled(bool status)
178 NETDUMP_ASSERT_LOCKED();
179 nd_is_enabled = status;
183 netdump_enabled_sysctl(SYSCTL_HANDLER_ARGS)
188 en = netdump_enabled();
191 error = SYSCTL_OUT(req, &en, sizeof(en));
192 if (error != 0 || req->newptr == NULL)
198 * Dumping specific primitives.
202 * Flush any buffered vmcore data.
205 netdump_flush_buf(void)
210 if (nd_conf.nd_buf_len != 0) {
211 struct debugnet_proto_aux auxdata = {
212 .dp_offset_start = nd_conf.nd_tx_off,
214 error = debugnet_send(nd_conf.nd_pcb, DEBUGNET_DATA, nd_buf,
215 nd_conf.nd_buf_len, &auxdata);
217 nd_conf.nd_buf_len = 0;
223 * Callback from dumpsys() to dump a chunk of memory.
224 * Copies it out to our static buffer then sends it across the network.
225 * Detects the initial KDH and makes sure it is given a special packet type.
228 * priv Unused. Optional private pointer.
229 * virtual Virtual address (where to read the data from)
230 * physical Unused. Physical memory address.
231 * offset Offset from start of core file
239 netdump_dumper(void *priv __unused, void *virtual,
240 vm_offset_t physical __unused, off_t offset, size_t length)
244 NETDDEBUGV("netdump_dumper(NULL, %p, NULL, %ju, %zu)\n",
245 virtual, (uintmax_t)offset, length);
247 if (virtual == NULL) {
248 error = netdump_flush_buf();
252 if (dump_failed != 0)
253 printf("failed to dump the kernel core\n");
255 debugnet_sendempty(nd_conf.nd_pcb, DEBUGNET_FINISHED) != 0)
256 printf("failed to close the transaction\n");
258 printf("\nnetdump finished.\n");
262 if (length > sizeof(nd_buf)) {
267 if (nd_conf.nd_buf_len + length > sizeof(nd_buf) ||
268 (nd_conf.nd_buf_len != 0 && nd_conf.nd_tx_off +
269 nd_conf.nd_buf_len != offset)) {
270 error = netdump_flush_buf();
276 nd_conf.nd_tx_off = offset;
279 memmove(nd_buf + nd_conf.nd_buf_len, virtual, length);
280 nd_conf.nd_buf_len += length;
286 * Perform any initialization needed prior to transmitting the kernel core.
289 netdump_start(struct dumperinfo *di, void *key, uint32_t keysize)
291 struct debugnet_conn_params dcp;
292 struct debugnet_pcb *pcb;
293 char buf[INET_ADDRSTRLEN];
298 /* Check if the dumping is allowed to continue. */
299 if (!netdump_enabled())
302 if (!KERNEL_PANICKED()) {
304 "netdump_start: netdump may only be used after a panic\n");
308 memset(&dcp, 0, sizeof(dcp));
310 if (nd_server.s_addr == INADDR_ANY) {
311 printf("netdump_start: can't netdump; no server IP given\n");
315 /* We start dumping at offset 0. */
320 dcp.dc_client = nd_client.s_addr;
321 dcp.dc_server = nd_server.s_addr;
322 dcp.dc_gateway = nd_gateway.s_addr;
324 dcp.dc_herald_port = NETDUMP_PORT;
325 dcp.dc_client_port = NETDUMP_ACKPORT;
327 dcp.dc_herald_data = nd_path;
328 dcp.dc_herald_datalen = (nd_path[0] == 0) ? 0 : strlen(nd_path) + 1;
330 error = debugnet_connect(&dcp, &pcb);
332 printf("failed to contact netdump server\n");
333 /* Squash debugnet to something the dumper code understands. */
337 printf("netdumping to %s (%6D)\n", inet_ntoa_r(nd_server, buf),
338 debugnet_get_gw_mac(pcb), ":");
339 nd_conf.nd_pcb = pcb;
341 /* Send the key before the dump so a partial dump is still usable. */
343 if (keysize > sizeof(nd_buf)) {
344 printf("crypto key is too large (%u)\n", keysize);
348 memcpy(nd_buf, key, keysize);
349 error = debugnet_send(pcb, NETDUMP_EKCD_KEY, nd_buf, keysize,
352 printf("error %d sending crypto key\n", error);
359 /* As above, squash errors. */
367 netdump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh)
371 error = netdump_flush_buf();
374 memcpy(nd_buf, kdh, sizeof(*kdh));
375 error = debugnet_send(nd_conf.nd_pcb, NETDUMP_KDH, nd_buf,
384 * Cleanup routine for a possibly failed netdump.
387 netdump_cleanup(void)
389 if (nd_conf.nd_pcb != NULL) {
390 debugnet_free(nd_conf.nd_pcb);
391 nd_conf.nd_pcb = NULL;
399 static struct cdevsw netdump_cdevsw = {
400 .d_version = D_VERSION,
401 .d_ioctl = netdump_ioctl,
405 static struct cdev *netdump_cdev;
408 netdump_unconfigure(void)
410 struct diocskerneldump_arg kda;
412 NETDUMP_ASSERT_WLOCKED();
413 KASSERT(netdump_enabled(), ("%s: not enabled", __func__));
415 bzero(&kda, sizeof(kda));
416 kda.kda_index = KDA_REMOVE_DEV;
417 (void)dumper_remove(nd_conf.ndc_iface, &kda);
422 netdump_set_enabled(false);
424 log(LOG_WARNING, "netdump: Lost configured interface %s\n",
427 bzero(&nd_conf, sizeof(nd_conf));
431 netdump_ifdetach(void *arg __unused, struct ifnet *ifp)
436 netdump_unconfigure();
441 * td of NULL is a sentinel value that indicates a kernel caller (ddb(4) or
442 * modload-based tunable parameters).
445 netdump_configure(struct diocskerneldump_arg *conf, struct thread *td)
449 NETDUMP_ASSERT_WLOCKED();
451 if (conf->kda_iface[0] != 0) {
452 if (td != NULL && !IS_DEFAULT_VNET(TD_TO_VNET(td)))
455 ifp = ifunit_ref(conf->kda_iface);
463 netdump_set_enabled(true);
465 #define COPY_SIZED(elm) do { \
466 _Static_assert(sizeof(nd_conf.ndc_ ## elm) == \
467 sizeof(conf->kda_ ## elm), "elm " __XSTRING(elm) " mismatch"); \
468 memcpy(&nd_conf.ndc_ ## elm, &conf->kda_ ## elm, \
469 sizeof(nd_conf.ndc_ ## elm)); \
482 * ioctl(2) handler for the netdump device. This is currently only used to
483 * register netdump as a dump device.
487 * cmd, The ioctl to be handled.
488 * addr, The parameter for the ioctl.
490 * td, The thread invoking this ioctl.
493 * 0 on success, and an errno value on failure.
496 netdump_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr,
497 int flags __unused, struct thread *td)
499 struct diocskerneldump_arg kda_copy, *conf;
500 struct dumperinfo dumper;
501 uint8_t *encryptedkey;
503 #ifdef COMPAT_FREEBSD11
506 #ifdef COMPAT_FREEBSD12
507 struct diocskerneldump_arg_freebsd12 *kda12;
508 struct netdump_conf_freebsd12 *conf12;
516 #ifdef COMPAT_FREEBSD11
517 case DIOCSKERNELDUMP_FREEBSD11:
518 gone_in(13, "11.x ABI compatibility");
524 if (netdump_enabled())
525 netdump_unconfigure();
528 #ifdef COMPAT_FREEBSD12
530 * Used by dumpon(8) in 12.x for clearing previous
531 * configuration -- then NETDUMPSCONF_FREEBSD12 is used to
532 * actually configure netdump.
534 case DIOCSKERNELDUMP_FREEBSD12:
535 gone_in(14, "12.x ABI compatibility");
537 kda12 = (void *)addr;
538 if (kda12->kda12_enable) {
542 if (netdump_enabled())
543 netdump_unconfigure();
546 case NETDUMPGCONF_FREEBSD12:
547 gone_in(14, "FreeBSD 12.x ABI compat");
548 conf12 = (void *)addr;
550 if (!netdump_enabled()) {
554 if (nd_conf.ndc_af != AF_INET) {
560 strlcpy(conf12->ndc12_iface, nd_ifp->if_xname,
561 sizeof(conf12->ndc12_iface));
562 memcpy(&conf12->ndc12_server, &nd_server,
563 sizeof(conf12->ndc12_server));
564 memcpy(&conf12->ndc12_client, &nd_client,
565 sizeof(conf12->ndc12_client));
566 memcpy(&conf12->ndc12_gateway, &nd_gateway,
567 sizeof(conf12->ndc12_gateway));
570 case DIOCGKERNELDUMP:
573 * For now, index is ignored; netdump doesn't support multiple
574 * configurations (yet).
576 if (!netdump_enabled()) {
583 strlcpy(conf->kda_iface, nd_ifp->if_xname,
584 sizeof(conf->kda_iface));
585 memcpy(&conf->kda_server, &nd_server, sizeof(nd_server));
586 memcpy(&conf->kda_client, &nd_client, sizeof(nd_client));
587 memcpy(&conf->kda_gateway, &nd_gateway, sizeof(nd_gateway));
588 conf->kda_af = nd_conf.ndc_af;
592 #ifdef COMPAT_FREEBSD12
593 case NETDUMPSCONF_FREEBSD12:
594 gone_in(14, "FreeBSD 12.x ABI compat");
596 conf12 = (struct netdump_conf_freebsd12 *)addr;
598 _Static_assert(offsetof(struct diocskerneldump_arg, kda_server)
599 == offsetof(struct netdump_conf_freebsd12, ndc12_server),
600 "simplifying assumption");
602 memset(&kda_copy, 0, sizeof(kda_copy));
603 memcpy(&kda_copy, conf12,
604 offsetof(struct diocskerneldump_arg, kda_server));
606 /* 12.x ABI could only configure IPv4 (INET) netdump. */
607 kda_copy.kda_af = AF_INET;
608 memcpy(&kda_copy.kda_server.in4, &conf12->ndc12_server,
609 sizeof(struct in_addr));
610 memcpy(&kda_copy.kda_client.in4, &conf12->ndc12_client,
611 sizeof(struct in_addr));
612 memcpy(&kda_copy.kda_gateway.in4, &conf12->ndc12_gateway,
613 sizeof(struct in_addr));
616 (conf12->ndc12_kda.kda12_enable ? 0 : KDA_REMOVE_ALL);
619 explicit_bzero(conf12, sizeof(*conf12));
622 case DIOCSKERNELDUMP:
624 if (cmd == DIOCSKERNELDUMP) {
626 memcpy(&kda_copy, conf, sizeof(kda_copy));
628 /* Netdump only supports IP4 at this time. */
629 if (conf->kda_af != AF_INET) {
630 error = EPROTONOSUPPORT;
634 conf->kda_iface[sizeof(conf->kda_iface) - 1] = '\0';
635 if (conf->kda_index == KDA_REMOVE ||
636 conf->kda_index == KDA_REMOVE_DEV ||
637 conf->kda_index == KDA_REMOVE_ALL) {
638 if (netdump_enabled())
639 netdump_unconfigure();
640 if (conf->kda_index == KDA_REMOVE_ALL)
641 error = dumper_remove(NULL, conf);
645 error = netdump_configure(conf, td);
649 if (conf->kda_encryption != KERNELDUMP_ENC_NONE) {
650 if (conf->kda_encryptedkeysize <= 0 ||
651 conf->kda_encryptedkeysize >
652 KERNELDUMP_ENCKEY_MAX_SIZE) {
656 encryptedkey = malloc(conf->kda_encryptedkeysize,
658 error = copyin(conf->kda_encryptedkey, encryptedkey,
659 conf->kda_encryptedkeysize);
661 free(encryptedkey, M_TEMP);
665 conf->kda_encryptedkey = encryptedkey;
668 memset(&dumper, 0, sizeof(dumper));
669 dumper.dumper_start = netdump_start;
670 dumper.dumper_hdr = netdump_write_headers;
671 dumper.dumper = netdump_dumper;
673 dumper.blocksize = NETDUMP_DATASIZE;
674 dumper.maxiosize = MAXDUMPPGS * PAGE_SIZE;
675 dumper.mediaoffset = 0;
676 dumper.mediasize = 0;
678 error = dumper_insert(&dumper, conf->kda_iface, conf);
679 zfree(encryptedkey, M_TEMP);
681 netdump_unconfigure();
687 explicit_bzero(&kda_copy, sizeof(kda_copy));
689 explicit_bzero(conf, sizeof(*conf));
695 * Called upon system init or kld load. Initializes the netdump parameters to
696 * sane defaults (locates the first available NIC and uses the first IPv4 IP on
697 * that card as the client IP). Leaves the server IP unconfigured.
701 * what, The module event type.
705 * int, An errno value if an error occured, 0 otherwise.
708 netdump_modevent(module_t mod __unused, int what, void *priv __unused)
710 struct diocskerneldump_arg conf;
717 error = make_dev_p(MAKEDEV_WAITOK, &netdump_cdev,
718 &netdump_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "netdump");
722 nd_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event,
723 netdump_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
725 if ((arg = kern_getenv("net.dump.iface")) != NULL) {
726 strlcpy(conf.kda_iface, arg, sizeof(conf.kda_iface));
729 if ((arg = kern_getenv("net.dump.server")) != NULL) {
730 inet_aton(arg, &conf.kda_server.in4);
733 if ((arg = kern_getenv("net.dump.client")) != NULL) {
734 inet_aton(arg, &conf.kda_client.in4);
737 if ((arg = kern_getenv("net.dump.gateway")) != NULL) {
738 inet_aton(arg, &conf.kda_gateway.in4);
741 conf.kda_af = AF_INET;
743 /* Ignore errors; we print a message to the console. */
745 (void)netdump_configure(&conf, NULL);
751 if (netdump_enabled()) {
752 printf("netdump: disabling dump device for unload\n");
753 netdump_unconfigure();
756 destroy_dev(netdump_cdev);
757 EVENTHANDLER_DEREGISTER(ifnet_departure_event,
767 static moduledata_t netdump_mod = {
773 MODULE_VERSION(netdump, 1);
774 DECLARE_MODULE(netdump, netdump_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
778 * Usage: netdump -s <server> [-g <gateway] -c <localip> -i <interface>
780 * Order is not significant.
782 * Currently, this command does not support configuring encryption or
785 DB_FUNC(netdump, db_netdump_cmd, db_cmd_table, CS_OWN, NULL)
787 static struct diocskerneldump_arg conf;
788 static char blockbuf[NETDUMP_DATASIZE];
790 struct dumperinfo di;
791 /* For valid di_devname. */
792 char di_buf[sizeof(struct dumperinfo) + 1];
795 struct debugnet_ddb_config params;
798 error = debugnet_parse_ddb_cmd("netdump", ¶ms);
800 db_printf("Error configuring netdump: %d\n", error);
804 /* Translate to a netdump dumper config. */
805 memset(&conf, 0, sizeof(conf));
807 if (params.dd_ifp != NULL)
808 strlcpy(conf.kda_iface, if_name(params.dd_ifp),
809 sizeof(conf.kda_iface));
811 conf.kda_af = AF_INET;
812 conf.kda_server.in4 = (struct in_addr) { params.dd_server };
813 if (params.dd_has_client)
814 conf.kda_client.in4 = (struct in_addr) { params.dd_client };
816 conf.kda_client.in4 = (struct in_addr) { INADDR_ANY };
817 if (params.dd_has_gateway)
818 conf.kda_gateway.in4 = (struct in_addr) { params.dd_gateway };
820 conf.kda_gateway.in4 = (struct in_addr) { INADDR_ANY };
822 /* Set the global netdump config to these options. */
823 error = netdump_configure(&conf, NULL);
825 db_printf("Error enabling netdump: %d\n", error);
829 /* Fake the generic dump configuration list entry to avoid malloc. */
830 memset(&u.di_buf, 0, sizeof(u.di_buf));
831 u.di.dumper_start = netdump_start;
832 u.di.dumper_hdr = netdump_write_headers;
833 u.di.dumper = netdump_dumper;
835 u.di.blocksize = NETDUMP_DATASIZE;
836 u.di.maxiosize = MAXDUMPPGS * PAGE_SIZE;
837 u.di.mediaoffset = 0;
839 u.di.blockbuf = blockbuf;
841 dumper_ddb_insert(&u.di);
843 error = doadump(false);
845 dumper_ddb_remove(&u.di);
847 db_printf("Cannot dump: %d\n", error);