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