1 /* 2 * Copyright (c) 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), 22 * University College London. 23 */ 24 25 /* 26 * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX. 27 * 28 * Notes: 29 * 30 * - Apparently the DLIOCRAW ioctl() is specific to SunOS. 31 * 32 * - There is a bug in bufmod(7) such that setting the snapshot 33 * length results in data being left of the front of the packet. 34 * 35 * - It might be desirable to use pfmod(7) to filter packets in the 36 * kernel when possible. 37 */ 38 39 #ifndef lint 40 static const char rcsid[] _U_ = 41 "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.91.2.3 2003/11/21 10:20:46 guy Exp $ (LBL)"; 42 #endif 43 44 #ifdef HAVE_CONFIG_H 45 #include "config.h" 46 #endif 47 48 #include <sys/types.h> 49 #include <sys/time.h> 50 #ifdef HAVE_SYS_BUFMOD_H 51 #include <sys/bufmod.h> 52 #endif 53 #include <sys/dlpi.h> 54 #ifdef HAVE_SYS_DLPI_EXT_H 55 #include <sys/dlpi_ext.h> 56 #endif 57 #ifdef HAVE_HPUX9 58 #include <sys/socket.h> 59 #endif 60 #ifdef DL_HP_PPA_ACK_OBS 61 #include <sys/stat.h> 62 #endif 63 #include <sys/stream.h> 64 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 65 #include <sys/systeminfo.h> 66 #endif 67 68 #ifdef HAVE_HPUX9 69 #include <net/if.h> 70 #endif 71 72 #include <ctype.h> 73 #ifdef HAVE_HPUX9 74 #include <nlist.h> 75 #endif 76 #include <errno.h> 77 #include <fcntl.h> 78 #include <memory.h> 79 #include <stdio.h> 80 #include <stdlib.h> 81 #include <string.h> 82 #include <stropts.h> 83 #include <unistd.h> 84 85 #include "pcap-int.h" 86 87 #ifdef HAVE_OS_PROTO_H 88 #include "os-proto.h" 89 #endif 90 91 #ifndef PCAP_DEV_PREFIX 92 #ifdef _AIX 93 #define PCAP_DEV_PREFIX "/dev/dlpi" 94 #else 95 #define PCAP_DEV_PREFIX "/dev" 96 #endif 97 #endif 98 99 #define MAXDLBUF 8192 100 101 #ifdef HAVE_SYS_BUFMOD_H 102 103 /* 104 * Size of a bufmod chunk to pass upstream; that appears to be the biggest 105 * value to which you can set it, and setting it to that value (which 106 * is bigger than what appears to be the Solaris default of 8192) 107 * reduces the number of packet drops. 108 */ 109 #define CHUNKSIZE 65536 110 111 /* 112 * Size of the buffer to allocate for packet data we read; it must be 113 * large enough to hold a chunk. 114 */ 115 #define PKTBUFSIZE CHUNKSIZE 116 117 #else /* HAVE_SYS_BUFMOD_H */ 118 119 /* 120 * Size of the buffer to allocate for packet data we read; this is 121 * what the value used to be - there's no particular reason why it 122 * should be tied to MAXDLBUF, but we'll leave it as this for now. 123 */ 124 #define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32)) 125 126 #endif 127 128 /* Forwards */ 129 static char *split_dname(char *, int *, char *); 130 static int dlattachreq(int, bpf_u_int32, char *); 131 static int dlbindack(int, char *, char *); 132 static int dlbindreq(int, bpf_u_int32, char *); 133 static int dlinfoack(int, char *, char *); 134 static int dlinforeq(int, char *); 135 static int dlokack(int, const char *, char *, char *); 136 static int recv_ack(int, int, const char *, char *, char *); 137 static char *dlstrerror(bpf_u_int32); 138 static char *dlprim(bpf_u_int32); 139 static int dlpromisconreq(int, bpf_u_int32, char *); 140 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 141 static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); 142 #endif 143 static int send_request(int, char *, int, char *, char *); 144 #ifdef HAVE_SYS_BUFMOD_H 145 static int strioctl(int, int, int, char *); 146 #endif 147 #ifdef HAVE_HPUX9 148 static int dlpi_kread(int, off_t, void *, u_int, char *); 149 #endif 150 #ifdef HAVE_DEV_DLPI 151 static int get_dlpi_ppa(int, const char *, int, char *); 152 #endif 153 154 static int 155 pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps) 156 { 157 158 /* 159 * "ps_recv" counts packets handed to the filter, not packets 160 * that passed the filter. As filtering is done in userland, 161 * this does not include packets dropped because we ran out 162 * of buffer space. 163 * 164 * "ps_drop" counts packets dropped inside the DLPI service 165 * provider device device because of flow control requirements 166 * or resource exhaustion; it doesn't count packets dropped by 167 * the interface driver, or packets dropped upstream. As 168 * filtering is done in userland, it counts packets regardless 169 * of whether they would've passed the filter. 170 * 171 * These statistics don't include packets not yet read from 172 * the kernel by libpcap, but they may include packets not 173 * yet read from libpcap by the application. 174 */ 175 *ps = p->md.stat; 176 return (0); 177 } 178 179 /* XXX Needed by HP-UX (at least) */ 180 static bpf_u_int32 ctlbuf[MAXDLBUF]; 181 static struct strbuf ctl = { 182 MAXDLBUF, 183 0, 184 (char *)ctlbuf 185 }; 186 187 static int 188 pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 189 { 190 register int cc, n, caplen, origlen; 191 register u_char *bp, *ep, *pk; 192 register struct bpf_insn *fcode; 193 #ifdef HAVE_SYS_BUFMOD_H 194 register struct sb_hdr *sbp; 195 #ifdef LBL_ALIGN 196 struct sb_hdr sbhdr; 197 #endif 198 #endif 199 int flags; 200 struct strbuf data; 201 struct pcap_pkthdr pkthdr; 202 203 flags = 0; 204 cc = p->cc; 205 if (cc == 0) { 206 data.buf = (char *)p->buffer + p->offset; 207 data.maxlen = p->bufsize; 208 data.len = 0; 209 do { 210 /* 211 * Has "pcap_breakloop()" been called? 212 */ 213 if (p->break_loop) { 214 /* 215 * Yes - clear the flag that indicates 216 * that it has, and return -2 to 217 * indicate that we were told to 218 * break out of the loop. 219 */ 220 p->break_loop = 0; 221 return (-2); 222 } 223 if (getmsg(p->fd, &ctl, &data, &flags) < 0) { 224 /* Don't choke when we get ptraced */ 225 if (errno == EINTR) { 226 cc = 0; 227 continue; 228 } 229 strlcpy(p->errbuf, pcap_strerror(errno), 230 sizeof(p->errbuf)); 231 return (-1); 232 } 233 cc = data.len; 234 } while (cc == 0); 235 bp = p->buffer + p->offset; 236 } else 237 bp = p->bp; 238 239 /* Loop through packets */ 240 fcode = p->fcode.bf_insns; 241 ep = bp + cc; 242 n = 0; 243 #ifdef HAVE_SYS_BUFMOD_H 244 while (bp < ep) { 245 /* 246 * Has "pcap_breakloop()" been called? 247 * If so, return immediately - if we haven't read any 248 * packets, clear the flag and return -2 to indicate 249 * that we were told to break out of the loop, otherwise 250 * leave the flag set, so that the *next* call will break 251 * out of the loop without having read any packets, and 252 * return the number of packets we've processed so far. 253 */ 254 if (p->break_loop) { 255 if (n == 0) { 256 p->break_loop = 0; 257 return (-2); 258 } else { 259 p->bp = bp; 260 p->cc = ep - bp; 261 return (n); 262 } 263 } 264 #ifdef LBL_ALIGN 265 if ((long)bp & 3) { 266 sbp = &sbhdr; 267 memcpy(sbp, bp, sizeof(*sbp)); 268 } else 269 #endif 270 sbp = (struct sb_hdr *)bp; 271 p->md.stat.ps_drop = sbp->sbh_drops; 272 pk = bp + sizeof(*sbp); 273 bp += sbp->sbh_totlen; 274 origlen = sbp->sbh_origlen; 275 caplen = sbp->sbh_msglen; 276 #else 277 origlen = cc; 278 caplen = min(p->snapshot, cc); 279 pk = bp; 280 bp += caplen; 281 #endif 282 ++p->md.stat.ps_recv; 283 if (bpf_filter(fcode, pk, origlen, caplen)) { 284 #ifdef HAVE_SYS_BUFMOD_H 285 pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec; 286 pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec; 287 #else 288 (void)gettimeofday(&pkthdr.ts, NULL); 289 #endif 290 pkthdr.len = origlen; 291 pkthdr.caplen = caplen; 292 /* Insure caplen does not exceed snapshot */ 293 if (pkthdr.caplen > p->snapshot) 294 pkthdr.caplen = p->snapshot; 295 (*callback)(user, &pkthdr, pk); 296 if (++n >= cnt && cnt >= 0) { 297 p->cc = ep - bp; 298 p->bp = bp; 299 return (n); 300 } 301 } 302 #ifdef HAVE_SYS_BUFMOD_H 303 } 304 #endif 305 p->cc = 0; 306 return (n); 307 } 308 309 #ifndef DL_IPATM 310 #define DL_IPATM 0x12 /* ATM Classical IP interface */ 311 #endif 312 313 #ifdef HAVE_SOLARIS 314 /* 315 * For SunATM. 316 */ 317 #ifndef A_GET_UNITS 318 #define A_GET_UNITS (('A'<<8)|118) 319 #endif /* A_GET_UNITS */ 320 #ifndef A_PROMISCON_REQ 321 #define A_PROMISCON_REQ (('A'<<8)|121) 322 #endif /* A_PROMISCON_REQ */ 323 #endif /* HAVE_SOLARIS */ 324 325 static void 326 pcap_close_dlpi(pcap_t *p) 327 { 328 if (p->buffer != NULL) 329 free(p->buffer); 330 if (p->fd >= 0) 331 close(p->fd); 332 } 333 334 pcap_t * 335 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 336 char *ebuf) 337 { 338 register char *cp; 339 register pcap_t *p; 340 int ppa; 341 #ifdef HAVE_SOLARIS 342 int isatm = 0; 343 #endif 344 register dl_info_ack_t *infop; 345 #ifdef HAVE_SYS_BUFMOD_H 346 bpf_u_int32 ss, chunksize; 347 #ifdef HAVE_SOLARIS 348 register char *release; 349 bpf_u_int32 osmajor, osminor, osmicro; 350 #endif 351 #endif 352 bpf_u_int32 buf[MAXDLBUF]; 353 char dname[100]; 354 #ifndef HAVE_DEV_DLPI 355 char dname2[100]; 356 #endif 357 358 p = (pcap_t *)malloc(sizeof(*p)); 359 if (p == NULL) { 360 strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 361 return (NULL); 362 } 363 memset(p, 0, sizeof(*p)); 364 p->fd = -1; /* indicate that it hasn't been opened yet */ 365 366 #ifdef HAVE_DEV_DLPI 367 /* 368 ** Remove any "/dev/" on the front of the device. 369 */ 370 cp = strrchr(device, '/'); 371 if (cp == NULL) 372 strlcpy(dname, device, sizeof(dname)); 373 else 374 strlcpy(dname, cp + 1, sizeof(dname)); 375 376 /* 377 * Split the device name into a device type name and a unit number; 378 * chop off the unit number, so "dname" is just a device type name. 379 */ 380 cp = split_dname(dname, &ppa, ebuf); 381 if (cp == NULL) 382 goto bad; 383 *cp = '\0'; 384 385 /* 386 * Use "/dev/dlpi" as the device. 387 * 388 * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that 389 * the "dl_mjr_num" field is for the "major number of interface 390 * driver"; that's the major of "/dev/dlpi" on the system on 391 * which I tried this, but there may be DLPI devices that 392 * use a different driver, in which case we may need to 393 * search "/dev" for the appropriate device with that major 394 * device number, rather than hardwiring "/dev/dlpi". 395 */ 396 cp = "/dev/dlpi"; 397 if ((p->fd = open(cp, O_RDWR)) < 0) { 398 snprintf(ebuf, PCAP_ERRBUF_SIZE, 399 "%s: %s", cp, pcap_strerror(errno)); 400 goto bad; 401 } 402 403 /* 404 * Get a table of all PPAs for that device, and search that 405 * table for the specified device type name and unit number. 406 */ 407 ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf); 408 if (ppa < 0) 409 goto bad; 410 #else 411 /* 412 * If the device name begins with "/", assume it begins with 413 * the pathname of the directory containing the device to open; 414 * otherwise, concatenate the device directory name and the 415 * device name. 416 */ 417 if (*device == '/') 418 strlcpy(dname, device, sizeof(dname)); 419 else 420 snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, 421 device); 422 423 /* 424 * Get the unit number, and a pointer to the end of the device 425 * type name. 426 */ 427 cp = split_dname(dname, &ppa, ebuf); 428 if (cp == NULL) 429 goto bad; 430 431 /* 432 * Make a copy of the device pathname, and then remove the unit 433 * number from the device pathname. 434 */ 435 strlcpy(dname2, dname, sizeof(dname)); 436 *cp = '\0'; 437 438 /* Try device without unit number */ 439 if ((p->fd = open(dname, O_RDWR)) < 0) { 440 if (errno != ENOENT) { 441 snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, 442 pcap_strerror(errno)); 443 goto bad; 444 } 445 446 /* Try again with unit number */ 447 if ((p->fd = open(dname2, O_RDWR)) < 0) { 448 snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2, 449 pcap_strerror(errno)); 450 goto bad; 451 } 452 /* XXX Assume unit zero */ 453 ppa = 0; 454 } 455 #endif 456 457 p->snapshot = snaplen; 458 459 /* 460 ** Attach if "style 2" provider 461 */ 462 if (dlinforeq(p->fd, ebuf) < 0 || 463 dlinfoack(p->fd, (char *)buf, ebuf) < 0) 464 goto bad; 465 infop = &((union DL_primitives *)buf)->info_ack; 466 #ifdef HAVE_SOLARIS 467 if (infop->dl_mac_type == DL_IPATM) 468 isatm = 1; 469 #endif 470 if (infop->dl_provider_style == DL_STYLE2 && 471 (dlattachreq(p->fd, ppa, ebuf) < 0 || 472 dlokack(p->fd, "attach", (char *)buf, ebuf) < 0)) 473 goto bad; 474 /* 475 ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if 476 ** using SINIX) 477 */ 478 #if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix) 479 #ifdef _AIX 480 /* According to IBM's AIX Support Line, the dl_sap value 481 ** should not be less than 0x600 (1536) for standard Ethernet. 482 ** However, we seem to get DL_BADADDR - "DLSAP addr in improper 483 ** format or invalid" - errors if we use 1537 on the "tr0" 484 ** device, which, given that its name starts with "tr" and that 485 ** it's IBM, probably means a Token Ring device. (Perhaps we 486 ** need to use 1537 on "/dev/dlpi/en" because that device is for 487 ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and 488 ** it rejects invalid Ethernet types.) 489 ** 490 ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea 491 ** says that works on Token Ring (he says that 0 does *not* 492 ** work; perhaps that's considered an invalid LLC SAP value - I 493 ** assume the SAP value in a DLPI bind is an LLC SAP for network 494 ** types that use 802.2 LLC). 495 */ 496 if ((dlbindreq(p->fd, 1537, ebuf) < 0 && 497 dlbindreq(p->fd, 2, ebuf) < 0) || 498 #else 499 if (dlbindreq(p->fd, 0, ebuf) < 0 || 500 #endif 501 dlbindack(p->fd, (char *)buf, ebuf) < 0) 502 goto bad; 503 #endif 504 505 #ifdef HAVE_SOLARIS 506 if (isatm) { 507 /* 508 ** Have to turn on some special ATM promiscuous mode 509 ** for SunATM. 510 ** Do *NOT* turn regular promiscuous mode on; it doesn't 511 ** help, and may break things. 512 */ 513 if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) { 514 snprintf(ebuf, PCAP_ERRBUF_SIZE, "A_PROMISCON_REQ: %s", 515 pcap_strerror(errno)); 516 goto bad; 517 } 518 } else 519 #endif 520 if (promisc) { 521 /* 522 ** Enable promiscuous 523 */ 524 if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 || 525 dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0) 526 goto bad; 527 528 /* 529 ** Try to enable multicast (you would have thought 530 ** promiscuous would be sufficient). (Skip if using 531 ** HP-UX or SINIX) 532 */ 533 #if !defined(__hpux) && !defined(sinix) 534 if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 || 535 dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0) 536 fprintf(stderr, 537 "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf); 538 #endif 539 } 540 /* 541 ** Try to enable sap (when not in promiscuous mode when using 542 ** using HP-UX, when not doing SunATM on Solaris, and never 543 ** under SINIX) 544 */ 545 #ifndef sinix 546 if ( 547 #ifdef __hpux 548 !promisc && 549 #endif 550 #ifdef HAVE_SOLARIS 551 !isatm && 552 #endif 553 (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 || 554 dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) { 555 /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ 556 if (promisc) 557 fprintf(stderr, 558 "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf); 559 else 560 goto bad; 561 } 562 #endif 563 564 /* 565 ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous 566 ** options) 567 */ 568 #if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) 569 if (dlbindreq(p->fd, 0, ebuf) < 0 || 570 dlbindack(p->fd, (char *)buf, ebuf) < 0) 571 goto bad; 572 #endif 573 574 /* 575 ** Determine link type 576 */ 577 if (dlinforeq(p->fd, ebuf) < 0 || 578 dlinfoack(p->fd, (char *)buf, ebuf) < 0) 579 goto bad; 580 581 infop = &((union DL_primitives *)buf)->info_ack; 582 switch (infop->dl_mac_type) { 583 584 case DL_CSMACD: 585 case DL_ETHER: 586 p->linktype = DLT_EN10MB; 587 p->offset = 2; 588 break; 589 590 case DL_FDDI: 591 p->linktype = DLT_FDDI; 592 p->offset = 3; 593 break; 594 595 case DL_TPR: 596 p->linktype = DLT_IEEE802; 597 p->offset = 2; 598 break; 599 600 #ifdef HAVE_SOLARIS 601 case DL_IPATM: 602 p->linktype = DLT_SUNATM; 603 p->offset = 0; /* works for LANE and LLC encapsulation */ 604 break; 605 #endif 606 607 default: 608 snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu", 609 (unsigned long)infop->dl_mac_type); 610 goto bad; 611 } 612 613 #ifdef DLIOCRAW 614 /* 615 ** This is a non standard SunOS hack to get the full raw link-layer 616 ** header. 617 */ 618 if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { 619 snprintf(ebuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", 620 pcap_strerror(errno)); 621 goto bad; 622 } 623 #endif 624 625 #ifdef HAVE_SYS_BUFMOD_H 626 /* 627 ** Another non standard call to get the data nicely buffered 628 */ 629 if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { 630 snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s", 631 pcap_strerror(errno)); 632 goto bad; 633 } 634 635 /* 636 ** Now that the bufmod is pushed lets configure it. 637 ** 638 ** There is a bug in bufmod(7). When dealing with messages of 639 ** less than snaplen size it strips data from the beginning not 640 ** the end. 641 ** 642 ** This bug is supposed to be fixed in 5.3.2. Also, there is a 643 ** patch available. Ask for bugid 1149065. 644 */ 645 ss = snaplen; 646 #ifdef HAVE_SOLARIS 647 release = get_release(&osmajor, &osminor, &osmicro); 648 if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && 649 getenv("BUFMOD_FIXED") == NULL) { 650 fprintf(stderr, 651 "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", 652 release); 653 ss = 0; 654 } 655 #endif 656 if (ss > 0 && 657 strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) { 658 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s", 659 pcap_strerror(errno)); 660 goto bad; 661 } 662 663 /* 664 ** Set up the bufmod timeout 665 */ 666 if (to_ms != 0) { 667 struct timeval to; 668 669 to.tv_sec = to_ms / 1000; 670 to.tv_usec = (to_ms * 1000) % 1000000; 671 if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { 672 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s", 673 pcap_strerror(errno)); 674 goto bad; 675 } 676 } 677 678 /* 679 ** Set the chunk length. 680 */ 681 chunksize = CHUNKSIZE; 682 if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize) 683 != 0) { 684 snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSCHUNKP: %s", 685 pcap_strerror(errno)); 686 goto bad; 687 } 688 #endif 689 690 /* 691 ** As the last operation flush the read side. 692 */ 693 if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { 694 snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", 695 pcap_strerror(errno)); 696 goto bad; 697 } 698 699 /* Allocate data buffer */ 700 p->bufsize = PKTBUFSIZE; 701 p->buffer = (u_char *)malloc(p->bufsize + p->offset); 702 if (p->buffer == NULL) { 703 strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 704 goto bad; 705 } 706 707 /* 708 * "p->fd" is an FD for a STREAMS device, so "select()" and 709 * "poll()" should work on it. 710 */ 711 p->selectable_fd = p->fd; 712 713 p->read_op = pcap_read_dlpi; 714 p->setfilter_op = install_bpf_program; /* no kernel filtering */ 715 p->set_datalink_op = NULL; /* can't change data link type */ 716 p->getnonblock_op = pcap_getnonblock_fd; 717 p->setnonblock_op = pcap_setnonblock_fd; 718 p->stats_op = pcap_stats_dlpi; 719 p->close_op = pcap_close_dlpi; 720 721 return (p); 722 bad: 723 if (p->fd >= 0) 724 close(p->fd); 725 free(p); 726 return (NULL); 727 } 728 729 /* 730 * Split a device name into a device type name and a unit number; 731 * return the a pointer to the beginning of the unit number, which 732 * is the end of the device type name, and set "*unitp" to the unit 733 * number. 734 * 735 * Returns NULL on error, and fills "ebuf" with an error message. 736 */ 737 static char * 738 split_dname(char *device, int *unitp, char *ebuf) 739 { 740 char *cp; 741 char *eos; 742 int unit; 743 744 /* 745 * Look for a number at the end of the device name string. 746 */ 747 cp = device + strlen(device) - 1; 748 if (*cp < '0' || *cp > '9') { 749 snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", 750 device); 751 return (NULL); 752 } 753 754 /* Digits at end of string are unit number */ 755 while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9') 756 cp--; 757 758 unit = strtol(cp, &eos, 10); 759 if (*eos != '\0') { 760 snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); 761 return (NULL); 762 } 763 *unitp = unit; 764 return (cp); 765 } 766 767 int 768 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 769 { 770 #ifdef HAVE_SOLARIS 771 int fd; 772 union { 773 u_int nunits; 774 char pad[516]; /* XXX - must be at least 513; is 516 775 in "atmgetunits" */ 776 } buf; 777 char baname[2+1+1]; 778 u_int i; 779 780 /* 781 * We may have to do special magic to get ATM devices. 782 */ 783 if ((fd = open("/dev/ba", O_RDWR)) < 0) { 784 /* 785 * We couldn't open the "ba" device. 786 * For now, just give up; perhaps we should 787 * return an error if the problem is neither 788 * a "that device doesn't exist" error (ENOENT, 789 * ENXIO, etc.) or a "you're not allowed to do 790 * that" error (EPERM, EACCES). 791 */ 792 return (0); 793 } 794 795 if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) { 796 snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s", 797 pcap_strerror(errno)); 798 return (-1); 799 } 800 for (i = 0; i < buf.nunits; i++) { 801 snprintf(baname, sizeof baname, "ba%u", i); 802 if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0) 803 return (-1); 804 } 805 #endif 806 807 return (0); 808 } 809 810 static int 811 send_request(int fd, char *ptr, int len, char *what, char *ebuf) 812 { 813 struct strbuf ctl; 814 int flags; 815 816 ctl.maxlen = 0; 817 ctl.len = len; 818 ctl.buf = ptr; 819 820 flags = 0; 821 if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { 822 snprintf(ebuf, PCAP_ERRBUF_SIZE, 823 "send_request: putmsg \"%s\": %s", 824 what, pcap_strerror(errno)); 825 return (-1); 826 } 827 return (0); 828 } 829 830 static int 831 recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) 832 { 833 union DL_primitives *dlp; 834 struct strbuf ctl; 835 int flags; 836 837 ctl.maxlen = MAXDLBUF; 838 ctl.len = 0; 839 ctl.buf = bufp; 840 841 flags = 0; 842 if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { 843 snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", 844 what, pcap_strerror(errno)); 845 return (-1); 846 } 847 848 dlp = (union DL_primitives *) ctl.buf; 849 switch (dlp->dl_primitive) { 850 851 case DL_INFO_ACK: 852 case DL_BIND_ACK: 853 case DL_OK_ACK: 854 #ifdef DL_HP_PPA_ACK 855 case DL_HP_PPA_ACK: 856 #endif 857 /* These are OK */ 858 break; 859 860 case DL_ERROR_ACK: 861 switch (dlp->error_ack.dl_errno) { 862 863 case DL_SYSERR: 864 snprintf(ebuf, PCAP_ERRBUF_SIZE, 865 "recv_ack: %s: UNIX error - %s", 866 what, pcap_strerror(dlp->error_ack.dl_unix_errno)); 867 break; 868 869 default: 870 snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", 871 what, dlstrerror(dlp->error_ack.dl_errno)); 872 break; 873 } 874 return (-1); 875 876 default: 877 snprintf(ebuf, PCAP_ERRBUF_SIZE, 878 "recv_ack: %s: Unexpected primitive ack %s", 879 what, dlprim(dlp->dl_primitive)); 880 return (-1); 881 } 882 883 if (ctl.len < size) { 884 snprintf(ebuf, PCAP_ERRBUF_SIZE, 885 "recv_ack: %s: Ack too small (%d < %d)", 886 what, ctl.len, size); 887 return (-1); 888 } 889 return (ctl.len); 890 } 891 892 static char * 893 dlstrerror(bpf_u_int32 dl_errno) 894 { 895 static char errstring[6+2+8+1]; 896 897 switch (dl_errno) { 898 899 case DL_ACCESS: 900 return ("Improper permissions for request"); 901 902 case DL_BADADDR: 903 return ("DLSAP addr in improper format or invalid"); 904 905 case DL_BADCORR: 906 return ("Seq number not from outstand DL_CONN_IND"); 907 908 case DL_BADDATA: 909 return ("User data exceeded provider limit"); 910 911 case DL_BADPPA: 912 #ifdef HAVE_DEV_DLPI 913 /* 914 * With a single "/dev/dlpi" device used for all 915 * DLPI providers, PPAs have nothing to do with 916 * unit numbers. 917 */ 918 return ("Specified PPA was invalid"); 919 #else 920 /* 921 * We have separate devices for separate devices; 922 * the PPA is just the unit number. 923 */ 924 return ("Specified PPA (device unit) was invalid"); 925 #endif 926 927 case DL_BADPRIM: 928 return ("Primitive received not known by provider"); 929 930 case DL_BADQOSPARAM: 931 return ("QOS parameters contained invalid values"); 932 933 case DL_BADQOSTYPE: 934 return ("QOS structure type is unknown/unsupported"); 935 936 case DL_BADSAP: 937 return ("Bad LSAP selector"); 938 939 case DL_BADTOKEN: 940 return ("Token used not an active stream"); 941 942 case DL_BOUND: 943 return ("Attempted second bind with dl_max_conind"); 944 945 case DL_INITFAILED: 946 return ("Physical link initialization failed"); 947 948 case DL_NOADDR: 949 return ("Provider couldn't allocate alternate address"); 950 951 case DL_NOTINIT: 952 return ("Physical link not initialized"); 953 954 case DL_OUTSTATE: 955 return ("Primitive issued in improper state"); 956 957 case DL_SYSERR: 958 return ("UNIX system error occurred"); 959 960 case DL_UNSUPPORTED: 961 return ("Requested service not supplied by provider"); 962 963 case DL_UNDELIVERABLE: 964 return ("Previous data unit could not be delivered"); 965 966 case DL_NOTSUPPORTED: 967 return ("Primitive is known but not supported"); 968 969 case DL_TOOMANY: 970 return ("Limit exceeded"); 971 972 case DL_NOTENAB: 973 return ("Promiscuous mode not enabled"); 974 975 case DL_BUSY: 976 return ("Other streams for PPA in post-attached"); 977 978 case DL_NOAUTO: 979 return ("Automatic handling XID&TEST not supported"); 980 981 case DL_NOXIDAUTO: 982 return ("Automatic handling of XID not supported"); 983 984 case DL_NOTESTAUTO: 985 return ("Automatic handling of TEST not supported"); 986 987 case DL_XIDAUTO: 988 return ("Automatic handling of XID response"); 989 990 case DL_TESTAUTO: 991 return ("Automatic handling of TEST response"); 992 993 case DL_PENDING: 994 return ("Pending outstanding connect indications"); 995 996 default: 997 sprintf(errstring, "Error %02x", dl_errno); 998 return (errstring); 999 } 1000 } 1001 1002 static char * 1003 dlprim(bpf_u_int32 prim) 1004 { 1005 static char primbuf[80]; 1006 1007 switch (prim) { 1008 1009 case DL_INFO_REQ: 1010 return ("DL_INFO_REQ"); 1011 1012 case DL_INFO_ACK: 1013 return ("DL_INFO_ACK"); 1014 1015 case DL_ATTACH_REQ: 1016 return ("DL_ATTACH_REQ"); 1017 1018 case DL_DETACH_REQ: 1019 return ("DL_DETACH_REQ"); 1020 1021 case DL_BIND_REQ: 1022 return ("DL_BIND_REQ"); 1023 1024 case DL_BIND_ACK: 1025 return ("DL_BIND_ACK"); 1026 1027 case DL_UNBIND_REQ: 1028 return ("DL_UNBIND_REQ"); 1029 1030 case DL_OK_ACK: 1031 return ("DL_OK_ACK"); 1032 1033 case DL_ERROR_ACK: 1034 return ("DL_ERROR_ACK"); 1035 1036 case DL_SUBS_BIND_REQ: 1037 return ("DL_SUBS_BIND_REQ"); 1038 1039 case DL_SUBS_BIND_ACK: 1040 return ("DL_SUBS_BIND_ACK"); 1041 1042 case DL_UNITDATA_REQ: 1043 return ("DL_UNITDATA_REQ"); 1044 1045 case DL_UNITDATA_IND: 1046 return ("DL_UNITDATA_IND"); 1047 1048 case DL_UDERROR_IND: 1049 return ("DL_UDERROR_IND"); 1050 1051 case DL_UDQOS_REQ: 1052 return ("DL_UDQOS_REQ"); 1053 1054 case DL_CONNECT_REQ: 1055 return ("DL_CONNECT_REQ"); 1056 1057 case DL_CONNECT_IND: 1058 return ("DL_CONNECT_IND"); 1059 1060 case DL_CONNECT_RES: 1061 return ("DL_CONNECT_RES"); 1062 1063 case DL_CONNECT_CON: 1064 return ("DL_CONNECT_CON"); 1065 1066 case DL_TOKEN_REQ: 1067 return ("DL_TOKEN_REQ"); 1068 1069 case DL_TOKEN_ACK: 1070 return ("DL_TOKEN_ACK"); 1071 1072 case DL_DISCONNECT_REQ: 1073 return ("DL_DISCONNECT_REQ"); 1074 1075 case DL_DISCONNECT_IND: 1076 return ("DL_DISCONNECT_IND"); 1077 1078 case DL_RESET_REQ: 1079 return ("DL_RESET_REQ"); 1080 1081 case DL_RESET_IND: 1082 return ("DL_RESET_IND"); 1083 1084 case DL_RESET_RES: 1085 return ("DL_RESET_RES"); 1086 1087 case DL_RESET_CON: 1088 return ("DL_RESET_CON"); 1089 1090 default: 1091 (void) sprintf(primbuf, "unknown primitive 0x%x", prim); 1092 return (primbuf); 1093 } 1094 } 1095 1096 static int 1097 dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf) 1098 { 1099 dl_attach_req_t req; 1100 1101 req.dl_primitive = DL_ATTACH_REQ; 1102 req.dl_ppa = ppa; 1103 1104 return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf)); 1105 } 1106 1107 static int 1108 dlbindreq(int fd, bpf_u_int32 sap, char *ebuf) 1109 { 1110 1111 dl_bind_req_t req; 1112 1113 memset((char *)&req, 0, sizeof(req)); 1114 req.dl_primitive = DL_BIND_REQ; 1115 #ifdef DL_HP_RAWDLS 1116 req.dl_max_conind = 1; /* XXX magic number */ 1117 /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */ 1118 req.dl_sap = 22; 1119 req.dl_service_mode = DL_HP_RAWDLS; 1120 #else 1121 req.dl_sap = sap; 1122 #ifdef DL_CLDLS 1123 req.dl_service_mode = DL_CLDLS; 1124 #endif 1125 #endif 1126 1127 return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); 1128 } 1129 1130 static int 1131 dlbindack(int fd, char *bufp, char *ebuf) 1132 { 1133 1134 return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf)); 1135 } 1136 1137 static int 1138 dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf) 1139 { 1140 dl_promiscon_req_t req; 1141 1142 req.dl_primitive = DL_PROMISCON_REQ; 1143 req.dl_level = level; 1144 1145 return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf)); 1146 } 1147 1148 static int 1149 dlokack(int fd, const char *what, char *bufp, char *ebuf) 1150 { 1151 1152 return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf)); 1153 } 1154 1155 1156 static int 1157 dlinforeq(int fd, char *ebuf) 1158 { 1159 dl_info_req_t req; 1160 1161 req.dl_primitive = DL_INFO_REQ; 1162 1163 return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf)); 1164 } 1165 1166 static int 1167 dlinfoack(int fd, char *bufp, char *ebuf) 1168 { 1169 1170 return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf)); 1171 } 1172 1173 #ifdef HAVE_SYS_BUFMOD_H 1174 static int 1175 strioctl(int fd, int cmd, int len, char *dp) 1176 { 1177 struct strioctl str; 1178 int rc; 1179 1180 str.ic_cmd = cmd; 1181 str.ic_timout = -1; 1182 str.ic_len = len; 1183 str.ic_dp = dp; 1184 rc = ioctl(fd, I_STR, &str); 1185 1186 if (rc < 0) 1187 return (rc); 1188 else 1189 return (str.ic_len); 1190 } 1191 #endif 1192 1193 #if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 1194 static char * 1195 get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) 1196 { 1197 char *cp; 1198 static char buf[32]; 1199 1200 *majorp = 0; 1201 *minorp = 0; 1202 *microp = 0; 1203 if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) 1204 return ("?"); 1205 cp = buf; 1206 if (!isdigit((unsigned char)*cp)) 1207 return (buf); 1208 *majorp = strtol(cp, &cp, 10); 1209 if (*cp++ != '.') 1210 return (buf); 1211 *minorp = strtol(cp, &cp, 10); 1212 if (*cp++ != '.') 1213 return (buf); 1214 *microp = strtol(cp, &cp, 10); 1215 return (buf); 1216 } 1217 #endif 1218 1219 #ifdef DL_HP_PPA_ACK_OBS 1220 /* 1221 * Under HP-UX 10 and HP-UX 11, we can ask for the ppa 1222 */ 1223 1224 1225 /* 1226 * Determine ppa number that specifies ifname. 1227 * 1228 * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, 1229 * the code that's used here is the old code for HP-UX 10.x. 1230 * 1231 * However, HP-UX 10.20, at least, appears to have such a member 1232 * in its "dl_hp_ppa_info_t" structure, so the new code is used. 1233 * The new code didn't work on an old 10.20 system on which Rick 1234 * Jones of HP tried it, but with later patches installed, it 1235 * worked - it appears that the older system had those members but 1236 * didn't put anything in them, so, if the search by name fails, we 1237 * do the old search. 1238 * 1239 * Rick suggests that making sure your system is "up on the latest 1240 * lancommon/DLPI/driver patches" is probably a good idea; it'd fix 1241 * that problem, as well as allowing libpcap to see packets sent 1242 * from the system on which the libpcap application is being run. 1243 * (On 10.20, in addition to getting the latest patches, you need 1244 * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; 1245 * a posting to "comp.sys.hp.hpux" at 1246 * 1247 * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 1248 * 1249 * says that, to see the machine's outgoing traffic, you'd need to 1250 * apply the right patches to your system, and also set that variable 1251 * with: 1252 1253 echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem 1254 1255 * which could be put in, for example, "/sbin/init.d/lan". 1256 * 1257 * Setting the variable is not necessary on HP-UX 11.x. 1258 */ 1259 static int 1260 get_dlpi_ppa(register int fd, register const char *device, register int unit, 1261 register char *ebuf) 1262 { 1263 register dl_hp_ppa_ack_t *ap; 1264 register dl_hp_ppa_info_t *ipstart, *ip; 1265 register int i; 1266 char dname[100]; 1267 register u_long majdev; 1268 struct stat statbuf; 1269 dl_hp_ppa_req_t req; 1270 char buf[MAXDLBUF]; 1271 char *ppa_data_buf; 1272 dl_hp_ppa_ack_t *dlp; 1273 struct strbuf ctl; 1274 int flags; 1275 int ppa; 1276 1277 memset((char *)&req, 0, sizeof(req)); 1278 req.dl_primitive = DL_HP_PPA_REQ; 1279 1280 memset((char *)buf, 0, sizeof(buf)); 1281 if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0) 1282 return (-1); 1283 1284 ctl.maxlen = DL_HP_PPA_ACK_SIZE; 1285 ctl.len = 0; 1286 ctl.buf = (char *)buf; 1287 1288 flags = 0; 1289 /* 1290 * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal 1291 * recv_ack will fail because it set the maxlen to MAXDLBUF (8192) 1292 * which is NOT big enough for a DL_HP_PPA_REQ. 1293 * 1294 * This causes libpcap applications to fail on a system with HP-APA 1295 * installed. 1296 * 1297 * To figure out how big the returned data is, we first call getmsg 1298 * to get the small head and peek at the head to get the actual data 1299 * length, and then issue another getmsg to get the actual PPA data. 1300 */ 1301 /* get the head first */ 1302 if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { 1303 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1304 "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); 1305 return (-1); 1306 } 1307 1308 dlp = (dl_hp_ppa_ack_t *)ctl.buf; 1309 if (dlp->dl_primitive != DL_HP_PPA_ACK) { 1310 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1311 "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", 1312 (bpf_u_int32)dlp->dl_primitive); 1313 return (-1); 1314 } 1315 1316 if (ctl.len < DL_HP_PPA_ACK_SIZE) { 1317 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1318 "get_dlpi_ppa: hpppa ack too small (%d < %lu)", 1319 ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); 1320 return (-1); 1321 } 1322 1323 /* allocate buffer */ 1324 if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { 1325 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1326 "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); 1327 return (-1); 1328 } 1329 ctl.maxlen = dlp->dl_length; 1330 ctl.len = 0; 1331 ctl.buf = (char *)ppa_data_buf; 1332 /* get the data */ 1333 if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { 1334 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1335 "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); 1336 free(ppa_data_buf); 1337 return (-1); 1338 } 1339 if (ctl.len < dlp->dl_length) { 1340 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1341 "get_dlpi_ppa: hpppa ack too small (%d < %d)", 1342 ctl.len, dlp->dl_length); 1343 free(ppa_data_buf); 1344 return (-1); 1345 } 1346 1347 ap = (dl_hp_ppa_ack_t *)buf; 1348 ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; 1349 ip = ipstart; 1350 1351 #ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 1352 /* 1353 * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" 1354 * member that should, in theory, contain the part of the 1355 * name for the device that comes before the unit number, 1356 * and should also have a "dl_module_id_2" member that may 1357 * contain an alternate name (e.g., I think Ethernet devices 1358 * have both "lan", for "lanN", and "snap", for "snapN", with 1359 * the former being for Ethernet packets and the latter being 1360 * for 802.3/802.2 packets). 1361 * 1362 * Search for the device that has the specified name and 1363 * instance number. 1364 */ 1365 for (i = 0; i < ap->dl_count; i++) { 1366 if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 || 1367 strcmp((const char *)ip->dl_module_id_2, device) == 0) && 1368 ip->dl_instance_num == unit) 1369 break; 1370 1371 ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 1372 } 1373 #else 1374 /* 1375 * We don't have that member, so the search is impossible; make it 1376 * look as if the search failed. 1377 */ 1378 i = ap->dl_count; 1379 #endif 1380 1381 if (i == ap->dl_count) { 1382 /* 1383 * Well, we didn't, or can't, find the device by name. 1384 * 1385 * HP-UX 10.20, whilst it has "dl_module_id_1" and 1386 * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", 1387 * doesn't seem to fill them in unless the system is 1388 * at a reasonably up-to-date patch level. 1389 * 1390 * Older HP-UX 10.x systems might not have those fields 1391 * at all. 1392 * 1393 * Therefore, we'll search for the entry with the major 1394 * device number of a device with the name "/dev/<dev><unit>", 1395 * if such a device exists, as the old code did. 1396 */ 1397 snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); 1398 if (stat(dname, &statbuf) < 0) { 1399 snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", 1400 dname, pcap_strerror(errno)); 1401 return (-1); 1402 } 1403 majdev = major(statbuf.st_rdev); 1404 1405 ip = ipstart; 1406 1407 for (i = 0; i < ap->dl_count; i++) { 1408 if (ip->dl_mjr_num == majdev && 1409 ip->dl_instance_num == unit) 1410 break; 1411 1412 ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 1413 } 1414 } 1415 if (i == ap->dl_count) { 1416 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1417 "can't find /dev/dlpi PPA for %s%d", device, unit); 1418 return (-1); 1419 } 1420 if (ip->dl_hdw_state == HDW_DEAD) { 1421 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1422 "%s%d: hardware state: DOWN\n", device, unit); 1423 free(ppa_data_buf); 1424 return (-1); 1425 } 1426 ppa = ip->dl_ppa; 1427 free(ppa_data_buf); 1428 return (ppa); 1429 } 1430 #endif 1431 1432 #ifdef HAVE_HPUX9 1433 /* 1434 * Under HP-UX 9, there is no good way to determine the ppa. 1435 * So punt and read it from /dev/kmem. 1436 */ 1437 static struct nlist nl[] = { 1438 #define NL_IFNET 0 1439 { "ifnet" }, 1440 { "" } 1441 }; 1442 1443 static char path_vmunix[] = "/hp-ux"; 1444 1445 /* Determine ppa number that specifies ifname */ 1446 static int 1447 get_dlpi_ppa(register int fd, register const char *ifname, register int unit, 1448 register char *ebuf) 1449 { 1450 register const char *cp; 1451 register int kd; 1452 void *addr; 1453 struct ifnet ifnet; 1454 char if_name[sizeof(ifnet.if_name) + 1]; 1455 1456 cp = strrchr(ifname, '/'); 1457 if (cp != NULL) 1458 ifname = cp + 1; 1459 if (nlist(path_vmunix, &nl) < 0) { 1460 snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", 1461 path_vmunix); 1462 return (-1); 1463 } 1464 if (nl[NL_IFNET].n_value == 0) { 1465 snprintf(ebuf, PCAP_ERRBUF_SIZE, 1466 "could't find %s kernel symbol", 1467 nl[NL_IFNET].n_name); 1468 return (-1); 1469 } 1470 kd = open("/dev/kmem", O_RDONLY); 1471 if (kd < 0) { 1472 snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", 1473 pcap_strerror(errno)); 1474 return (-1); 1475 } 1476 if (dlpi_kread(kd, nl[NL_IFNET].n_value, 1477 &addr, sizeof(addr), ebuf) < 0) { 1478 close(kd); 1479 return (-1); 1480 } 1481 for (; addr != NULL; addr = ifnet.if_next) { 1482 if (dlpi_kread(kd, (off_t)addr, 1483 &ifnet, sizeof(ifnet), ebuf) < 0 || 1484 dlpi_kread(kd, (off_t)ifnet.if_name, 1485 if_name, sizeof(ifnet.if_name), ebuf) < 0) { 1486 (void)close(kd); 1487 return (-1); 1488 } 1489 if_name[sizeof(ifnet.if_name)] = '\0'; 1490 if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) 1491 return (ifnet.if_index); 1492 } 1493 1494 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); 1495 return (-1); 1496 } 1497 1498 static int 1499 dlpi_kread(register int fd, register off_t addr, 1500 register void *buf, register u_int len, register char *ebuf) 1501 { 1502 register int cc; 1503 1504 if (lseek(fd, addr, SEEK_SET) < 0) { 1505 snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", 1506 pcap_strerror(errno)); 1507 return (-1); 1508 } 1509 cc = read(fd, buf, len); 1510 if (cc < 0) { 1511 snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", 1512 pcap_strerror(errno)); 1513 return (-1); 1514 } else if (cc != len) { 1515 snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, 1516 len); 1517 return (-1); 1518 } 1519 return (cc); 1520 } 1521 #endif 1522