📄 ethersim.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * *//* * ethersim.c -- * * Simuation of a local ethernet with a gateway interface. * This program simulates a local ethernet with a gateway machine * attached to it. The simulated ethernet accepts ethernet packets * that arrive on the special UDP port. It is assumed that these * packets are send by the network module of simos services running * on top of Unix. This program decodes the ethernet header and * uses it to determine which UDP port to output the packet on. * This is done by keeping track of the ethernet address of the machine * sending packets to the ethernet port. * * When this program receives an ethernet packet of type IP to an IP * destination address outside the subnet of the local ethernet, it * outputs the packet to the local (phsyical) ethernet attached to * the machine. By doing this the program acts like a gateway machine. * * The program also opens the network interface of the machines and * grabs any packets with an IP destination of the simulated subnet. * This is done using Sun's NIT protocol and packet filter. Packets * addressed to a known simulated host will be forward on to that * host's UDP port. * * NOTES: * 1) Because this program uses NIT to get packets from the outside * packets arriving at network interfaces other than the one * specified are not seen. In particular, packets sent thru * the loopback (lo0) interface are not seen by this program. * This means that processes on the local machine can't talk IP * to the simulated machines. * 2) This program is a big security hole because it accepts packets * from an non-privledged UDP port and forwards them on to the * local ethernet. I think that outputPacket() does enough * checking to stop this from being a problem. * */#include <sys/types.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/file.h>#include <sys/wait.h>#include <sys/time.h>#include <net/if.h>#include <net/nit_if.h>#include <net/nit_pf.h>#include <net/nit_buf.h>#include <net/packetfilt.h>#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#include <arpa/inet.h>#include <stdio.h>#include <signal.h>#include <pwd.h>#include <setjmp.h>#include <netdb.h>#include <errno.h>#include <strings.h>#include <varargs.h>#include <stropts.h>#include <poll.h>#include <search.h>#include <memory.h>#include <stdlib.h>#include <unistd.h>#include "hash.h"#include "ethersim.h"#ifdef MACH_NRP#include <netinet/udp.h>#include "nd.h"#endif/* * Program options setable from the command line. */u_long subnetaddr = 0xab404fe0; /* Subnet address (i.e. 171.64.79.224). */int simportnumber = ETHER_SIM_PORT; /* UDP port of simulated ethernet. */int noipforwarding = 0; /* Boolean - Don't forward ip packet. */char interfacename[32] = "le0"; /* Name of interface to forward IP * packets on. */int verbose = 0; /* verbose: tell user about pkts */u_long routeraddr = (u_long)-1;/* * Buffer to hold the current packet being transmitted on the ethernet. * This must be big enought to hold an ethernet MTU and its header. We * add 128 bytes for good measure. */char curPacket[ETHERMTU + sizeof(struct ether_header) + 128];int simfd; /* Open file descriptor of simulated ethernet port. */int netfd; /* Open file descriptor of network interface tap. */#ifdef MACH_NRPint nrpfd = -1; /* Open file descriptor of socket or NRP server. */char *nrphost = "localhost"; /* Host with NRP server. */struct sockaddr_in nrpaddr;int nrpaddrlen;struct ether_addr my_simetheraddr; /* My simulated ether addr. */struct in_addr my_simipaddr; /* My simulated ip addr. */#endif /* * The ethernet address and IP network address of the interface being used. */struct ether_addr myetheraddr;u_long mynetaddr;/* * The internet address and netmask of the interface being used. */u_long myinetAddr;u_long mynetmask;/* * HostInfoRecord - Info kept per simulated host. */typedef struct HostInfoRecord { struct ether_addr etheraddr;/* Ethernet address of host. */ u_long inetAddr; /* Internet address of host. */ struct sockaddr fromaddr; /* Socket the of the simulated machines * ethernet interface. */ int fromlen; /* Length in bytes of fromaddr. */} HostInfoRecord;/* * Hash tables that map * etheraddrTable - Ethernet addresses to HostInfoRecord. * ipaddrTable - IP addresses to HostInfoRecord. */Hash_Table etheraddrTable;Hash_Table ipaddrTable;/* * Stupid SunOS header missing stuff. */ /* Options stuff. */extern char *optarg;extern int optind;extern int getopt _ARGS_((int argc, char **argv, char *optstring));extern int fprintf (); /* fprintf and fscanf are varags so no prototype. */extern int fscanf ();extern int fgetc _ARGS_((FILE *stream));extern void perror _ARGS_((char *msg));extern int pclose _ARGS_((FILE *stream));extern int ioctl _ARGS_((int fd, int request, caddr_t arg));extern int socket _ARGS_((int domain, int type, int protocol));extern int bind _ARGS_((int s, struct sockaddr *name, int namelen));extern int recvfrom _ARGS_((int s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen));extern int sendto _ARGS_((int s, char *msg, int len, int flags, struct sockaddr *to, int tolen));extern u_long inet_netof _ARGS_((struct in_addr in));extern void bzero _ARGS_((void *b, int length));extern void bcopy _ARGS_((void *a, void *b, int length));extern int poll _ARGS_((struct pollfd *fds, unsigned long nfds, int timeout));extern int putmsg _ARGS_((int fd, struct strbuf *ctlptr, struct strbuf *dataptr, int flags));extern long strtol _ARGS_((char *str, char **ptr, int base));/* * offsetof() return the offset of a field into the structure. */#ifndef offsetof#define offsetof(_t, _f) ((int) &(((_t *) 0)->_f))#endif#define NIT_DEV "/dev/nit"/* * Forward routine declartions. */int serviceSimPort _ARGS_((void));int serviceNetPort _ARGS_((void));#ifdef MACH_NRPint serviceNrpPort _ARGS_((void));int IsMachNRPPacket _ARGS_((struct ether_header *hdrPtr,int size));#endifint initNITdevice _ARGS_((char *device, u_long subNetAddr, u_long netmask));int outputPacket _ARGS_((char *packet, int size));int lookupInterface _ARGS_((char *interfacename, u_long *inetAddrPtr, u_long *netmaskPtr));int validPacket _ARGS_((char *packet, int size, struct sockaddr *fromAddr, int fromlen));#ifdef MACH_NRP/* Forwards */#endif/* *---------------------------------------------------------------------- * * main -- * * Main routine and loop for ethersim. * * Results: * Only returns if an error occurs. * * Side effects: * *---------------------------------------------------------------------- */intmain(argc, argv)int argc;char *argv[];{ int c, errflg; struct sockaddr_in addr; int nfds; struct pollfd fds[3]; int (*serviceRoutine[3])(); simfd = netfd = -1; errflg = 0;#ifdef MACH_NRP#define OPTS "vfg:p:n:s:r:"#else#define OPTS "vfg:p:n:r:"#endif while ((c = getopt(argc, argv, OPTS)) != -1) { switch (c) { case 'v': verbose = 1; break; case 'f': noipforwarding = 1; break; case 'i': strncpy(interfacename, optarg, sizeof(optarg)-1); break; case 'g': subnetaddr = inet_network(optarg); if (subnetaddr == (u_long) -1) { fprintf(stderr, "%s: Malformed gateway address %s\n", argv[0], optarg); errflg++; } break; case 'r': routeraddr = inet_network(optarg); if (routeraddr == (u_long) -1) { fprintf(stderr, "%s: Malformed router address %s\n", argv[0], optarg); errflg++; } break; case 'p': simportnumber = atoi(optarg); if (simportnumber < 0) { fprintf(stderr, "%s: Illegal port number %s\n", argv[0], optarg); errflg++; } break;#ifdef MACH_NRP case 's': nrphost = optarg; break;#endif case '?': errflg++; } } if (errflg) {#ifdef MACH_NRP (void)fprintf(stderr, "usage: %s [-v] [-g netaddr] [-p portnumber] [-n netmask] [-s nrphost]\n", argv[0]);#else (void)fprintf(stderr, "usage: %s [-v] [-g netaddr] [-p portnumber] [-n netmask]\n", argv[0]);#endif exit (2); } /* * Create the socket that transmits on the simulated ethernet will be * sent. It is a UDP port number ETHER_SIM_PORT. The mostly likely * cause of failure is another ethersim running causing the bind * to fail with address in use. */ simfd = socket(AF_INET, SOCK_DGRAM, 0); if (simfd < 0) { perror("main: socket"); exit(1); } bzero((char *)&addr, sizeof(addr)); addr.sin_port = htons(simportnumber); addr.sin_family = AF_INET; if (bind(simfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("main: bind"); exit(2); }#ifdef MACH_NRP /* * Create the socket the commonicates with the nrp server. */ nrpfd = socket(AF_INET, SOCK_DGRAM, 0); if (nrpfd < 0) { perror("main: nrp socket"); exit(1); } bzero((char *)&addr, sizeof(addr)); addr.sin_family = AF_INET; if (bind(nrpfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { perror("main: nrp bind"); exit(2); } { struct hostent *host; host = gethostbyname(nrphost); if (!host) { perror(nrphost); exit(2); } nrpaddr.sin_family = host->h_addrtype; bcopy(host->h_addr, &nrpaddr.sin_addr, host->h_length); nrpaddr.sin_port = htons(IPPORT_NDREQUEST); nrpaddrlen = sizeof(nrpaddr); } bcopy("ETHERS", &my_simetheraddr, 6); my_simipaddr.s_addr = htonl(subnetaddr | 0xFEFE);#endif /* MACH_NRP */ if (!noipforwarding && (geteuid() != 0)) { fprintf(stderr, "%s: not running as root - IP forwarding disabled\n", argv[0]); noipforwarding = 1; } if (!noipforwarding) { if (lookupInterface(interfacename, &myinetAddr, &mynetmask) < 0) { fprintf(stderr, "Couldn't find interface %s\n", interfacename); exit(3); } { struct in_addr tmp; tmp.s_addr = myinetAddr; mynetaddr = inet_netof(tmp); } netfd = initNITdevice(interfacename, subnetaddr, mynetmask); if (netfd < 0) { fprintf(stderr, "Couldn't initialize network tap\n"); exit(3); } } /* * Initialize mapping hash tables. */ Hash_InitTable(ðeraddrTable, 0, 2); Hash_InitTable(&ipaddrTable, 0, HASH_ONE_WORD_KEYS); /* * Loop waiting for packets to arrive. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -