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

📄 bpf.c

📁 wm PNE 3.3 source code, running at more than vxworks6.x version.
💻 C
字号:
/* $Header: /usr/cvsroot/target/src/wrn/wm/demo/lib/bpf.c,v 1.3 2003/01/15 14:04:30 josh 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 1993-1997 Epilogue Technology Corporation. *  Copyright 1998 Integrated Systems, Inc. *  All rights reserved. ****************************************************************************//* * $Log: bpf.c,v $ * Revision 1.3  2003/01/15 14:04:30  josh * directory structure shifting * * Revision 1.2  2001/11/08 15:56:20  tneale * Updated for newest file layout * * Revision 1.1.1.1  2001/11/05 17:48:41  tneale * Tornado shuffle * * Revision 2.14  2001/01/19 22:23:38  paul * Update copyright. * * Revision 2.13  2000/10/16 19:21:49  paul * Restore sockets and mempool code. * * Revision 2.12  2000/03/17 00:12:36  meister * Update copyright message * * Revision 2.11  2000/03/13 21:22:01  paul * Removed some code that we are no longer working on. * * Revision 2.10  1999/02/18 04:41:32  wes * Sockets merge: Everything Else *  - memory pools *  - thread support *  - port-specific headers * * Revision 2.9.12.1  1998/09/23 19:17:15  wes * Merge socket-branch-1 changes to socket-branch-2 * * Revision 2.9.10.1  1998/08/19 13:26:22  wes * Merge sockets-pthreads work to shared branch * * Revision 2.9.4.1  1998/08/05 20:48:47  wes * XXX: Deal with mit-pthreads header file dane brammage * * Revision 2.9  1998/04/09 22:03:08  wes * Rip out ntohl/ntohs stuff since anyone still running NetBSD 0.8 gets what they deserve... * * Revision 2.8  1998/02/25 04:57:20  sra * Update copyrights. * * Revision 2.7  1998/02/17 18:28:53  sra * Add filter support for IPv4 multicast. * * Revision 2.6  1997/06/03 05:12:30  sra * Tighter BPF filter (souvenir of N+I Vegas '97). * * Revision 2.5  1997/04/25 01:02:25  sra * Fix code to set explicit MAC addresses for BPF, allow non-promiscuous mode. * * Revision 2.4  1997/03/20 06:52:51  sra * DFARS-safe copyright text.  Zap! * * Revision 2.3  1997/02/25 10:58:16  sra * Update copyright notice, dust under the bed. * * Revision 2.2  1996/03/22 10:05:39  sra * Update copyrights prior to Attache 3.2 release. * * Revision 2.1  1995/06/22  05:29:06  sra * Preliminary changes for multicast and OSPF. * * Revision 2.0  1995/05/10  22:38:15  sra * Attache release 3.0. * * Revision 1.4  1995/01/06  00:52:48  sra * Update copyright notice for 2.1 release. * * Revision 1.3  1994/09/02  21:15:48  sra * Add still more parentheses to the for() loop from hell in bpf_find(). * * Revision 1.2  1993/07/29  04:30:26  sra * Don't use the inline versions of the byteswap routines, GCC gets * confused. * * Revision 1.1  1993/07/05  21:53:30  sra * Initial revision * *//* [clearcase]modification history-------------------01a,19apr05,job  update copyright notices*//* * BPF interface to ethernet for attache testing under 386BSD/NetBSD/FreeBSD. * * All access to BPF 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. * * References: BPF sample RARP server *	       tcpdump { bpf_image.c, bpf_dump.c, pcap-bpf.c } *	       bpf(4) manual page *	       netintro(4) manual page *	       routed.c */#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <stdlib.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 <net/bpf.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.h>#include <netinet/in.h>#include <wrn/wm/common/install.h>/* * Stuff dealing with the BPF filter itself. */#ifndef INSTALL_SNARK_BSD_BPF_LOOSE_FILTER#define INSTALL_SNARK_BSD_BPF_LOOSE_FILTER 0#endif#ifndef INSTALL_SNARK_BSD_BPF_NO_V4_MULTICAST#define INSTALL_SNARK_BSD_BPF_NO_V4_MULTICAST 0#endif#if INSTALL_SNARK_BSD_BPF_LOOSE_FILTER/* * Filter expression (see tcpdump(1) man page for translation): * '-s 1500 ether multicast or ether dst e1:e2:e3:e4:e5:e6' */static struct bpf_insn instructions[] = {  { 0x30, 0, 0, 0x00000000 },	/* (000) ldb [0] */  { 0x45, 4, 0, 0x00000001 },	/* (001) jset #0x1 jt 6 jf 2 */  { 0x20, 0, 0, 0x00000002 },	/* (002) ld [2] */  { 0x15, 0, 3, 0xe3e4e5e6 },	/* (003) jeq #0xe3e4e5e6 jt 4 jf 7 */  { 0x28, 0, 0, 0x00000000 },	/* (004) ldh [0] */  { 0x15, 0, 1, 0x0000e1e2 },	/* (005) jeq #0xe1e2 jt 6 jf 7 */  { 0x6, 0, 0, 0x000005dc },	/* (006) ret #1500 */  { 0x6, 0, 0, 0x00000000 },	/* (007) ret #0 */};#else /* INSTALL_SNARK_BSD_BPF_LOOSE_FILTER */#if INSTALL_SNARK_BSD_BPF_NO_V4_MULTICAST/* * Filter expression (see tcpdump(1) man page for translation): * '-s 1514 ether[0:2] = 0x3333 or ether broadcast or ether dst e1:e2:e3:d4:e5:e6' */static struct bpf_insn instructions[] = {  { 0x28, 0, 0, 0x00000000 },	/* (000) ldh [0] */  { 0x15, 7, 0, 0x00003333 },	/* (001) jeq #0x3333 jt 9 jf 2 */  { 0x20, 0, 0, 0x00000002 },	/* (002) ld [2] */  { 0x15, 0, 2, 0xffffffff },	/* (003) jeq #0xffffffff jt 4 jf 6 */  { 0x28, 0, 0, 0x00000000 },	/* (004) ldh [0] */  { 0x15, 3, 4, 0x0000ffff },	/* (005) jeq #0xffff jt 9 jf 10 */  { 0x15, 0, 3, 0xe3d4e5e6 },	/* (006) jeq #0xe3d4e5e6 jt 7 jf 10 */  { 0x28, 0, 0, 0x00000000 },	/* (007) ldh [0] */  { 0x15, 0, 1, 0x0000e1e2 },	/* (008) jeq #0xe1e2 jt 9 jf 10 */  { 0x6, 0, 0, 0x000005ea },	/* (009) ret #1514 */  { 0x6, 0, 0, 0x00000000 },	/* (010) ret #0 */};#else /* INSTALL_SNARK_BSD_BPF_NO_V4_MULTICAST *//* * Filter expression (see tcpdump(1) man page for translation): * '-s 1514 ether[0:2] = 0x3333 or ( ether[0:2] = 0x0100 and ether[2:1] = 0x5e ) or ether broadcast or ether dst e1:e2:e3:d4:e5:e6' */static struct bpf_insn instructions[] = {  { 0x28, 0, 0, 0x00000000 },	/* (000) ldh [0] */  { 0x15, 10, 0, 0x00003333 },	/* (001) jeq #0x3333 jt 12 jf 2 */  { 0x15, 0, 2, 0x00000100 },	/* (002) jeq #0x100 jt 3 jf 5 */  { 0x30, 0, 0, 0x00000002 },	/* (003) ldb [2] */  { 0x15, 7, 0, 0x0000005e },	/* (004) jeq #0x5e jt 12 jf 5 */  { 0x20, 0, 0, 0x00000002 },	/* (005) ld [2] */  { 0x15, 0, 2, 0xffffffff },	/* (006) jeq #0xffffffff jt 7 jf 9 */  { 0x28, 0, 0, 0x00000000 },	/* (007) ldh [0] */  { 0x15, 3, 4, 0x0000ffff },	/* (008) jeq #0xffff jt 12 jf 13 */  { 0x15, 0, 3, 0xe3d4e5e6 },	/* (009) jeq #0xe3d4e5e6 jt 10 jf 13 */  { 0x28, 0, 0, 0x00000000 },	/* (010) ldh [0] */  { 0x15, 0, 1, 0x0000e1e2 },	/* (011) jeq #0xe1e2 jt 12 jf 13 */  { 0x6, 0, 0, 0x000005ea },	/* (012) ret #1514 */  { 0x6, 0, 0, 0x00000000 },	/* (013) ret #0 */};#endif /* INSTALL_SNARK_BSD_BPF_NO_V4_MULTICAST */#endif /* INSTALL_SNARK_BSD_BPF_LOOSE_FILTER */struct bpf_program filter = {  sizeof(instructions) / sizeof(*instructions),  instructions};/* * Macros to set filter componants at runtime.  These macros should * be the only code that knows anything about the guts of the filter. * * SET_FILTER_MAC sets the filter's MAC addr (in case the board is * in promiscuous mode) to the value of the six-byte string given * as an argument.  Presumably this is from the sockaddr sa_data field * or an explict argument given to bpf_open(). * * SET_FILTER_MTU sets the filter MTU for inbound packets; this is really * the truncation length for the kernel, but since it should match the * buffer size you're using it's effectively the same thing. */#if INSTALL_SNARK_BSD_BPF_LOOSE_FILTER#define	SET_FILTER_MAC(_x_) \  do { \    instructions[5].k = ntohs(*(u_short *) ((_x_)+0)); \    instructions[3].k = ntohl(*(u_long  *) ((_x_)+2)); \  } while (0)#define	SET_FILTER_MTU(_x_) \  do { \    instructions[6].k = (_x_); \  } while (0)#else /* INSTALL_SNARK_BSD_BPF_LOOSE_FILTER */#if INSTALL_SNARK_BSD_BPF_NO_V4_MULTICAST#define	SET_FILTER_MAC(_x_) \  do { \    instructions[8].k = ntohs(*(u_short *) ((_x_)+0)); \    instructions[6].k = ntohl(*(u_long  *) ((_x_)+2)); \  } while (0)#define	SET_FILTER_MTU(_x_) \  do { \    instructions[9].k = (_x_); \  } while (0)#else /* INSTALL_SNARK_BSD_BPF_NO_V4_MULTICAST */#define	SET_FILTER_MAC(_x_) \  do { \    instructions[11].k = ntohs(*(u_short *) ((_x_)+0)); \    instructions[ 9].k = ntohl(*(u_long  *) ((_x_)+2)); \  } while (0)#define	SET_FILTER_MTU(_x_) \  do { \    instructions[12].k = (_x_); \  } while (0)#endif /* INSTALL_SNARK_BSD_BPF_NO_V4_MULTICAST */#endif /* INSTALL_SNARK_BSD_BPF_LOOSE_FILTER *//* * Macro for calculating the size of buffer to tell BPF to use, based * on the MTU of the interface.  This would be the BPF header size * plus the MTU, except that BPF does some rounding for alignment. The * intent is that the size of buffer we use be just big enough that * BPF will never truncate a packet that we know how to handle. */#define	ROUNDED_BPF_MTU(_x_) \  (BPF_WORDALIGN((_x_)) + BPF_WORDALIGN(sizeof(struct bpf_hdr)))/* * Open a BPF file and attach it to the interface named 'device'. * Returns BPF file descriptor, or -1 if an error occurs. * * This is cobbled together from code in rarpd and tcpdump. */int bpf_open(char *ifname, unsigned mtu, unsigned char *mac, int promiscuous){  struct bpf_version bv;  struct ifreq ifr;  int fd, i;  u_int u;  /*   * Look for a BPF device that's not in use.   */  i = 0;  do {    char bpfname[sizeof "/dev/bpf000"];    (void) sprintf(bpfname, "/dev/bpf%d", i++);    fd = open(bpfname, O_RDWR);  } while (fd < 0 && errno == EBUSY);  if (fd < 0) {    perror("couldn't get a BPF device");    return -1;  }  /*   * Check the filter language version number.   */  if (ioctl(fd, BIOCVERSION, (char *) &bv) < 0) {    fprintf(stderr, "kernel BPF interpreter out of date");    return -1;  } else if (bv.bv_major != BPF_MAJOR_VERSION ||	     bv.bv_minor < BPF_MINOR_VERSION) {    fprintf(stderr, "requires BPF language %d.%d or higher; kernel is %d.%d",	    BPF_MAJOR_VERSION, BPF_MINOR_VERSION, bv.bv_major, bv.bv_minor);    return -1;  }  /*   * Set immediate mode so packets are processed as they arrive.   */  i = 1;  if (ioctl(fd, BIOCIMMEDIATE, (char *) &i) < 0) {    perror("BIOCIMMEDIATE");    return -1;  }  /*   * Set the read() buffer size.   */  u = ROUNDED_BPF_MTU(mtu);  if (ioctl(fd, BIOCSBLEN, (char *) &u) < 0) {    perror("BIOCSBLEN");    return -1;  }  /*   * Attach the BPF device to the interface.   */  (void) strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));  if (ioctl(fd, BIOCSETIF, (char *) &ifr) < 0) {    perror("BIOCSETIF");    return -1;  }  /*   * Check that the data link layer is an Ethernet; this code won't   * work with anything else.   */  if (ioctl(fd, BIOCGDLT, (char *) &u) < 0) {    perror("BIOCGDLT");    return -1;  }  if (u != DLT_EN10MB) {    fprintf(stderr, "%s is not an ethernet", ifname);    return -1;  }  /*   * Put the interface in promiscuous mode so we'll see packets   * to our faked MAC address.   */  if (promiscuous && ioctl(fd, BIOCPROMISC, 0) < 0) {    perror("BIOCPROMISC");    return -1;  }  /*   * If we were given a MAC address, use it to set up a filter.   * Otherwise, assume we're happy being in promiscuous mode.   */  if (mac) {    SET_FILTER_MAC(mac);    SET_FILTER_MTU(mtu);    if (ioctl(fd, BIOCSETF, (char *) &filter) < 0) {      perror("BIOCSETF");      return -1;    }  }  return fd;}/* * Read a BPF buffer and hand its contents off to Attache as packets. * This is based on the readloop() function in tcpdump's BPF code. * * 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. */#define bhp ((struct bpf_hdr *) bp)#if defined(__NetBSD__) && defined(INSTALL_SNARK_THREADS)/* mit_pthreads has broken stdlib.h !!! */#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)#if defined(alloca) && (alloca == __builtin_alloca) && (__GNUC__ < 2)void	*alloca __P((int));     /* built-in for gcc */ #else void	*alloca __P((size_t)); #endif /* __GNUC__ */ #endif#endifint bpf_read  (int fd,   unsigned mtu,   void (*handler)(unsigned char *, unsigned, unsigned, void *),   void *cookie){  unsigned char *buf, *bp, *ep;  int i;  mtu = ROUNDED_BPF_MTU(mtu);  if ((buf = (unsigned char *) alloca(mtu)) == 0) {    fprintf(stderr, "alloca(%d) failed\n", mtu);    return -1;  }  /*   * Try to read a packet, restart if we get screwed by the debugger.   * Return on other error or on EOF.   */  do {    i = read(fd, buf, mtu);  } while (i < 0 && errno == EINTR);  if (i <= 0)    return i;  /*   * Got a buffer full of data, chop it into packets and hand it off.   */  bp = buf;  ep = bp + i;  for (i = 0; bp < ep; ++i) {    handler(bp + bhp->bh_hdrlen, bhp->bh_caplen, bhp->bh_datalen, cookie);    bp += BPF_WORDALIGN(bhp->bh_caplen + bhp->bh_hdrlen);  }  /*   * Return the number of packets we got.   */  return i;}#undef bhp/* * Write a packet to the BPF file.  Per BPF manual page, we can only * write one packet at a time.  This shouldn't be a problem. */int bpf_write(int fd, unsigned char *data, unsigned datalen){  return write(fd, data, datalen);}/* * Close a BPF interface. */void bpf_close(int fd){  (void) close(fd);}#if defined(SIOCGIFCONF)/* * Find all ethernet interfaces.  Works on NetBSD, your milage may vary. * The "array" returned by SIOCGIFCONF is kinda bizzare.... */void bpf_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;  }  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 = ((struct ifreq *)	      (((char *) ifr) + sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)))    if (ifr->ifr_addr.sa_family == AF_LINK &&	((struct sockaddr_dl *) &ifr->ifr_addr)->sdl_type == IFT_ETHER)      handler(ifr->ifr_name, cookie);  (void) close(s);}#endif /* defined(SIOCGIFCONF) */

⌨️ 快捷键说明

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