]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/netdump/netdump_client.c
Merge clang trunk r366426, resolve conflicts, and update FREEBSD-Xlist.
[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  * Flush any buffered vmcore data.
927  */
928 static int
929 netdump_flush_buf(void)
930 {
931         int error;
932
933         error = 0;
934         if (nd_conf.nd_buf_len != 0) {
935                 error = netdump_send(NETDUMP_VMCORE, nd_conf.nd_tx_off,
936                     nd_buf, nd_conf.nd_buf_len);
937                 if (error == 0)
938                         nd_conf.nd_buf_len = 0;
939         }
940         return (error);
941 }
942
943 /*
944  * Callback from dumpsys() to dump a chunk of memory.
945  * Copies it out to our static buffer then sends it across the network.
946  * Detects the initial KDH and makes sure it is given a special packet type.
947  *
948  * Parameters:
949  *      priv     Unused. Optional private pointer.
950  *      virtual  Virtual address (where to read the data from)
951  *      physical Unused. Physical memory address.
952  *      offset   Offset from start of core file
953  *      length   Data length
954  *
955  * Return value:
956  *      0 on success
957  *      errno on error
958  */
959 static int
960 netdump_dumper(void *priv __unused, void *virtual,
961     vm_offset_t physical __unused, off_t offset, size_t length)
962 {
963         int error;
964
965         NETDDEBUGV("netdump_dumper(NULL, %p, NULL, %ju, %zu)\n",
966             virtual, (uintmax_t)offset, length);
967
968         if (virtual == NULL) {
969                 error = netdump_flush_buf();
970                 if (error != 0)
971                         dump_failed = 1;
972
973                 if (dump_failed != 0)
974                         printf("failed to dump the kernel core\n");
975                 else if (netdump_send(NETDUMP_FINISHED, 0, NULL, 0) != 0)
976                         printf("failed to close the transaction\n");
977                 else
978                         printf("\nnetdump finished.\n");
979                 netdump_cleanup();
980                 return (0);
981         }
982         if (length > sizeof(nd_buf))
983                 return (ENOSPC);
984
985         if (nd_conf.nd_buf_len + length > sizeof(nd_buf) ||
986             (nd_conf.nd_buf_len != 0 && nd_conf.nd_tx_off +
987             nd_conf.nd_buf_len != offset)) {
988                 error = netdump_flush_buf();
989                 if (error != 0) {
990                         dump_failed = 1;
991                         return (error);
992                 }
993                 nd_conf.nd_tx_off = offset;
994         }
995
996         memmove(nd_buf + nd_conf.nd_buf_len, virtual, length);
997         nd_conf.nd_buf_len += length;
998
999         return (0);
1000 }
1001
1002 /*
1003  * Perform any initalization needed prior to transmitting the kernel core.
1004  */
1005 static int
1006 netdump_start(struct dumperinfo *di)
1007 {
1008         char *path;
1009         char buf[INET_ADDRSTRLEN];
1010         uint32_t len;
1011         int error;
1012
1013         error = 0;
1014
1015         /* Check if the dumping is allowed to continue. */
1016         if (!netdump_enabled())
1017                 return (EINVAL);
1018
1019         if (panicstr == NULL) {
1020                 printf(
1021                     "netdump_start: netdump may only be used after a panic\n");
1022                 return (EINVAL);
1023         }
1024
1025         if (nd_server.s_addr == INADDR_ANY) {
1026                 printf("netdump_start: can't netdump; no server IP given\n");
1027                 return (EINVAL);
1028         }
1029         if (nd_client.s_addr == INADDR_ANY) {
1030                 printf("netdump_start: can't netdump; no client IP given\n");
1031                 return (EINVAL);
1032         }
1033
1034         /* We start dumping at offset 0. */
1035         di->dumpoff = 0;
1036
1037         nd_seqno = 1;
1038
1039         /*
1040          * nd_server_port could have switched after the first ack the
1041          * first time it gets called.  Adjust it accordingly.
1042          */
1043         nd_server_port = NETDUMP_PORT;
1044
1045         /* Switch to the netdump mbuf zones. */
1046         netdump_mbuf_dump();
1047
1048         nd_ifp->if_netdump_methods->nd_event(nd_ifp, NETDUMP_START);
1049
1050         /* Make the card use *our* receive callback. */
1051         drv_if_input = nd_ifp->if_input;
1052         nd_ifp->if_input = netdump_pkt_in;
1053
1054         if (nd_gateway.s_addr == INADDR_ANY) {
1055                 restore_gw_addr = 1;
1056                 nd_gateway.s_addr = nd_server.s_addr;
1057         }
1058
1059         printf("netdump in progress. searching for server...\n");
1060         if (netdump_arp_gw()) {
1061                 printf("failed to locate server MAC address\n");
1062                 error = EINVAL;
1063                 goto trig_abort;
1064         }
1065
1066         if (nd_path[0] != '\0') {
1067                 path = nd_path;
1068                 len = strlen(path) + 1;
1069         } else {
1070                 path = NULL;
1071                 len = 0;
1072         }
1073         if (netdump_send(NETDUMP_HERALD, 0, path, len) != 0) {
1074                 printf("failed to contact netdump server\n");
1075                 error = EINVAL;
1076                 goto trig_abort;
1077         }
1078         printf("netdumping to %s (%6D)\n", inet_ntoa_r(nd_server, buf),
1079             nd_gw_mac.octet, ":");
1080         return (0);
1081
1082 trig_abort:
1083         netdump_cleanup();
1084         return (error);
1085 }
1086
1087 static int
1088 netdump_write_headers(struct dumperinfo *di, struct kerneldumpheader *kdh,
1089     void *key, uint32_t keysize)
1090 {
1091         int error;
1092
1093         error = netdump_flush_buf();
1094         if (error != 0)
1095                 return (error);
1096         memcpy(nd_buf, kdh, sizeof(*kdh));
1097         error = netdump_send(NETDUMP_KDH, 0, nd_buf, sizeof(*kdh));
1098         if (error == 0 && keysize > 0) {
1099                 if (keysize > sizeof(nd_buf))
1100                         return (EINVAL);
1101                 memcpy(nd_buf, key, keysize);
1102                 error = netdump_send(NETDUMP_EKCD_KEY, 0, nd_buf, keysize);
1103         }
1104         return (error);
1105 }
1106
1107 /*
1108  * Cleanup routine for a possibly failed netdump.
1109  */
1110 static void
1111 netdump_cleanup(void)
1112 {
1113
1114         if (restore_gw_addr != 0) {
1115                 nd_gateway.s_addr = INADDR_ANY;
1116                 restore_gw_addr = 0;
1117         }
1118         if (drv_if_input != NULL) {
1119                 nd_ifp->if_input = drv_if_input;
1120                 drv_if_input = NULL;
1121         }
1122         nd_ifp->if_netdump_methods->nd_event(nd_ifp, NETDUMP_END);
1123 }
1124
1125 /*-
1126  * KLD specific code.
1127  */
1128
1129 static struct cdevsw netdump_cdevsw = {
1130         .d_version =    D_VERSION,
1131         .d_ioctl =      netdump_ioctl,
1132         .d_name =       "netdump",
1133 };
1134
1135 static struct cdev *netdump_cdev;
1136
1137 static void
1138 netdump_unconfigure(void)
1139 {
1140         struct diocskerneldump_arg kda;
1141
1142         NETDUMP_ASSERT_WLOCKED();
1143         KASSERT(netdump_enabled(), ("%s: nd_ifp NULL", __func__));
1144
1145         bzero(&kda, sizeof(kda));
1146         kda.kda_index = KDA_REMOVE_DEV;
1147         (void)dumper_remove(nd_conf.ndc_iface, &kda);
1148
1149         netdump_mbuf_drain();
1150
1151         if_rele(nd_ifp);
1152         nd_ifp = NULL;
1153
1154         bzero(&nd_conf, sizeof(nd_conf));
1155 }
1156
1157 static void
1158 netdump_ifdetach(void *arg __unused, struct ifnet *ifp)
1159 {
1160
1161         NETDUMP_WLOCK();
1162         if (ifp == nd_ifp)
1163                 netdump_unconfigure();
1164         NETDUMP_WUNLOCK();
1165 }
1166
1167 static int
1168 netdump_configure(struct diocskerneldump_arg *conf, struct thread *td)
1169 {
1170         struct ifnet *ifp;
1171
1172         NETDUMP_ASSERT_WLOCKED();
1173
1174         CURVNET_SET(TD_TO_VNET(td));
1175         if (!IS_DEFAULT_VNET(curvnet)) {
1176                 CURVNET_RESTORE();
1177                 return (EINVAL);
1178         }
1179         ifp = ifunit_ref(conf->kda_iface);
1180         CURVNET_RESTORE();
1181
1182         if (ifp == NULL)
1183                 return (ENOENT);
1184         if ((if_getflags(ifp) & IFF_UP) == 0) {
1185                 if_rele(ifp);
1186                 return (ENXIO);
1187         }
1188         if (!netdump_supported_nic(ifp) || ifp->if_type != IFT_ETHER) {
1189                 if_rele(ifp);
1190                 return (ENODEV);
1191         }
1192
1193         if (netdump_enabled())
1194                 if_rele(nd_ifp);
1195         nd_ifp = ifp;
1196
1197         netdump_reinit_internal(ifp);
1198
1199 #define COPY_SIZED(elm) do {    \
1200         _Static_assert(sizeof(nd_conf.ndc_ ## elm) ==                   \
1201             sizeof(conf->kda_ ## elm), "elm " __XSTRING(elm) " mismatch"); \
1202         memcpy(&nd_conf.ndc_ ## elm, &conf->kda_ ## elm,                \
1203             sizeof(nd_conf.ndc_ ## elm));                               \
1204 } while (0)
1205         COPY_SIZED(iface);
1206         COPY_SIZED(server);
1207         COPY_SIZED(client);
1208         COPY_SIZED(gateway);
1209         COPY_SIZED(af);
1210 #undef COPY_SIZED
1211
1212         return (0);
1213 }
1214
1215 /*
1216  * Reinitialize the mbuf pool used by drivers while dumping. This is called
1217  * from the generic ioctl handler for SIOCSIFMTU after any NIC driver has
1218  * reconfigured itself.  (I.e., it may not be a configured netdump interface.)
1219  */
1220 void
1221 netdump_reinit(struct ifnet *ifp)
1222 {
1223
1224         NETDUMP_WLOCK();
1225         if (ifp != nd_ifp) {
1226                 NETDUMP_WUNLOCK();
1227                 return;
1228         }
1229         netdump_reinit_internal(ifp);
1230         NETDUMP_WUNLOCK();
1231 }
1232
1233 static void
1234 netdump_reinit_internal(struct ifnet *ifp)
1235 {
1236         int clsize, nmbuf, ncl, nrxr;
1237
1238         NETDUMP_ASSERT_WLOCKED();
1239
1240         ifp->if_netdump_methods->nd_init(ifp, &nrxr, &ncl, &clsize);
1241         KASSERT(nrxr > 0, ("invalid receive ring count %d", nrxr));
1242
1243         /*
1244          * We need two headers per message on the transmit side. Multiply by
1245          * four to give us some breathing room.
1246          */
1247         nmbuf = ncl * (4 + nrxr);
1248         ncl *= nrxr;
1249         netdump_mbuf_reinit(nmbuf, ncl, clsize);
1250 }
1251
1252 /*
1253  * ioctl(2) handler for the netdump device. This is currently only used to
1254  * register netdump as a dump device.
1255  *
1256  * Parameters:
1257  *     dev, Unused.
1258  *     cmd, The ioctl to be handled.
1259  *     addr, The parameter for the ioctl.
1260  *     flags, Unused.
1261  *     td, The thread invoking this ioctl.
1262  *
1263  * Returns:
1264  *     0 on success, and an errno value on failure.
1265  */
1266 static int
1267 netdump_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr,
1268     int flags __unused, struct thread *td)
1269 {
1270         struct diocskerneldump_arg kda_copy, *conf;
1271         struct dumperinfo dumper;
1272         uint8_t *encryptedkey;
1273         int error;
1274 #ifdef COMPAT_FREEBSD11
1275         u_int u;
1276 #endif
1277 #ifdef COMPAT_FREEBSD12
1278         struct diocskerneldump_arg_freebsd12 *kda12;
1279         struct netdump_conf_freebsd12 *conf12;
1280 #endif
1281
1282         conf = NULL;
1283         error = 0;
1284         NETDUMP_WLOCK();
1285
1286         switch (cmd) {
1287 #ifdef COMPAT_FREEBSD11
1288         case DIOCSKERNELDUMP_FREEBSD11:
1289                 gone_in(13, "11.x ABI compatibility");
1290                 u = *(u_int *)addr;
1291                 if (u != 0) {
1292                         error = ENXIO;
1293                         break;
1294                 }
1295                 if (netdump_enabled())
1296                         netdump_unconfigure();
1297                 break;
1298 #endif
1299 #ifdef COMPAT_FREEBSD12
1300                 /*
1301                  * Used by dumpon(8) in 12.x for clearing previous
1302                  * configuration -- then NETDUMPSCONF_FREEBSD12 is used to
1303                  * actually configure netdump.
1304                  */
1305         case DIOCSKERNELDUMP_FREEBSD12:
1306                 gone_in(14, "12.x ABI compatibility");
1307
1308                 kda12 = (void *)addr;
1309                 if (kda12->kda12_enable) {
1310                         error = ENXIO;
1311                         break;
1312                 }
1313                 if (netdump_enabled())
1314                         netdump_unconfigure();
1315                 break;
1316
1317         case NETDUMPGCONF_FREEBSD12:
1318                 gone_in(14, "FreeBSD 12.x ABI compat");
1319                 conf12 = (void *)addr;
1320
1321                 if (!netdump_enabled()) {
1322                         error = ENXIO;
1323                         break;
1324                 }
1325                 if (nd_conf.ndc_af != AF_INET) {
1326                         error = EOPNOTSUPP;
1327                         break;
1328                 }
1329
1330                 strlcpy(conf12->ndc12_iface, nd_ifp->if_xname,
1331                     sizeof(conf12->ndc12_iface));
1332                 memcpy(&conf12->ndc12_server, &nd_server,
1333                     sizeof(conf12->ndc12_server));
1334                 memcpy(&conf12->ndc12_client, &nd_client,
1335                     sizeof(conf12->ndc12_client));
1336                 memcpy(&conf12->ndc12_gateway, &nd_gateway,
1337                     sizeof(conf12->ndc12_gateway));
1338                 break;
1339 #endif
1340         case DIOCGKERNELDUMP:
1341                 conf = (void *)addr;
1342                 /*
1343                  * For now, index is ignored; netdump doesn't support multiple
1344                  * configurations (yet).
1345                  */
1346                 if (!netdump_enabled()) {
1347                         error = ENXIO;
1348                         conf = NULL;
1349                         break;
1350                 }
1351
1352                 strlcpy(conf->kda_iface, nd_ifp->if_xname,
1353                     sizeof(conf->kda_iface));
1354                 memcpy(&conf->kda_server, &nd_server, sizeof(nd_server));
1355                 memcpy(&conf->kda_client, &nd_client, sizeof(nd_client));
1356                 memcpy(&conf->kda_gateway, &nd_gateway, sizeof(nd_gateway));
1357                 conf->kda_af = nd_conf.ndc_af;
1358                 conf = NULL;
1359                 break;
1360
1361 #ifdef COMPAT_FREEBSD12
1362         case NETDUMPSCONF_FREEBSD12:
1363                 gone_in(14, "FreeBSD 12.x ABI compat");
1364
1365                 conf12 = (struct netdump_conf_freebsd12 *)addr;
1366
1367                 _Static_assert(offsetof(struct diocskerneldump_arg, kda_server)
1368                     == offsetof(struct netdump_conf_freebsd12, ndc12_server),
1369                     "simplifying assumption");
1370
1371                 memset(&kda_copy, 0, sizeof(kda_copy));
1372                 memcpy(&kda_copy, conf12,
1373                     offsetof(struct diocskerneldump_arg, kda_server));
1374
1375                 /* 12.x ABI could only configure IPv4 (INET) netdump. */
1376                 kda_copy.kda_af = AF_INET;
1377                 memcpy(&kda_copy.kda_server.in4, &conf12->ndc12_server,
1378                     sizeof(struct in_addr));
1379                 memcpy(&kda_copy.kda_client.in4, &conf12->ndc12_client,
1380                     sizeof(struct in_addr));
1381                 memcpy(&kda_copy.kda_gateway.in4, &conf12->ndc12_gateway,
1382                     sizeof(struct in_addr));
1383
1384                 kda_copy.kda_index =
1385                     (conf12->ndc12_kda.kda12_enable ? 0 : KDA_REMOVE_ALL);
1386
1387                 conf = &kda_copy;
1388                 explicit_bzero(conf12, sizeof(*conf12));
1389                 /* FALLTHROUGH */
1390 #endif
1391         case DIOCSKERNELDUMP:
1392                 encryptedkey = NULL;
1393                 if (cmd == DIOCSKERNELDUMP) {
1394                         conf = (void *)addr;
1395                         memcpy(&kda_copy, conf, sizeof(kda_copy));
1396                 }
1397                 /* Netdump only supports IP4 at this time. */
1398                 if (conf->kda_af != AF_INET) {
1399                         error = EPROTONOSUPPORT;
1400                         break;
1401                 }
1402
1403                 conf->kda_iface[sizeof(conf->kda_iface) - 1] = '\0';
1404                 if (conf->kda_index == KDA_REMOVE ||
1405                     conf->kda_index == KDA_REMOVE_DEV ||
1406                     conf->kda_index == KDA_REMOVE_ALL) {
1407                         if (netdump_enabled())
1408                                 netdump_unconfigure();
1409                         if (conf->kda_index == KDA_REMOVE_ALL)
1410                                 error = dumper_remove(NULL, conf);
1411                         break;
1412                 }
1413
1414                 error = netdump_configure(conf, td);
1415                 if (error != 0)
1416                         break;
1417
1418                 if (conf->kda_encryption != KERNELDUMP_ENC_NONE) {
1419                         if (conf->kda_encryptedkeysize <= 0 ||
1420                             conf->kda_encryptedkeysize >
1421                             KERNELDUMP_ENCKEY_MAX_SIZE) {
1422                                 error = EINVAL;
1423                                 break;
1424                         }
1425                         encryptedkey = malloc(conf->kda_encryptedkeysize,
1426                             M_TEMP, M_WAITOK);
1427                         error = copyin(conf->kda_encryptedkey, encryptedkey,
1428                             conf->kda_encryptedkeysize);
1429                         if (error != 0) {
1430                                 free(encryptedkey, M_TEMP);
1431                                 break;
1432                         }
1433
1434                         conf->kda_encryptedkey = encryptedkey;
1435                 }
1436
1437                 memset(&dumper, 0, sizeof(dumper));
1438                 dumper.dumper_start = netdump_start;
1439                 dumper.dumper_hdr = netdump_write_headers;
1440                 dumper.dumper = netdump_dumper;
1441                 dumper.priv = NULL;
1442                 dumper.blocksize = NETDUMP_DATASIZE;
1443                 dumper.maxiosize = MAXDUMPPGS * PAGE_SIZE;
1444                 dumper.mediaoffset = 0;
1445                 dumper.mediasize = 0;
1446
1447                 error = dumper_insert(&dumper, conf->kda_iface, conf);
1448                 if (encryptedkey != NULL) {
1449                         explicit_bzero(encryptedkey,
1450                             conf->kda_encryptedkeysize);
1451                         free(encryptedkey, M_TEMP);
1452                 }
1453                 if (error != 0)
1454                         netdump_unconfigure();
1455                 break;
1456         default:
1457                 error = ENOTTY;
1458                 break;
1459         }
1460         explicit_bzero(&kda_copy, sizeof(kda_copy));
1461         if (conf != NULL)
1462                 explicit_bzero(conf, sizeof(*conf));
1463         NETDUMP_WUNLOCK();
1464         return (error);
1465 }
1466
1467 /*
1468  * Called upon system init or kld load.  Initializes the netdump parameters to
1469  * sane defaults (locates the first available NIC and uses the first IPv4 IP on
1470  * that card as the client IP).  Leaves the server IP unconfigured.
1471  *
1472  * Parameters:
1473  *      mod, Unused.
1474  *      what, The module event type.
1475  *      priv, Unused.
1476  *
1477  * Returns:
1478  *      int, An errno value if an error occured, 0 otherwise.
1479  */
1480 static int
1481 netdump_modevent(module_t mod __unused, int what, void *priv __unused)
1482 {
1483         struct diocskerneldump_arg conf;
1484         char *arg;
1485         int error;
1486
1487         error = 0;
1488         switch (what) {
1489         case MOD_LOAD:
1490                 error = make_dev_p(MAKEDEV_WAITOK, &netdump_cdev,
1491                     &netdump_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "netdump");
1492                 if (error != 0)
1493                         return (error);
1494
1495                 nd_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event,
1496                     netdump_ifdetach, NULL, EVENTHANDLER_PRI_ANY);
1497
1498                 if ((arg = kern_getenv("net.dump.iface")) != NULL) {
1499                         strlcpy(conf.kda_iface, arg, sizeof(conf.kda_iface));
1500                         freeenv(arg);
1501
1502                         if ((arg = kern_getenv("net.dump.server")) != NULL) {
1503                                 inet_aton(arg, &conf.kda_server.in4);
1504                                 freeenv(arg);
1505                         }
1506                         if ((arg = kern_getenv("net.dump.client")) != NULL) {
1507                                 inet_aton(arg, &conf.kda_client.in4);
1508                                 freeenv(arg);
1509                         }
1510                         if ((arg = kern_getenv("net.dump.gateway")) != NULL) {
1511                                 inet_aton(arg, &conf.kda_gateway.in4);
1512                                 freeenv(arg);
1513                         }
1514                         conf.kda_af = AF_INET;
1515
1516                         /* Ignore errors; we print a message to the console. */
1517                         NETDUMP_WLOCK();
1518                         (void)netdump_configure(&conf, curthread);
1519                         NETDUMP_WUNLOCK();
1520                 }
1521                 break;
1522         case MOD_UNLOAD:
1523                 NETDUMP_WLOCK();
1524                 if (netdump_enabled()) {
1525                         printf("netdump: disabling dump device for unload\n");
1526                         netdump_unconfigure();
1527                 }
1528                 NETDUMP_WUNLOCK();
1529                 destroy_dev(netdump_cdev);
1530                 EVENTHANDLER_DEREGISTER(ifnet_departure_event,
1531                     nd_detach_cookie);
1532                 break;
1533         default:
1534                 error = EOPNOTSUPP;
1535                 break;
1536         }
1537         return (error);
1538 }
1539
1540 static moduledata_t netdump_mod = {
1541         "netdump",
1542         netdump_modevent,
1543         NULL,
1544 };
1545
1546 MODULE_VERSION(netdump, 1);
1547 DECLARE_MODULE(netdump, netdump_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);