nit.c

来自「wm PNE 3.3 source code, running at more 」· C语言 代码 · 共 374 行

C
374
字号
/* $Header: /usr/cvsroot/target/src/wrn/wm/demo/lib/nit.c,v 1.2 2001/11/08 15:56:23 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 1994-1997 Epilogue Technology Corporation. *  Copyright 1998 Integrated Systems, Inc. *  All rights reserved. ****************************************************************************//* * $Log: nit.c,v $ * Revision 1.2  2001/11/08 15:56:23  tneale * Updated for newest file layout * * Revision 1.1.1.1  2001/11/05 17:48:42  tneale * Tornado shuffle * * Revision 2.10  2001/01/19 22:23:46  paul * Update copyright. * * Revision 2.9  2000/03/17 00:12:40  meister * Update copyright message * * Revision 2.8  1998/07/31 19:45:45  wes * Put packet filtering into NIT driver... * * Revision 2.7  1998/02/25 04:57:27  sra * Update copyrights. * * Revision 2.6  1997/11/21 00:06:24  josh * updating files for Liaison support for NIT * * Revision 2.5  1997/05/17 23:08:55  sra * Clean up some SunOS/gcc warnings. * * Revision 2.4  1997/05/02 02:45:49  sra * Support NIT in promiscuous mode, for IPv6 multicast. * * Revision 2.3  1997/03/20 06:52:59  sra * DFARS-safe copyright text.  Zap! * * Revision 2.2  1997/02/25 10:58:16  sra * Update copyright notice, dust under the bed. * * Revision 2.1  1996/03/22 10:05:39  sra * Update copyrights prior to Attache 3.2 release. * * Revision 2.0  1995/05/10  22:38:15  sra * Attache release 3.0. * * Revision 1.2  1995/01/06  00:52:48  sra * Update copyright notice for 2.1 release. * * Revision 1.1  1994/01/09  23:57:29  sra * Add support for NIT under SunOS 4.1.2. * *//* [clearcase]modification history-------------------01a,19apr05,job  update copyright notices*//* * NIT interface to ethernet for Attache testing under SunOS 4.1.2. * * All access to NIT 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: NIT manual pages *	       tcpdump source *	       CAP ethertalk source *	       netintro(4) manual page *	       NET-2 routed source */#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/if.h>#include <net/nit.h>#include <net/nit_if.h>#include <net/nit_pf.h>#include <net/nit_buf.h>#include <net/packetfilt.h>#include <stropts.h>#include <netinet/in.h>#include <netinet/if_ether.h>#define __(x) x#include <wrn/wm/demo/nit.h>#ifdef __GNUC__#define	alloca	__builtin_alloca#endif/* 1997 and they still can't prototype the system functions. */extern int ioctl(), putmsg(), socket();/* * Open a NIT file and attach it to the interface named 'device'. * Returns NIT 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. */int nit_open(char *ifname, unsigned mtu, unsigned char *mac){  struct strioctl si;  struct ifreq ifr;  int fd;  int promiscuous = 1;    /*   * Look for cloned NIT device.   */  if ((fd = open("/dev/nit", O_RDWR)) < 0) {    perror("couldn't clone NIT device");    return -1;  }  /*   * Enable discrete messages.   */  if (ioctl(fd, I_SRDOPT, (char *) RMSGD) < 0) {    perror("couldn't enable discrete NIT messages");    return -1;  }  /*   * Attach the NIT device to the interface.   */  (void) strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));  si.ic_cmd = NIOCBIND;  si.ic_timout = INFTIM;  si.ic_len = sizeof(ifr);  si.ic_dp = (char *) &ifr;  if (ioctl(fd, I_STR, (char *) &si) < 0) {    perror("couldn't bind NIT to interface");    return -1;  }  /*   * Turn on promiscuous mode for multicast, etc.   * Only root can do this, so just continue if this fails.   */  {    unsigned long flags = NI_PROMISC;    si.ic_cmd = NIOCSFLAGS;    si.ic_len = sizeof(flags);    si.ic_dp = (char *) &flags;    if (ioctl(fd, I_STR, (char *) &si) < 0) {      perror("Couldn't set promiscuous mode, continuing");      promiscuous = 0;    }  }  /*   * Flush the read queue, don't worry about it if we can't.   */  (void) ioctl(fd, I_FLUSH, (char *) FLUSHR);  /*   * Get local MAC address for Attache to use, if we were given one   */  if (mac && !promiscuous) {    if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {      perror("couldn't get local MAC address");    } else {      memcpy(mac, ((struct sockaddr *) &ifr.ifr_data)->sa_data, 6);    }  }  /*   * Push packet filter module.   */  if (ioctl(fd, I_PUSH, "pf") < 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];    si.ic_cmd = NIOCSETF;    si.ic_timout = -1;    si.ic_len = sizeof(pfil);    si.ic_dp = (void *)&pfil;    if (ioctl(fd, I_STR, &si) < 0) {      perror("couldn't set packet filter, continuing..");    }  }  /*   * Don't bother with buffering or truncation for now.   */  /*   * Flush the read queue, don't worry about it if we can't.   */  (void) ioctl(fd, I_FLUSH, (char *) FLUSHR);  return fd;}/* * Read a NIT 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 nit(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 nit_read  (int fd,   unsigned mtu,   void (*handler)(unsigned char *, unsigned, unsigned, void *),   void *cookie){  unsigned char *buf;  int i;  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;    /*   * 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 NIT stream. */int nit_write(int fd, unsigned char *data, unsigned datalen){  struct strbuf pbuf, dbuf;  struct sockaddr sa;  sa.sa_family = AF_UNSPEC;  memcpy(sa.sa_data, data, sizeof(struct ether_header));  pbuf.len = sizeof(sa);  pbuf.buf = (char *) &sa;  dbuf.len = datalen - sizeof(struct ether_header);  dbuf.buf = (char *) data + sizeof(struct ether_header);  return putmsg(fd, &pbuf, &dbuf, 0) < 0 ? -1 : datalen;}/* * Close a NIT interface. */void nit_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 nit_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)    handler(ifr->ifr_name, cookie);  (void) close(s);}#endif /* defined(SIOCGIFCONF) */

⌨️ 快捷键说明

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