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 *) 𝔦 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 + -
显示快捷键?