1 /* 2 * scamper_dl: manage BPF/PF_PACKET datalink instances for scamper 3 * 4 * $Id: scamper_dl.c,v 1.187 2020/03/17 07:32:16 mjl Exp $ 5 * 6 * Matthew Luckie 7 * Ben Stasiewicz added fragmentation support. 8 * Stephen Eichler added SACK support. 9 * 10 * Supported by: 11 * The University of Waikato 12 * NLANR Measurement and Network Analysis 13 * CAIDA 14 * The WIDE Project 15 * 16 * Copyright (C) 2004-2006 Matthew Luckie 17 * Copyright (C) 2006-2011 The University of Waikato 18 * Copyright (C) 2012 Matthew Luckie 19 * Copyright (C) 2014-2015 The Regents of the University of California 20 * 21 * This program is free software; you can redistribute it and/or modify 22 * it under the terms of the GNU General Public License as published by 23 * the Free Software Foundation, version 2. 24 * 25 * This program is distributed in the hope that it will be useful, 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 * GNU General Public License for more details. 29 * 30 * You should have received a copy of the GNU General Public License 31 * along with this program; if not, write to the Free Software 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33 * 34 */ 35 36 #ifdef HAVE_CONFIG_H 37 #include "config.h" 38 #endif 39 #include "internal.h" 40 41 #if defined(HAVE_BPF) || defined(__linux__) 42 #define HAVE_BPF_FILTER 43 #endif 44 45 #include "scamper.h" 46 #include "scamper_debug.h" 47 #include "scamper_addr.h" 48 #include "scamper_fds.h" 49 #include "scamper_dl.h" 50 #include "scamper_privsep.h" 51 #include "scamper_task.h" 52 #include "scamper_if.h" 53 #include "scamper_osinfo.h" 54 #include "utils.h" 55 56 #if defined(HAVE_BPF) && defined(DLT_APPLE_IP_OVER_IEEE1394) 57 #define HAVE_FIREWIRE 58 #elif defined(__linux__) && defined(ARPHRD_IEEE1394) 59 #define HAVE_FIREWIRE 60 #endif 61 62 struct scamper_dl 63 { 64 /* the file descriptor that scamper has on the datalink */ 65 scamper_fd_t *fdn; 66 67 /* the callback used to read packets off the datalink */ 68 int (*dlt_cb)(scamper_dl_rec_t *dl, uint8_t *pkt, size_t len); 69 70 /* the underlying type of the datalink (DLT_* or ARPHDR_* values) */ 71 int type; 72 73 /* how the user should frame packet to transmit on the datalink */ 74 int tx_type; 75 76 /* if we're using BPF, then we need to use an appropriately sized buffer */ 77 #if defined(HAVE_BPF) 78 u_int readbuf_len; 79 #endif 80 81 }; 82 83 static uint8_t *readbuf = NULL; 84 static size_t readbuf_len = 0; 85 86 #if defined(HAVE_BPF) 87 static const scamper_osinfo_t *osinfo = NULL; 88 #endif 89 90 /* 91 * dl_parse_ip 92 * 93 * pkt points to the beginning of an IP header. given the length of the 94 * packet, parse the contents into a datalink record structure. 95 */ 96 static int dl_parse_ip(scamper_dl_rec_t *dl, uint8_t *pktbuf, size_t pktlen) 97 { 98 struct ip *ip4; 99 struct ip6_hdr *ip6; 100 struct ip6_ext *ip6_exthdr; 101 struct ip6_frag *ip6_fraghdr; 102 struct icmp *icmp4; 103 struct icmp6_hdr *icmp6; 104 struct tcphdr *tcp; 105 struct udphdr *udp; 106 size_t iplen; 107 size_t extlen; 108 uint8_t *pkt = pktbuf; 109 size_t len = pktlen; 110 size_t off; 111 uint8_t *tmp; 112 uint16_t u16; 113 int i; 114 115 if((pkt[0] >> 4) == 4) /* IPv4 */ 116 { 117 ip4 = (struct ip *)pkt; 118 119 #ifndef _WIN32 120 iplen = (ip4->ip_hl << 2); 121 #else 122 iplen = ((ip4->ip_vhl) & 0xf) << 2; 123 #endif 124 125 /* 126 * make sure that the captured packet has enough to cover the whole 127 * of the IP header 128 */ 129 if(iplen > len) 130 return 0; 131 132 /* figure out fragmentation details */ 133 u16 = ntohs(ip4->ip_off); 134 dl->dl_ip_off = (u16 & IP_OFFMASK) * 8; 135 if(dl->dl_ip_off != 0 || (u16 & IP_MF) != 0) 136 dl->dl_ip_flags |= SCAMPER_DL_IP_FLAG_FRAG; 137 if((u16 & IP_DF) != 0) 138 dl->dl_ip_flags |= SCAMPER_DL_IP_FLAG_DF; 139 if((u16 & IP_MF) != 0) 140 dl->dl_ip_flags |= SCAMPER_DL_IP_FLAG_MF; 141 142 dl->dl_af = AF_INET; 143 dl->dl_ip_hl = iplen; 144 dl->dl_ip_proto = ip4->ip_p; 145 dl->dl_ip_size = ntohs(ip4->ip_len); 146 dl->dl_ip_id = ntohs(ip4->ip_id); 147 dl->dl_ip_tos = ip4->ip_tos; 148 dl->dl_ip_ttl = ip4->ip_ttl; 149 dl->dl_ip_src = (uint8_t *)&ip4->ip_src; 150 dl->dl_ip_dst = (uint8_t *)&ip4->ip_dst; 151 152 dl->dl_flags |= SCAMPER_DL_REC_FLAG_NET; 153 dl->dl_net_type = SCAMPER_DL_REC_NET_TYPE_IP; 154 155 pkt += iplen; 156 len -= iplen; 157 } 158 else if((pkt[0] >> 4) == 6) /* IPv6 */ 159 { 160 ip6 = (struct ip6_hdr *)pkt; 161 162 if((iplen = sizeof(struct ip6_hdr)) > len) 163 return 0; 164 165 dl->dl_af = AF_INET6; 166 dl->dl_ip_hl = iplen; 167 dl->dl_ip_flow = ntohl(ip6->ip6_flow) & 0xfffff; 168 dl->dl_ip_proto = ip6->ip6_nxt; 169 dl->dl_ip_size = ntohs(ip6->ip6_plen) + sizeof(struct ip6_hdr); 170 dl->dl_ip_hlim = ip6->ip6_hlim; 171 dl->dl_ip_src = (uint8_t *)&ip6->ip6_src; 172 dl->dl_ip_dst = (uint8_t *)&ip6->ip6_dst; 173 dl->dl_flags |= SCAMPER_DL_REC_FLAG_NET; 174 dl->dl_net_type = SCAMPER_DL_REC_NET_TYPE_IP; 175 176 pkt += iplen; 177 len -= iplen; 178 179 /* Process any IPv6 fragmentation headers */ 180 for(;;) 181 { 182 switch(dl->dl_ip_proto) 183 { 184 case IPPROTO_HOPOPTS: 185 case IPPROTO_DSTOPTS: 186 case IPPROTO_ROUTING: 187 if(sizeof(struct ip6_ext) > len) 188 return 0; 189 ip6_exthdr = (struct ip6_ext *)pkt; 190 if((extlen = (ip6_exthdr->ip6e_len * 8) + 8) > len) 191 return 0; 192 dl->dl_ip_proto = ip6_exthdr->ip6e_nxt; 193 break; 194 195 case IPPROTO_FRAGMENT: 196 if((extlen = sizeof(struct ip6_frag)) > len) 197 return 0; 198 ip6_fraghdr = (struct ip6_frag *)pkt; 199 dl->dl_ip6_id = ntohl(ip6_fraghdr->ip6f_ident); 200 dl->dl_ip_off = ntohs(ip6_fraghdr->ip6f_offlg) & 0xfff8; 201 dl->dl_ip_proto = ip6_fraghdr->ip6f_nxt; 202 dl->dl_ip_flags |= SCAMPER_DL_IP_FLAG_FRAG; 203 if(ntohs(ip6_fraghdr->ip6f_offlg) & 0x1) 204 dl->dl_ip_flags |= SCAMPER_DL_IP_FLAG_MF; 205 break; 206 207 default: 208 extlen = 0; 209 break; 210 } 211 212 if(extlen == 0) 213 break; 214 215 dl->dl_ip_hl += extlen; 216 pkt += extlen; 217 len -= extlen; 218 } 219 } 220 else 221 { 222 return 0; 223 } 224 225 dl->dl_ip_data = pkt; 226 dl->dl_ip_datalen = len; 227 228 /* 229 * can't do any further processing of the packet if we're seeing 230 * a later fragment 231 */ 232 if(dl->dl_ip_off != 0) 233 return 1; 234 235 if(dl->dl_ip_proto == IPPROTO_UDP) 236 { 237 if((int)sizeof(struct udphdr) > len) 238 { 239 return 0; 240 } 241 242 udp = (struct udphdr *)pkt; 243 dl->dl_udp_dport = ntohs(udp->uh_dport); 244 dl->dl_udp_sport = ntohs(udp->uh_sport); 245 dl->dl_udp_sum = udp->uh_sum; 246 dl->dl_flags |= SCAMPER_DL_REC_FLAG_TRANS; 247 } 248 else if(dl->dl_ip_proto == IPPROTO_TCP) 249 { 250 if((int)sizeof(struct tcphdr) > len) 251 { 252 return 0; 253 } 254 255 tcp = (struct tcphdr *)pkt; 256 dl->dl_tcp_dport = ntohs(tcp->th_dport); 257 dl->dl_tcp_sport = ntohs(tcp->th_sport); 258 dl->dl_tcp_seq = ntohl(tcp->th_seq); 259 dl->dl_tcp_ack = ntohl(tcp->th_ack); 260 #ifndef _WIN32 261 dl->dl_tcp_hl = tcp->th_off * 4; 262 #else 263 dl->dl_tcp_hl = (tcp->th_offx2 >> 4) * 4; 264 #endif 265 dl->dl_tcp_flags = tcp->th_flags; 266 dl->dl_tcp_win = ntohs(tcp->th_win); 267 dl->dl_flags |= SCAMPER_DL_REC_FLAG_TRANS; 268 269 if(dl->dl_tcp_hl >= 20 && len >= dl->dl_tcp_hl) 270 { 271 off = 20; 272 while(off < dl->dl_tcp_hl) 273 { 274 tmp = pkt + off; 275 276 if(tmp[0] == 0) /* End of option list */ 277 break; 278 279 if(tmp[0] == 1) /* no-op */ 280 { 281 off++; 282 continue; 283 } 284 285 if(tmp[1] == 0) 286 break; 287 288 /* make sure the option can be extracted */ 289 if(off + tmp[1] > dl->dl_tcp_hl) 290 break; 291 292 if(tmp[0] == 2 && tmp[1] == 4) /* mss option */ 293 dl->dl_tcp_mss = bytes_ntohs(tmp+2); 294 295 if(tmp[0] == 4 && tmp[1] == 2) /* sack permitted option */ 296 dl->dl_tcp_opts |= SCAMPER_DL_TCP_OPT_SACKP; 297 298 if(tmp[0] == 8 && tmp[1] == 10) /* timestamps */ 299 { 300 dl->dl_tcp_opts |= SCAMPER_DL_TCP_OPT_TS; 301 dl->dl_tcp_tsval = bytes_ntohl(tmp+2); 302 dl->dl_tcp_tsecr = bytes_ntohl(tmp+6); 303 } 304 305 if(tmp[0] == 5) 306 { 307 if(tmp[1]==10 || tmp[1]==18 || tmp[1]==26 || tmp[1]==34) 308 { 309 dl->dl_tcp_sack_edgec = (tmp[1]-2) / 4; 310 for(i=0; i<(tmp[1]-2)/4; i++) 311 dl->dl_tcp_sack_edges[i] = bytes_ntohl(tmp+2 + (i*4)); 312 } 313 else 314 { 315 dl->dl_tcp_sack_edgec = -1; 316 } 317 } 318 319 if(tmp[0] == 34 && tmp[1] >= 2) 320 { 321 dl->dl_tcp_opts |= SCAMPER_DL_TCP_OPT_FO; 322 dl->dl_tcp_fo_cookielen = tmp[1] - 2; 323 for(i=0; i<dl->dl_tcp_fo_cookielen; i++) 324 dl->dl_tcp_fo_cookie[i] = tmp[2+i]; 325 } 326 327 if(tmp[0] == 254 && tmp[1] >= 4 && bytes_ntohs(tmp+2) == 0xF989) 328 { 329 dl->dl_tcp_opts |= SCAMPER_DL_TCP_OPT_FO_EXP; 330 dl->dl_tcp_fo_cookielen = tmp[1] - 4; 331 for(i=0; i<dl->dl_tcp_fo_cookielen; i++) 332 dl->dl_tcp_fo_cookie[i] = tmp[4+i]; 333 } 334 335 off += tmp[1]; 336 } 337 338 dl->dl_tcp_datalen = dl->dl_ip_size - dl->dl_ip_hl - dl->dl_tcp_hl; 339 if(dl->dl_tcp_datalen > 0) 340 dl->dl_tcp_data = pkt + dl->dl_tcp_hl; 341 } 342 } 343 else if(dl->dl_ip_proto == IPPROTO_ICMP) 344 { 345 /* the absolute minimum ICMP header size is 8 bytes */ 346 if(ICMP_MINLEN > len) 347 { 348 return 0; 349 } 350 351 icmp4 = (struct icmp *)pkt; 352 dl->dl_icmp_type = icmp4->icmp_type; 353 dl->dl_icmp_code = icmp4->icmp_code; 354 355 switch(dl->dl_icmp_type) 356 { 357 case ICMP_UNREACH: 358 case ICMP_TIMXCEED: 359 if(ICMP_MINLEN + (int)sizeof(struct ip) > len) 360 { 361 return 0; 362 } 363 364 if(dl->dl_icmp_type == ICMP_UNREACH && 365 dl->dl_icmp_code == ICMP_UNREACH_NEEDFRAG) 366 { 367 dl->dl_icmp_nhmtu = ntohs(icmp4->icmp_nextmtu); 368 } 369 370 ip4 = &icmp4->icmp_ip; 371 372 dl->dl_icmp_ip_proto = ip4->ip_p; 373 dl->dl_icmp_ip_size = ntohs(ip4->ip_len); 374 dl->dl_icmp_ip_id = ntohs(ip4->ip_id); 375 dl->dl_icmp_ip_tos = ip4->ip_tos; 376 dl->dl_icmp_ip_ttl = ip4->ip_ttl; 377 dl->dl_icmp_ip_src = (uint8_t *)&ip4->ip_src; 378 dl->dl_icmp_ip_dst = (uint8_t *)&ip4->ip_dst; 379 380 /* 381 * the ICMP response should include the IP header and the first 382 * 8 bytes of the transport header. 383 */ 384 #ifndef _WIN32 385 if((size_t)(ICMP_MINLEN + (ip4->ip_hl << 2) + 8) > len) 386 #else 387 if((size_t)(ICMP_MINLEN + ((ip4->ip_vhl & 0xf) << 2) + 8) > len) 388 #endif 389 { 390 return 0; 391 } 392 393 pkt = (uint8_t *)ip4; 394 395 #ifndef _WIN32 396 iplen = (ip4->ip_hl << 2); 397 #else 398 iplen = ((ip4->ip_vhl & 0xf) << 2); 399 #endif 400 401 pkt += iplen; 402 403 if(dl->dl_icmp_ip_proto == IPPROTO_UDP) 404 { 405 udp = (struct udphdr *)pkt; 406 dl->dl_icmp_udp_sport = ntohs(udp->uh_sport); 407 dl->dl_icmp_udp_dport = ntohs(udp->uh_dport); 408 dl->dl_icmp_udp_sum = udp->uh_sum; 409 } 410 else if(dl->dl_icmp_ip_proto == IPPROTO_ICMP) 411 { 412 icmp4 = (struct icmp *)pkt; 413 dl->dl_icmp_icmp_type = icmp4->icmp_type; 414 dl->dl_icmp_icmp_code = icmp4->icmp_code; 415 dl->dl_icmp_icmp_id = ntohs(icmp4->icmp_id); 416 dl->dl_icmp_icmp_seq = ntohs(icmp4->icmp_seq); 417 } 418 else if(dl->dl_icmp_ip_proto == IPPROTO_TCP) 419 { 420 tcp = (struct tcphdr *)pkt; 421 dl->dl_icmp_tcp_sport = ntohs(tcp->th_sport); 422 dl->dl_icmp_tcp_dport = ntohs(tcp->th_dport); 423 dl->dl_icmp_tcp_seq = ntohl(tcp->th_seq); 424 } 425 break; 426 427 case ICMP_ECHOREPLY: 428 case ICMP_ECHO: 429 case ICMP_TSTAMPREPLY: 430 case ICMP_TSTAMP: 431 dl->dl_icmp_id = ntohs(icmp4->icmp_id); 432 dl->dl_icmp_seq = ntohs(icmp4->icmp_seq); 433 break; 434 435 default: 436 return 0; 437 } 438 439 dl->dl_flags |= SCAMPER_DL_REC_FLAG_TRANS; 440 } 441 else if(dl->dl_ip_proto == IPPROTO_ICMPV6) 442 { 443 /* the absolute minimum ICMP header size is 8 bytes */ 444 if((int)sizeof(struct icmp6_hdr) > len) 445 { 446 return 0; 447 } 448 449 icmp6 = (struct icmp6_hdr *)pkt; 450 dl->dl_icmp_type = icmp6->icmp6_type; 451 dl->dl_icmp_code = icmp6->icmp6_code; 452 pkt += sizeof(struct icmp6_hdr); 453 len -= sizeof(struct icmp6_hdr); 454 455 switch(dl->dl_icmp_type) 456 { 457 case ICMP6_TIME_EXCEEDED: 458 case ICMP6_DST_UNREACH: 459 case ICMP6_PACKET_TOO_BIG: 460 if((int)sizeof(struct ip6_hdr) + 8 > len) 461 { 462 return 0; 463 } 464 465 if(dl->dl_icmp_type == ICMP6_PACKET_TOO_BIG) 466 { 467 #ifndef _WIN32 468 dl->dl_icmp_nhmtu = (ntohl(icmp6->icmp6_mtu) % 0xffff); 469 #else 470 dl->dl_icmp_nhmtu = ntohs(icmp6->icmp6_seq); 471 #endif 472 } 473 474 ip6 = (struct ip6_hdr *)pkt; 475 pkt += sizeof(struct ip6_hdr); 476 477 dl->dl_icmp_ip_proto = ip6->ip6_nxt; 478 dl->dl_icmp_ip_size = ntohs(ip6->ip6_plen) + sizeof(struct ip6_hdr); 479 dl->dl_icmp_ip_hlim = ip6->ip6_hlim; 480 dl->dl_icmp_ip_flow = ntohl(ip6->ip6_flow) & 0xfffff; 481 dl->dl_icmp_ip_src = (uint8_t *)&ip6->ip6_src; 482 dl->dl_icmp_ip_dst = (uint8_t *)&ip6->ip6_dst; 483 484 if(dl->dl_icmp_ip_proto == IPPROTO_UDP) 485 { 486 udp = (struct udphdr *)pkt; 487 dl->dl_icmp_udp_sport = ntohs(udp->uh_sport); 488 dl->dl_icmp_udp_dport = ntohs(udp->uh_dport); 489 dl->dl_icmp_udp_sum = udp->uh_sum; 490 } 491 else if(dl->dl_icmp_ip_proto == IPPROTO_ICMPV6) 492 { 493 icmp6 = (struct icmp6_hdr *)pkt; 494 dl->dl_icmp_icmp_type = icmp6->icmp6_type; 495 dl->dl_icmp_icmp_code = icmp6->icmp6_code; 496 dl->dl_icmp_icmp_id = ntohs(icmp6->icmp6_id); 497 dl->dl_icmp_icmp_seq = ntohs(icmp6->icmp6_seq); 498 } 499 else if(dl->dl_icmp_ip_proto == IPPROTO_TCP) 500 { 501 tcp = (struct tcphdr *)pkt; 502 dl->dl_icmp_tcp_sport = ntohs(tcp->th_sport); 503 dl->dl_icmp_tcp_dport = ntohs(tcp->th_dport); 504 dl->dl_icmp_tcp_seq = ntohl(tcp->th_seq); 505 } 506 break; 507 508 case ICMP6_ECHO_REPLY: 509 case ICMP6_ECHO_REQUEST: 510 dl->dl_icmp_id = ntohs(icmp6->icmp6_id); 511 dl->dl_icmp_seq = ntohs(icmp6->icmp6_seq); 512 break; 513 514 case ND_NEIGHBOR_ADVERT: 515 dl->dl_icmp6_nd_target = pkt; 516 dl->dl_icmp6_nd_opts = pkt + 16; 517 dl->dl_icmp6_nd_opts_len = len - 16; 518 break; 519 520 default: 521 return 0; 522 } 523 524 dl->dl_flags |= SCAMPER_DL_REC_FLAG_TRANS; 525 } 526 else 527 { 528 return 0; 529 } 530 531 return 1; 532 } 533 534 /* 535 * dlt_raw_cb 536 * 537 * handle raw IP frames. 538 * i'm not sure how many of these interface types there are, but the linux 539 * sit interface is an example of one that is... 540 * 541 */ 542 static int dlt_raw_cb(scamper_dl_rec_t *dl, uint8_t *pkt, size_t len) 543 { 544 int ret; 545 546 if((ret = dl_parse_ip(dl, pkt, len)) != 0) 547 { 548 dl->dl_type = SCAMPER_DL_TYPE_RAW; 549 dl->dl_net_raw = pkt; 550 dl->dl_net_rawlen = len; 551 } 552 553 return ret; 554 } 555 556 /* 557 * dlt_null_cb 558 * 559 * handle the BSD loopback encapsulation. the first 4 bytes say what protocol 560 * family is used. filter out anything that is not IPv4 / IPv6 561 * 562 */ 563 #ifdef HAVE_BPF 564 static int dlt_null_cb(scamper_dl_rec_t *dl, uint8_t *pkt, size_t len) 565 { 566 uint32_t pf; 567 int ret; 568 569 /* ensure the packet holds at least 4 bytes for the psuedo header */ 570 if(len <= 4) 571 { 572 return 0; 573 } 574 575 memcpy(&pf, pkt, 4); 576 if(pf == PF_INET || pf == PF_INET6) 577 { 578 if((ret = dl_parse_ip(dl, pkt+4, len-4)) != 0) 579 { 580 dl->dl_type = SCAMPER_DL_TYPE_NULL; 581 dl->dl_net_raw = pkt+4; 582 dl->dl_net_rawlen = len-4; 583 } 584 585 return ret; 586 } 587 588 return 0; 589 } 590 #endif 591 592 /* 593 * dlt_en10mb_cb 594 * 595 * handle ethernet frames. 596 * 597 * an ethernet frame consists of 598 * - 6 bytes dst mac 599 * - 6 bytes src mac 600 * - 2 bytes type 601 * 602 */ 603 static int dlt_en10mb_cb(scamper_dl_rec_t *dl, uint8_t *pkt, size_t len) 604 { 605 uint16_t u16; 606 size_t off; 607 608 /* ensure the packet holds at least the length of the ethernet header */ 609 if(len <= 14) 610 return 0; 611 612 u16 = bytes_ntohs(pkt+12); 613 if(u16 == ETHERTYPE_IP || u16 == ETHERTYPE_IPV6) 614 { 615 if(dl_parse_ip(dl, pkt+14, len-14) == 0) 616 return 0; 617 } 618 else if(u16 == ETHERTYPE_ARP) 619 { 620 /* need to at least have a header */ 621 if(14 + 8 >= len) 622 return 0; 623 624 off = 14; 625 dl->dl_arp_hrd = bytes_ntohs(pkt+off); off += 2; 626 dl->dl_arp_pro = bytes_ntohs(pkt+off); off += 2; 627 dl->dl_arp_hln = pkt[off++]; 628 dl->dl_arp_pln = pkt[off++]; 629 dl->dl_arp_op = bytes_ntohs(pkt+off); off += 2; 630 631 /* make sure all the bits are found after the arp header */ 632 if(14 + 8 + (dl->dl_arp_hln*2) + (dl->dl_arp_pln*2) > len) 633 return 0; 634 635 dl->dl_arp_sha = pkt+off; off += dl->dl_arp_hln; 636 dl->dl_arp_spa = pkt+off; off += dl->dl_arp_pln; 637 dl->dl_arp_tha = pkt+off; off += dl->dl_arp_hln; 638 dl->dl_arp_tpa = pkt+off; 639 640 /* completed record is an arp frame */ 641 dl->dl_net_type = SCAMPER_DL_REC_NET_TYPE_ARP; 642 } 643 else return 0; 644 645 dl->dl_type = SCAMPER_DL_TYPE_ETHERNET; 646 dl->dl_lladdr_dst = pkt; 647 dl->dl_lladdr_src = pkt+6; 648 dl->dl_net_raw = pkt+14; 649 dl->dl_net_rawlen = len-14; 650 651 return 1; 652 } 653 654 /* 655 * dlt_firewire_cb 656 * 657 * handle IP frames on firewire devices. a firewire layer-2 frame consists 658 * of two 8 byte EUI64 addresses which represent the dst and the src 659 * addresses, and a 2 byte ethertype 660 */ 661 #ifdef HAVE_FIREWIRE 662 static int dlt_firewire_cb(scamper_dl_rec_t *dl, uint8_t *pkt, size_t len) 663 { 664 int ret; 665 uint16_t type; 666 667 /* ensure the packet holds at least the length of the firewire header */ 668 if(len <= 18) 669 { 670 return 0; 671 } 672 673 memcpy(&type, pkt+16, 2); type = ntohs(type); 674 if(type == ETHERTYPE_IP || type == ETHERTYPE_IPV6) 675 { 676 if((ret = dl_parse_ip(dl, pkt+18, len-18)) != 0) 677 { 678 dl->dl_type = SCAMPER_DL_TYPE_FIREWIRE; 679 dl->dl_lladdr_dst = pkt; 680 dl->dl_lladdr_src = pkt + 8; 681 dl->dl_net_raw = pkt + 18; 682 dl->dl_net_rawlen = len - 18; 683 } 684 685 return ret; 686 } 687 688 return 0; 689 } 690 #endif 691 692 #if defined(HAVE_BPF) 693 static int dl_bpf_open_dev(char *dev, const size_t len) 694 { 695 int i=0, fd; 696 697 do 698 { 699 snprintf(dev, len, "/dev/bpf%d", i); 700 if((fd = open(dev, O_RDWR)) == -1) 701 { 702 if(errno == EBUSY) 703 { 704 continue; 705 } 706 else 707 { 708 printerror(__func__, "could not open %s", dev); 709 return -1; 710 } 711 } 712 else break; 713 } 714 while(++i < 32768); 715 716 return fd; 717 } 718 719 static int dl_bpf_open(const int ifindex) 720 { 721 struct ifreq ifreq; 722 char dev[16]; 723 u_int blen; 724 int fd = -1; 725 726 /* work out the name corresponding to the ifindex */ 727 memset(&ifreq, 0, sizeof(ifreq)); 728 if(if_indextoname((unsigned int)ifindex, ifreq.ifr_name) == NULL) 729 { 730 printerror(__func__, "if_indextoname failed"); 731 goto err; 732 } 733 734 if((fd = dl_bpf_open_dev(dev, sizeof(dev))) == -1) 735 { 736 goto err; 737 } 738 739 /* get the suggested read buffer size */ 740 if(ioctl(fd, BIOCGBLEN, &blen) == -1) 741 { 742 printerror(__func__, "BIOCGBLEN %s", ifreq.ifr_name); 743 goto err; 744 } 745 746 /* 747 * try and get the system to use a larger buffer. need to do this 748 * before the call to BIOCSETIF. 749 */ 750 if(blen < 65536) 751 { 752 blen = 65536; 753 if(ioctl(fd, BIOCSBLEN, &blen) == -1) 754 { 755 printerror(__func__, "BIOCSBLEN %s: %d", ifreq.ifr_name, blen); 756 goto err; 757 } 758 } 759 760 /* set the interface that will be sniffed */ 761 if(ioctl(fd, BIOCSETIF, &ifreq) == -1) 762 { 763 printerror(__func__, "%s BIOCSETIF %s failed", dev, ifreq.ifr_name); 764 goto err; 765 } 766 767 return fd; 768 769 err: 770 if(fd != -1) close(fd); 771 return -1; 772 } 773 774 static int dl_bpf_node_init(const scamper_fd_t *fdn, scamper_dl_t *node) 775 { 776 char ifname[IFNAMSIZ]; 777 u_int tmp; 778 int ifindex, fd; 779 uint8_t *buf; 780 781 /* get the file descriptor associated with the fd node */ 782 if((fd = scamper_fd_fd_get(fdn)) < 0) 783 { 784 goto err; 785 } 786 787 /* get the interface index */ 788 if(scamper_fd_ifindex(fdn, &ifindex) != 0) 789 { 790 goto err; 791 } 792 793 /* convert the interface index to a name */ 794 if(if_indextoname((unsigned int)ifindex, ifname) == NULL) 795 { 796 printerror(__func__,"if_indextoname %d failed", ifindex); 797 goto err; 798 } 799 800 /* get the read buffer size */ 801 if(ioctl(fd, BIOCGBLEN, &node->readbuf_len) == -1) 802 { 803 printerror(__func__, "bpf BIOCGBLEN %s failed", ifname); 804 goto err; 805 } 806 807 /* get the DLT type for the interface */ 808 if(ioctl(fd, BIOCGDLT, &tmp) == -1) 809 { 810 printerror(__func__, "bpf BIOCGDLT %s failed", ifname); 811 goto err; 812 } 813 node->type = tmp; 814 815 switch(node->type) 816 { 817 case DLT_NULL: 818 node->dlt_cb = dlt_null_cb; 819 if(osinfo->os_id == SCAMPER_OSINFO_OS_FREEBSD && 820 osinfo->os_rel_dots > 0 && osinfo->os_rel[0] >= 6) 821 { 822 node->tx_type = SCAMPER_DL_TX_NULL; 823 } 824 else 825 { 826 node->tx_type = SCAMPER_DL_TX_UNSUPPORTED; 827 } 828 break; 829 830 case DLT_EN10MB: 831 node->dlt_cb = dlt_en10mb_cb; 832 node->tx_type = SCAMPER_DL_TX_ETHERNET; 833 break; 834 835 case DLT_RAW: 836 node->dlt_cb = dlt_raw_cb; 837 node->tx_type = SCAMPER_DL_TX_UNSUPPORTED; 838 break; 839 840 #if defined(DLT_APPLE_IP_OVER_IEEE1394) 841 case DLT_APPLE_IP_OVER_IEEE1394: 842 node->dlt_cb = dlt_firewire_cb; 843 node->tx_type = SCAMPER_DL_TX_UNSUPPORTED; 844 break; 845 #endif 846 847 default: 848 scamper_debug(__func__, "%s unhandled datalink %d", ifname, node->type); 849 goto err; 850 } 851 852 scamper_debug(__func__, "bpf if %s index %d buflen %d datalink %d", 853 ifname, ifindex, node->readbuf_len, node->type); 854 855 tmp = 1; 856 if(ioctl(fd, BIOCIMMEDIATE, &tmp) == -1) 857 { 858 printerror(__func__, "bpf BIOCIMMEDIATE failed"); 859 goto err; 860 } 861 862 if(readbuf_len < node->readbuf_len) 863 { 864 if((buf = realloc(readbuf, node->readbuf_len)) == NULL) 865 { 866 printerror(__func__, "could not realloc"); 867 return -1; 868 } 869 readbuf = buf; 870 readbuf_len = node->readbuf_len; 871 } 872 873 return 0; 874 875 err: 876 return -1; 877 } 878 879 static int dl_bpf_init(void) 880 { 881 struct bpf_version bv; 882 int fd; 883 char buf[16]; 884 int err; 885 886 if((fd = dl_bpf_open_dev(buf, sizeof(buf))) == -1) 887 { 888 if(errno == ENXIO) 889 { 890 return 0; 891 } 892 return -1; 893 } 894 895 err = ioctl(fd, BIOCVERSION, &bv); 896 close(fd); 897 if(err == -1) 898 { 899 printerror(__func__, "BIOCVERSION failed"); 900 return -1; 901 } 902 903 scamper_debug(__func__, "bpf version %d.%d", bv.bv_major, bv.bv_minor); 904 if(bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) 905 { 906 printerror_msg(__func__, "bpf ver %d.%d is incompatible with %d.%d", 907 bv.bv_major, bv.bv_minor, 908 BPF_MAJOR_VERSION, BPF_MINOR_VERSION); 909 return -1; 910 } 911 912 osinfo = scamper_osinfo_get(); 913 if(osinfo->os_id == SCAMPER_OSINFO_OS_FREEBSD && 914 osinfo->os_rel_dots >= 2 && osinfo->os_rel[0] == 4 && 915 (osinfo->os_rel[1] == 3 || osinfo->os_rel[1] == 4)) 916 { 917 printerror_msg(__func__, 918 "BPF file descriptors do not work with " 919 "select in FreeBSD 4.3 or 4.4"); 920 return -1; 921 } 922 923 return 0; 924 } 925 926 static int dl_bpf_read(const int fd, scamper_dl_t *node) 927 { 928 struct bpf_hdr *bpf_hdr; 929 scamper_dl_rec_t dl; 930 ssize_t len; 931 uint8_t *buf = readbuf; 932 933 while((len = read(fd, buf, node->readbuf_len)) == -1) 934 { 935 if(errno == EINTR) continue; 936 if(errno == EWOULDBLOCK) return 0; 937 printerror(__func__, "read %d bytes from fd %d failed", 938 node->readbuf_len, fd); 939 return -1; 940 } 941 942 /* record the ifindex now, as the cb may need it */ 943 if(scamper_fd_ifindex(node->fdn, &dl.dl_ifindex) != 0) 944 { 945 return -1; 946 } 947 948 while(buf < readbuf + len) 949 { 950 bpf_hdr = (struct bpf_hdr *)buf; 951 952 /* reset the datalink record */ 953 memset(&dl, 0, sizeof(dl)); 954 955 if(node->dlt_cb(&dl, buf + bpf_hdr->bh_hdrlen, bpf_hdr->bh_caplen)) 956 { 957 /* bpf always supplies a timestamp */ 958 dl.dl_flags |= SCAMPER_DL_REC_FLAG_TIMESTAMP; 959 960 dl.dl_tv.tv_sec = bpf_hdr->bh_tstamp.tv_sec; 961 dl.dl_tv.tv_usec = bpf_hdr->bh_tstamp.tv_usec; 962 963 scamper_task_handledl(&dl); 964 } 965 966 buf += BPF_WORDALIGN(bpf_hdr->bh_caplen + bpf_hdr->bh_hdrlen); 967 } 968 969 return 0; 970 } 971 972 static int dl_bpf_tx(const scamper_dl_t *node, 973 const uint8_t *pkt, const size_t len) 974 { 975 ssize_t wb; 976 977 if((wb = write(scamper_fd_fd_get(node->fdn), pkt, len)) < (ssize_t)len) 978 { 979 if(wb == -1) 980 printerror(__func__, "%d bytes failed", len); 981 else 982 scamper_debug(__func__, "%d bytes sent of %d total", wb, len); 983 return -1; 984 } 985 986 return 0; 987 } 988 989 static int dl_bpf_filter(scamper_dl_t *node, struct bpf_insn *insns, int len) 990 { 991 struct bpf_program prog; 992 993 prog.bf_len = len; 994 prog.bf_insns = insns; 995 996 if(ioctl(scamper_fd_fd_get(node->fdn), BIOCSETF, (caddr_t)&prog) == -1) 997 { 998 printerror(__func__, "BIOCSETF failed"); 999 return -1; 1000 } 1001 1002 return 0; 1003 } 1004 1005 #elif defined(__linux__) 1006 1007 static int dl_linux_open(const int ifindex) 1008 { 1009 struct sockaddr_ll sll; 1010 int fd; 1011 1012 /* open the socket in non cooked mode for now */ 1013 if((fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) 1014 { 1015 printerror(__func__, "could not open PF_PACKET"); 1016 return -1; 1017 } 1018 1019 /* scamper only wants packets on this interface */ 1020 memset(&sll, 0, sizeof(sll)); 1021 sll.sll_family = AF_PACKET; 1022 sll.sll_ifindex = ifindex; 1023 sll.sll_protocol = htons(ETH_P_ALL); 1024 if(bind(fd, (struct sockaddr *)&sll, sizeof(sll)) == -1) 1025 { 1026 printerror(__func__, "could not bind to %d", ifindex); 1027 close(fd); 1028 return -1; 1029 } 1030 1031 return fd; 1032 } 1033 1034 static int dl_linux_node_init(const scamper_fd_t *fdn, scamper_dl_t *node) 1035 { 1036 struct ifreq ifreq; 1037 char ifname[IFNAMSIZ]; 1038 int fd, ifindex; 1039 1040 if(scamper_fd_ifindex(fdn, &ifindex) != 0) 1041 { 1042 goto err; 1043 } 1044 1045 if((fd = scamper_fd_fd_get(fdn)) < 0) 1046 { 1047 goto err; 1048 } 1049 1050 if(if_indextoname(ifindex, ifname) == NULL) 1051 { 1052 printerror(__func__, "if_indextoname %d failed", ifindex); 1053 goto err; 1054 } 1055 1056 /* find out what type of datalink the interface has */ 1057 memcpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name)); 1058 if(ioctl(fd, SIOCGIFHWADDR, &ifreq) == -1) 1059 { 1060 printerror(__func__, "%s SIOCGIFHWADDR failed", ifname); 1061 goto err; 1062 } 1063 1064 node->type = ifreq.ifr_hwaddr.sa_family; 1065 1066 /* scamper can only deal with ethernet datalinks at this time */ 1067 switch(node->type) 1068 { 1069 case ARPHRD_ETHER: 1070 node->dlt_cb = dlt_en10mb_cb; 1071 node->tx_type = SCAMPER_DL_TX_ETHERNET; 1072 break; 1073 1074 case ARPHRD_LOOPBACK: 1075 node->dlt_cb = dlt_en10mb_cb; 1076 node->tx_type = SCAMPER_DL_TX_ETHLOOP; 1077 break; 1078 1079 #if defined(ARPHRD_SIT) 1080 case ARPHRD_SIT: 1081 node->dlt_cb = dlt_raw_cb; 1082 node->tx_type = SCAMPER_DL_TX_RAW; 1083 break; 1084 #endif 1085 1086 #if defined(ARPHRD_IEEE1394) 1087 case ARPHRD_IEEE1394: 1088 node->dlt_cb = dlt_firewire_cb; 1089 node->tx_type = SCAMPER_DL_TX_UNSUPPORTED; 1090 break; 1091 #endif 1092 1093 #if defined(ARPHRD_VOID) 1094 case ARPHRD_VOID: 1095 node->dlt_cb = dlt_raw_cb; 1096 node->tx_type = SCAMPER_DL_TX_UNSUPPORTED; 1097 break; 1098 #endif 1099 1100 default: 1101 scamper_debug(__func__, "%s unhandled datalink %d", ifname, node->type); 1102 goto err; 1103 } 1104 1105 return 0; 1106 1107 err: 1108 return -1; 1109 } 1110 1111 static int dl_linux_read(const int fd, scamper_dl_t *node) 1112 { 1113 scamper_dl_rec_t dl; 1114 ssize_t len; 1115 struct sockaddr_ll from; 1116 socklen_t fromlen; 1117 1118 fromlen = sizeof(from); 1119 while((len = recvfrom(fd, readbuf, readbuf_len, MSG_TRUNC, 1120 (struct sockaddr *)&from, &fromlen)) == -1) 1121 { 1122 if(errno == EINTR) 1123 { 1124 fromlen = sizeof(from); 1125 continue; 1126 } 1127 if(errno == EAGAIN) 1128 { 1129 return 0; 1130 } 1131 printerror(__func__, "read %d bytes from fd %d failed", readbuf_len, fd); 1132 return -1; 1133 } 1134 1135 /* sanity check the packet length */ 1136 if(len > readbuf_len) len = readbuf_len; 1137 1138 /* reset the datalink record */ 1139 memset(&dl, 0, sizeof(dl)); 1140 1141 /* record the ifindex now, as the cb routine may need it */ 1142 if(scamper_fd_ifindex(node->fdn, &dl.dl_ifindex) != 0) 1143 { 1144 return -1; 1145 } 1146 1147 /* if the packet passes the filter, we need to get the time it was rx'd */ 1148 if(node->dlt_cb(&dl, readbuf, len)) 1149 { 1150 /* scamper treats the failure of this ioctl as non-fatal */ 1151 if(ioctl(fd, SIOCGSTAMP, &dl.dl_tv) == 0) 1152 { 1153 dl.dl_flags |= SCAMPER_DL_REC_FLAG_TIMESTAMP; 1154 } 1155 else 1156 { 1157 printerror(__func__, "could not SIOCGSTAMP on fd %d", fd); 1158 } 1159 1160 scamper_task_handledl(&dl); 1161 } 1162 1163 return 0; 1164 } 1165 1166 static int dl_linux_tx(const scamper_dl_t *node, 1167 const uint8_t *pkt, const size_t len) 1168 { 1169 struct sockaddr_ll sll; 1170 struct sockaddr *sa = (struct sockaddr *)&sll; 1171 ssize_t wb; 1172 int fd, ifindex; 1173 1174 if(scamper_fd_ifindex(node->fdn, &ifindex) != 0) 1175 { 1176 return -1; 1177 } 1178 1179 memset(&sll, 0, sizeof(sll)); 1180 sll.sll_family = AF_PACKET; 1181 sll.sll_ifindex = ifindex; 1182 1183 if(node->type == ARPHRD_SIT) 1184 sll.sll_protocol = htons(ETH_P_IPV6); 1185 else 1186 sll.sll_protocol = htons(ETH_P_ALL); 1187 1188 fd = scamper_fd_fd_get(node->fdn); 1189 1190 if((wb = sendto(fd, pkt, len, 0, sa, sizeof(sll))) < (ssize_t)len) 1191 { 1192 if(wb == -1) 1193 printerror(__func__, "%d bytes failed", len); 1194 else 1195 scamper_debug(__func__, "%d bytes sent of %d total", wb, len); 1196 return -1; 1197 } 1198 1199 return 0; 1200 } 1201 1202 static int dl_linux_filter(scamper_dl_t *node, 1203 struct sock_filter *insns, int len) 1204 { 1205 struct sock_fprog prog; 1206 int i; 1207 1208 for(i=0; i<len; i++) 1209 { 1210 if(insns[i].code == (BPF_RET+BPF_K) && insns[i].k > 0) 1211 { 1212 insns[i].k = 65535; 1213 } 1214 } 1215 1216 prog.len = len; 1217 prog.filter = insns; 1218 1219 if(setsockopt(scamper_fd_fd_get(node->fdn), SOL_SOCKET, SO_ATTACH_FILTER, 1220 (caddr_t)&prog, sizeof(prog)) == -1) 1221 { 1222 printerror(__func__, "SO_ATTACH_FILTER failed"); 1223 return -1; 1224 } 1225 1226 return 0; 1227 } 1228 1229 #elif defined(HAVE_DLPI) 1230 1231 static int dl_dlpi_open(const int ifindex) 1232 { 1233 char ifname[5+IFNAMSIZ]; 1234 int fd; 1235 1236 strncpy(ifname, "/dev/", sizeof(ifname)); 1237 if(if_indextoname(ifindex, ifname+5) == NULL) 1238 { 1239 printerror(__func__, "if_indextoname %d failed", ifindex); 1240 return -1; 1241 } 1242 1243 if((fd = open(ifname, O_RDWR)) == -1) 1244 { 1245 printerror(__func__, "could not open %s", ifname); 1246 return -1; 1247 } 1248 1249 return fd; 1250 } 1251 1252 static int dl_dlpi_req(const int fd, void *req, size_t len) 1253 { 1254 union DL_primitives *dlp; 1255 struct strbuf ctl; 1256 1257 ctl.maxlen = 0; 1258 ctl.len = len; 1259 ctl.buf = (char *)req; 1260 1261 if(putmsg(fd, &ctl, NULL, 0) == -1) 1262 { 1263 dlp = req; 1264 printerror(__func__, "could not putmsg %d", dlp->dl_primitive); 1265 return -1; 1266 } 1267 1268 return 0; 1269 } 1270 1271 static int dl_dlpi_ack(const int fd, void *ack, int primitive) 1272 { 1273 union DL_primitives *dlp; 1274 struct strbuf ctl; 1275 int flags; 1276 1277 flags = 0; 1278 ctl.maxlen = MAXDLBUF; 1279 ctl.len = 0; 1280 ctl.buf = (char *)ack; 1281 if(getmsg(fd, &ctl, NULL, &flags) == -1) 1282 { 1283 printerror(__func__, "could not getmsg %d", primitive); 1284 return -1; 1285 } 1286 1287 dlp = ack; 1288 if(dlp->dl_primitive != primitive) 1289 { 1290 scamper_debug(__func__, 1291 "expected %d, got %d", primitive, dlp->dl_primitive); 1292 return -1; 1293 } 1294 1295 return 0; 1296 } 1297 1298 static int dl_dlpi_promisc(const int fd, const int level) 1299 { 1300 dl_promiscon_req_t promiscon_req; 1301 uint32_t buf[MAXDLBUF]; 1302 1303 promiscon_req.dl_primitive = DL_PROMISCON_REQ; 1304 promiscon_req.dl_level = level; 1305 if(dl_dlpi_req(fd, &promiscon_req, sizeof(promiscon_req)) == -1) 1306 { 1307 return -1; 1308 } 1309 1310 /* check for an ack to the promisc req */ 1311 if(dl_dlpi_ack(fd, buf, DL_OK_ACK) == -1) 1312 { 1313 return -1; 1314 } 1315 1316 return 0; 1317 } 1318 1319 static int strioctl(int fd, int cmd, void *dp, int len) 1320 { 1321 struct strioctl str; 1322 1323 str.ic_cmd = cmd; 1324 str.ic_timout = -1; 1325 str.ic_len = len; 1326 str.ic_dp = (char *)dp; 1327 if(ioctl(fd, I_STR, &str) == -1) 1328 { 1329 return -1; 1330 } 1331 1332 return str.ic_len; 1333 } 1334 1335 static int dl_dlpi_node_init(const scamper_fd_t *fdn, scamper_dl_t *node) 1336 { 1337 uint32_t buf[MAXDLBUF]; 1338 struct timeval tv; 1339 dl_info_req_t info_req; 1340 dl_info_ack_t *info_ack; 1341 dl_attach_req_t attach_req; 1342 dl_bind_req_t bind_req; 1343 int i, fd; 1344 1345 #ifndef NDEBUG 1346 char ifname[IFNAMSIZ]; 1347 int ifindex; 1348 #endif 1349 1350 if((fd = scamper_fd_fd_get(fdn)) < 0) 1351 { 1352 return -1; 1353 } 1354 1355 /* 1356 * send an information request to the datalink to determine what type 1357 * of packets they supply 1358 */ 1359 info_req.dl_primitive = DL_INFO_REQ; 1360 if(dl_dlpi_req(fd, &info_req, sizeof(info_req)) == -1) 1361 { 1362 return -1; 1363 } 1364 1365 /* 1366 * read the information acknowledgement, which contains details on the 1367 * type of the interface, etc. 1368 */ 1369 if(dl_dlpi_ack(fd, buf, DL_INFO_ACK) == -1) 1370 { 1371 return -1; 1372 } 1373 info_ack = (dl_info_ack_t *)buf; 1374 1375 /* record the mac type with the node */ 1376 node->type = info_ack->dl_mac_type; 1377 1378 /* determine how to handle the datalink */ 1379 switch(node->type) 1380 { 1381 case DL_CSMACD: 1382 case DL_ETHER: 1383 node->dlt_cb = dlt_en10mb_cb; 1384 node->tx_type = SCAMPER_DL_TX_ETHERNET; 1385 break; 1386 1387 default: 1388 node->tx_type = SCAMPER_DL_TX_UNSUPPORTED; 1389 scamper_debug(__func__, "unhandled datalink %d", node->type); 1390 return -1; 1391 } 1392 1393 /* attach to the interface */ 1394 if(info_ack->dl_provider_style == DL_STYLE2) 1395 { 1396 attach_req.dl_primitive = DL_ATTACH_REQ; 1397 attach_req.dl_ppa = 0; 1398 if(dl_dlpi_req(fd, &attach_req, sizeof(attach_req)) == -1) 1399 { 1400 return -1; 1401 } 1402 1403 /* check for a generic ack */ 1404 if(dl_dlpi_ack(fd, buf, DL_OK_ACK) == -1) 1405 { 1406 return -1; 1407 } 1408 } 1409 1410 /* bind the interface */ 1411 memset(&bind_req, 0, sizeof(bind_req)); 1412 bind_req.dl_primitive = DL_BIND_REQ; 1413 bind_req.dl_service_mode = DL_CLDLS; 1414 if(dl_dlpi_req(fd, &bind_req, sizeof(bind_req)) == -1) 1415 { 1416 return -1; 1417 } 1418 1419 /* check for an ack to the bind */ 1420 if(dl_dlpi_ack(fd, buf, DL_BIND_ACK) == -1) 1421 { 1422 return -1; 1423 } 1424 1425 /* 1426 * turn on phys and sap promisc modes. dlpi will not supply outbound 1427 * probe packets unless in phys promisc mode. 1428 */ 1429 if(dl_dlpi_promisc(fd, DL_PROMISC_PHYS) == -1 || 1430 dl_dlpi_promisc(fd, DL_PROMISC_SAP) == -1) 1431 { 1432 return -1; 1433 } 1434 1435 /* get full link layer */ 1436 if(strioctl(fd, DLIOCRAW, NULL, 0) == -1) 1437 { 1438 printerror(__func__, "could not DLIOCRAW"); 1439 return -1; 1440 } 1441 1442 /* push bufmod */ 1443 if(ioctl(fd, I_PUSH, "bufmod") == -1) 1444 { 1445 printerror(__func__, "could not push bufmod"); 1446 return -1; 1447 } 1448 1449 /* we need the first 1500 bytes of the packet */ 1450 i = 1500; 1451 if(strioctl(fd, SBIOCSSNAP, &i, sizeof(i)) == -1) 1452 { 1453 printerror(__func__, "could not SBIOCSSNAP %d", i); 1454 return -1; 1455 } 1456 1457 /* send the data every 50ms */ 1458 tv.tv_sec = 0; 1459 tv.tv_usec = 50000; 1460 if(strioctl(fd, SBIOCSTIME, &tv, sizeof(tv)) == -1) 1461 { 1462 printerror(__func__, "could not SBIOCSTIME %d.%06d", 1463 tv.tv_sec, tv.tv_usec); 1464 return -1; 1465 } 1466 1467 /* set the chunk length */ 1468 i = 65535; 1469 if(strioctl(fd, SBIOCSCHUNK, &i, sizeof(i)) == -1) 1470 { 1471 printerror(__func__, "could not SBIOCSCHUNK %d", i); 1472 return -1; 1473 } 1474 1475 if(ioctl(fd, I_FLUSH, FLUSHR) == -1) 1476 { 1477 printerror(__func__, "could not flushr"); 1478 return -1; 1479 } 1480 1481 #ifndef NDEBUG 1482 if(scamper_fd_ifindex(fdn, &ifindex) != 0 || 1483 if_indextoname(ifindex, ifname) == NULL) 1484 { 1485 strncpy(ifname, "<null>", sizeof(ifname)-1); 1486 ifname[sizeof(ifname)-1] = '\0'; 1487 } 1488 scamper_debug(__func__, "dlpi if %s index %d datalink %d", 1489 ifname, ifindex, node->type); 1490 #endif 1491 1492 return 0; 1493 } 1494 1495 static int dl_dlpi_read(const int fd, scamper_dl_t *node) 1496 { 1497 scamper_dl_rec_t dl; 1498 struct strbuf data; 1499 struct sb_hdr *sbh; 1500 uint8_t *buf = readbuf; 1501 int flags; 1502 1503 flags = 0; 1504 data.buf = (void *)readbuf; 1505 data.maxlen = readbuf_len; 1506 data.len = 0; 1507 1508 if(getmsg(fd, NULL, &data, &flags) == -1) 1509 { 1510 printerror(__func__, "could not getmsg"); 1511 return -1; 1512 } 1513 1514 while(buf < readbuf + data.len) 1515 { 1516 sbh = (struct sb_hdr *)buf; 1517 1518 memset(&dl, 0, sizeof(dl)); 1519 dl.dl_flags = SCAMPER_DL_REC_FLAG_TIMESTAMP; 1520 1521 if(node->dlt_cb(&dl, buf + sizeof(struct sb_hdr), sbh->sbh_msglen)) 1522 { 1523 dl.dl_tv.tv_sec = sbh->sbh_timestamp.tv_sec; 1524 dl.dl_tv.tv_usec = sbh->sbh_timestamp.tv_usec; 1525 scamper_task_handledl(&dl); 1526 } 1527 1528 buf += sbh->sbh_totlen; 1529 } 1530 1531 return -1; 1532 } 1533 1534 static int dl_dlpi_tx(const scamper_dl_t *node, 1535 const uint8_t *pkt, const size_t len) 1536 { 1537 struct strbuf data; 1538 int fd; 1539 1540 if((fd = scamper_fd_fd_get(node->fdn)) < 0) 1541 return -1; 1542 1543 memset(&data, 0, sizeof(data)); 1544 data.buf = (void *)pkt; 1545 data.len = len; 1546 1547 if(putmsg(fd, NULL, &data, 0) != 0) 1548 { 1549 printerror(__func__, "could not putmsg"); 1550 return -1; 1551 } 1552 1553 return 0; 1554 } 1555 1556 #endif 1557 1558 #if defined(HAVE_BPF_FILTER) 1559 1560 #if defined(HAVE_BPF) 1561 static void bpf_stmt(struct bpf_insn *insn, uint16_t code, uint32_t k) 1562 #else 1563 static void bpf_stmt(struct sock_filter *insn, uint16_t code, uint32_t k) 1564 #endif 1565 { 1566 insn->code = code; 1567 insn->jt = 0; 1568 insn->jf = 0; 1569 insn->k = k; 1570 return; 1571 } 1572 1573 static int dl_filter(scamper_dl_t *node) 1574 { 1575 #if defined(HAVE_BPF) 1576 struct bpf_insn insns[1]; 1577 #else 1578 struct sock_filter insns[1]; 1579 #endif 1580 1581 bpf_stmt(&insns[0], BPF_RET+BPF_K, 65535); 1582 1583 #if defined(HAVE_BPF) 1584 if(dl_bpf_filter(node, insns, 1) == -1) 1585 #elif defined(__linux__) 1586 if(dl_linux_filter(node, insns, 1) == -1) 1587 #endif 1588 { 1589 return -1; 1590 } 1591 1592 return 0; 1593 } 1594 #endif 1595 1596 int scamper_dl_rec_src(scamper_dl_rec_t *dl, scamper_addr_t *addr) 1597 { 1598 if(dl->dl_af == AF_INET) 1599 addr->type = SCAMPER_ADDR_TYPE_IPV4; 1600 else if(dl->dl_af == AF_INET6) 1601 addr->type = SCAMPER_ADDR_TYPE_IPV6; 1602 else 1603 return -1; 1604 1605 addr->addr = dl->dl_ip_src; 1606 return 0; 1607 } 1608 1609 int scamper_dl_rec_icmp_ip_dst(scamper_dl_rec_t *dl, scamper_addr_t *addr) 1610 { 1611 if(dl->dl_af == AF_INET) 1612 addr->type = SCAMPER_ADDR_TYPE_IPV4; 1613 else if(dl->dl_af == AF_INET6) 1614 addr->type = SCAMPER_ADDR_TYPE_IPV6; 1615 else 1616 return -1; 1617 1618 addr->addr = dl->dl_icmp_ip_dst; 1619 return 0; 1620 } 1621 1622 #if !defined(NDEBUG) && !defined(WITHOUT_DEBUGFILE) 1623 void scamper_dl_rec_frag_print(const scamper_dl_rec_t *dl) 1624 { 1625 char addr[64]; 1626 uint32_t id; 1627 1628 assert(dl->dl_af == AF_INET || dl->dl_af == AF_INET6); 1629 1630 if(dl->dl_af == AF_INET) 1631 id = dl->dl_ip_id; 1632 else 1633 id = dl->dl_ip6_id; 1634 1635 scamper_debug(NULL, "from %s len %d ipid %u off %u", 1636 addr_tostr(dl->dl_af, dl->dl_ip_src, addr, sizeof(addr)), 1637 dl->dl_ip_size, id, dl->dl_ip_off); 1638 1639 return; 1640 } 1641 1642 void scamper_dl_rec_udp_print(const scamper_dl_rec_t *dl) 1643 { 1644 char addr[64], ipid[16]; 1645 1646 assert(dl->dl_af == AF_INET || dl->dl_af == AF_INET6); 1647 assert(dl->dl_ip_proto == IPPROTO_UDP); 1648 1649 if(dl->dl_af == AF_INET) 1650 snprintf(ipid, sizeof(ipid), "ipid 0x%04x ", dl->dl_ip_id); 1651 else 1652 ipid[0] = '\0'; 1653 1654 scamper_debug(NULL, "from %s %sudp %d:%d len %d", 1655 addr_tostr(dl->dl_af, dl->dl_ip_src, addr, sizeof(addr)), 1656 ipid, dl->dl_tcp_sport, dl->dl_tcp_dport, dl->dl_ip_size); 1657 return; 1658 } 1659 1660 void scamper_dl_rec_tcp_print(const scamper_dl_rec_t *dl) 1661 { 1662 static const char *tcpflags[] = { 1663 "fin", 1664 "syn", 1665 "rst", 1666 "psh", 1667 "ack", 1668 "urg", 1669 "ece", 1670 "cwr" 1671 }; 1672 uint8_t u8; 1673 size_t off; 1674 char addr[64]; 1675 char fbuf[32], *flags; 1676 char pos[32]; 1677 char ipid[16]; 1678 int i; 1679 1680 assert(dl->dl_af == AF_INET || dl->dl_af == AF_INET6); 1681 assert(dl->dl_ip_proto == IPPROTO_TCP); 1682 1683 if((u8 = dl->dl_tcp_flags) != 0) 1684 { 1685 flags = fbuf; 1686 for(i=0; i<8; i++) 1687 { 1688 if((dl->dl_tcp_flags & (1<<i)) != 0) 1689 { 1690 memcpy(flags, tcpflags[i], 3); flags += 3; 1691 u8 &= ~(1<<i); 1692 if(u8 != 0) 1693 { 1694 *flags = '-'; 1695 flags++; 1696 } 1697 else break; 1698 } 1699 } 1700 *flags = '\0'; 1701 flags = fbuf; 1702 } 1703 else 1704 { 1705 flags = "nil"; 1706 } 1707 1708 off = 0; 1709 string_concat(pos, sizeof(pos), &off, "%u", dl->dl_tcp_seq); 1710 if(dl->dl_tcp_flags & TH_ACK) 1711 string_concat(pos, sizeof(pos), &off, ":%u", dl->dl_tcp_ack); 1712 1713 if(dl->dl_af == AF_INET) 1714 snprintf(ipid, sizeof(ipid), "ipid 0x%04x ", dl->dl_ip_id); 1715 else 1716 ipid[0] = '\0'; 1717 1718 scamper_debug(NULL, "from %s %stcp %d:%d %s %s len %d", 1719 addr_tostr(dl->dl_af, dl->dl_ip_src, addr, sizeof(addr)), 1720 ipid, dl->dl_tcp_sport, dl->dl_tcp_dport, flags, pos, 1721 dl->dl_ip_size); 1722 1723 return; 1724 } 1725 1726 void scamper_dl_rec_icmp_print(const scamper_dl_rec_t *dl) 1727 { 1728 char *t = NULL, tbuf[64]; 1729 char *c = NULL, cbuf[64]; 1730 char addr[64]; 1731 char ip[256]; 1732 char icmp[256]; 1733 char inner_ip[256]; 1734 char inner_transport[256]; 1735 size_t off; 1736 1737 assert(dl->dl_af == AF_INET || dl->dl_af == AF_INET6); 1738 1739 if(dl->dl_af == AF_INET) 1740 { 1741 addr_tostr(AF_INET, dl->dl_ip_src, addr, sizeof(addr)); 1742 snprintf(ip, sizeof(ip), "from %s size %d ttl %d tos 0x%02x ipid 0x%04x", 1743 addr, dl->dl_ip_size, dl->dl_ip_ttl, dl->dl_ip_tos, 1744 dl->dl_ip_id); 1745 1746 switch(dl->dl_icmp_type) 1747 { 1748 case ICMP_UNREACH: 1749 t = "unreach"; 1750 switch(dl->dl_icmp_code) 1751 { 1752 case ICMP_UNREACH_NET: c = "net"; break; 1753 case ICMP_UNREACH_HOST: c = "host"; break; 1754 case ICMP_UNREACH_PROTOCOL: c = "protocol"; break; 1755 case ICMP_UNREACH_PORT: c = "port"; break; 1756 case ICMP_UNREACH_SRCFAIL: c = "src-rt failed"; break; 1757 case ICMP_UNREACH_NET_UNKNOWN: c = "net unknown"; break; 1758 case ICMP_UNREACH_HOST_UNKNOWN: c = "host unknown"; break; 1759 case ICMP_UNREACH_ISOLATED: c = "isolated"; break; 1760 case ICMP_UNREACH_NET_PROHIB: c = "net prohib"; break; 1761 case ICMP_UNREACH_HOST_PROHIB: c = "host prohib"; break; 1762 case ICMP_UNREACH_TOSNET: c = "tos net"; break; 1763 case ICMP_UNREACH_TOSHOST: c = "tos host"; break; 1764 case ICMP_UNREACH_FILTER_PROHIB: c = "admin prohib"; break; 1765 case ICMP_UNREACH_NEEDFRAG: 1766 /* 1767 * use the type buf to be consistent with the ICMP6 1768 * fragmentation required message 1769 */ 1770 snprintf(tbuf, sizeof(tbuf), "need frag %d", dl->dl_icmp_nhmtu); 1771 t = tbuf; 1772 break; 1773 1774 default: 1775 snprintf(cbuf, sizeof(cbuf), "code %d", dl->dl_icmp_code); 1776 c = cbuf; 1777 break; 1778 } 1779 break; 1780 1781 case ICMP_TIMXCEED: 1782 t = "time exceeded"; 1783 switch(dl->dl_icmp_code) 1784 { 1785 case ICMP_TIMXCEED_INTRANS: c = "in trans"; break; 1786 case ICMP_TIMXCEED_REASS: c = "in reass"; break; 1787 default: 1788 snprintf(cbuf, sizeof(cbuf), "code %d", dl->dl_icmp_code); 1789 c = cbuf; 1790 break; 1791 } 1792 break; 1793 1794 case ICMP_ECHOREPLY: 1795 t = "echo reply"; 1796 snprintf(cbuf, sizeof(cbuf), "id %d seq %d", 1797 dl->dl_icmp_id, dl->dl_icmp_seq); 1798 c = cbuf; 1799 break; 1800 1801 case ICMP_TSTAMPREPLY: 1802 t = "time reply"; 1803 snprintf(cbuf, sizeof(cbuf), "id %d seq %d", 1804 dl->dl_icmp_id, dl->dl_icmp_seq); 1805 c = cbuf; 1806 break; 1807 } 1808 } 1809 else 1810 { 1811 addr_tostr(AF_INET6, dl->dl_ip_src, addr, sizeof(addr)); 1812 off = 0; 1813 string_concat(ip, sizeof(ip), &off, "from %s size %d hlim %d", addr, 1814 dl->dl_ip_size, dl->dl_ip_hlim); 1815 if(dl->dl_ip_flags & SCAMPER_DL_IP_FLAG_FRAG) 1816 string_concat(ip, sizeof(ip), &off, " ipid 0x%08x", dl->dl_ip6_id); 1817 1818 switch(dl->dl_icmp_type) 1819 { 1820 case ICMP6_DST_UNREACH: 1821 t = "unreach"; 1822 switch(dl->dl_icmp_code) 1823 { 1824 case ICMP6_DST_UNREACH_NOROUTE: c = "no route"; break; 1825 case ICMP6_DST_UNREACH_ADMIN: c = "admin prohib"; break; 1826 case ICMP6_DST_UNREACH_BEYONDSCOPE: c = "beyond scope"; break; 1827 case ICMP6_DST_UNREACH_ADDR: c = "addr"; break; 1828 case ICMP6_DST_UNREACH_NOPORT: c = "port"; break; 1829 1830 default: 1831 snprintf(cbuf, sizeof(cbuf), "code %d", dl->dl_icmp_code); 1832 c = cbuf; 1833 break; 1834 } 1835 break; 1836 1837 case ICMP6_TIME_EXCEEDED: 1838 t = "time exceeded"; 1839 switch(dl->dl_icmp_code) 1840 { 1841 case ICMP6_TIME_EXCEED_TRANSIT: c = "in trans"; break; 1842 case ICMP6_TIME_EXCEED_REASSEMBLY: c = "in reass"; break; 1843 1844 default: 1845 snprintf(cbuf, sizeof(cbuf), "code %d", dl->dl_icmp_code); 1846 c = cbuf; 1847 break; 1848 } 1849 break; 1850 1851 case ICMP6_PACKET_TOO_BIG: 1852 snprintf(tbuf, sizeof(tbuf), "need frag %d", dl->dl_icmp_nhmtu); 1853 t = tbuf; 1854 break; 1855 1856 case ICMP6_ECHO_REPLY: 1857 t = "echo reply"; 1858 snprintf(cbuf, sizeof(cbuf), "id %d seq %d", 1859 dl->dl_icmp_id, dl->dl_icmp_seq); 1860 c = cbuf; 1861 break; 1862 } 1863 } 1864 1865 if(t == NULL) 1866 { 1867 snprintf(icmp, sizeof(icmp), "icmp %d code %d", 1868 dl->dl_icmp_type, dl->dl_icmp_code); 1869 } 1870 else if(c == NULL) 1871 { 1872 snprintf(icmp, sizeof(icmp), "icmp %s", t); 1873 } 1874 else 1875 { 1876 snprintf(icmp, sizeof(icmp), "icmp %s %s", t, c); 1877 } 1878 1879 if(dl->dl_icmp_ip_dst != NULL) 1880 { 1881 if(dl->dl_af == AF_INET) 1882 { 1883 addr_tostr(AF_INET, dl->dl_icmp_ip_dst, addr, sizeof(addr)); 1884 snprintf(inner_ip, sizeof(inner_ip), 1885 " to %s size %d ttl %d tos 0x%02x ipid 0x%04x", 1886 addr, dl->dl_icmp_ip_size, dl->dl_icmp_ip_ttl, 1887 dl->dl_icmp_ip_tos, dl->dl_icmp_ip_id); 1888 } 1889 else 1890 { 1891 addr_tostr(AF_INET6, dl->dl_icmp_ip_dst, addr, sizeof(addr)); 1892 snprintf(inner_ip, sizeof(inner_ip), 1893 " to %s size %d hlim %d flow 0x%05x", addr, 1894 dl->dl_icmp_ip_size, dl->dl_icmp_ip_hlim, 1895 dl->dl_icmp_ip_flow); 1896 } 1897 1898 switch(dl->dl_icmp_ip_proto) 1899 { 1900 case IPPROTO_UDP: 1901 snprintf(inner_transport, sizeof(inner_transport), 1902 " proto UDP sport %d dport %d sum 0x%04x", 1903 dl->dl_icmp_udp_sport, dl->dl_icmp_udp_dport, 1904 ntohs(dl->dl_icmp_udp_sum)); 1905 break; 1906 1907 case IPPROTO_ICMP: 1908 case IPPROTO_ICMPV6: 1909 snprintf(inner_transport, sizeof(inner_transport), 1910 " proto ICMP type %d code %d id %04x seq %d", 1911 dl->dl_icmp_icmp_type, dl->dl_icmp_icmp_code, 1912 dl->dl_icmp_icmp_id, dl->dl_icmp_icmp_seq); 1913 break; 1914 1915 case IPPROTO_TCP: 1916 snprintf(inner_transport, sizeof(inner_transport), 1917 " proto TCP sport %d dport %d seq %08x", 1918 dl->dl_icmp_tcp_sport, dl->dl_icmp_tcp_dport, 1919 dl->dl_icmp_tcp_seq); 1920 break; 1921 1922 default: 1923 inner_transport[0] = '\0'; 1924 break; 1925 } 1926 } 1927 else 1928 { 1929 inner_ip[0] = '\0'; 1930 inner_transport[0] = '\0'; 1931 } 1932 1933 scamper_debug(NULL, "%s %s%s%s", ip, icmp, inner_ip, inner_transport); 1934 return; 1935 } 1936 #endif 1937 1938 /* 1939 * dl_read_cb 1940 * 1941 * this function is called by scamper_fds when a BPF fd fires as being 1942 * available to read from. 1943 */ 1944 void scamper_dl_read_cb(const int fd, void *param) 1945 { 1946 assert(param != NULL); 1947 1948 #if defined(HAVE_BPF) 1949 dl_bpf_read(fd, (scamper_dl_t *)param); 1950 #elif defined(__linux__) 1951 dl_linux_read(fd, (scamper_dl_t *)param); 1952 #elif defined(HAVE_DLPI) 1953 dl_dlpi_read(fd, (scamper_dl_t *)param); 1954 #endif 1955 1956 return; 1957 } 1958 1959 void scamper_dl_state_free(scamper_dl_t *dl) 1960 { 1961 assert(dl != NULL); 1962 free(dl); 1963 return; 1964 } 1965 1966 /* 1967 * scamper_dl_state_alloc 1968 * 1969 * given the scamper_fd_t supplied, initialise the file descriptor and do 1970 * initial setup tasks, then compile and set a filter to pick up the packets 1971 * scamper is responsible for transmitting. 1972 */ 1973 scamper_dl_t *scamper_dl_state_alloc(scamper_fd_t *fdn) 1974 { 1975 scamper_dl_t *dl = NULL; 1976 1977 if((dl = malloc_zero(sizeof(scamper_dl_t))) == NULL) 1978 { 1979 printerror(__func__, "malloc node failed"); 1980 goto err; 1981 } 1982 dl->fdn = fdn; 1983 1984 #if defined(HAVE_BPF) 1985 if(dl_bpf_node_init(fdn, dl) == -1) 1986 #elif defined(__linux__) 1987 if(dl_linux_node_init(fdn, dl) == -1) 1988 #elif defined(HAVE_DLPI) 1989 if(dl_dlpi_node_init(fdn, dl) == -1) 1990 #endif 1991 { 1992 goto err; 1993 } 1994 1995 #if defined(HAVE_BPF_FILTER) 1996 dl_filter(dl); 1997 #endif 1998 1999 return dl; 2000 2001 err: 2002 scamper_dl_state_free(dl); 2003 return NULL; 2004 } 2005 2006 int scamper_dl_tx(const scamper_dl_t *node, 2007 const uint8_t *pkt, const size_t len) 2008 { 2009 #if defined(HAVE_BPF) 2010 if(dl_bpf_tx(node, pkt, len) == -1) 2011 #elif defined(__linux__) 2012 if(dl_linux_tx(node, pkt, len) == -1) 2013 #elif defined(HAVE_DLPI) 2014 if(dl_dlpi_tx(node, pkt, len) == -1) 2015 #endif 2016 { 2017 return -1; 2018 } 2019 2020 return 0; 2021 } 2022 2023 int scamper_dl_tx_type(scamper_dl_t *dl) 2024 { 2025 return dl->tx_type; 2026 } 2027 2028 void scamper_dl_close(int fd) 2029 { 2030 #ifndef _WIN32 2031 close(fd); 2032 #endif 2033 return; 2034 } 2035 2036 /* 2037 * scamper_dl_open_fd 2038 * 2039 * routine to actually open a datalink. called by scamper_dl_open below, 2040 * as well as by the privsep code. 2041 */ 2042 int scamper_dl_open_fd(const int ifindex) 2043 { 2044 #if defined(HAVE_BPF) 2045 return dl_bpf_open(ifindex); 2046 #elif defined(__linux__) 2047 return dl_linux_open(ifindex); 2048 #elif defined(HAVE_DLPI) 2049 return dl_dlpi_open(ifindex); 2050 #elif defined(_WIN32) 2051 return -1; 2052 #endif 2053 } 2054 2055 /* 2056 * scamper_dl_open 2057 * 2058 * return a file descriptor for the datalink for the interface specified. 2059 * use privilege separation if required, otherwise open fd directly. 2060 */ 2061 int scamper_dl_open(const int ifindex) 2062 { 2063 int fd; 2064 2065 #if defined(WITHOUT_PRIVSEP) 2066 if((fd = scamper_dl_open_fd(ifindex)) == -1) 2067 #else 2068 if((fd = scamper_privsep_open_datalink(ifindex)) == -1) 2069 #endif 2070 { 2071 scamper_debug(__func__, "could not open ifindex %d", ifindex); 2072 return -1; 2073 } 2074 2075 return fd; 2076 } 2077 2078 void scamper_dl_cleanup() 2079 { 2080 if(readbuf != NULL) 2081 { 2082 free(readbuf); 2083 readbuf = NULL; 2084 } 2085 2086 return; 2087 } 2088 2089 int scamper_dl_init() 2090 { 2091 #if defined(HAVE_BPF) 2092 if(dl_bpf_init() == -1) 2093 { 2094 return -1; 2095 } 2096 #elif defined(__linux__) 2097 readbuf_len = 128; 2098 if((readbuf = malloc_zero(readbuf_len)) == NULL) 2099 { 2100 printerror(__func__, "could not malloc readbuf"); 2101 readbuf_len = 0; 2102 return -1; 2103 } 2104 #elif defined(HAVE_DLPI) 2105 readbuf_len = 65536; /* magic obtained from pcap-dlpi.c */ 2106 if((readbuf = malloc_zero(readbuf_len)) == NULL) 2107 { 2108 printerror(__func__, "could not malloc readbuf"); 2109 readbuf_len = 0; 2110 return -1; 2111 } 2112 #endif 2113 2114 return 0; 2115 } 2116