]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/netdump/netdump_client.c
MFHead @347527
[FreeBSD/FreeBSD.git] / sys / netinet / netdump / netdump_client.c
1 /*-
2  * Copyright (c) 2005-2014 Sandvine Incorporated. All rights reserved.
3  * Copyright (c) 2000 Darrell Anderson
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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.
14  *
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
25  * SUCH DAMAGE.
26  */
27
28 /*
29  * netdump_client.c
30  * FreeBSD subsystem supporting netdump network dumps.
31  * A dedicated server must be running to accept client dumps.
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include <sys/param.h>
38 #include <sys/conf.h>
39 #include <sys/disk.h>
40 #include <sys/endian.h>
41 #include <sys/jail.h>
42 #include <sys/kernel.h>
43 #include <sys/kerneldump.h>
44 #include <sys/mbuf.h>
45 #include <sys/module.h>
46 #include <sys/priv.h>
47 #include <sys/proc.h>
48 #include <sys/protosw.h>
49 #include <sys/socket.h>
50 #include <sys/sysctl.h>
51 #include <sys/systm.h>
52
53 #include <net/ethernet.h>
54 #include <net/if.h>
55 #include <net/if_arp.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58 #include <net/if_var.h>
59
60 #include <netinet/in.h>
61 #include <netinet/in_systm.h>
62 #include <netinet/in_var.h>
63 #include <netinet/ip.h>
64 #include <netinet/ip_var.h>
65 #include <netinet/ip_options.h>
66 #include <netinet/udp.h>
67 #include <netinet/udp_var.h>
68 #include <netinet/netdump/netdump.h>
69
70 #include <machine/in_cksum.h>
71 #include <machine/pcb.h>
72
73 #define NETDDEBUG(f, ...) do {                                          \
74         if (nd_debug > 0)                                               \
75                 printf(("%s: " f), __func__, ## __VA_ARGS__);           \
76 } while (0)
77 #define NETDDEBUG_IF(i, f, ...) do {                                    \
78         if (nd_debug > 0)                                               \
79                 if_printf((i), ("%s: " f), __func__, ## __VA_ARGS__);   \
80 } while (0)
81 #define NETDDEBUGV(f, ...) do {                                         \
82         if (nd_debug > 1)                                               \
83                 printf(("%s: " f), __func__, ## __VA_ARGS__);           \
84 } while (0)
85 #define NETDDEBUGV_IF(i, f, ...) do {                                   \
86         if (nd_debug > 1)                                               \
87                 if_printf((i), ("%s: " f), __func__, ## __VA_ARGS__);   \
88 } while (0)
89
90 static int       netdump_arp_gw(void);
91 static void      netdump_cleanup(void);
92 static int       netdump_configure(struct diocskerneldump_arg *,
93                     struct thread *);
94 static int       netdump_dumper(void *priv __unused, void *virtual,
95                     vm_offset_t physical __unused, off_t offset, size_t length);
96 static bool      netdump_enabled(void);
97 static int       netdump_enabled_sysctl(SYSCTL_HANDLER_ARGS);
98 static int       netdump_ether_output(struct mbuf *m, struct ifnet *ifp,
99                     struct ether_addr dst, u_short etype);
100 static void      netdump_handle_arp(struct mbuf **mb);
101 static void      netdump_handle_ip(struct mbuf **mb);
102 static int       netdump_ioctl(struct cdev *dev __unused, u_long cmd,
103                     caddr_t addr, int flags __unused, struct thread *td);
104 static int       netdump_modevent(module_t mod, int type, void *priv);
105 static void      netdump_network_poll(void);
106 static void      netdump_pkt_in(struct ifnet *ifp, struct mbuf *m);
107 static void      netdump_reinit_internal(struct ifnet *ifp);
108 static int       netdump_send(uint32_t type, off_t offset, unsigned char *data,
109                     uint32_t datalen);
110 static int       netdump_send_arp(in_addr_t dst);
111 static int       netdump_start(struct dumperinfo *di);
112 static int       netdump_udp_output(struct mbuf *m);
113 static void      netdump_unconfigure(void);
114
115 /* Must be at least as big as the chunks dumpsys() gives us. */
116 static unsigned char nd_buf[MAXDUMPPGS * PAGE_SIZE];
117 static uint32_t nd_seqno;
118 static int dump_failed, have_gw_mac;
119 static void (*drv_if_input)(struct ifnet *, struct mbuf *);
120 static int restore_gw_addr;
121
122 static uint64_t rcvd_acks;
123 CTASSERT(sizeof(rcvd_acks) * NBBY == NETDUMP_MAX_IN_FLIGHT);
124
125 /* Configuration parameters. */
126 static struct {
127         char             ndc_iface[IFNAMSIZ];
128         union kd_ip      ndc_server;
129         union kd_ip      ndc_client;
130         union kd_ip      ndc_gateway;
131         uint8_t          ndc_af;
132 } nd_conf;
133 #define nd_server       nd_conf.ndc_server.in4
134 #define nd_client       nd_conf.ndc_client.in4
135 #define nd_gateway      nd_conf.ndc_gateway.in4
136
137 /* General dynamic settings. */
138 static struct sx nd_conf_lk;
139 SX_SYSINIT(nd_conf, &nd_conf_lk, "netdump configuration lock");
140 #define NETDUMP_WLOCK()                 sx_xlock(&nd_conf_lk)
141 #define NETDUMP_WUNLOCK()               sx_xunlock(&nd_conf_lk)
142 #define NETDUMP_RLOCK()                 sx_slock(&nd_conf_lk)
143 #define NETDUMP_RUNLOCK()               sx_sunlock(&nd_conf_lk)
144 #define NETDUMP_ASSERT_WLOCKED()        sx_assert(&nd_conf_lk, SA_XLOCKED)
145 #define NETDUMP_ASSERT_LOCKED()         sx_assert(&nd_conf_lk, SA_LOCKED)
146 static struct ether_addr nd_gw_mac;
147 static struct ifnet *nd_ifp;
148 static eventhandler_tag nd_detach_cookie;
149 static uint16_t nd_server_port = NETDUMP_PORT;
150
151 FEATURE(netdump, "Netdump client support");
152
153 static SYSCTL_NODE(_net, OID_AUTO, netdump, CTLFLAG_RD, NULL,
154     "netdump parameters");
155
156 static int nd_debug;
157 SYSCTL_INT(_net_netdump, OID_AUTO, debug, CTLFLAG_RWTUN,
158     &nd_debug, 0,
159     "Debug message verbosity");
160 SYSCTL_PROC(_net_netdump, OID_AUTO, enabled, CTLFLAG_RD | CTLTYPE_INT,
161     &nd_ifp, 0, netdump_enabled_sysctl, "I", "netdump configuration status");
162 static char nd_path[MAXPATHLEN];
163 SYSCTL_STRING(_net_netdump, OID_AUTO, path, CTLFLAG_RW,
164     nd_path, sizeof(nd_path),
165     "Server path for output files");
166 static int nd_polls = 2000;
167 SYSCTL_INT(_net_netdump, OID_AUTO, polls, CTLFLAG_RWTUN,
168     &nd_polls, 0,
169     "Number of times to poll before assuming packet loss (0.5ms per poll)");
170 static int nd_retries = 10;
171 SYSCTL_INT(_net_netdump, OID_AUTO, retries, CTLFLAG_RWTUN,
172     &nd_retries, 0,
173     "Number of retransmit attempts before giving up");
174 static int nd_arp_retries = 3;
175 SYSCTL_INT(_net_netdump, OID_AUTO, arp_retries, CTLFLAG_RWTUN,
176     &nd_arp_retries, 0,
177     "Number of ARP attempts before giving up");
178
179 static bool
180 netdump_enabled(void)
181 {
182
183         NETDUMP_ASSERT_LOCKED();
184         return (nd_ifp != NULL);
185 }
186
187 static int
188 netdump_enabled_sysctl(SYSCTL_HANDLER_ARGS)
189 {
190         int en, error;
191
192         NETDUMP_RLOCK();
193         en = netdump_enabled();
194         NETDUMP_RUNLOCK();
195
196         error = SYSCTL_OUT(req, &en, sizeof(en));
197         if (error != 0 || req->newptr == NULL)
198                 return (error);
199         return (EPERM);
200 }
201
202 /*
203  * Checks for netdump support on a network interface
204  *
205  * Parameters:
206  *      ifp     The network interface that is being tested for support
207  *
208  * Returns:
209  *      int     1 if the interface is supported, 0 if not
210  */
211 static bool
212 netdump_supported_nic(struct ifnet *ifp)
213 {
214
215         return (ifp->if_netdump_methods != NULL);
216 }
217
218 /*-
219  * Network specific primitives.
220  * Following down the code they are divided ordered as:
221  * - Packet buffer primitives
222  * - Output primitives
223  * - Input primitives
224  * - Polling primitives
225  */
226
227 /*
228  * Handles creation of the ethernet header, then places outgoing packets into
229  * the tx buffer for the NIC
230  *
231  * Parameters:
232  *      m       The mbuf containing the packet to be sent (will be freed by
233  *              this function or the NIC driver)
234  *      ifp     The interface to send on
235  *      dst     The destination ethernet address (source address will be looked
236  *              up using ifp)
237  *      etype   The ETHERTYPE_* value for the protocol that is being sent
238  *
239  * Returns:
240  *      int     see errno.h, 0 for success
241  */
242 static int
243 netdump_ether_output(struct mbuf *m, struct ifnet *ifp, struct ether_addr dst,
244     u_short etype)
245 {
246         struct ether_header *eh;
247
248         if (((ifp->if_flags & (IFF_MONITOR | IFF_UP)) != IFF_UP) ||
249             (ifp->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING) {
250                 if_printf(ifp, "netdump_ether_output: interface isn't up\n");
251                 m_freem(m);
252                 return (ENETDOWN);
253         }
254
255         /* Fill in the ethernet header. */
256         M_PREPEND(m, ETHER_HDR_LEN, M_NOWAIT);
257         if (m == NULL) {
258                 printf("%s: out of mbufs\n", __func__);
259                 return (ENOBUFS);
260         }
261         eh = mtod(m, struct ether_header *);
262         memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
263         memcpy(eh->ether_dhost, dst.octet, ETHER_ADDR_LEN);
264         eh->ether_type = htons(etype);
265         return ((ifp->if_netdump_methods->nd_transmit)(ifp, m));
266 }
267
268 /*
269  * Unreliable transmission of an mbuf chain to the netdump server
270  * Note: can't handle fragmentation; fails if the packet is larger than
271  *       nd_ifp->if_mtu after adding the UDP/IP headers
272  *
273  * Parameters:
274  *      m       mbuf chain
275  *
276  * Returns:
277  *      int     see errno.h, 0 for success
278  */
279 static int
280 netdump_udp_output(struct mbuf *m)
281 {
282         struct udpiphdr *ui;
283         struct ip *ip;
284
285         MPASS(netdump_enabled());
286
287         M_PREPEND(m, sizeof(struct udpiphdr), M_NOWAIT);
288         if (m == NULL) {
289                 printf("%s: out of mbufs\n", __func__);
290                 return (ENOBUFS);
291         }
292
293         if (m->m_pkthdr.len > nd_ifp->if_mtu) {
294                 printf("netdump_udp_output: Packet is too big: %d > MTU %u\n",
295                     m->m_pkthdr.len, nd_ifp->if_mtu);
296                 m_freem(m);
297                 return (ENOBUFS);
298         }
299
300         ui = mtod(m, struct udpiphdr *);
301         bzero(ui->ui_x1, sizeof(ui->ui_x1));
302         ui->ui_pr = IPPROTO_UDP;
303         ui->ui_len = htons(m->m_pkthdr.len - sizeof(struct ip));
304         ui->ui_ulen = ui->ui_len;
305         ui->ui_src = nd_client;
306         ui->ui_dst = nd_server;
307         /* Use this src port so that the server can connect() the socket */
308         ui->ui_sport = htons(NETDUMP_ACKPORT);
309         ui->ui_dport = htons(nd_server_port);
310         ui->ui_sum = 0;
311         if ((ui->ui_sum = in_cksum(m, m->m_pkthdr.len)) == 0)
312                 ui->ui_sum = 0xffff;
313
314         ip = mtod(m, struct ip *);
315         ip->ip_v = IPVERSION;
316         ip->ip_hl = sizeof(struct ip) >> 2;
317         ip->ip_tos = 0;
318         ip->ip_len = htons(m->m_pkthdr.len);
319         ip->ip_id = 0;
320         ip->ip_off = htons(IP_DF);
321         ip->ip_ttl = 255;
322         ip->ip_sum = 0;
323         ip->ip_sum = in_cksum(m, sizeof(struct ip));
324
325         return (netdump_ether_output(m, nd_ifp, nd_gw_mac, ETHERTYPE_IP));
326 }
327
328 /*
329  * Builds and sends a single ARP request to locate the server
330  *
331  * Return value:
332  *      0 on success
333  *      errno on error
334  */
335 static int
336 netdump_send_arp(in_addr_t dst)
337 {
338         struct ether_addr bcast;
339         struct mbuf *m;
340         struct arphdr *ah;
341         int pktlen;
342
343         MPASS(netdump_enabled());
344
345         /* Fill-up a broadcast address. */
346         memset(&bcast, 0xFF, ETHER_ADDR_LEN);
347         m = m_gethdr(M_NOWAIT, MT_DATA);
348         if (m == NULL) {
349                 printf("netdump_send_arp: Out of mbufs\n");
350                 return (ENOBUFS);
351         }
352         pktlen = arphdr_len2(ETHER_ADDR_LEN, sizeof(struct in_addr));
353         m->m_len = pktlen;
354         m->m_pkthdr.len = pktlen;
355         MH_ALIGN(m, pktlen);
356         ah = mtod(m, struct arphdr *);
357         ah->ar_hrd = htons(ARPHRD_ETHER);
358         ah->ar_pro = htons(ETHERTYPE_IP);
359         ah->ar_hln = ETHER_ADDR_LEN;
360         ah->ar_pln = sizeof(struct in_addr);
361         ah->ar_op = htons(ARPOP_REQUEST);
362         memcpy(ar_sha(ah), IF_LLADDR(nd_ifp), ETHER_ADDR_LEN);
363         ((struct in_addr *)ar_spa(ah))->s_addr = nd_client.s_addr;
364         bzero(ar_tha(ah), ETHER_ADDR_LEN);
365         ((struct in_addr *)ar_tpa(ah))->s_addr = dst;
366         return (netdump_ether_output(m, nd_ifp, bcast, ETHERTYPE_ARP));
367 }
368
369 /*
370  * Sends ARP requests to locate the server and waits for a response.
371  * We first try to ARP the server itself, and fall back to the provided
372  * gateway if the server appears to be off-link.
373  *
374  * Return value:
375  *      0 on success
376  *      errno on error
377  */
378 static int
379 netdump_arp_gw(void)
380 {
381         in_addr_t dst;
382         int error, polls, retries;
383
384         dst = nd_server.s_addr;
385 restart:
386         for (retries = 0; retries < nd_arp_retries && have_gw_mac == 0;
387             retries++) {
388                 error = netdump_send_arp(dst);
389                 if (error != 0)
390                         return (error);
391                 for (polls = 0; polls < nd_polls && have_gw_mac == 0; polls++) {
392                         netdump_network_poll();
393                         DELAY(500);
394                 }
395                 if (have_gw_mac == 0)
396                         printf("(ARP retry)");
397         }
398         if (have_gw_mac != 0)
399                 return (0);
400         if (dst == nd_server.s_addr && nd_server.s_addr != nd_gateway.s_addr) {
401                 printf("Failed to ARP server, trying to reach gateway...\n");
402                 dst = nd_gateway.s_addr;
403                 goto restart;
404         }
405
406         printf("\nARP timed out.\n");
407         return (ETIMEDOUT);
408 }
409
410 /*
411  * Dummy free function for netdump clusters.
412  */
413 static void
414 netdump_mbuf_free(struct mbuf *m __unused)
415 {
416 }
417
418 /*
419  * Construct and reliably send a netdump packet.  May fail from a resource
420  * shortage or extreme number of unacknowledged retransmissions.  Wait for
421  * an acknowledgement before returning.  Splits packets into chunks small
422  * enough to be sent without fragmentation (looks up the interface MTU)
423  *
424  * Parameters:
425  *      type    netdump packet type (HERALD, FINISHED, or VMCORE)
426  *      offset  vmcore data offset (bytes)
427  *      data    vmcore data
428  *      datalen vmcore data size (bytes)
429  *
430  * Returns:
431  *      int see errno.h, 0 for success
432  */
433 static int
434 netdump_send(uint32_t type, off_t offset, unsigned char *data, uint32_t datalen)
435 {
436         struct netdump_msg_hdr *nd_msg_hdr;
437         struct mbuf *m, *m2;
438         uint64_t want_acks;
439         uint32_t i, pktlen, sent_so_far;
440         int retries, polls, error;
441
442         want_acks = 0;
443         rcvd_acks = 0;
444         retries = 0;
445
446         MPASS(netdump_enabled());
447
448 retransmit:
449         /* Chunks can be too big to fit in packets. */
450         for (i = sent_so_far = 0; sent_so_far < datalen ||
451             (i == 0 && datalen == 0); i++) {
452                 pktlen = datalen - sent_so_far;
453
454                 /* First bound: the packet structure. */
455                 pktlen = min(pktlen, NETDUMP_DATASIZE);
456
457                 /* Second bound: the interface MTU (assume no IP options). */
458                 pktlen = min(pktlen, nd_ifp->if_mtu - sizeof(struct udpiphdr) -
459                     sizeof(struct netdump_msg_hdr));
460
461                 /*
462                  * Check if it is retransmitting and this has been ACKed
463                  * already.
464                  */
465                 if ((rcvd_acks & (1 << i)) != 0) {
466                         sent_so_far += pktlen;
467                         continue;
468                 }
469
470                 /*
471                  * Get and fill a header mbuf, then chain data as an extended
472                  * mbuf.
473                  */
474                 m = m_gethdr(M_NOWAIT, MT_DATA);
475                 if (m == NULL) {
476                         printf("netdump_send: Out of mbufs\n");
477                         return (ENOBUFS);
478                 }
479                 m->m_len = sizeof(struct netdump_msg_hdr);
480                 m->m_pkthdr.len = sizeof(struct netdump_msg_hdr);
481                 MH_ALIGN(m, sizeof(struct netdump_msg_hdr));
482                 nd_msg_hdr = mtod(m, struct netdump_msg_hdr *);
483                 nd_msg_hdr->mh_seqno = htonl(nd_seqno + i);
484                 nd_msg_hdr->mh_type = htonl(type);
485                 nd_msg_hdr->mh_offset = htobe64(offset + sent_so_far);
486                 nd_msg_hdr->mh_len = htonl(pktlen);
487                 nd_msg_hdr->mh__pad = 0;
488
489                 if (pktlen != 0) {
490                         m2 = m_get(M_NOWAIT, MT_DATA);
491                         if (m2 == NULL) {
492                                 m_freem(m);
493                                 printf("netdump_send: Out of mbufs\n");
494                                 return (ENOBUFS);
495                         }
496                         MEXTADD(m2, data + sent_so_far, pktlen,
497                             netdump_mbuf_free, NULL, NULL, 0, EXT_DISPOSABLE);
498                         m2->m_len = pktlen;
499
500                         m_cat(m, m2);
501                         m->m_pkthdr.len += pktlen;
502                 }
503                 error = netdump_udp_output(m);
504                 if (error != 0)
505                         return (error);
506
507                 /* Note that we're waiting for this packet in the bitfield. */
508                 want_acks |= (1 << i);
509                 sent_so_far += pktlen;
510         }
511         if (i >= NETDUMP_MAX_IN_FLIGHT)
512                 printf("Warning: Sent more than %d packets (%d). "
513                     "Acknowledgements will fail unless the size of "
514                     "rcvd_acks/want_acks is increased.\n",
515                     NETDUMP_MAX_IN_FLIGHT, i);
516
517         /*
518          * Wait for acks.  A *real* window would speed things up considerably.
519          */
520         polls = 0;
521         while (rcvd_acks != want_acks) {
522                 if (polls++ > nd_polls) {
523                         if (retries++ > nd_retries)
524                                 return (ETIMEDOUT);
525                         printf(". ");
526                         goto retransmit;
527                 }
528                 netdump_network_poll();
529                 DELAY(500);
530         }
531         nd_seqno += i;
532         return (0);
533 }
534
535 /*
536  * Handler for IP packets: checks their sanity and then processes any netdump
537  * ACK packets it finds.
538  *
539  * It needs to replicate partially the behaviour of ip_input() and
540  * udp_input().
541  *
542  * Parameters:
543  *      mb      a pointer to an mbuf * containing the packet received
544  *              Updates *mb if m_pullup et al change the pointer
545  *              Assumes the calling function will take care of freeing the mbuf
546  */
547 static void
548 netdump_handle_ip(struct mbuf **mb)
549 {
550         struct ip *ip;
551         struct udpiphdr *udp;
552         struct netdump_ack *nd_ack;
553         struct mbuf *m;
554         int rcv_ackno;
555         unsigned short hlen;
556
557         /* IP processing. */
558         m = *mb;
559         if (m->m_pkthdr.len < sizeof(struct ip)) {
560                 NETDDEBUG("dropping packet too small for IP header\n");
561                 return;
562         }
563         if (m->m_len < sizeof(struct ip)) {
564                 m = m_pullup(m, sizeof(struct ip));
565                 *mb = m;
566                 if (m == NULL) {
567                         NETDDEBUG("m_pullup failed\n");
568                         return;
569                 }
570         }
571         ip = mtod(m, struct ip *);
572
573         /* IP version. */
574         if (ip->ip_v != IPVERSION) {
575                 NETDDEBUG("bad IP version %d\n", ip->ip_v);
576                 return;
577         }
578
579         /* Header length. */
580         hlen = ip->ip_hl << 2;
581         if (hlen < sizeof(struct ip)) {
582                 NETDDEBUG("bad IP header length (%hu)\n", hlen);
583                 return;
584         }
585         if (hlen > m->m_len) {
586                 m = m_pullup(m, hlen);
587                 *mb = m;
588                 if (m == NULL) {
589                         NETDDEBUG("m_pullup failed\n");
590                         return;
591                 }
592                 ip = mtod(m, struct ip *);
593         }
594         /* Ignore packets with IP options. */
595         if (hlen > sizeof(struct ip)) {
596                 NETDDEBUG("drop packet with IP options\n");
597                 return;
598         }
599
600 #ifdef INVARIANTS
601         if ((IN_LOOPBACK(ntohl(ip->ip_dst.s_addr)) ||
602             IN_LOOPBACK(ntohl(ip->ip_src.s_addr))) &&
603             (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
604                 NETDDEBUG("Bad IP header (RFC1122)\n");
605                 return;
606         }
607 #endif
608
609         /* Checksum. */
610         if ((m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) != 0) {
611                 if ((m->m_pkthdr.csum_flags & CSUM_IP_VALID) == 0) {
612                         NETDDEBUG("bad IP checksum\n");
613                         return;
614                 }
615         } else {
616                 /* XXX */ ;
617         }
618
619         /* Convert fields to host byte order. */
620         ip->ip_len = ntohs(ip->ip_len);
621         if (ip->ip_len < hlen) {
622                 NETDDEBUG("IP packet smaller (%hu) than header (%hu)\n",
623                     ip->ip_len, hlen);
624                 return;
625         }
626         if (m->m_pkthdr.len < ip->ip_len) {
627                 NETDDEBUG("IP packet bigger (%hu) than ethernet packet (%d)\n",
628                     ip->ip_len, m->m_pkthdr.len);
629                 return;
630         }
631         if (m->m_pkthdr.len > ip->ip_len) {
632
633                 /* Truncate the packet to the IP length. */
634                 if (m->m_len == m->m_pkthdr.len) {
635                         m->m_len = ip->ip_len;
636                         m->m_pkthdr.len = ip->ip_len;
637                 } else
638                         m_adj(m, ip->ip_len - m->m_pkthdr.len);
639         }
640
641         ip->ip_off = ntohs(ip->ip_off);
642
643         /* Check that the source is the server's IP. */
644         if (ip->ip_src.s_addr != nd_server.s_addr) {
645                 NETDDEBUG("drop packet not from server (from 0x%x)\n",
646                     ip->ip_src.s_addr);
647                 return;
648         }
649
650         /* Check if the destination IP is ours. */
651         if (ip->ip_dst.s_addr != nd_client.s_addr) {
652                 NETDDEBUGV("drop packet not to our IP\n");
653                 return;
654         }
655
656         if (ip->ip_p != IPPROTO_UDP) {
657                 NETDDEBUG("drop non-UDP packet\n");
658                 return;
659         }
660
661         /* Do not deal with fragments. */
662         if ((ip->ip_off & (IP_MF | IP_OFFMASK)) != 0) {
663                 NETDDEBUG("drop fragmented packet\n");
664                 return;
665         }
666
667         /* UDP custom is to have packet length not include IP header. */
668         ip->ip_len -= hlen;
669
670         /* UDP processing. */
671
672         /* Get IP and UDP headers together, along with the netdump packet. */
673         if (m->m_pkthdr.len <
674             sizeof(struct udpiphdr) + sizeof(struct netdump_ack)) {
675                 NETDDEBUG("ignoring small packet\n");
676                 return;
677         }
678         if (m->m_len < sizeof(struct udpiphdr) + sizeof(struct netdump_ack)) {
679                 m = m_pullup(m, sizeof(struct udpiphdr) +
680                     sizeof(struct netdump_ack));
681                 *mb = m;
682                 if (m == NULL) {
683                         NETDDEBUG("m_pullup failed\n");
684                         return;
685                 }
686         }
687         udp = mtod(m, struct udpiphdr *);
688
689         if (ntohs(udp->ui_u.uh_dport) != NETDUMP_ACKPORT) {
690                 NETDDEBUG("not on the netdump port.\n");
691                 return;
692         }
693
694         /* Netdump processing. */
695
696         /*
697          * Packet is meant for us.  Extract the ack sequence number and the
698          * port number if necessary.
699          */
700         nd_ack = (struct netdump_ack *)(mtod(m, caddr_t) +
701             sizeof(struct udpiphdr));
702         rcv_ackno = ntohl(nd_ack->na_seqno);
703         if (nd_server_port == NETDUMP_PORT)
704                 nd_server_port = ntohs(udp->ui_u.uh_sport);
705         if (rcv_ackno >= nd_seqno + NETDUMP_MAX_IN_FLIGHT)
706                 printf("%s: ACK %d too far in future!\n", __func__, rcv_ackno);
707         else if (rcv_ackno >= nd_seqno) {
708                 /* We're interested in this ack. Record it. */
709                 rcvd_acks |= 1 << (rcv_ackno - nd_seqno);
710         }
711 }
712
713 /*
714  * Handler for ARP packets: checks their sanity and then
715  * 1. If the ARP is a request for our IP, respond with our MAC address
716  * 2. If the ARP is a response from our server, record its MAC address
717  *
718  * It needs to replicate partially the behaviour of arpintr() and
719  * in_arpinput().
720  *
721  * Parameters:
722  *      mb      a pointer to an mbuf * containing the packet received
723  *              Updates *mb if m_pullup et al change the pointer
724  *              Assumes the calling function will take care of freeing the mbuf
725  */
726 static void
727 netdump_handle_arp(struct mbuf **mb)
728 {
729         char buf[INET_ADDRSTRLEN];
730         struct in_addr isaddr, itaddr, myaddr;
731         struct ether_addr dst;
732         struct mbuf *m;
733         struct arphdr *ah;
734         struct ifnet *ifp;
735         uint8_t *enaddr;
736         int req_len, op;
737
738         m = *mb;
739         ifp = m->m_pkthdr.rcvif;
740         if (m->m_len < sizeof(struct arphdr)) {
741                 m = m_pullup(m, sizeof(struct arphdr));
742                 *mb = m;
743                 if (m == NULL) {
744                         NETDDEBUG("runt packet: m_pullup failed\n");
745                         return;
746                 }
747         }
748
749         ah = mtod(m, struct arphdr *);
750         if (ntohs(ah->ar_hrd) != ARPHRD_ETHER) {
751                 NETDDEBUG("unknown hardware address 0x%2D)\n",
752                     (unsigned char *)&ah->ar_hrd, "");
753                 return;
754         }
755         if (ntohs(ah->ar_pro) != ETHERTYPE_IP) {
756                 NETDDEBUG("drop ARP for unknown protocol %d\n",
757                     ntohs(ah->ar_pro));
758                 return;
759         }
760         req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr));
761         if (m->m_len < req_len) {
762                 m = m_pullup(m, req_len);
763                 *mb = m;
764                 if (m == NULL) {
765                         NETDDEBUG("runt packet: m_pullup failed\n");
766                         return;
767                 }
768         }
769         ah = mtod(m, struct arphdr *);
770
771         op = ntohs(ah->ar_op);
772         memcpy(&isaddr, ar_spa(ah), sizeof(isaddr));
773         memcpy(&itaddr, ar_tpa(ah), sizeof(itaddr));
774         enaddr = (uint8_t *)IF_LLADDR(ifp);
775         myaddr = nd_client;
776
777         if (memcmp(ar_sha(ah), enaddr, ifp->if_addrlen) == 0) {
778                 NETDDEBUG("ignoring ARP from myself\n");
779                 return;
780         }
781
782         if (isaddr.s_addr == nd_client.s_addr) {
783                 printf("%s: %*D is using my IP address %s!\n", __func__,
784                     ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
785                     inet_ntoa_r(isaddr, buf));
786                 return;
787         }
788
789         if (memcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen) == 0) {
790                 NETDDEBUG("ignoring ARP from broadcast address\n");
791                 return;
792         }
793
794         if (op == ARPOP_REPLY) {
795                 if (isaddr.s_addr != nd_gateway.s_addr &&
796                     isaddr.s_addr != nd_server.s_addr) {
797                         inet_ntoa_r(isaddr, buf);
798                         NETDDEBUG(
799                             "ignoring ARP reply from %s (not netdump server)\n",
800                             buf);
801                         return;
802                 }
803                 memcpy(nd_gw_mac.octet, ar_sha(ah),
804                     min(ah->ar_hln, ETHER_ADDR_LEN));
805                 have_gw_mac = 1;
806                 NETDDEBUG("got server MAC address %6D\n", nd_gw_mac.octet, ":");
807                 return;
808         }
809
810         if (op != ARPOP_REQUEST) {
811                 NETDDEBUG("ignoring ARP non-request/reply\n");
812                 return;
813         }
814
815         if (itaddr.s_addr != nd_client.s_addr) {
816                 NETDDEBUG("ignoring ARP not to our IP\n");
817                 return;
818         }
819
820         memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
821         memcpy(ar_sha(ah), enaddr, ah->ar_hln);
822         memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln);
823         memcpy(ar_spa(ah), &itaddr, ah->ar_pln);
824         ah->ar_op = htons(ARPOP_REPLY);
825         ah->ar_pro = htons(ETHERTYPE_IP);
826         m->m_flags &= ~(M_BCAST|M_MCAST);
827         m->m_len = arphdr_len(ah);
828         m->m_pkthdr.len = m->m_len;
829
830         memcpy(dst.octet, ar_tha(ah), ETHER_ADDR_LEN);
831         netdump_ether_output(m, ifp, dst, ETHERTYPE_ARP);
832         *mb = NULL;
833 }
834
835 /*
836  * Handler for incoming packets directly from the network adapter
837  * Identifies the packet type (IP or ARP) and passes it along to one of the
838  * helper functions netdump_handle_ip or netdump_handle_arp.
839  *
840  * It needs to replicate partially the behaviour of ether_input() and
841  * ether_demux().
842  *
843  * Parameters:
844  *      ifp     the interface the packet came from (should be nd_ifp)
845  *      m       an mbuf containing the packet received
846  */
847 static void
848 netdump_pkt_in(struct ifnet *ifp, struct mbuf *m)
849 {
850         struct ifreq ifr;
851         struct ether_header *eh;
852         u_short etype;
853
854         /* Ethernet processing. */
855         if ((m->m_flags & M_PKTHDR) == 0) {
856                 NETDDEBUG_IF(ifp, "discard frame without packet header\n");
857                 goto done;
858         }
859         if (m->m_len < ETHER_HDR_LEN) {
860                 NETDDEBUG_IF(ifp,
861             "discard frame without leading eth header (len %u pktlen %u)\n",
862                     m->m_len, m->m_pkthdr.len);
863                 goto done;
864         }
865         if ((m->m_flags & M_HASFCS) != 0) {
866                 m_adj(m, -ETHER_CRC_LEN);
867                 m->m_flags &= ~M_HASFCS;
868         }
869         eh = mtod(m, struct ether_header *);
870         etype = ntohs(eh->ether_type);
871         if ((m->m_flags & M_VLANTAG) != 0 || etype == ETHERTYPE_VLAN) {
872                 NETDDEBUG_IF(ifp, "ignoring vlan packets\n");
873                 goto done;
874         }
875         if (if_gethwaddr(ifp, &ifr) != 0) {
876                 NETDDEBUG_IF(ifp, "failed to get hw addr for interface\n");
877                 goto done;
878         }
879         if (memcmp(ifr.ifr_addr.sa_data, eh->ether_dhost,
880             ETHER_ADDR_LEN) != 0) {
881                 NETDDEBUG_IF(ifp,
882                     "discard frame with incorrect destination addr\n");
883                 goto done;
884         }
885
886         /* Done ethernet processing. Strip off the ethernet header. */
887         m_adj(m, ETHER_HDR_LEN);
888         switch (etype) {
889         case ETHERTYPE_ARP:
890                 netdump_handle_arp(&m);
891                 break;
892         case ETHERTYPE_IP:
893                 netdump_handle_ip(&m);
894                 break;
895         default:
896                 NETDDEBUG_IF(ifp, "dropping unknown ethertype %hu\n", etype);
897                 break;
898         }
899 done:
900         if (m != NULL)
901                 m_freem(m);
902 }
903
904 /*
905  * After trapping, instead of assuming that most of the network stack is sane,
906  * we just poll the driver directly for packets.
907  */
908 static void
909 netdump_network_poll(void)
910 {
911
912         MPASS(netdump_enabled());
913
914         nd_ifp->if_netdump_methods->nd_poll(nd_ifp, 1000);
915 }
916
917 /*-
918  * Dumping specific primitives.
919  */
920
921 /*
922  * Callback from dumpsys() to dump a chunk of memory.
923  * Copies it out to our static buffer then sends it across the network.
924  * Detects the initial KDH and makes sure it is given a special packet type.
925  *
926  * Parameters:
927  *      priv     Unused. Optional private pointer.
928  *      virtual  Virtual address (where to read the data from)
929  *      physical Unused. Physical memory address.
930  *      offset   Offset from start of core file
931  *      length   Data length
932  *
933  * Return value:
934  *      0 on success
935  *      errno on error
936  */
937 static int
938 netdump_dumper(void *priv __unused, void *virtual,
939     vm_offset_t physical __unused, off_t offset, size_t length)
940 {
941         int error;
942
943         NETDDEBUGV("netdump_dumper(NULL, %p, NULL, %ju, %zu)\n",
944             virtual, (uintmax_t)offset, length);
945
946         if (virtual == NULL) {
947                 if (dump_failed != 0)
948                         printf("failed to dump the kernel core\n");
949                 else if (netdump_send(NETDUMP_FINISHED, 0, NULL, 0) != 0)
950                         printf("failed to close the transaction\n");
951                 else
952                         printf("\nnetdump finished.\n");
953                 netdump_cleanup();
954                 return (0);
955         }
956         if (length > sizeof(nd_buf))
957                 return (ENOSPC);
958
959         memmove(nd_buf, virtual, length);
960         error = netdump_send(NETDUMP_VMCORE, offset, nd_buf, length);
961         if (error != 0) {
962                 dump_failed = 1;
963                 return (error);
964         }
965         return (0);
966 }
967
968 /*
969  * Perform any initalization needed prior to transmitting the kernel core.
970  */
971 static int
972 netdump_start(struct dumperinfo *di)
973 {
974         char *path;
975         char buf[INET_ADDRSTRLEN];
976         uint32_t len;
977         int error;
978
979         error = 0;
980
981         /* Check if the dumping is allowed to continue. */
982         if (!netdump_enabled())
983                 return (EINVAL);
984
985         if (panicstr == NULL) {
986                 printf(
987                     "netdump_start: netdump may only be used after a panic\n");
988                 return (EINVAL);
989         }
990
991         if (nd_server.s_addr == INADDR_ANY) {
992                 printf("netdump_start: can't netdump; no server IP given\n");
993                 return (EINVAL);
994         }
995         if (nd_client.s_addr == INADDR_ANY) {
996                 printf("netdump_start: can't netdump; no client IP given\n");
997                 return (EINVAL);
998         }
999
1000         /* We start dumping at offset 0. */
1001         di->dumpoff = 0;
1002
1003         nd_seqno = 1;
1004
1005         /*
1006          * nd_server_port could have switched after the first ack the
1007          * first time it gets called.  Adjust it accordingly.
1008          */
1009         nd_server_port = NETDUMP_PORT;
1010
1011         /* Switch to the netdump mbuf zones. */
1012         netdump_mbuf_dump();
1013
1014         nd_ifp->if_netdump_methods->nd_event(nd_ifp, NETDUMP_START);
1015
1016         /* Make the card use *our* receive callback. */
1017         drv_if_input = nd_ifp->if_input;
1018         nd_ifp->if_input = netdump_pkt_in;
1019
1020         if (nd_gateway.s_addr == INADDR_ANY) {
1021                 restore_gw_addr = 1;
1022                 nd_gateway.s_addr = nd_server.s_addr;
1023         }
1024
1025         printf("netdump in progress. searching for server...\n");
1026         if (netdump_arp_gw()) {
1027                 printf("failed to locate server MAC address\n");
1028                 error = EINVAL;
1029                 goto trig_abort;
1030         }
1031
1032         if (nd_path[0] != '\0') {
1033                 path = nd_path;
1034                 len = strlen(path) + 1;
1035         } else {
1036                 path = NULL;
1037                 len = 0;
1038         }
1039         if (netdump_send(NETDUMP_HERALD, 0, path, len) != 0) {
1040                 printf("failed to contact netdump server\n");
1041                 error = EINVAL;
1042                 goto trig_abort;
1043         }
1044         printf("netdumping to %s (%6D)\n", inet_ntoa_r(nd_server, buf),
1045             nd_gw_mac.octet, ":");
1046         return (0);
1047
1048 trig_abort:
1049         netdump_cleanup();
1050         return (error);
1051 }
1052
1053 static int
1054 netdump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh,
1055     void *key, uint32_t keysize)
1056 {
1057         int error;
1058
1059         memcpy(nd_buf, kdh, sizeof(*kdh));
1060         error = netdump_send(NETDUMP_KDH, 0, nd_buf, sizeof(*kdh));
1061         if (error == 0 && keysize > 0) {
1062                 if (keysize > sizeof(nd_buf))
1063                         return (EINVAL);
1064                 memcpy(nd_buf, key, keysize);
1065                 error = netdump_send(NETDUMP_EKCD_KEY, 0, nd_buf, keysize);
1066         }
1067         return (error);
1068 }
1069
1070 /*
1071  * Cleanup routine for a possibly failed netdump.
1072  */
1073 static void
1074 netdump_cleanup(void)
1075 {
1076
1077         if (restore_gw_addr != 0) {
1078                 nd_gateway.s_addr = INADDR_ANY;
1079                 restore_gw_addr = 0;
1080         }
1081         if (drv_if_input != NULL) {
1082                 nd_ifp->if_input = drv_if_input;
1083                 drv_if_input = NULL;
1084         }
1085         nd_ifp->if_netdump_methods->nd_event(nd_ifp, NETDUMP_END);
1086 }
1087
1088 /*-
1089  * KLD specific code.
1090  */
1091
1092 static struct cdevsw netdump_cdevsw = {
1093         .d_version =    D_VERSION,
1094         .d_ioctl =      netdump_ioctl,
1095         .d_name =       "netdump",
1096 };
1097
1098 static struct cdev *netdump_cdev;
1099
1100 static void
1101 netdump_unconfigure(void)
1102 {
1103         struct diocskerneldump_arg kda;
1104
1105         NETDUMP_ASSERT_WLOCKED();
1106         KASSERT(netdump_enabled(), ("%s: nd_ifp NULL", __func__));
1107
1108         bzero(&kda, sizeof(kda));
1109         kda.kda_index = KDA_REMOVE_DEV;
1110         (void)dumper_remove(nd_conf.ndc_iface, &kda);
1111
1112         netdump_mbuf_drain();
1113
1114         if_rele(nd_ifp);
1115         nd_ifp = NULL;
1116
1117         bzero(&nd_conf, sizeof(nd_conf));
1118 }
1119
1120 static void
1121 netdump_ifdetach(void *arg __unused, struct ifnet *ifp)
1122 {
1123
1124         NETDUMP_WLOCK();
1125         if (ifp == nd_ifp)
1126                 netdump_unconfigure();
1127         NETDUMP_WUNLOCK();
1128 }
1129
1130 static int
1131 netdump_configure(struct diocskerneldump_arg *conf, struct thread *td)
1132 {
1133         struct ifnet *ifp;
1134
1135         NETDUMP_ASSERT_WLOCKED();
1136
1137         CURVNET_SET(TD_TO_VNET(td));
1138         if (!IS_DEFAULT_VNET(curvnet)) {
1139                 CURVNET_RESTORE();
1140                 return (EINVAL);
1141         }
1142         ifp = ifunit_ref(conf->kda_iface);
1143         CURVNET_RESTORE();
1144
1145         if (ifp == NULL)
1146                 return (ENOENT);
1147         if ((if_getflags(ifp) & IFF_UP) == 0) {
1148                 if_rele(ifp);
1149                 return (ENXIO);
1150         }
1151         if (!netdump_supported_nic(ifp) || ifp->if_type != IFT_ETHER) {
1152                 if_rele(ifp);
1153                 return (ENODEV);
1154         }
1155
1156         if (netdump_enabled())
1157                 if_rele(nd_ifp);
1158         nd_ifp = ifp;
1159
1160         netdump_reinit_internal(ifp);
1161
1162 #define COPY_SIZED(elm) do {    \
1163         _Static_assert(sizeof(nd_conf.ndc_ ## elm) ==                   \
1164             sizeof(conf->kda_ ## elm), "elm " __XSTRING(elm) " mismatch"); \
1165         memcpy(&nd_conf.ndc_ ## elm, &conf->kda_ ## elm,                \
1166             sizeof(nd_conf.ndc_ ## elm));                               \
1167 } while (0)
1168         COPY_SIZED(iface);
1169         COPY_SIZED(server);
1170         COPY_SIZED(client);
1171         COPY_SIZED(gateway);
1172         COPY_SIZED(af);
1173 #undef COPY_SIZED
1174
1175         return (0);
1176 }
1177
1178 /*
1179  * Reinitialize the mbuf pool used by drivers while dumping. This is called
1180  * from the generic ioctl handler for SIOCSIFMTU after any NIC driver has
1181  * reconfigured itself.  (I.e., it may not be a configured netdump interface.)
1182  */
1183 void
1184 netdump_reinit(struct ifnet *ifp)
1185 {
1186
1187         NETDUMP_WLOCK();
1188         if (ifp != nd_ifp) {
1189                 NETDUMP_WUNLOCK();
1190                 return;
1191         }
1192         netdump_reinit_internal(ifp);
1193         NETDUMP_WUNLOCK();
1194 }
1195
1196 static void
1197 netdump_reinit_internal(struct ifnet *ifp)
1198 {
1199         int clsize, nmbuf, ncl, nrxr;
1200
1201         NETDUMP_ASSERT_WLOCKED();
1202
1203         ifp->if_netdump_methods->nd_init(ifp, &nrxr, &ncl, &clsize);
1204         KASSERT(nrxr > 0, ("invalid receive ring count %d", nrxr));
1205
1206         /*
1207          * We need two headers per message on the transmit side. Multiply by
1208          * four to give us some breathing room.
1209          */
1210         nmbuf = ncl * (4 + nrxr);
1211         ncl *= nrxr;
1212         netdump_mbuf_reinit(nmbuf, ncl, clsize);
1213 }
1214
1215 /*
1216  * ioctl(2) handler for the netdump device. This is currently only used to
1217  * register netdump as a dump device.
1218  *
1219  * Parameters:
1220  *     dev, Unused.
1221  *     cmd, The ioctl to be handled.
1222  *     addr, The parameter for the ioctl.
1223  *     flags, Unused.
1224  *     td, The thread invoking this ioctl.
1225  *
1226  * Returns:
1227  *     0 on success, and an errno value on failure.
1228  */
1229 static int
1230 netdump_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr,
1231     int flags __unused, struct thread *td)
1232 {
1233         struct diocskerneldump_arg kda_copy, *conf;
1234         struct dumperinfo dumper;
1235         uint8_t *encryptedkey;
1236         int error;
1237 #ifdef COMPAT_FREEBSD11
1238         u_int u;
1239 #endif
1240 #ifdef COMPAT_FREEBSD12
1241         struct diocskerneldump_arg_freebsd12 *kda12;
1242         struct netdump_conf_freebsd12 *conf12;
1243 #endif
1244
1245         conf = NULL;
1246         error = 0;
1247         NETDUMP_WLOCK();
1248
1249         switch (cmd) {
1250 #ifdef COMPAT_FREEBSD11
1251         case DIOCSKERNELDUMP_FREEBSD11:
1252                 gone_in(13, "11.x ABI compatibility");
1253                 u = *(u_int *)addr;
1254                 if (u != 0) {
1255                         error = ENXIO;
1256                         break;
1257                 }
1258                 if (netdump_enabled())
1259                         netdump_unconfigure();
1260                 break;
1261 #endif
1262 #ifdef COMPAT_FREEBSD12
1263                 /*
1264                  * Used by dumpon(8) in 12.x for clearing previous
1265                  * configuration -- then NETDUMPSCONF_FREEBSD12 is used to
1266                  * actually configure netdump.
1267                  */
1268         case DIOCSKERNELDUMP_FREEBSD12:
1269                 gone_in(14, "12.x ABI compatibility");
1270
1271                 kda12 = (void *)addr;
1272                 if (kda12->kda12_enable) {
1273                         error = ENXIO;
1274                         break;
1275                 }
1276                 if (netdump_enabled())
1277                         netdump_unconfigure();
1278                 break;
1279
1280         case NETDUMPGCONF_FREEBSD12:
1281                 gone_in(14, "FreeBSD 12.x ABI compat");
1282                 conf12 = (void *)addr;
1283
1284                 if (!netdump_enabled()) {
1285                         error = ENXIO;
1286                         break;
1287                 }
1288                 if (nd_conf.ndc_af != AF_INET) {
1289                         error = EOPNOTSUPP;
1290                         break;
1291                 }
1292
1293                 strlcpy(conf12->ndc12_iface, nd_ifp->if_xname,
1294                     sizeof(conf12->ndc12_iface));
1295                 memcpy(&conf12->ndc12_server, &nd_server,
1296                     sizeof(conf12->ndc12_server));
1297                 memcpy(&conf12->ndc12_client, &nd_client,
1298                     sizeof(conf12->ndc12_client));
1299                 memcpy(&conf12->ndc12_gateway, &nd_gateway,
1300                     sizeof(conf12->ndc12_gateway));
1301                 break;
1302 #endif
1303         case DIOCGKERNELDUMP:
1304                 conf = (void *)addr;
1305                 /*
1306                  * For now, index is ignored; netdump doesn't support multiple
1307                  * configurations (yet).
1308                  */
1309                 if (!netdump_enabled()) {
1310                         error = ENXIO;
1311                         conf = NULL;
1312                         break;
1313                 }
1314
1315                 strlcpy(conf->kda_iface, nd_ifp->if_xname,
1316                     sizeof(conf->kda_iface));
1317                 memcpy(&conf->kda_server, &nd_server, sizeof(nd_server));
1318                 memcpy(&conf->kda_client, &nd_client, sizeof(nd_client));
1319                 memcpy(&conf->kda_gateway, &nd_gateway, sizeof(nd_gateway));
1320                 conf->kda_af = nd_conf.ndc_af;
1321                 conf = NULL;
1322                 break;
1323
1324 #ifdef COMPAT_FREEBSD12
1325         case NETDUMPSCONF_FREEBSD12:
1326                 gone_in(14, "FreeBSD 12.x ABI compat");
1327
1328                 conf12 = (struct netdump_conf_freebsd12 *)addr;
1329
1330                 _Static_assert(offsetof(struct diocskerneldump_arg, kda_server)
1331                     == offsetof(struct netdump_conf_freebsd12, ndc12_server),
1332                     "simplifying assumption");
1333
1334                 memset(&kda_copy, 0, sizeof(kda_copy));
1335                 memcpy(&kda_copy, conf12,
1336                     offsetof(struct diocskerneldump_arg, kda_server));
1337
1338                 /* 12.x ABI could only configure IPv4 (INET) netdump. */
1339                 kda_copy.kda_af = AF_INET;
1340                 memcpy(&kda_copy.kda_server.in4, &conf12->ndc12_server,
1341                     sizeof(struct in_addr));
1342                 memcpy(&kda_copy.kda_client.in4, &conf12->ndc12_client,
1343                     sizeof(struct in_addr));
1344                 memcpy(&kda_copy.kda_gateway.in4, &conf12->ndc12_gateway,
1345                     sizeof(struct in_addr));
1346
1347                 kda_copy.kda_index =
1348                     (conf12->ndc12_kda.kda12_enable ? 0 : KDA_REMOVE_ALL);
1349
1350                 conf = &kda_copy;
1351                 explicit_bzero(conf12, sizeof(*conf12));
1352                 /* FALLTHROUGH */
1353 #endif
1354         case DIOCSKERNELDUMP:
1355                 encryptedkey = NULL;
1356                 if (cmd == DIOCSKERNELDUMP) {
1357                         conf = (void *)addr;
1358                         memcpy(&kda_copy, conf, sizeof(kda_copy));
1359                 }
1360                 /* Netdump only supports IP4 at this time. */
1361                 if (conf->kda_af != AF_INET) {
1362                         error = EPROTONOSUPPORT;
1363                         break;
1364                 }
1365
1366                 conf->kda_iface[sizeof(conf->kda_iface) - 1] = '\0';
1367                 if (conf->kda_index == KDA_REMOVE ||
1368                     conf->kda_index == KDA_REMOVE_DEV ||
1369                     conf->kda_index == KDA_REMOVE_ALL) {
1370                         if (netdump_enabled())
1371                                 netdump_unconfigure();
1372                         if (conf->kda_index == KDA_REMOVE_ALL)
1373                                 error = dumper_remove(NULL, conf);
1374                         break;
1375                 }
1376
1377                 error = netdump_configure(conf, td);
1378                 if (error != 0)
1379                         break;
1380
1381                 if (conf->kda_encryption != KERNELDUMP_ENC_NONE) {
1382                         if (conf->kda_encryptedkeysize <= 0 ||
1383                             conf->kda_encryptedkeysize >
1384                             KERNELDUMP_ENCKEY_MAX_SIZE) {
1385                                 error = EINVAL;
1386                                 break;
1387                         }
1388                         encryptedkey = malloc(conf->kda_encryptedkeysize,
1389                             M_TEMP, M_WAITOK);
1390                         error = copyin(conf->kda_encryptedkey, encryptedkey,
1391                             conf->kda_encryptedkeysize);
1392                         if (error != 0) {
1393                                 free(encryptedkey, M_TEMP);
1394                                 break;
1395                         }
1396
1397                         conf->kda_encryptedkey = encryptedkey;
1398                 }
1399
1400                 memset(&dumper, 0, sizeof(dumper));
1401                 dumper.dumper_start = netdump_start;
1402                 dumper.dumper_hdr = netdump_write_headers;
1403                 dumper.dumper = netdump_dumper;
1404                 dumper.priv = NULL;
1405                 dumper.blocksize = NETDUMP_DATASIZE;
1406                 dumper.maxiosize = MAXDUMPPGS * PAGE_SIZE;
1407                 dumper.mediaoffset = 0;
1408                 dumper.mediasize = 0;
1409
1410                 error = dumper_insert(&dumper, conf->kda_iface, conf);
1411                 if (encryptedkey != NULL) {
1412                         explicit_bzero(encryptedkey,
1413                             conf->kda_encryptedkeysize);
1414                         free(encryptedkey, M_TEMP);
1415                 }
1416                 if (error != 0)
1417                         netdump_unconfigure();
1418                 break;
1419         default:
1420                 error = ENOTTY;
1421                 break;
1422         }
1423         explicit_bzero(&kda_copy, sizeof(kda_copy));
1424         if (conf != NULL)
1425                 explicit_bzero(conf, sizeof(*conf));
1426         NETDUMP_WUNLOCK();
1427         return (error);
1428 }
1429
1430 /*
1431  * Called upon system init or kld load.  Initializes the netdump parameters to
1432  * sane defaults (locates the first available NIC and uses the first IPv4 IP on
1433  * that card as the client IP).  Leaves the server IP unconfigured.
1434  *
1435  * Parameters:
1436  *      mod, Unused.
1437  *      what, The module event type.
1438  *      priv, Unused.
1439  *
1440  * Returns:
1441  *      int, An errno value if an error occured, 0 otherwise.
1442  */
1443 static int
1444 netdump_modevent(module_t mod __unused, int what, void *priv __unused)
1445 {
1446         struct diocskerneldump_arg conf;
1447         char *arg;
1448         int error;
1449
1450         error = 0;
1451         switch (what) {
1452         case MOD_LOAD:
1453                 error = make_dev_p(MAKEDEV_WAITOK, &netdump_cdev,
1454                     &netdump_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "netdump");
1455                 if (error != 0)
1456                         return (error);
1457
1458                 nd_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event,
1459                     netdump_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
1460
1461                 if ((arg = kern_getenv("net.dump.iface")) != NULL) {
1462                         strlcpy(conf.kda_iface, arg, sizeof(conf.kda_iface));
1463                         freeenv(arg);
1464
1465                         if ((arg = kern_getenv("net.dump.server")) != NULL) {
1466                                 inet_aton(arg, &conf.kda_server.in4);
1467                                 freeenv(arg);
1468                         }
1469                         if ((arg = kern_getenv("net.dump.client")) != NULL) {
1470                                 inet_aton(arg, &conf.kda_client.in4);
1471                                 freeenv(arg);
1472                         }
1473                         if ((arg = kern_getenv("net.dump.gateway")) != NULL) {
1474                                 inet_aton(arg, &conf.kda_gateway.in4);
1475                                 freeenv(arg);
1476                         }
1477                         conf.kda_af = AF_INET;
1478
1479                         /* Ignore errors; we print a message to the console. */
1480                         NETDUMP_WLOCK();
1481                         (void)netdump_configure(&conf, curthread);
1482                         NETDUMP_WUNLOCK();
1483                 }
1484                 break;
1485         case MOD_UNLOAD:
1486                 NETDUMP_WLOCK();
1487                 if (netdump_enabled()) {
1488                         printf("netdump: disabling dump device for unload\n");
1489                         netdump_unconfigure();
1490                 }
1491                 NETDUMP_WUNLOCK();
1492                 destroy_dev(netdump_cdev);
1493                 EVENTHANDLER_DEREGISTER(ifnet_departure_event,
1494                     nd_detach_cookie);
1495                 break;
1496         default:
1497                 error = EOPNOTSUPP;
1498                 break;
1499         }
1500         return (error);
1501 }
1502
1503 static moduledata_t netdump_mod = {
1504         "netdump",
1505         netdump_modevent,
1506         NULL,
1507 };
1508
1509 MODULE_VERSION(netdump, 1);
1510 DECLARE_MODULE(netdump, netdump_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);