117683Spst/* 239291Sfenner * Copyright (c) 1993, 1994, 1995, 1996, 1997 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that: (1) source code distributions 717683Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817683Spst * distributions including binary code include the above copyright notice and 917683Spst * this paragraph in its entirety in the documentation or other materials 1017683Spst * provided with the distribution, and (3) all advertising materials mentioning 1117683Spst * features or use of this software display the following acknowledgement: 1217683Spst * ``This product includes software developed by the University of California, 1317683Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417683Spst * the University nor the names of its contributors may be used to endorse 1517683Spst * or promote products derived from this software without specific prior 1617683Spst * written permission. 1717683Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817683Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917683Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017683Spst * 2117683Spst * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), 22146768Ssam * University College London, and subsequently modified by 23147894Ssam * Guy Harris (guy@alum.mit.edu), Mark Pizzolato 24147894Ssam * <List-tcpdump-workers@subscriptions.pizzolato.net>, 25190225Srpaulo * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>. 2617683Spst */ 2717683Spst 2817683Spst/* 29127664Sbms * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX. 3017683Spst * 3117683Spst * Notes: 3217683Spst * 33146768Ssam * - The DLIOCRAW ioctl() is specific to SunOS. 3417683Spst * 3517683Spst * - There is a bug in bufmod(7) such that setting the snapshot 3617683Spst * length results in data being left of the front of the packet. 3717683Spst * 3817683Spst * - It might be desirable to use pfmod(7) to filter packets in the 39127664Sbms * kernel when possible. 40146768Ssam * 41147894Ssam * - An older version of the HP-UX DLPI Programmer's Guide, which 42147894Ssam * I think was advertised as the 10.20 version, used to be available 43146768Ssam * at 44146768Ssam * 45146768Ssam * http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html 46146768Ssam * 47146768Ssam * but is no longer available; it can still be found at 48146768Ssam * 49146768Ssam * http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf 50146768Ssam * 51146768Ssam * in PDF form. 52146768Ssam * 53147894Ssam * - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI 54147894Ssam * Programmer's Guide, which I think was once advertised as the 55147894Ssam * 11.00 version is available at 56146768Ssam * 57147894Ssam * http://docs.hp.com/en/B2355-90139/index.html 58146768Ssam * 59147894Ssam * - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide 60147894Ssam * is available at 61146768Ssam * 62147894Ssam * http://docs.hp.com/en/B2355-90871/index.html 63146768Ssam * 64147894Ssam * - All of the HP documents describe raw-mode services, which are 65147894Ssam * what we use if DL_HP_RAWDLS is defined. XXX - we use __hpux 66147894Ssam * in some places to test for HP-UX, but use DL_HP_RAWDLS in 67147894Ssam * other places; do we support any versions of HP-UX without 68147894Ssam * DL_HP_RAWDLS? 6917683Spst */ 7017683Spst 7126175Sfenner#ifndef lint 72127664Sbmsstatic const char rcsid[] _U_ = 73214518Srpaulo "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.128 2008-12-02 16:20:23 guy Exp $ (LBL)"; 7426175Sfenner#endif 7526175Sfenner 7675107Sfenner#ifdef HAVE_CONFIG_H 7775107Sfenner#include "config.h" 7875107Sfenner#endif 7975107Sfenner 8017683Spst#include <sys/types.h> 8117683Spst#include <sys/time.h> 8217683Spst#ifdef HAVE_SYS_BUFMOD_H 8317683Spst#include <sys/bufmod.h> 8417683Spst#endif 8517683Spst#include <sys/dlpi.h> 8617683Spst#ifdef HAVE_SYS_DLPI_EXT_H 8717683Spst#include <sys/dlpi_ext.h> 8817683Spst#endif 8917683Spst#ifdef HAVE_HPUX9 9017683Spst#include <sys/socket.h> 9117683Spst#endif 92146768Ssam#ifdef DL_HP_PPA_REQ 9317683Spst#include <sys/stat.h> 9417683Spst#endif 9517683Spst#include <sys/stream.h> 9617683Spst#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 9717683Spst#include <sys/systeminfo.h> 9817683Spst#endif 9917683Spst 10017683Spst#ifdef HAVE_HPUX9 10117683Spst#include <net/if.h> 10217683Spst#endif 10317683Spst 10417683Spst#include <ctype.h> 10517683Spst#ifdef HAVE_HPUX9 10617683Spst#include <nlist.h> 10717683Spst#endif 10817683Spst#include <errno.h> 10917683Spst#include <fcntl.h> 11017683Spst#include <memory.h> 11117683Spst#include <stdio.h> 11217683Spst#include <stdlib.h> 11317683Spst#include <string.h> 11417683Spst#include <stropts.h> 11517683Spst#include <unistd.h> 11617683Spst 117146768Ssam#ifdef HAVE_LIMITS_H 118146768Ssam#include <limits.h> 119146768Ssam#else 120146768Ssam#define INT_MAX 2147483647 121146768Ssam#endif 122146768Ssam 12317683Spst#include "pcap-int.h" 124190225Srpaulo#include "dlpisubs.h" 12517683Spst 12617683Spst#ifdef HAVE_OS_PROTO_H 12717683Spst#include "os-proto.h" 12817683Spst#endif 12917683Spst 13017683Spst#ifndef PCAP_DEV_PREFIX 13198530Sfenner#ifdef _AIX 13298530Sfenner#define PCAP_DEV_PREFIX "/dev/dlpi" 13398530Sfenner#else 13417683Spst#define PCAP_DEV_PREFIX "/dev" 13517683Spst#endif 13698530Sfenner#endif 13717683Spst 13817683Spst#define MAXDLBUF 8192 13917683Spst 14017683Spst/* Forwards */ 14198530Sfennerstatic char *split_dname(char *, int *, char *); 142146768Ssamstatic int dl_doattach(int, int, char *); 143147894Ssam#ifdef DL_HP_RAWDLS 144147894Ssamstatic int dl_dohpuxbind(int, char *); 145147894Ssam#endif 146235426Sdelphijstatic int dlpromiscon(pcap_t *, bpf_u_int32); 147146768Ssamstatic int dlbindreq(int, bpf_u_int32, char *); 148147894Ssamstatic int dlbindack(int, char *, char *, int *); 149146768Ssamstatic int dlokack(int, const char *, char *, char *); 150146768Ssamstatic int dlinforeq(int, char *); 15117683Spststatic int dlinfoack(int, char *, char *); 152190225Srpaulo 153190225Srpaulo#ifdef HAVE_DLPI_PASSIVE 154190225Srpaulostatic void dlpassive(int, char *); 155190225Srpaulo#endif 156190225Srpaulo 157146768Ssam#ifdef DL_HP_RAWDLS 158146768Ssamstatic int dlrawdatareq(int, const u_char *, int); 159146768Ssam#endif 160147894Ssamstatic int recv_ack(int, int, const char *, char *, char *, int *); 16198530Sfennerstatic char *dlstrerror(bpf_u_int32); 16298530Sfennerstatic char *dlprim(bpf_u_int32); 16317683Spst#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 16417683Spststatic char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); 16517683Spst#endif 16617683Spststatic int send_request(int, char *, int, char *, char *); 16717683Spst#ifdef HAVE_HPUX9 16817683Spststatic int dlpi_kread(int, off_t, void *, u_int, char *); 16917683Spst#endif 17017683Spst#ifdef HAVE_DEV_DLPI 17117683Spststatic int get_dlpi_ppa(int, const char *, int, char *); 17217683Spst#endif 17317683Spst 17417683Spst/* XXX Needed by HP-UX (at least) */ 17517683Spststatic bpf_u_int32 ctlbuf[MAXDLBUF]; 17617683Spststatic struct strbuf ctl = { 17717683Spst MAXDLBUF, 17817683Spst 0, 17917683Spst (char *)ctlbuf 18017683Spst}; 18117683Spst 182214518Srpaulo/* 183214518Srpaulo * Cast a buffer to "union DL_primitives" without provoking warnings 184214518Srpaulo * from the compiler. 185214518Srpaulo */ 186214518Srpaulo#define MAKE_DL_PRIMITIVES(ptr) ((union DL_primitives *)(void *)(ptr)) 187214518Srpaulo 188127664Sbmsstatic int 189127664Sbmspcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 19017683Spst{ 191190225Srpaulo int cc; 192190225Srpaulo u_char *bp; 19317683Spst int flags; 19417683Spst struct strbuf data; 19517683Spst 19617683Spst flags = 0; 19717683Spst cc = p->cc; 19817683Spst if (cc == 0) { 19917683Spst data.buf = (char *)p->buffer + p->offset; 200127664Sbms data.maxlen = p->bufsize; 20117683Spst data.len = 0; 20217683Spst do { 203127664Sbms /* 204127664Sbms * Has "pcap_breakloop()" been called? 205127664Sbms */ 206127664Sbms if (p->break_loop) { 207127664Sbms /* 208127664Sbms * Yes - clear the flag that indicates 209127664Sbms * that it has, and return -2 to 210127664Sbms * indicate that we were told to 211127664Sbms * break out of the loop. 212127664Sbms */ 213127664Sbms p->break_loop = 0; 214127664Sbms return (-2); 215127664Sbms } 216146768Ssam /* 217146768Ssam * XXX - check for the DLPI primitive, which 218146768Ssam * would be DL_HP_RAWDATA_IND on HP-UX 219146768Ssam * if we're in raw mode? 220146768Ssam */ 22117683Spst if (getmsg(p->fd, &ctl, &data, &flags) < 0) { 22217683Spst /* Don't choke when we get ptraced */ 223146768Ssam switch (errno) { 224146768Ssam 225146768Ssam case EINTR: 22617683Spst cc = 0; 22717683Spst continue; 228146768Ssam 229146768Ssam case EAGAIN: 230146768Ssam return (0); 23117683Spst } 23275107Sfenner strlcpy(p->errbuf, pcap_strerror(errno), 23375107Sfenner sizeof(p->errbuf)); 23417683Spst return (-1); 23517683Spst } 23617683Spst cc = data.len; 23717683Spst } while (cc == 0); 23817683Spst bp = p->buffer + p->offset; 23917683Spst } else 24017683Spst bp = p->bp; 24117683Spst 242190225Srpaulo return (pcap_process_pkts(p, callback, user, cnt, bp, cc)); 24317683Spst} 24417683Spst 245146768Ssamstatic int 246146768Ssampcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) 247146768Ssam{ 248146768Ssam int ret; 249146768Ssam 250146768Ssam#if defined(DLIOCRAW) 251146768Ssam ret = write(p->fd, buf, size); 252146768Ssam if (ret == -1) { 253146768Ssam snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", 254146768Ssam pcap_strerror(errno)); 255146768Ssam return (-1); 256146768Ssam } 257146768Ssam#elif defined(DL_HP_RAWDLS) 258146768Ssam if (p->send_fd < 0) { 259146768Ssam snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 260146768Ssam "send: Output FD couldn't be opened"); 261146768Ssam return (-1); 262146768Ssam } 263146768Ssam ret = dlrawdatareq(p->send_fd, buf, size); 264146768Ssam if (ret == -1) { 265146768Ssam snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", 266146768Ssam pcap_strerror(errno)); 267146768Ssam return (-1); 268146768Ssam } 269172677Smlaier /* 270172677Smlaier * putmsg() returns either 0 or -1; it doesn't indicate how 271172677Smlaier * many bytes were written (presumably they were all written 272172677Smlaier * or none of them were written). OpenBSD's pcap_inject() 273172677Smlaier * returns the number of bytes written, so, for API compatibility, 274172677Smlaier * we return the number of bytes we were told to write. 275172677Smlaier */ 276172677Smlaier ret = size; 277146768Ssam#else /* no raw mode */ 278146768Ssam /* 279146768Ssam * XXX - this is a pain, because you might have to extract 280146768Ssam * the address from the packet and use it in a DL_UNITDATA_REQ 281146768Ssam * request. That would be dependent on the link-layer type. 282146768Ssam * 283146768Ssam * I also don't know what SAP you'd have to bind the descriptor 284146768Ssam * to, or whether you'd need separate "receive" and "send" FDs, 285146768Ssam * nor do I know whether you'd need different bindings for 286146768Ssam * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus 287146768Ssam * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP. 288146768Ssam * 289146768Ssam * So, for now, we just return a "you can't send" indication, 290146768Ssam * and leave it up to somebody with a DLPI-based system lacking 291146768Ssam * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement 292146768Ssam * packet transmission on that system. If they do, they should 293146768Ssam * send it to us - but should not send us code that assumes 294146768Ssam * Ethernet; if the code doesn't work on non-Ethernet interfaces, 295146768Ssam * it should check "p->linktype" and reject the send request if 296146768Ssam * it's anything other than DLT_EN10MB. 297146768Ssam */ 298146768Ssam strlcpy(p->errbuf, "send: Not supported on this version of this OS", 299146768Ssam PCAP_ERRBUF_SIZE); 300146768Ssam ret = -1; 301146768Ssam#endif /* raw mode */ 302146768Ssam return (ret); 303147894Ssam} 304146768Ssam 305127664Sbms#ifndef DL_IPATM 306127664Sbms#define DL_IPATM 0x12 /* ATM Classical IP interface */ 307127664Sbms#endif 308127664Sbms 309127664Sbms#ifdef HAVE_SOLARIS 310127664Sbms/* 311127664Sbms * For SunATM. 312127664Sbms */ 313127664Sbms#ifndef A_GET_UNITS 314127664Sbms#define A_GET_UNITS (('A'<<8)|118) 315127664Sbms#endif /* A_GET_UNITS */ 316127664Sbms#ifndef A_PROMISCON_REQ 317127664Sbms#define A_PROMISCON_REQ (('A'<<8)|121) 318127664Sbms#endif /* A_PROMISCON_REQ */ 319127664Sbms#endif /* HAVE_SOLARIS */ 320127664Sbms 321127664Sbmsstatic void 322190225Srpaulopcap_cleanup_dlpi(pcap_t *p) 323127664Sbms{ 324190225Srpaulo if (p->send_fd >= 0) { 325146768Ssam close(p->send_fd); 326190225Srpaulo p->send_fd = -1; 327190225Srpaulo } 328190225Srpaulo pcap_cleanup_live_common(p); 329127664Sbms} 330127664Sbms 331190225Srpaulostatic int 332190225Srpaulopcap_activate_dlpi(pcap_t *p) 33317683Spst{ 33417683Spst register char *cp; 33598530Sfenner int ppa; 336127664Sbms#ifdef HAVE_SOLARIS 337127664Sbms int isatm = 0; 338127664Sbms#endif 33917683Spst register dl_info_ack_t *infop; 34017683Spst#ifdef HAVE_SYS_BUFMOD_H 341190225Srpaulo bpf_u_int32 ss; 34217683Spst#ifdef HAVE_SOLARIS 34317683Spst register char *release; 34417683Spst bpf_u_int32 osmajor, osminor, osmicro; 34517683Spst#endif 34617683Spst#endif 34717683Spst bpf_u_int32 buf[MAXDLBUF]; 34817683Spst char dname[100]; 34917683Spst#ifndef HAVE_DEV_DLPI 35017683Spst char dname2[100]; 35117683Spst#endif 352190225Srpaulo int status = PCAP_ERROR; 35317683Spst 35475107Sfenner#ifdef HAVE_DEV_DLPI 35517683Spst /* 35675107Sfenner ** Remove any "/dev/" on the front of the device. 35717683Spst */ 358190225Srpaulo cp = strrchr(p->opt.source, '/'); 35975107Sfenner if (cp == NULL) 360190225Srpaulo strlcpy(dname, p->opt.source, sizeof(dname)); 36175107Sfenner else 362127664Sbms strlcpy(dname, cp + 1, sizeof(dname)); 36375107Sfenner 36475107Sfenner /* 36598530Sfenner * Split the device name into a device type name and a unit number; 36698530Sfenner * chop off the unit number, so "dname" is just a device type name. 36775107Sfenner */ 368190225Srpaulo cp = split_dname(dname, &ppa, p->errbuf); 369190225Srpaulo if (cp == NULL) { 370190225Srpaulo status = PCAP_ERROR_NO_SUCH_DEVICE; 37117683Spst goto bad; 372190225Srpaulo } 37375107Sfenner *cp = '\0'; 37417683Spst 37575107Sfenner /* 37675107Sfenner * Use "/dev/dlpi" as the device. 37775107Sfenner * 37875107Sfenner * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that 37975107Sfenner * the "dl_mjr_num" field is for the "major number of interface 38075107Sfenner * driver"; that's the major of "/dev/dlpi" on the system on 38175107Sfenner * which I tried this, but there may be DLPI devices that 38275107Sfenner * use a different driver, in which case we may need to 38375107Sfenner * search "/dev" for the appropriate device with that major 38475107Sfenner * device number, rather than hardwiring "/dev/dlpi". 38575107Sfenner */ 38617683Spst cp = "/dev/dlpi"; 38717683Spst if ((p->fd = open(cp, O_RDWR)) < 0) { 388190225Srpaulo if (errno == EPERM || errno == EACCES) 389190225Srpaulo status = PCAP_ERROR_PERM_DENIED; 390190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 39175107Sfenner "%s: %s", cp, pcap_strerror(errno)); 39217683Spst goto bad; 39317683Spst } 39475107Sfenner 395146768Ssam#ifdef DL_HP_RAWDLS 39675107Sfenner /* 397146768Ssam * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and 398147894Ssam * receiving packets on the same descriptor - you need separate 399147894Ssam * descriptors for sending and receiving, bound to different SAPs. 400146768Ssam * 401146768Ssam * If the open fails, we just leave -1 in "p->send_fd" and reject 402146768Ssam * attempts to send packets, just as if, in pcap-bpf.c, we fail 403146768Ssam * to open the BPF device for reading and writing, we just try 404146768Ssam * to open it for reading only and, if that succeeds, just let 405146768Ssam * the send attempts fail. 406146768Ssam */ 407146768Ssam p->send_fd = open(cp, O_RDWR); 408146768Ssam#endif 409146768Ssam 410146768Ssam /* 41175107Sfenner * Get a table of all PPAs for that device, and search that 41275107Sfenner * table for the specified device type name and unit number. 41375107Sfenner */ 414190225Srpaulo ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf); 415190225Srpaulo if (ppa < 0) { 416190225Srpaulo status = ppa; 41717683Spst goto bad; 418190225Srpaulo } 41917683Spst#else 42075107Sfenner /* 42198530Sfenner * If the device name begins with "/", assume it begins with 42298530Sfenner * the pathname of the directory containing the device to open; 42398530Sfenner * otherwise, concatenate the device directory name and the 42498530Sfenner * device name. 42598530Sfenner */ 426190225Srpaulo if (*p->opt.source == '/') 427190225Srpaulo strlcpy(dname, p->opt.source, sizeof(dname)); 42875107Sfenner else 42975107Sfenner snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, 430190225Srpaulo p->opt.source); 43175107Sfenner 43298530Sfenner /* 433127664Sbms * Get the unit number, and a pointer to the end of the device 434127664Sbms * type name. 435127664Sbms */ 436190225Srpaulo cp = split_dname(dname, &ppa, p->errbuf); 437190225Srpaulo if (cp == NULL) { 438190225Srpaulo status = PCAP_ERROR_NO_SUCH_DEVICE; 439127664Sbms goto bad; 440190225Srpaulo } 441127664Sbms 442127664Sbms /* 44398530Sfenner * Make a copy of the device pathname, and then remove the unit 44498530Sfenner * number from the device pathname. 44598530Sfenner */ 44698530Sfenner strlcpy(dname2, dname, sizeof(dname)); 447127664Sbms *cp = '\0'; 44898530Sfenner 44917683Spst /* Try device without unit number */ 45017683Spst if ((p->fd = open(dname, O_RDWR)) < 0) { 45117683Spst if (errno != ENOENT) { 452235426Sdelphij if (errno == EPERM || errno == EACCES) 453190225Srpaulo status = PCAP_ERROR_PERM_DENIED; 454190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, 45575107Sfenner pcap_strerror(errno)); 45617683Spst goto bad; 45717683Spst } 45817683Spst 45917683Spst /* Try again with unit number */ 46017683Spst if ((p->fd = open(dname2, O_RDWR)) < 0) { 461146768Ssam if (errno == ENOENT) { 462190225Srpaulo status = PCAP_ERROR_NO_SUCH_DEVICE; 463190225Srpaulo 464146768Ssam /* 465190225Srpaulo * We provide an error message even 466190225Srpaulo * for this error, for diagnostic 467190225Srpaulo * purposes (so that, for example, 468190225Srpaulo * the app can show the message if the 469190225Srpaulo * user requests it). 470190225Srpaulo * 471190225Srpaulo * In it, we just report "No DLPI device 472190225Srpaulo * found" with the device name, so people 473190225Srpaulo * don't get confused and think, for example, 474146768Ssam * that if they can't capture on "lo0" 475146768Ssam * on Solaris the fix is to change libpcap 476146768Ssam * (or the application that uses it) to 477146768Ssam * look for something other than "/dev/lo0", 478146768Ssam * as the fix is to look for an operating 479146768Ssam * system other than Solaris - you just 480146768Ssam * *can't* capture on a loopback interface 481146768Ssam * on Solaris, the lack of a DLPI device 482146768Ssam * for the loopback interface is just a 483146768Ssam * symptom of that inability. 484146768Ssam */ 485190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 486190225Srpaulo "%s: No DLPI device found", p->opt.source); 487146768Ssam } else { 488235426Sdelphij if (errno == EPERM || errno == EACCES) 489190225Srpaulo status = PCAP_ERROR_PERM_DENIED; 490190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", 491146768Ssam dname2, pcap_strerror(errno)); 492146768Ssam } 49317683Spst goto bad; 49417683Spst } 49517683Spst /* XXX Assume unit zero */ 49617683Spst ppa = 0; 49717683Spst } 49817683Spst#endif 49917683Spst 50017683Spst /* 50117683Spst ** Attach if "style 2" provider 50217683Spst */ 503190225Srpaulo if (dlinforeq(p->fd, p->errbuf) < 0 || 504190225Srpaulo dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) 50517683Spst goto bad; 506214518Srpaulo infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack; 507127664Sbms#ifdef HAVE_SOLARIS 508127664Sbms if (infop->dl_mac_type == DL_IPATM) 509127664Sbms isatm = 1; 510127664Sbms#endif 511146768Ssam if (infop->dl_provider_style == DL_STYLE2) { 512190225Srpaulo status = dl_doattach(p->fd, ppa, p->errbuf); 513190225Srpaulo if (status < 0) 514146768Ssam goto bad; 515146768Ssam#ifdef DL_HP_RAWDLS 516146768Ssam if (p->send_fd >= 0) { 517190225Srpaulo if (dl_doattach(p->send_fd, ppa, p->errbuf) < 0) 518146768Ssam goto bad; 519146768Ssam } 520146768Ssam#endif 521146768Ssam } 522146768Ssam 523190225Srpaulo if (p->opt.rfmon) { 524190225Srpaulo /* 525190225Srpaulo * This device exists, but we don't support monitor mode 526190225Srpaulo * any platforms that support DLPI. 527190225Srpaulo */ 528190225Srpaulo status = PCAP_ERROR_RFMON_NOTSUP; 529190225Srpaulo goto bad; 530190225Srpaulo } 531190225Srpaulo 532190225Srpaulo#ifdef HAVE_DLPI_PASSIVE 53317683Spst /* 534190225Srpaulo * Enable Passive mode to be able to capture on aggregated link. 535190225Srpaulo * Not supported in all Solaris versions. 536190225Srpaulo */ 537190225Srpaulo dlpassive(p->fd, p->errbuf); 538190225Srpaulo#endif 539190225Srpaulo /* 540147894Ssam ** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally 541147894Ssam ** skip if using SINIX) 54217683Spst */ 543147894Ssam#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix) 54475107Sfenner#ifdef _AIX 545147894Ssam /* 546147894Ssam ** AIX. 547147894Ssam ** According to IBM's AIX Support Line, the dl_sap value 54898530Sfenner ** should not be less than 0x600 (1536) for standard Ethernet. 54998530Sfenner ** However, we seem to get DL_BADADDR - "DLSAP addr in improper 55098530Sfenner ** format or invalid" - errors if we use 1537 on the "tr0" 55198530Sfenner ** device, which, given that its name starts with "tr" and that 55298530Sfenner ** it's IBM, probably means a Token Ring device. (Perhaps we 55398530Sfenner ** need to use 1537 on "/dev/dlpi/en" because that device is for 55498530Sfenner ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and 55598530Sfenner ** it rejects invalid Ethernet types.) 55698530Sfenner ** 55798530Sfenner ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea 55898530Sfenner ** says that works on Token Ring (he says that 0 does *not* 55998530Sfenner ** work; perhaps that's considered an invalid LLC SAP value - I 56098530Sfenner ** assume the SAP value in a DLPI bind is an LLC SAP for network 56198530Sfenner ** types that use 802.2 LLC). 56298530Sfenner */ 563190225Srpaulo if ((dlbindreq(p->fd, 1537, p->errbuf) < 0 && 564190225Srpaulo dlbindreq(p->fd, 2, p->errbuf) < 0) || 565190225Srpaulo dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) 566146768Ssam goto bad; 567146768Ssam#elif defined(DL_HP_RAWDLS) 568146768Ssam /* 569147894Ssam ** HP-UX 10.0x and 10.1x. 570146768Ssam */ 571190225Srpaulo if (dl_dohpuxbind(p->fd, p->errbuf) < 0) 572146768Ssam goto bad; 573146768Ssam if (p->send_fd >= 0) { 574146768Ssam /* 575147894Ssam ** XXX - if this fails, just close send_fd and 576147894Ssam ** set it to -1, so that you can't send but can 577147894Ssam ** still receive? 578146768Ssam */ 579190225Srpaulo if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0) 580146768Ssam goto bad; 581146768Ssam } 582146768Ssam#else /* neither AIX nor HP-UX */ 583147894Ssam /* 584147894Ssam ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other 585147894Ssam ** OS using DLPI. 586147894Ssam **/ 587190225Srpaulo if (dlbindreq(p->fd, 0, p->errbuf) < 0 || 588190225Srpaulo dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) 58917683Spst goto bad; 590147894Ssam#endif /* AIX vs. HP-UX vs. other */ 591147894Ssam#endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */ 59217683Spst 593127664Sbms#ifdef HAVE_SOLARIS 594127664Sbms if (isatm) { 595127664Sbms /* 596127664Sbms ** Have to turn on some special ATM promiscuous mode 597127664Sbms ** for SunATM. 598127664Sbms ** Do *NOT* turn regular promiscuous mode on; it doesn't 599127664Sbms ** help, and may break things. 600127664Sbms */ 601127664Sbms if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) { 602190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 603190225Srpaulo "A_PROMISCON_REQ: %s", pcap_strerror(errno)); 604127664Sbms goto bad; 605127664Sbms } 606127664Sbms } else 607127664Sbms#endif 608190225Srpaulo if (p->opt.promisc) { 60917683Spst /* 610146768Ssam ** Enable promiscuous (not necessary on send FD) 61117683Spst */ 612235426Sdelphij status = dlpromiscon(p, DL_PROMISC_PHYS); 613235426Sdelphij if (status < 0) { 614235426Sdelphij if (status == PCAP_ERROR_PERM_DENIED) 615235426Sdelphij status = PCAP_ERROR_PROMISC_PERM_DENIED; 61617683Spst goto bad; 617235426Sdelphij } 61817683Spst 61917683Spst /* 62017683Spst ** Try to enable multicast (you would have thought 62139291Sfenner ** promiscuous would be sufficient). (Skip if using 622146768Ssam ** HP-UX or SINIX) (Not necessary on send FD) 62317683Spst */ 62439291Sfenner#if !defined(__hpux) && !defined(sinix) 625235426Sdelphij status = dlpromiscon(p, DL_PROMISC_MULTI); 626235426Sdelphij if (status < 0) 627190225Srpaulo status = PCAP_WARNING; 62817683Spst#endif 62917683Spst } 63017683Spst /* 631147894Ssam ** Try to enable SAP promiscuity (when not in promiscuous mode 632147894Ssam ** when using HP-UX, when not doing SunATM on Solaris, and never 633146768Ssam ** under SINIX) (Not necessary on send FD) 63417683Spst */ 63517683Spst#ifndef sinix 636235426Sdelphij#if defined(__hpux) 637235426Sdelphij /* HP-UX - only do this when not in promiscuous mode */ 638235426Sdelphij if (!p->opt.promisc) { 639235426Sdelphij#elif defined(HAVE_SOLARIS) 640235426Sdelphij /* Solaris - don't do this on SunATM devices */ 641235426Sdelphij if (!isatm) { 642235426Sdelphij#else 643235426Sdelphij /* Everything else (except for SINIX) - always do this */ 644235426Sdelphij { 64539291Sfenner#endif 646235426Sdelphij status = dlpromiscon(p, DL_PROMISC_SAP); 647235426Sdelphij if (status < 0) { 648235426Sdelphij /* 649235426Sdelphij * Not fatal, since the DL_PROMISC_PHYS mode worked. 650235426Sdelphij * Report it as a warning, however. 651235426Sdelphij */ 652235426Sdelphij if (p->opt.promisc) 653235426Sdelphij status = PCAP_WARNING; 654235426Sdelphij else 655235426Sdelphij goto bad; 656235426Sdelphij } 65717683Spst } 658147894Ssam#endif /* sinix */ 65917683Spst 66017683Spst /* 661147894Ssam ** HP-UX 9, and HP-UX 10.20 or later, must bind after setting 662147894Ssam ** promiscuous options. 66317683Spst */ 664147894Ssam#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER) 665190225Srpaulo if (dl_dohpuxbind(p->fd, p->errbuf) < 0) 66617683Spst goto bad; 667147894Ssam /* 668147894Ssam ** We don't set promiscuous mode on the send FD, but we'll defer 669147894Ssam ** binding it anyway, just to keep the HP-UX 9/10.20 or later 670147894Ssam ** code together. 671147894Ssam */ 672147894Ssam if (p->send_fd >= 0) { 673147894Ssam /* 674147894Ssam ** XXX - if this fails, just close send_fd and 675147894Ssam ** set it to -1, so that you can't send but can 676147894Ssam ** still receive? 677147894Ssam */ 678190225Srpaulo if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0) 679147894Ssam goto bad; 680147894Ssam } 68117683Spst#endif 68217683Spst 68317683Spst /* 68417683Spst ** Determine link type 685146768Ssam ** XXX - get SAP length and address length as well, for use 686146768Ssam ** when sending packets. 68717683Spst */ 688190225Srpaulo if (dlinforeq(p->fd, p->errbuf) < 0 || 689190225Srpaulo dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) 69017683Spst goto bad; 69117683Spst 692214518Srpaulo infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack; 693190225Srpaulo if (pcap_process_mactype(p, infop->dl_mac_type) != 0) 69417683Spst goto bad; 69517683Spst 69617683Spst#ifdef DLIOCRAW 69717683Spst /* 698127664Sbms ** This is a non standard SunOS hack to get the full raw link-layer 699127664Sbms ** header. 70017683Spst */ 70117683Spst if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { 702190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", 70375107Sfenner pcap_strerror(errno)); 70417683Spst goto bad; 70517683Spst } 70617683Spst#endif 70717683Spst 708214518Srpaulo#ifdef HAVE_SYS_BUFMOD_H 709190225Srpaulo ss = p->snapshot; 71017683Spst 71117683Spst /* 71217683Spst ** There is a bug in bufmod(7). When dealing with messages of 71317683Spst ** less than snaplen size it strips data from the beginning not 71417683Spst ** the end. 71517683Spst ** 716190225Srpaulo ** This bug is fixed in 5.3.2. Also, there is a patch available. 717190225Srpaulo ** Ask for bugid 1149065. 71817683Spst */ 71917683Spst#ifdef HAVE_SOLARIS 72017683Spst release = get_release(&osmajor, &osminor, &osmicro); 72117683Spst if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && 72217683Spst getenv("BUFMOD_FIXED") == NULL) { 723190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, 724190225Srpaulo "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.", 72517683Spst release); 72617683Spst ss = 0; 727190225Srpaulo status = PCAP_WARNING; 72817683Spst } 72917683Spst#endif 73017683Spst 731190225Srpaulo /* Push and configure bufmod. */ 732190225Srpaulo if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0) 733127664Sbms goto bad; 73417683Spst#endif 73517683Spst 73617683Spst /* 73717683Spst ** As the last operation flush the read side. 73817683Spst */ 73917683Spst if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { 740190225Srpaulo snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", 74175107Sfenner pcap_strerror(errno)); 74217683Spst goto bad; 74317683Spst } 744127664Sbms 745190225Srpaulo /* Allocate data buffer. */ 746190225Srpaulo if (pcap_alloc_databuf(p) != 0) 747127664Sbms goto bad; 74817683Spst 749190225Srpaulo /* Success - but perhaps with a warning */ 750190225Srpaulo if (status < 0) 751190225Srpaulo status = 0; 752190225Srpaulo 753127664Sbms /* 754127664Sbms * "p->fd" is an FD for a STREAMS device, so "select()" and 755127664Sbms * "poll()" should work on it. 756127664Sbms */ 757127664Sbms p->selectable_fd = p->fd; 758127664Sbms 759127664Sbms p->read_op = pcap_read_dlpi; 760146768Ssam p->inject_op = pcap_inject_dlpi; 761127664Sbms p->setfilter_op = install_bpf_program; /* no kernel filtering */ 762147894Ssam p->setdirection_op = NULL; /* Not implemented.*/ 763127664Sbms p->set_datalink_op = NULL; /* can't change data link type */ 764127664Sbms p->getnonblock_op = pcap_getnonblock_fd; 765127664Sbms p->setnonblock_op = pcap_setnonblock_fd; 766127664Sbms p->stats_op = pcap_stats_dlpi; 767190225Srpaulo p->cleanup_op = pcap_cleanup_dlpi; 768127664Sbms 769190225Srpaulo return (status); 77017683Spstbad: 771190225Srpaulo pcap_cleanup_dlpi(p); 772190225Srpaulo return (status); 77317683Spst} 77417683Spst 77598530Sfenner/* 77698530Sfenner * Split a device name into a device type name and a unit number; 77798530Sfenner * return the a pointer to the beginning of the unit number, which 77898530Sfenner * is the end of the device type name, and set "*unitp" to the unit 77998530Sfenner * number. 78098530Sfenner * 78198530Sfenner * Returns NULL on error, and fills "ebuf" with an error message. 78298530Sfenner */ 78398530Sfennerstatic char * 78498530Sfennersplit_dname(char *device, int *unitp, char *ebuf) 78598530Sfenner{ 78698530Sfenner char *cp; 78798530Sfenner char *eos; 788146768Ssam long unit; 78998530Sfenner 79098530Sfenner /* 79198530Sfenner * Look for a number at the end of the device name string. 79298530Sfenner */ 79398530Sfenner cp = device + strlen(device) - 1; 79498530Sfenner if (*cp < '0' || *cp > '9') { 79598530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number", 79698530Sfenner device); 79798530Sfenner return (NULL); 79898530Sfenner } 79998530Sfenner 80098530Sfenner /* Digits at end of string are unit number */ 80198530Sfenner while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9') 80298530Sfenner cp--; 80398530Sfenner 804146768Ssam errno = 0; 80598530Sfenner unit = strtol(cp, &eos, 10); 80698530Sfenner if (*eos != '\0') { 80798530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); 80898530Sfenner return (NULL); 80998530Sfenner } 810146768Ssam if (errno == ERANGE || unit > INT_MAX) { 811146768Ssam snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large", 812146768Ssam device); 813146768Ssam return (NULL); 814146768Ssam } 815146768Ssam if (unit < 0) { 816146768Ssam snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative", 817146768Ssam device); 818146768Ssam return (NULL); 819146768Ssam } 820146768Ssam *unitp = (int)unit; 82198530Sfenner return (cp); 82298530Sfenner} 82398530Sfenner 824146768Ssamstatic int 825146768Ssamdl_doattach(int fd, int ppa, char *ebuf) 826146768Ssam{ 827235426Sdelphij dl_attach_req_t req; 828146768Ssam bpf_u_int32 buf[MAXDLBUF]; 829190225Srpaulo int err; 830146768Ssam 831235426Sdelphij req.dl_primitive = DL_ATTACH_REQ; 832235426Sdelphij req.dl_ppa = ppa; 833235426Sdelphij if (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf) < 0) 834190225Srpaulo return (PCAP_ERROR); 835235426Sdelphij 836190225Srpaulo err = dlokack(fd, "attach", (char *)buf, ebuf); 837190225Srpaulo if (err < 0) 838190225Srpaulo return (err); 839146768Ssam return (0); 840146768Ssam} 841146768Ssam 842147894Ssam#ifdef DL_HP_RAWDLS 843147894Ssamstatic int 844147894Ssamdl_dohpuxbind(int fd, char *ebuf) 845147894Ssam{ 846147894Ssam int hpsap; 847147894Ssam int uerror; 848147894Ssam bpf_u_int32 buf[MAXDLBUF]; 849147894Ssam 850147894Ssam /* 851147894Ssam * XXX - we start at 22 because we used to use only 22, but 852147894Ssam * that was just because that was the value used in some 853147894Ssam * sample code from HP. With what value *should* we start? 854147894Ssam * Does it matter, given that we're enabling SAP promiscuity 855147894Ssam * on the input FD? 856147894Ssam */ 857147894Ssam hpsap = 22; 858147894Ssam for (;;) { 859147894Ssam if (dlbindreq(fd, hpsap, ebuf) < 0) 860147894Ssam return (-1); 861147894Ssam if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0) 862147894Ssam break; 863147894Ssam /* 864147894Ssam * For any error other than a UNIX EBUSY, give up. 865147894Ssam */ 866162012Ssam if (uerror != EBUSY) { 867162012Ssam /* 868162012Ssam * dlbindack() has already filled in ebuf for 869162012Ssam * this error. 870162012Ssam */ 871147894Ssam return (-1); 872162012Ssam } 873147894Ssam 874147894Ssam /* 875147894Ssam * For EBUSY, try the next SAP value; that means that 876147894Ssam * somebody else is using that SAP. Clear ebuf so 877147894Ssam * that application doesn't report the "Device busy" 878147894Ssam * error as a warning. 879147894Ssam */ 880147894Ssam *ebuf = '\0'; 881147894Ssam hpsap++; 882162012Ssam if (hpsap > 100) { 883162012Ssam strlcpy(ebuf, 884162012Ssam "All SAPs from 22 through 100 are in use", 885162012Ssam PCAP_ERRBUF_SIZE); 886147894Ssam return (-1); 887162012Ssam } 888147894Ssam } 889162012Ssam return (0); 890147894Ssam} 891147894Ssam#endif 892147894Ssam 893235426Sdelphij#define STRINGIFY(n) #n 894235426Sdelphij 895235426Sdelphijstatic int 896235426Sdelphijdlpromiscon(pcap_t *p, bpf_u_int32 level) 897235426Sdelphij{ 898235426Sdelphij dl_promiscon_req_t req; 899235426Sdelphij bpf_u_int32 buf[MAXDLBUF]; 900235426Sdelphij int err; 901235426Sdelphij 902235426Sdelphij req.dl_primitive = DL_PROMISCON_REQ; 903235426Sdelphij req.dl_level = level; 904235426Sdelphij if (send_request(p->fd, (char *)&req, sizeof(req), "promiscon", 905235426Sdelphij p->errbuf) < 0) 906235426Sdelphij return (PCAP_ERROR); 907235426Sdelphij err = dlokack(p->fd, "promiscon" STRINGIFY(level), (char *)buf, 908235426Sdelphij p->errbuf); 909235426Sdelphij if (err < 0) 910235426Sdelphij return (err); 911235426Sdelphij return (0); 912235426Sdelphij} 913235426Sdelphij 91417683Spstint 915127664Sbmspcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 91617683Spst{ 917127664Sbms#ifdef HAVE_SOLARIS 918127664Sbms int fd; 919127664Sbms union { 920127664Sbms u_int nunits; 921127664Sbms char pad[516]; /* XXX - must be at least 513; is 516 922127664Sbms in "atmgetunits" */ 923127664Sbms } buf; 924127664Sbms char baname[2+1+1]; 925127664Sbms u_int i; 92617683Spst 927127664Sbms /* 928127664Sbms * We may have to do special magic to get ATM devices. 929127664Sbms */ 930127664Sbms if ((fd = open("/dev/ba", O_RDWR)) < 0) { 931127664Sbms /* 932127664Sbms * We couldn't open the "ba" device. 933127664Sbms * For now, just give up; perhaps we should 934127664Sbms * return an error if the problem is neither 935127664Sbms * a "that device doesn't exist" error (ENOENT, 936127664Sbms * ENXIO, etc.) or a "you're not allowed to do 937127664Sbms * that" error (EPERM, EACCES). 938127664Sbms */ 939127664Sbms return (0); 940127664Sbms } 941127664Sbms 942127664Sbms if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) { 943127664Sbms snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s", 944127664Sbms pcap_strerror(errno)); 94575107Sfenner return (-1); 946127664Sbms } 947127664Sbms for (i = 0; i < buf.nunits; i++) { 948127664Sbms snprintf(baname, sizeof baname, "ba%u", i); 949127664Sbms if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0) 950127664Sbms return (-1); 951127664Sbms } 952127664Sbms#endif 953127664Sbms 95417683Spst return (0); 95517683Spst} 95617683Spst 95717683Spststatic int 95817683Spstsend_request(int fd, char *ptr, int len, char *what, char *ebuf) 95917683Spst{ 96017683Spst struct strbuf ctl; 96117683Spst int flags; 96217683Spst 96317683Spst ctl.maxlen = 0; 96417683Spst ctl.len = len; 96517683Spst ctl.buf = ptr; 96617683Spst 96717683Spst flags = 0; 96817683Spst if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { 96975107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 97075107Sfenner "send_request: putmsg \"%s\": %s", 97117683Spst what, pcap_strerror(errno)); 97217683Spst return (-1); 97317683Spst } 97417683Spst return (0); 97517683Spst} 97617683Spst 97717683Spststatic int 978147894Ssamrecv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror) 97917683Spst{ 98017683Spst union DL_primitives *dlp; 98117683Spst struct strbuf ctl; 98217683Spst int flags; 98317683Spst 984162012Ssam /* 985162012Ssam * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR, 986162012Ssam * making that the only place where EBUSY is treated specially. 987162012Ssam */ 988162012Ssam if (uerror != NULL) 989162012Ssam *uerror = 0; 990162012Ssam 99117683Spst ctl.maxlen = MAXDLBUF; 99217683Spst ctl.len = 0; 99317683Spst ctl.buf = bufp; 99417683Spst 99517683Spst flags = 0; 99617683Spst if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { 99775107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", 99817683Spst what, pcap_strerror(errno)); 999190225Srpaulo return (PCAP_ERROR); 100017683Spst } 100117683Spst 1002214518Srpaulo dlp = MAKE_DL_PRIMITIVES(ctl.buf); 100317683Spst switch (dlp->dl_primitive) { 100417683Spst 100517683Spst case DL_INFO_ACK: 100617683Spst case DL_BIND_ACK: 100717683Spst case DL_OK_ACK: 100817683Spst#ifdef DL_HP_PPA_ACK 100917683Spst case DL_HP_PPA_ACK: 101017683Spst#endif 101117683Spst /* These are OK */ 101217683Spst break; 101317683Spst 101417683Spst case DL_ERROR_ACK: 101517683Spst switch (dlp->error_ack.dl_errno) { 101617683Spst 101798530Sfenner case DL_SYSERR: 1018147894Ssam if (uerror != NULL) 1019147894Ssam *uerror = dlp->error_ack.dl_unix_errno; 102075107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 102198530Sfenner "recv_ack: %s: UNIX error - %s", 102217683Spst what, pcap_strerror(dlp->error_ack.dl_unix_errno)); 1023235426Sdelphij if (dlp->error_ack.dl_unix_errno == EPERM || 1024235426Sdelphij dlp->error_ack.dl_unix_errno == EACCES) 1025190225Srpaulo return (PCAP_ERROR_PERM_DENIED); 102617683Spst break; 102717683Spst 102817683Spst default: 102998530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", 103098530Sfenner what, dlstrerror(dlp->error_ack.dl_errno)); 1031190225Srpaulo if (dlp->error_ack.dl_errno == DL_BADPPA) 1032190225Srpaulo return (PCAP_ERROR_NO_SUCH_DEVICE); 1033190225Srpaulo else if (dlp->error_ack.dl_errno == DL_ACCESS) 1034190225Srpaulo return (PCAP_ERROR_PERM_DENIED); 103517683Spst break; 103617683Spst } 1037190225Srpaulo return (PCAP_ERROR); 103817683Spst 103917683Spst default: 104075107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 104198530Sfenner "recv_ack: %s: Unexpected primitive ack %s", 104298530Sfenner what, dlprim(dlp->dl_primitive)); 1043190225Srpaulo return (PCAP_ERROR); 104417683Spst } 104517683Spst 104617683Spst if (ctl.len < size) { 104775107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 104898530Sfenner "recv_ack: %s: Ack too small (%d < %d)", 104917683Spst what, ctl.len, size); 1050190225Srpaulo return (PCAP_ERROR); 105117683Spst } 105217683Spst return (ctl.len); 105317683Spst} 105417683Spst 105598530Sfennerstatic char * 105698530Sfennerdlstrerror(bpf_u_int32 dl_errno) 105798530Sfenner{ 105898530Sfenner static char errstring[6+2+8+1]; 105998530Sfenner 106098530Sfenner switch (dl_errno) { 106198530Sfenner 106298530Sfenner case DL_ACCESS: 106398530Sfenner return ("Improper permissions for request"); 106498530Sfenner 106598530Sfenner case DL_BADADDR: 106698530Sfenner return ("DLSAP addr in improper format or invalid"); 106798530Sfenner 106898530Sfenner case DL_BADCORR: 106998530Sfenner return ("Seq number not from outstand DL_CONN_IND"); 107098530Sfenner 107198530Sfenner case DL_BADDATA: 107298530Sfenner return ("User data exceeded provider limit"); 107398530Sfenner 107498530Sfenner case DL_BADPPA: 107598530Sfenner#ifdef HAVE_DEV_DLPI 107698530Sfenner /* 107798530Sfenner * With a single "/dev/dlpi" device used for all 107898530Sfenner * DLPI providers, PPAs have nothing to do with 107998530Sfenner * unit numbers. 108098530Sfenner */ 108198530Sfenner return ("Specified PPA was invalid"); 108298530Sfenner#else 108398530Sfenner /* 108498530Sfenner * We have separate devices for separate devices; 108598530Sfenner * the PPA is just the unit number. 108698530Sfenner */ 108798530Sfenner return ("Specified PPA (device unit) was invalid"); 108898530Sfenner#endif 108998530Sfenner 109098530Sfenner case DL_BADPRIM: 109198530Sfenner return ("Primitive received not known by provider"); 109298530Sfenner 109398530Sfenner case DL_BADQOSPARAM: 109498530Sfenner return ("QOS parameters contained invalid values"); 109598530Sfenner 109698530Sfenner case DL_BADQOSTYPE: 109798530Sfenner return ("QOS structure type is unknown/unsupported"); 109898530Sfenner 109998530Sfenner case DL_BADSAP: 110098530Sfenner return ("Bad LSAP selector"); 110198530Sfenner 110298530Sfenner case DL_BADTOKEN: 110398530Sfenner return ("Token used not an active stream"); 110498530Sfenner 110598530Sfenner case DL_BOUND: 110698530Sfenner return ("Attempted second bind with dl_max_conind"); 110798530Sfenner 110898530Sfenner case DL_INITFAILED: 110998530Sfenner return ("Physical link initialization failed"); 111098530Sfenner 111198530Sfenner case DL_NOADDR: 111298530Sfenner return ("Provider couldn't allocate alternate address"); 111398530Sfenner 111498530Sfenner case DL_NOTINIT: 111598530Sfenner return ("Physical link not initialized"); 111698530Sfenner 111798530Sfenner case DL_OUTSTATE: 111898530Sfenner return ("Primitive issued in improper state"); 111998530Sfenner 112098530Sfenner case DL_SYSERR: 112198530Sfenner return ("UNIX system error occurred"); 112298530Sfenner 112398530Sfenner case DL_UNSUPPORTED: 112498530Sfenner return ("Requested service not supplied by provider"); 112598530Sfenner 112698530Sfenner case DL_UNDELIVERABLE: 112798530Sfenner return ("Previous data unit could not be delivered"); 112898530Sfenner 112998530Sfenner case DL_NOTSUPPORTED: 113098530Sfenner return ("Primitive is known but not supported"); 113198530Sfenner 113298530Sfenner case DL_TOOMANY: 113398530Sfenner return ("Limit exceeded"); 113498530Sfenner 113598530Sfenner case DL_NOTENAB: 113698530Sfenner return ("Promiscuous mode not enabled"); 113798530Sfenner 113898530Sfenner case DL_BUSY: 113998530Sfenner return ("Other streams for PPA in post-attached"); 114098530Sfenner 114198530Sfenner case DL_NOAUTO: 114298530Sfenner return ("Automatic handling XID&TEST not supported"); 114398530Sfenner 114498530Sfenner case DL_NOXIDAUTO: 114598530Sfenner return ("Automatic handling of XID not supported"); 114698530Sfenner 114798530Sfenner case DL_NOTESTAUTO: 114898530Sfenner return ("Automatic handling of TEST not supported"); 114998530Sfenner 115098530Sfenner case DL_XIDAUTO: 115198530Sfenner return ("Automatic handling of XID response"); 115298530Sfenner 115398530Sfenner case DL_TESTAUTO: 115498530Sfenner return ("Automatic handling of TEST response"); 115598530Sfenner 115698530Sfenner case DL_PENDING: 115798530Sfenner return ("Pending outstanding connect indications"); 115898530Sfenner 115998530Sfenner default: 116098530Sfenner sprintf(errstring, "Error %02x", dl_errno); 116198530Sfenner return (errstring); 116298530Sfenner } 116398530Sfenner} 116498530Sfenner 116598530Sfennerstatic char * 116698530Sfennerdlprim(bpf_u_int32 prim) 116798530Sfenner{ 116898530Sfenner static char primbuf[80]; 116998530Sfenner 117098530Sfenner switch (prim) { 117198530Sfenner 117298530Sfenner case DL_INFO_REQ: 117398530Sfenner return ("DL_INFO_REQ"); 117498530Sfenner 117598530Sfenner case DL_INFO_ACK: 117698530Sfenner return ("DL_INFO_ACK"); 117798530Sfenner 117898530Sfenner case DL_ATTACH_REQ: 117998530Sfenner return ("DL_ATTACH_REQ"); 118098530Sfenner 118198530Sfenner case DL_DETACH_REQ: 118298530Sfenner return ("DL_DETACH_REQ"); 118398530Sfenner 118498530Sfenner case DL_BIND_REQ: 118598530Sfenner return ("DL_BIND_REQ"); 118698530Sfenner 118798530Sfenner case DL_BIND_ACK: 118898530Sfenner return ("DL_BIND_ACK"); 118998530Sfenner 119098530Sfenner case DL_UNBIND_REQ: 119198530Sfenner return ("DL_UNBIND_REQ"); 119298530Sfenner 119398530Sfenner case DL_OK_ACK: 119498530Sfenner return ("DL_OK_ACK"); 119598530Sfenner 119698530Sfenner case DL_ERROR_ACK: 119798530Sfenner return ("DL_ERROR_ACK"); 119898530Sfenner 119998530Sfenner case DL_SUBS_BIND_REQ: 120098530Sfenner return ("DL_SUBS_BIND_REQ"); 120198530Sfenner 120298530Sfenner case DL_SUBS_BIND_ACK: 120398530Sfenner return ("DL_SUBS_BIND_ACK"); 120498530Sfenner 120598530Sfenner case DL_UNITDATA_REQ: 120698530Sfenner return ("DL_UNITDATA_REQ"); 120798530Sfenner 120898530Sfenner case DL_UNITDATA_IND: 120998530Sfenner return ("DL_UNITDATA_IND"); 121098530Sfenner 121198530Sfenner case DL_UDERROR_IND: 121298530Sfenner return ("DL_UDERROR_IND"); 121398530Sfenner 121498530Sfenner case DL_UDQOS_REQ: 121598530Sfenner return ("DL_UDQOS_REQ"); 121698530Sfenner 121798530Sfenner case DL_CONNECT_REQ: 121898530Sfenner return ("DL_CONNECT_REQ"); 121998530Sfenner 122098530Sfenner case DL_CONNECT_IND: 122198530Sfenner return ("DL_CONNECT_IND"); 122298530Sfenner 122398530Sfenner case DL_CONNECT_RES: 122498530Sfenner return ("DL_CONNECT_RES"); 122598530Sfenner 122698530Sfenner case DL_CONNECT_CON: 122798530Sfenner return ("DL_CONNECT_CON"); 122898530Sfenner 122998530Sfenner case DL_TOKEN_REQ: 123098530Sfenner return ("DL_TOKEN_REQ"); 123198530Sfenner 123298530Sfenner case DL_TOKEN_ACK: 123398530Sfenner return ("DL_TOKEN_ACK"); 123498530Sfenner 123598530Sfenner case DL_DISCONNECT_REQ: 123698530Sfenner return ("DL_DISCONNECT_REQ"); 123798530Sfenner 123898530Sfenner case DL_DISCONNECT_IND: 123998530Sfenner return ("DL_DISCONNECT_IND"); 124098530Sfenner 124198530Sfenner case DL_RESET_REQ: 124298530Sfenner return ("DL_RESET_REQ"); 124398530Sfenner 124498530Sfenner case DL_RESET_IND: 124598530Sfenner return ("DL_RESET_IND"); 124698530Sfenner 124798530Sfenner case DL_RESET_RES: 124898530Sfenner return ("DL_RESET_RES"); 124998530Sfenner 125098530Sfenner case DL_RESET_CON: 125198530Sfenner return ("DL_RESET_CON"); 125298530Sfenner 125398530Sfenner default: 125498530Sfenner (void) sprintf(primbuf, "unknown primitive 0x%x", prim); 125598530Sfenner return (primbuf); 125698530Sfenner } 125798530Sfenner} 125898530Sfenner 125917683Spststatic int 126017683Spstdlbindreq(int fd, bpf_u_int32 sap, char *ebuf) 126117683Spst{ 126217683Spst 126317683Spst dl_bind_req_t req; 126417683Spst 126517683Spst memset((char *)&req, 0, sizeof(req)); 126617683Spst req.dl_primitive = DL_BIND_REQ; 1267147894Ssam /* XXX - what if neither of these are defined? */ 1268147894Ssam#if defined(DL_HP_RAWDLS) 126917683Spst req.dl_max_conind = 1; /* XXX magic number */ 127017683Spst req.dl_service_mode = DL_HP_RAWDLS; 1271147894Ssam#elif defined(DL_CLDLS) 127226175Sfenner req.dl_service_mode = DL_CLDLS; 127317683Spst#endif 1274147894Ssam req.dl_sap = sap; 127517683Spst 127617683Spst return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); 127717683Spst} 127817683Spst 127917683Spststatic int 1280147894Ssamdlbindack(int fd, char *bufp, char *ebuf, int *uerror) 128117683Spst{ 128217683Spst 1283147894Ssam return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror)); 128417683Spst} 128517683Spst 128617683Spststatic int 128717683Spstdlokack(int fd, const char *what, char *bufp, char *ebuf) 128817683Spst{ 128917683Spst 1290147894Ssam return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL)); 129117683Spst} 129217683Spst 129317683Spst 129417683Spststatic int 129517683Spstdlinforeq(int fd, char *ebuf) 129617683Spst{ 129717683Spst dl_info_req_t req; 129817683Spst 129917683Spst req.dl_primitive = DL_INFO_REQ; 130017683Spst 130117683Spst return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf)); 130217683Spst} 130317683Spst 130417683Spststatic int 130517683Spstdlinfoack(int fd, char *bufp, char *ebuf) 130617683Spst{ 130717683Spst 1308147894Ssam return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL)); 130917683Spst} 131017683Spst 1311190225Srpaulo#ifdef HAVE_DLPI_PASSIVE 1312190225Srpaulo/* 1313190225Srpaulo * Enable DLPI passive mode. We do not care if this request fails, as this 1314190225Srpaulo * indicates the underlying DLPI device does not support link aggregation. 1315190225Srpaulo */ 1316190225Srpaulostatic void 1317190225Srpaulodlpassive(int fd, char *ebuf) 1318190225Srpaulo{ 1319190225Srpaulo dl_passive_req_t req; 1320190225Srpaulo bpf_u_int32 buf[MAXDLBUF]; 1321190225Srpaulo 1322190225Srpaulo req.dl_primitive = DL_PASSIVE_REQ; 1323190225Srpaulo 1324190225Srpaulo if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0) 1325190225Srpaulo (void) dlokack(fd, "dlpassive", (char *)buf, ebuf); 1326190225Srpaulo} 1327190225Srpaulo#endif 1328190225Srpaulo 1329146768Ssam#ifdef DL_HP_RAWDLS 1330146768Ssam/* 1331146768Ssam * There's an ack *if* there's an error. 1332146768Ssam */ 1333146768Ssamstatic int 1334146768Ssamdlrawdatareq(int fd, const u_char *datap, int datalen) 1335146768Ssam{ 1336146768Ssam struct strbuf ctl, data; 1337146768Ssam long buf[MAXDLBUF]; /* XXX - char? */ 1338146768Ssam union DL_primitives *dlp; 1339146768Ssam int dlen; 1340146768Ssam 1341214518Srpaulo dlp = MAKE_DL_PRIMITIVES(buf); 1342146768Ssam 1343146768Ssam dlp->dl_primitive = DL_HP_RAWDATA_REQ; 1344146768Ssam dlen = DL_HP_RAWDATA_REQ_SIZE; 1345146768Ssam 1346146768Ssam /* 1347146768Ssam * HP's documentation doesn't appear to show us supplying any 1348146768Ssam * address pointed to by the control part of the message. 1349146768Ssam * I think that's what raw mode means - you just send the raw 1350146768Ssam * packet, you don't specify where to send it to, as that's 1351146768Ssam * implied by the destination address. 1352146768Ssam */ 1353146768Ssam ctl.maxlen = 0; 1354146768Ssam ctl.len = dlen; 1355146768Ssam ctl.buf = (void *)buf; 1356146768Ssam 1357146768Ssam data.maxlen = 0; 1358146768Ssam data.len = datalen; 1359146768Ssam data.buf = (void *)datap; 1360146768Ssam 1361146768Ssam return (putmsg(fd, &ctl, &data, 0)); 1362146768Ssam} 1363146768Ssam#endif /* DL_HP_RAWDLS */ 1364146768Ssam 136517683Spst#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) 136617683Spststatic char * 136717683Spstget_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) 136817683Spst{ 136917683Spst char *cp; 137017683Spst static char buf[32]; 137117683Spst 137217683Spst *majorp = 0; 137317683Spst *minorp = 0; 137417683Spst *microp = 0; 137517683Spst if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) 137617683Spst return ("?"); 137717683Spst cp = buf; 137898530Sfenner if (!isdigit((unsigned char)*cp)) 137917683Spst return (buf); 138017683Spst *majorp = strtol(cp, &cp, 10); 138117683Spst if (*cp++ != '.') 138217683Spst return (buf); 138317683Spst *minorp = strtol(cp, &cp, 10); 138417683Spst if (*cp++ != '.') 138517683Spst return (buf); 138617683Spst *microp = strtol(cp, &cp, 10); 138717683Spst return (buf); 138817683Spst} 138917683Spst#endif 139017683Spst 1391146768Ssam#ifdef DL_HP_PPA_REQ 139217683Spst/* 139375107Sfenner * Under HP-UX 10 and HP-UX 11, we can ask for the ppa 139417683Spst */ 139517683Spst 139617683Spst 139775107Sfenner/* 139875107Sfenner * Determine ppa number that specifies ifname. 139975107Sfenner * 140075107Sfenner * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member, 140175107Sfenner * the code that's used here is the old code for HP-UX 10.x. 140275107Sfenner * 140375107Sfenner * However, HP-UX 10.20, at least, appears to have such a member 140475107Sfenner * in its "dl_hp_ppa_info_t" structure, so the new code is used. 140575107Sfenner * The new code didn't work on an old 10.20 system on which Rick 140675107Sfenner * Jones of HP tried it, but with later patches installed, it 140775107Sfenner * worked - it appears that the older system had those members but 140875107Sfenner * didn't put anything in them, so, if the search by name fails, we 140975107Sfenner * do the old search. 141075107Sfenner * 141175107Sfenner * Rick suggests that making sure your system is "up on the latest 141275107Sfenner * lancommon/DLPI/driver patches" is probably a good idea; it'd fix 141375107Sfenner * that problem, as well as allowing libpcap to see packets sent 141475107Sfenner * from the system on which the libpcap application is being run. 141575107Sfenner * (On 10.20, in addition to getting the latest patches, you need 141675107Sfenner * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB; 141775107Sfenner * a posting to "comp.sys.hp.hpux" at 141875107Sfenner * 141975107Sfenner * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266 142075107Sfenner * 142175107Sfenner * says that, to see the machine's outgoing traffic, you'd need to 142275107Sfenner * apply the right patches to your system, and also set that variable 142375107Sfenner * with: 1424127664Sbms 142575107Sfennerecho 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem 142675107Sfenner 142775107Sfenner * which could be put in, for example, "/sbin/init.d/lan". 142875107Sfenner * 142975107Sfenner * Setting the variable is not necessary on HP-UX 11.x. 143075107Sfenner */ 143117683Spststatic int 143217683Spstget_dlpi_ppa(register int fd, register const char *device, register int unit, 143317683Spst register char *ebuf) 143417683Spst{ 143517683Spst register dl_hp_ppa_ack_t *ap; 143675107Sfenner register dl_hp_ppa_info_t *ipstart, *ip; 143717683Spst register int i; 143875107Sfenner char dname[100]; 143917683Spst register u_long majdev; 144075107Sfenner struct stat statbuf; 144117683Spst dl_hp_ppa_req_t req; 144298530Sfenner char buf[MAXDLBUF]; 144398530Sfenner char *ppa_data_buf; 144498530Sfenner dl_hp_ppa_ack_t *dlp; 144598530Sfenner struct strbuf ctl; 144698530Sfenner int flags; 144798530Sfenner int ppa; 144817683Spst 144917683Spst memset((char *)&req, 0, sizeof(req)); 145017683Spst req.dl_primitive = DL_HP_PPA_REQ; 145117683Spst 145217683Spst memset((char *)buf, 0, sizeof(buf)); 145398530Sfenner if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0) 1454190225Srpaulo return (PCAP_ERROR); 145517683Spst 145698530Sfenner ctl.maxlen = DL_HP_PPA_ACK_SIZE; 145798530Sfenner ctl.len = 0; 145898530Sfenner ctl.buf = (char *)buf; 145998530Sfenner 146098530Sfenner flags = 0; 146198530Sfenner /* 146298530Sfenner * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal 146398530Sfenner * recv_ack will fail because it set the maxlen to MAXDLBUF (8192) 146498530Sfenner * which is NOT big enough for a DL_HP_PPA_REQ. 146598530Sfenner * 146698530Sfenner * This causes libpcap applications to fail on a system with HP-APA 146798530Sfenner * installed. 146898530Sfenner * 146998530Sfenner * To figure out how big the returned data is, we first call getmsg 147098530Sfenner * to get the small head and peek at the head to get the actual data 147198530Sfenner * length, and then issue another getmsg to get the actual PPA data. 147298530Sfenner */ 147398530Sfenner /* get the head first */ 147498530Sfenner if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { 147598530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 147698530Sfenner "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); 1477190225Srpaulo return (PCAP_ERROR); 147898530Sfenner } 147998530Sfenner 148098530Sfenner dlp = (dl_hp_ppa_ack_t *)ctl.buf; 148198530Sfenner if (dlp->dl_primitive != DL_HP_PPA_ACK) { 148298530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 148398530Sfenner "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", 148498530Sfenner (bpf_u_int32)dlp->dl_primitive); 1485190225Srpaulo return (PCAP_ERROR); 148698530Sfenner } 1487127664Sbms 148898530Sfenner if (ctl.len < DL_HP_PPA_ACK_SIZE) { 148998530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 1490127664Sbms "get_dlpi_ppa: hpppa ack too small (%d < %lu)", 1491127664Sbms ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); 1492190225Srpaulo return (PCAP_ERROR); 149398530Sfenner } 1494127664Sbms 149598530Sfenner /* allocate buffer */ 149698530Sfenner if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { 149798530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 149898530Sfenner "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); 1499190225Srpaulo return (PCAP_ERROR); 150098530Sfenner } 150198530Sfenner ctl.maxlen = dlp->dl_length; 150298530Sfenner ctl.len = 0; 150398530Sfenner ctl.buf = (char *)ppa_data_buf; 150498530Sfenner /* get the data */ 150598530Sfenner if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { 150698530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 150798530Sfenner "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); 150898530Sfenner free(ppa_data_buf); 1509190225Srpaulo return (PCAP_ERROR); 151098530Sfenner } 151198530Sfenner if (ctl.len < dlp->dl_length) { 151298530Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 1513214518Srpaulo "get_dlpi_ppa: hpppa ack too small (%d < %lu)", 1514214518Srpaulo ctl.len, (unsigned long)dlp->dl_length); 151598530Sfenner free(ppa_data_buf); 1516190225Srpaulo return (PCAP_ERROR); 151798530Sfenner } 151898530Sfenner 151917683Spst ap = (dl_hp_ppa_ack_t *)buf; 152098530Sfenner ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; 152175107Sfenner ip = ipstart; 152217683Spst 152375107Sfenner#ifdef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 152475107Sfenner /* 152575107Sfenner * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1" 152675107Sfenner * member that should, in theory, contain the part of the 152775107Sfenner * name for the device that comes before the unit number, 152875107Sfenner * and should also have a "dl_module_id_2" member that may 152975107Sfenner * contain an alternate name (e.g., I think Ethernet devices 153075107Sfenner * have both "lan", for "lanN", and "snap", for "snapN", with 153175107Sfenner * the former being for Ethernet packets and the latter being 153275107Sfenner * for 802.3/802.2 packets). 153375107Sfenner * 153475107Sfenner * Search for the device that has the specified name and 153575107Sfenner * instance number. 153675107Sfenner */ 153775107Sfenner for (i = 0; i < ap->dl_count; i++) { 153898530Sfenner if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 || 153998530Sfenner strcmp((const char *)ip->dl_module_id_2, device) == 0) && 154075107Sfenner ip->dl_instance_num == unit) 154175107Sfenner break; 154217683Spst 154375107Sfenner ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 154475107Sfenner } 154575107Sfenner#else 154675107Sfenner /* 154775107Sfenner * We don't have that member, so the search is impossible; make it 154875107Sfenner * look as if the search failed. 154975107Sfenner */ 155075107Sfenner i = ap->dl_count; 155175107Sfenner#endif 155275107Sfenner 155375107Sfenner if (i == ap->dl_count) { 155475107Sfenner /* 155575107Sfenner * Well, we didn't, or can't, find the device by name. 155675107Sfenner * 155775107Sfenner * HP-UX 10.20, whilst it has "dl_module_id_1" and 155875107Sfenner * "dl_module_id_2" fields in the "dl_hp_ppa_info_t", 155975107Sfenner * doesn't seem to fill them in unless the system is 156075107Sfenner * at a reasonably up-to-date patch level. 156175107Sfenner * 156275107Sfenner * Older HP-UX 10.x systems might not have those fields 156375107Sfenner * at all. 156475107Sfenner * 156575107Sfenner * Therefore, we'll search for the entry with the major 156675107Sfenner * device number of a device with the name "/dev/<dev><unit>", 156775107Sfenner * if such a device exists, as the old code did. 156875107Sfenner */ 156975107Sfenner snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); 157075107Sfenner if (stat(dname, &statbuf) < 0) { 157175107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", 157275107Sfenner dname, pcap_strerror(errno)); 1573190225Srpaulo return (PCAP_ERROR); 157475107Sfenner } 157575107Sfenner majdev = major(statbuf.st_rdev); 157675107Sfenner 157775107Sfenner ip = ipstart; 157875107Sfenner 157975107Sfenner for (i = 0; i < ap->dl_count; i++) { 158075107Sfenner if (ip->dl_mjr_num == majdev && 158175107Sfenner ip->dl_instance_num == unit) 158275107Sfenner break; 158375107Sfenner 158475107Sfenner ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset); 158575107Sfenner } 158675107Sfenner } 1587147894Ssam if (i == ap->dl_count) { 1588147894Ssam snprintf(ebuf, PCAP_ERRBUF_SIZE, 158975107Sfenner "can't find /dev/dlpi PPA for %s%d", device, unit); 1590190225Srpaulo return (PCAP_ERROR_NO_SUCH_DEVICE); 1591147894Ssam } 1592147894Ssam if (ip->dl_hdw_state == HDW_DEAD) { 1593147894Ssam snprintf(ebuf, PCAP_ERRBUF_SIZE, 159475107Sfenner "%s%d: hardware state: DOWN\n", device, unit); 159598530Sfenner free(ppa_data_buf); 1596190225Srpaulo return (PCAP_ERROR); 1597147894Ssam } 1598147894Ssam ppa = ip->dl_ppa; 1599147894Ssam free(ppa_data_buf); 1600147894Ssam return (ppa); 160117683Spst} 160217683Spst#endif 160317683Spst 160417683Spst#ifdef HAVE_HPUX9 160517683Spst/* 160617683Spst * Under HP-UX 9, there is no good way to determine the ppa. 160717683Spst * So punt and read it from /dev/kmem. 160817683Spst */ 160917683Spststatic struct nlist nl[] = { 161017683Spst#define NL_IFNET 0 161117683Spst { "ifnet" }, 161217683Spst { "" } 161317683Spst}; 161417683Spst 161517683Spststatic char path_vmunix[] = "/hp-ux"; 161617683Spst 161717683Spst/* Determine ppa number that specifies ifname */ 161817683Spststatic int 161917683Spstget_dlpi_ppa(register int fd, register const char *ifname, register int unit, 162017683Spst register char *ebuf) 162117683Spst{ 162217683Spst register const char *cp; 162317683Spst register int kd; 162417683Spst void *addr; 162517683Spst struct ifnet ifnet; 162675107Sfenner char if_name[sizeof(ifnet.if_name) + 1]; 162717683Spst 162817683Spst cp = strrchr(ifname, '/'); 162917683Spst if (cp != NULL) 163017683Spst ifname = cp + 1; 163117683Spst if (nlist(path_vmunix, &nl) < 0) { 163275107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", 163375107Sfenner path_vmunix); 163417683Spst return (-1); 163517683Spst } 163617683Spst if (nl[NL_IFNET].n_value == 0) { 163775107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 163875107Sfenner "could't find %s kernel symbol", 163917683Spst nl[NL_IFNET].n_name); 164017683Spst return (-1); 164117683Spst } 164217683Spst kd = open("/dev/kmem", O_RDONLY); 164317683Spst if (kd < 0) { 164475107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", 164575107Sfenner pcap_strerror(errno)); 164617683Spst return (-1); 164717683Spst } 164817683Spst if (dlpi_kread(kd, nl[NL_IFNET].n_value, 164917683Spst &addr, sizeof(addr), ebuf) < 0) { 165017683Spst close(kd); 165117683Spst return (-1); 165217683Spst } 165317683Spst for (; addr != NULL; addr = ifnet.if_next) { 165417683Spst if (dlpi_kread(kd, (off_t)addr, 165517683Spst &ifnet, sizeof(ifnet), ebuf) < 0 || 165617683Spst dlpi_kread(kd, (off_t)ifnet.if_name, 165775107Sfenner if_name, sizeof(ifnet.if_name), ebuf) < 0) { 165817683Spst (void)close(kd); 165917683Spst return (-1); 166017683Spst } 166175107Sfenner if_name[sizeof(ifnet.if_name)] = '\0'; 166275107Sfenner if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) 166317683Spst return (ifnet.if_index); 166417683Spst } 166517683Spst 166675107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); 166717683Spst return (-1); 166817683Spst} 166917683Spst 167017683Spststatic int 167117683Spstdlpi_kread(register int fd, register off_t addr, 167217683Spst register void *buf, register u_int len, register char *ebuf) 167317683Spst{ 167417683Spst register int cc; 167517683Spst 167639291Sfenner if (lseek(fd, addr, SEEK_SET) < 0) { 167775107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", 167875107Sfenner pcap_strerror(errno)); 167917683Spst return (-1); 168017683Spst } 168117683Spst cc = read(fd, buf, len); 168217683Spst if (cc < 0) { 168375107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", 168475107Sfenner pcap_strerror(errno)); 168517683Spst return (-1); 168617683Spst } else if (cc != len) { 168775107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, 168875107Sfenner len); 168917683Spst return (-1); 169017683Spst } 169117683Spst return (cc); 169217683Spst} 169317683Spst#endif 1694190225Srpaulo 1695190225Srpaulopcap_t * 1696251129Sdelphijpcap_create_interface(const char *device, char *ebuf) 1697190225Srpaulo{ 1698190225Srpaulo pcap_t *p; 1699190225Srpaulo 1700190225Srpaulo p = pcap_create_common(device, ebuf); 1701190225Srpaulo if (p == NULL) 1702190225Srpaulo return (NULL); 1703190225Srpaulo 1704190225Srpaulo p->send_fd = -1; /* it hasn't been opened yet */ 1705190225Srpaulo 1706190225Srpaulo p->activate_op = pcap_activate_dlpi; 1707190225Srpaulo return (p); 1708190225Srpaulo} 1709