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