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