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