📄 libnet_link_dlpi.c
字号:
/* * $Id: libnet_link_dlpi.c,v 1.4 2003/10/17 15:54:35 kkuehl Exp $ * * libnet * libnet_dlpi.c - dlpi routines * * Copyright (c) 1998 - 2003 Mike D. Schiffman <mike@infonexus.com> * All rights reserved. * * Copyright (c) 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), * University College London. */#if (HAVE_CONFIG_H)#include "../include/config.h"#endif#include <sys/types.h>#include <sys/time.h>#ifdef HAVE_SYS_BUFMOD_H#include <sys/bufmod.h>#endif#include <sys/dlpi.h>#ifdef HAVE_HPUX9#include <sys/socket.h>#endif#ifdef DL_HP_PPA_ACK_OBS#include <sys/stat.h>#endif#include <sys/stream.h>#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)#include <sys/systeminfo.h>#endif#ifdef HAVE_SYS_DLPI_EXT_H#include <sys/dlpi_ext.h>#endif#ifdef HAVE_HPUX9#include <net/if.h>#endif#include <ctype.h>#ifdef HAVE_HPUX9#include <nlist.h>#include <dlpi_ext.h>#endif#include <errno.h>#include <fcntl.h>#include <memory.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stropts.h>#include <unistd.h>#include "../include/libnet.h"#include "../include/bpf.h"#include "../include/gnuc.h"#ifdef HAVE_OS_PROTO_H#include "../include/os-proto.h"#endif#ifndef DLPI_DEV_PREFIX#define DLPI_DEV_PREFIX "/dev"#endif#define MAXDLBUF 8192/* Forwards */static int dlattachreq(int, bpf_u_int32, int8_t *);static int dlbindack(int, int8_t *, int8_t *);static int dlbindreq(int, bpf_u_int32, int8_t *);static int dlinfoack(int, int8_t *, int8_t *);static int dlinforeq(int, int8_t *);static int dlokack(int, const int8_t *, int8_t *, int8_t *);static int recv_ack(int, int, const int8_t *, int8_t *, int8_t *);static int send_request(int, int8_t *, int, int8_t *, int8_t *, int);#ifdef HAVE_SYS_BUFMOD_Hstatic int strioctl(int, int, int, int8_t *);#endif#ifdef HAVE_HPUX9static int dlpi_kread(int, off_t, void *, u_int, int8_t *);#endif#ifdef HAVE_DEV_DLPIstatic int get_dlpi_ppa(int, const int8_t *, int, int8_t *);#endif/* XXX Needed by HP-UX (at least) */static bpf_u_int32 ctlbuf[MAXDLBUF];intlibnet_open_link(libnet_t *l){ register int8_t *cp; int8_t *eos; register int ppa; register dl_info_ack_t *infop; bpf_u_int32 buf[MAXDLBUF]; int8_t dname[100];#ifndef HAVE_DEV_DLPI int8_t dname2[100];#endif if (l == NULL) { return (-1); } /* * Determine device and ppa */ cp = strpbrk(l->device, "0123456789"); if (cp == NULL) { sprintf(l->err_buf, "%s missing unit number", l->device); goto bad; } ppa = strtol(cp, &eos, 10); if (*eos != '\0') { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "libnet_open_link: %s bad unit number", l->device); goto bad; } if (*(l->device) == '/') { memset(&dname, 0, sizeof(dname)); strncpy(dname, l->device, sizeof(dname) - 1);
dname[sizeof(dname) - 1] = '\0'; } else { sprintf(dname, "%s/%s", DLPI_DEV_PREFIX, l->device); }#ifdef HAVE_DEV_DLPI /* * Map network device to /dev/dlpi unit */ cp = "/dev/dlpi"; l->fd = open(cp, O_RDWR); if (l->fd == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "libnet_open_link: %s: %s", cp, strerror(errno)); goto bad; } /* * Map network interface to /dev/dlpi unit */ ppa = get_dlpi_ppa(l->fd, dname, ppa, l->err_buf); if (ppa < 0) { goto bad; }#else /* * Try device without unit number */ strcpy(dname2, dname); cp = strchr(dname, *cp); *cp = '\0'; l->fd = open(dname, O_RDWR); if (l->fd == -1) { if (errno != ENOENT) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "libnet_open_link: %s: %s", dname, strerror(errno)); goto bad; } /* * Try again with unit number */ l->fd = open(dname2, O_RDWR); if (l->fd == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "libnet_open_link: %s: %s", dname2, strerror(errno)); goto bad; } cp = dname2; while (*cp && !isdigit((int)*cp)) cp++; if (*cp) ppa = atoi(cp); else /* * XXX Assume unit zero */ ppa = 0; }#endif /* * Attach if "style 2" provider */ if (dlinforeq(l->fd, l->err_buf) < 0 || dlinfoack(l->fd, (int8_t *)buf, l->err_buf) < 0) { goto bad; } infop = &((union DL_primitives *)buf)->info_ack; if (infop->dl_provider_style == DL_STYLE2 && (dlattachreq(l->fd, ppa, l->err_buf) < 0 || dlokack(l->fd, "attach", (int8_t *)buf, l->err_buf) < 0)) { goto bad; } /* * Bind HP-UX 9 and HP-UX 10.20 */#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) || defined(HAVE_HPUX11) || defined(HAVE_SOLARIS) if (dlbindreq(l->fd, 0, l->err_buf) < 0 || dlbindack(l->fd, (int8_t *)buf, l->err_buf) < 0) { goto bad; }#endif /* * Determine link type */ if (dlinforeq(l->fd, l->err_buf) < 0 || dlinfoack(l->fd, (int8_t *)buf, l->err_buf) < 0) { goto bad; } infop = &((union DL_primitives *)buf)->info_ack; switch (infop->dl_mac_type) { case DL_CSMACD: case DL_ETHER: l->link_type = DLT_EN10MB; l->link_offset = 0xe; break; case DL_FDDI: l->link_type = DLT_FDDI; l->link_offset = 0x15; break; case DL_TPR: l->link_type = DLT_PRONET; l->link_offset = 0x16; break; default: sprintf(l->err_buf, "libnet_open_link(): unknown mac type 0x%lu", (u_int32_t) infop->dl_mac_type); goto bad; }#ifdef DLIOCRAW /* * This is a non standard SunOS hack to get the ethernet header. */ if (strioctl(l->fd, DLIOCRAW, 0, NULL) < 0) { sprintf(l->err_buf, "libnet_open_link(): DLIOCRAW: %s", strerror(errno)); goto bad; }#endif return (1);bad: if (l->fd > 0) { close(l->fd); /* this can fail ok */ } return (-1);}static intsend_request(int fd, int8_t *ptr, int len, int8_t *what, int8_t *ebuf, int flags){ struct strbuf ctl; ctl.maxlen = 0; ctl.len = len; ctl.buf = ptr; if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { sprintf(ebuf, "send_request: putmsg \"%s\": %s", what, strerror(errno)); return (-1); } return (0);}static intrecv_ack(int fd, int size, const int8_t *what, int8_t *bufp, int8_t *ebuf){ union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; flags = 0; if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { sprintf(ebuf, "recv_ack: %s getmsg: %s", what, strerror(errno)); return (-1); } dlp = (union DL_primitives *)ctl.buf; switch (dlp->dl_primitive) { case DL_INFO_ACK: case DL_PHYS_ADDR_ACK: case DL_BIND_ACK: case DL_OK_ACK:#ifdef DL_HP_PPA_ACK case DL_HP_PPA_ACK:#endif /* * These are OK */ break; case DL_ERROR_ACK: switch (dlp->error_ack.dl_errno) { case DL_BADPPA: sprintf(ebuf, "recv_ack: %s bad ppa (device unit)", what); break; case DL_SYSERR: sprintf(ebuf, "recv_ack: %s: %s", what, strerror(dlp->error_ack.dl_unix_errno)); break; case DL_UNSUPPORTED: sprintf(ebuf, "recv_ack: %s: Service not supplied by provider", what); break; default: sprintf(ebuf, "recv_ack: %s error 0x%x", what, (bpf_u_int32)dlp->error_ack.dl_errno); break; } return (-1); default: sprintf(ebuf, "recv_ack: %s unexpected primitive ack 0x%x ", what, (bpf_u_int32)dlp->dl_primitive); return (-1); } if (ctl.len < size) { sprintf(ebuf, "recv_ack: %s ack too small (%d < %d)", what, ctl.len, size); return (-1); } return (ctl.len);}static intdlattachreq(int fd, bpf_u_int32 ppa, int8_t *ebuf){ dl_attach_req_t req; req.dl_primitive = DL_ATTACH_REQ; req.dl_ppa = ppa; return (send_request(fd, (int8_t *)&req, sizeof(req), "attach", ebuf, 0));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -