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