⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlpi.c

📁 wm PNE 3.3 source code, running at more than vxworks6.x version.
💻 C
字号:
/* $Header: /usr/cvsroot/target/src/wrn/wm/demo/lib/dlpi.c,v 1.2 2001/11/08 15:56:21 tneale Exp $ *//* * Copyright (C) 1999-2005 Wind River Systems, Inc. * All rights reserved.  Provided under license only. * Distribution or other use of this software is only * permitted pursuant to the terms of a license agreement * from Wind River Systems (and is otherwise prohibited). * Refer to that license agreement for terms of use. *//**************************************************************************** *  Copyright 1998 Integrated Systems, Inc. *  All rights reserved. ****************************************************************************//* * $Log: dlpi.c,v $ * Revision 1.2  2001/11/08 15:56:21  tneale * Updated for newest file layout * * Revision 1.1.1.1  2001/11/05 17:48:41  tneale * Tornado shuffle * * Revision 2.3  2001/01/19 22:23:40  paul * Update copyright. * * Revision 2.2  2000/03/17 00:12:37  meister * Update copyright message * * Revision 2.1  1998/07/29 20:54:51  wes * First cut of the Solaris port. * (DLPI support, termios, minor tweaks to libraries and port header files) * * Revision 1.1.2.1  1998/07/24 21:45:41  wes * Initial implementation * *//* [clearcase]modification history-------------------01a,19apr05,job  update copyright notices*//* * DLPI interface to ethernet for Attache testing under Solaris 2.x * * All access to DLPI should be through this module, the only thing we * expect our caller to do with our file descriptor is use it in * select() calls.  There are enough name conflicts between the unix * networking code and the Attache networking code that it's probably * hopeless to have the two mingled in the same file. * * This was brutally converted from nit.c in a fit of madness. * * References: NIT manual pages *	       tcpdump source *	       CAP ethertalk source *	       netintro(4) manual page *	       NET-2 routed source *	       "How to use DLPI" document from Sun Internet Engineering, dated 30 Jun 1992 *		DLPI specification. */#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <ctype.h>#include <fcntl.h>#include <sys/param.h>#include <sys/types.h>#include <sys/time.h>#include <sys/timeb.h>#include <sys/socket.h>#include <sys/file.h>#include <sys/ioctl.h>#include <stropts.h>#include <sys/dlpi.h>#include <sys/pfmod.h>#include <sys/sockio.h>#include <netinet/in.h>#include <net/if.h>#define __(x) x#include <wrn/wm/demo/dlpi.h>#ifdef __GNUC__#define	alloca	__builtin_alloca#endif#define MAXDLBUF	8192#define		OFFADDR(s, n)	(u_char*)((char*)(s) + (int)(n))/* * DLPI client stubs. */int dlreqspew (int fd, void *buf, size_t size){  struct strbuf ctl;  ctl.maxlen = 0;  ctl.len = size;  ctl.buf = buf;  return putmsg(fd, &ctl, NULL, 0);}int dlgetack (int fd, int exp_prim, int exp_flags, char *respbuf, int exp_size){  union DL_primitives *dlp;  struct strbuf ctl;  char tmpbuf[MAXDLBUF];  int flags = 0;  if (!respbuf)    respbuf = tmpbuf;    /* XXX do a poll() here to wait for the response.. */  ctl.maxlen = exp_size;  ctl.len = 0;  ctl.buf = respbuf;  if (getmsg(fd, &ctl, NULL, &flags) < 0)    return -4;  dlp = (union DL_primitives *)ctl.buf;  if (dlp->dl_primitive != exp_prim)    return -1;  if (flags != exp_flags)    return -2;  if (ctl.len < exp_size)    return -3;  return 0;}int dlsar (int fd, void *reqbuf, size_t size,	   int exp_prim, int exp_flags, void *respbuf, int exp_size){  /* Flush the read queue, don't worry about it if we can't. */  (void) ioctl(fd, I_FLUSH, (char *) FLUSHR);  if (dlreqspew(fd, reqbuf, size) < 0)    return -1;  return dlgetack(fd, exp_prim, exp_flags, respbuf, exp_size);}int dlattach(int fd, u_long ppa){  dl_attach_req_t	attach_req;  attach_req.dl_primitive = DL_ATTACH_REQ;  attach_req.dl_ppa = ppa;  return dlsar(fd, &attach_req, sizeof(attach_req),	       DL_OK_ACK, RS_HIPRI, NULL, sizeof(dl_ok_ack_t));}int dlbind(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest){  dl_bind_req_t	bind_req;  bind_req.dl_primitive = DL_BIND_REQ;  bind_req.dl_sap = sap;  bind_req.dl_max_conind = max_conind;  bind_req.dl_service_mode = service_mode;  bind_req.dl_conn_mgmt = conn_mgmt;  bind_req.dl_xidtest_flg = xidtest;    return dlsar(fd, &bind_req, sizeof(bind_req),	       DL_BIND_ACK, RS_HIPRI, NULL, sizeof(dl_bind_ack_t));}int dlpromiscon(int fd, int level) {  dl_promiscon_req_t promiscon_req;  promiscon_req.dl_primitive = DL_PROMISCON_REQ;  promiscon_req.dl_level = level;  return dlsar (fd, &promiscon_req, sizeof(promiscon_req),		DL_OK_ACK, RS_HIPRI, NULL, sizeof(dl_ok_ack_t));}int dlphysaddr(int fd, int which, char *phy, int len){  dl_phys_addr_req_t phys_addr_req;  dl_phys_addr_ack_t phys_addr_ack;  int tmp;  union DL_primitives *dlp;    phys_addr_req.dl_primitive = DL_PHYS_ADDR_REQ;  phys_addr_req.dl_addr_type = which;  tmp = dlsar (fd, &phys_addr_req, sizeof(phys_addr_req),	       DL_PHYS_ADDR_ACK, RS_HIPRI, &phys_addr_ack, sizeof(phys_addr_ack));  if (tmp < 0)    return tmp;  dlp=(union DL_primitives *)&phys_addr_ack;  memcpy(phy, OFFADDR(dlp, dlp->physaddr_ack.dl_addr_offset), len);  return 0;  }/* * Open a STREAMS driver for the interface and attach it to the interface named 'device'. * Returns DLPI file descriptor, or -1 if an error occurs. * * Since this implementation uses the same ethernet address as the host * on which it's running, fill in Attache's idea of the MAC address. * * N.B.  the order of calls of the STREAMS primitives here is * evidently fairly subtle and is not covered by existing documentation. * * Looking at known working code (e.g., LBL libpcap) finally allowed * me to get things to work right; based on reading that other code, * it appears that this will require some work on systems other than * Solaris. */int dlpi_open(char *ifname, unsigned mtu, unsigned char *mac){  struct strioctl sioc;    char driver[16];  int fd;  u_long unit;  char *cp;  /*   * parse the unit number out of the ifname..   */  sprintf(driver, "/dev/%s", ifname);  cp = &driver[strlen(driver)];  while(isdigit((int)cp[-1]))	/* XXX int cast to quiet gcc  */    --cp;  unit = atoi(cp);  *cp = '\0';    /*   * Look for cloned link-layer driver..   */  if ((fd = open(driver, O_RDWR)) < 0) {    perror("couldn't clone DLPI device");    return -1;  }  if (dlattach(fd, unit) < 0) {    perror("couldn't attach dlpi unit\n");    return -1;  }  /*   * Enable discrete messages.   */  if (ioctl(fd, I_SRDOPT, (char *) RMSGD) < 0) {    perror("couldn't enable discrete DLPI messages");    return -1;  }  /*   * Don't bother with buffering, or truncation for now.   */  /*   * Put the interface into promiscuous mode so that we'll see packets   * to our faked MAC address..   */  if (dlpromiscon(fd, DL_PROMISC_PHYS) < 0) {    perror("dlpi: failed to set promisc PHYS mode\n");  }    /*   * Get all SAP's (this apparently needs to happen *after* setting   * the lower-level promiscuous mode   */  if (dlpromiscon(fd, DL_PROMISC_SAP) < 0)    perror("dlpi: failed to set promisc SAP mode");  /*   * We bind last since comments in libpcap suggest that this is most portable.   */  if (dlbind(fd, 0, 0, DL_CLDLS, 0, 0) < 0) {    perror("couldn't dlbind\n");  }  /* Set raw mode.  if this fails, we *should* blow up since the protocol's different.. */  sioc.ic_cmd = DLIOCRAW;  sioc.ic_timout = -1;  sioc.ic_len = 0;  sioc.ic_dp = 0;  if (ioctl(fd, I_STR, &sioc) < 0) {    perror("couldn't set RAW mode, continuing..\n");  }  /*   * Push packet filter module.   */  if (ioctl(fd, I_PUSH, "pfmod") < 0) {    perror("couldn't push packet filter STREAMS module, continuing..");  } else {    struct packetfilt pfil;    u_short *pfp = &pfil.Pf_Filter[0];    /*     * Yum. Interpreted LIW code, the result of several hours of mental pain.     * This *might* be an optimal instruction schedule.     *     * Whoever named the ENF_C{N,}{AND,OR} ops was.. confused...     * But, well...     */        *pfp++ = ENF_PUSHLIT;					        *pfp++ = 0x0100;				/* multicast bit */    *pfp++ = (ENF_PUSHWORD+0) | ENF_AND;	/* mask with first word of mac */    *pfp++ = ENF_PUSHZERO | ENF_CNAND;		/* succeed if nonzero */        *pfp++ = ENF_PUSHLIT;    *pfp++ = ntohs(*(u_short *)mac);		/* first word of mac */    *pfp++ = (ENF_PUSHWORD+0) | ENF_CAND;	/* fail if not equal */    *pfp++ = ENF_PUSHLIT;    *pfp++ = ntohs(*(u_short *)(mac+2));	/* second word of mac */    *pfp++ = (ENF_PUSHWORD+1) | ENF_CAND;       /* fail if not equal */    *pfp++ = ENF_PUSHLIT;    *pfp++ = ntohs(*(u_short *)(mac+4));	/* third word  of mac */    *pfp++ = (ENF_PUSHWORD+2) | ENF_EQ;		/* succeed if equal.. */        pfil.Pf_Priority = 0;    pfil.Pf_FilterLen = pfp - &pfil.Pf_Filter[0];    sioc.ic_cmd = PFIOCSETF;    sioc.ic_timout = -1;    sioc.ic_len = sizeof(pfil);    sioc.ic_dp = (void *)&pfil;    if (ioctl(fd, I_STR, &sioc) < 0) {      perror("couldn't set packet filter, continuing..");    }  }  /* As last action, flush the read queue.. */  (void) ioctl(fd, I_FLUSH, (char *) FLUSHR);    return fd;}/* * Read a DLPI buffer and hand its contents off to Attache as packets. * This is based on the readloop() function in tcpdump's BPF code and * on the dlpi(4) manual page. * * The handler routine supplied by the Attache-side code gets three * arguments: a pointer to the packet data, the length of the packet * data, and the length that the real packet was on the wire. * * There's probably nothing useful that Attache can do with a truncated * packet, but the info is there, so we may as well pass it along. */int dlpi_read  (int fd,   unsigned mtu,   void (*handler)(unsigned char *, unsigned, unsigned, void *),   void *cookie){  unsigned char *buf;  int i, flags;  struct strbuf data;    if ((buf = (unsigned char *) alloca(mtu)) == 0) {    fprintf(stderr, "alloca(%d) failed\n", mtu);    return -1;  }  data.buf = buf;  data.maxlen = mtu;  data.len = 0;  /*   * Try to read a packet, restart if we get screwed by the debugger.   * Return on other error or on EOF.   */  flags = 0;  do {    i = getmsg(fd, NULL, &data, &flags);  } while (i < 0 && errno == EINTR);  if (i>=0)    i=data.len;    if (i <= 0)    return i;  /*   * In theory, since we've got the stream in discrete message mode,   * we can just assume that we got one packet.   */  handler(buf, i, i, cookie);  return 1;}/* * Write a packet to the DLPI stream. */int dlpi_write(int fd, unsigned char *data, unsigned datalen){  struct strbuf dbuf;  dbuf.buf = data;  dbuf.len = datalen;  dbuf.maxlen = 0;  return putmsg(fd, 0, &dbuf, 0) < 0 ? -1 : datalen;}/* * Close a DLPI interface. */void dlpi_close(int fd){  (void) close(fd);}#if defined(SIOCGIFCONF)/* * Find all ethernet interfaces.  This is a simplified version of the * code that works on NetBSD, I dunno yet whether this will work on SunOS. */void dlpi_find(void (*handler)(char *, void *), void *cookie){  char buffer[5000];  struct ifconf ifc;  struct ifreq *ifr;  int s;  if (!handler)    return;  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {    perror("socket");    return;  }  /* shut up purify whining about uninit memory.. */  memset(buffer, 0, sizeof(buffer));  ifc.ifc_len = sizeof(buffer);  ifc.ifc_buf = buffer;  if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) {    perror("ioctl");    (void) close(s);    return;  }  for (ifr = ifc.ifc_req; ((char *) ifr) < ifc.ifc_buf + ifc.ifc_len; ++ifr) {    handler(ifr->ifr_name, cookie);  }    (void) close(s);}#endif /* defined(SIOCGIFCONF) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -