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