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