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