xref: /freebsd/sys/netinet/netdump/netdump_client.c (revision 86aa9539fef591a363b06a0ebd3aa7a07f4c1579)
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);
1548