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