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

📄 ethersim.c

📁 一个用在mips体系结构中的操作系统
💻 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 gateway could be running on two kinds of machines: mips and *       sparc. On SGI's mips machine, the program uses SNOOP protocol, *       while  *	 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 "ethersim.h"/* * Program options setable from the command line. */u_long subnetaddr = 0x24840000; 	/* Subnet address (i.e. 36.132.0.0). */int    simportnumber = ETHER_SIM_PORT;  /* UDP port of simulated ethernet. */int    noipforwarding = 0;		/* Boolean - Don't forward ip packet. */char   interfacename[32] = "et0";	/* Name of interface to forward IP */u_long   routeraddr = (u_long)-1;#ifdef SIM_PROXY#define MAX_ADDRS 16u_long nproxys = 0;u_long proxyaddr[MAX_ADDRS];#endifextern int arpverbose;int  verbose = 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. *//* * The ethernet address and IP network address of the interface being used. */u_char myetheraddr[6];u_long mynetaddr;/* * The internet address and netmask of the interface being used. */u_long myinetAddr;u_long mynetmask;/* * Hash tables that map  *	etheraddrTable - Ethernet addresses to HostInfoRecord. *	ipaddrTable    - IP addresses to HostInfoRecord.  */Hash_Table etheraddrTable;Hash_Table ipaddrTable;/* *---------------------------------------------------------------------- * * main --  * *       Main routine and loop for ethersim. * * Results: *      Only returns if an error occurs. * * Side effects: * *---------------------------------------------------------------------- */intmain(int argc, char *argv[]){    int	c, errflg;    struct sockaddr_in addr;    int	   nfds;    struct pollfd  fds[3];    int	   (*serviceRoutine[3])(void);    simfd = netfd = -1;    errflg = 0;#ifdef SIM_PROXY#define OPTS "fg:p:n:r:x:i:v"#else#define OPTS "fg:p:n:r:i:v"#endif    while ((c = getopt(argc, argv,  OPTS)) != -1) {       switch (c) {	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;#ifdef SIM_PROXY	   case 'x':	     proxyaddr[nproxys] = inet_network(optarg);	     if (proxyaddr[nproxys] == (u_long) -1) {		 fprintf(stderr, "%s: Malformed proxy address %s\n", argv[0],					optarg);		 errflg++;	     }	     nproxys++;	     break;#endif	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;        case 'v':            verbose = 1;	    arpverbose = 1;            break;	case '?':	     errflg++;	}    }    if (errflg) {	(void)fprintf(stderr, 		"usage: %s [-g netaddr] [-p portnumber] [-n netmask]\n", 				argv[0]);	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);    }    simportnumber = ETHER_SIM_PORT;    bzero((char *)&addr, sizeof(addr));    addr.sin_port = htons(simportnumber);    addr.sin_addr.s_addr = htonl(INADDR_ANY);    addr.sin_family = AF_INET;    if (bind(simfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {        perror("main: bind");        exit(2);    }    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);	}		if(verbose) {	    printf("Address:0x%x, Netmask:0x%x\n", myinetAddr,mynetmask);	}#ifdef SIM_PROXY	netfd = initSNPdevice(interfacename, proxyaddr, nproxys, 0xffffffff);#else	netfd = initSNPdevice(interfacename, subnetaddr, mynetmask);#endif	if (netfd < 0) {	    fprintf(stderr, "Couldn't initialize network tap\n");	    exit(3);	}    }     /*     * Initialize mapping hash tables.     */    Hash_InitTable(&etheraddrTable, 0, 2);    Hash_InitTable(&ipaddrTable, 0, HASH_ONE_WORD_KEYS);    /*     * Loop waiting for packets to arrive.     */    nfds = 0;    fds[nfds].fd = simfd;    fds[nfds].events = POLLIN;    serviceRoutine[nfds] = serviceSimPort;    nfds++;    if (netfd >= 0) {	fds[nfds].fd = netfd;	fds[nfds].events = POLLIN;    	serviceRoutine[nfds] = serviceNetPort;	nfds++;    }    while (1) {        int     n;	int	i;	fds[0].revents = fds[1].revents = fds[2].revents = 0;	n = poll(fds, nfds, -1);	if (n < 0) {	    if (errno == EINTR) continue;	    perror("poll");	    exit(1);	}	for (i = 0; i < nfds; i++) { 		if (fds[i].revents & POLLIN) {		    (void) serviceRoutine[i]();		}	}    }}voiddispEtherPacket(int n, struct ether_header* hdrPtr, int tab){    struct ip *ipPtr;    struct udphdr *udpPtr;    struct tcphdr *tcpPtr;    char *dataPtr;    struct in_addr ipdst, ipsrc;    char blankhead[40];    if (tab == 0)        sprintf(blankhead,"%s"," ");    else if (tab == 1)        sprintf(blankhead,"%s","\t\t");    else if (tab == 2)       sprintf(blankhead,"%s","\t\t\t\t");    printf("%s<S>%x:%x:%x:%x:%x:%x\n",blankhead,A(0),A(1),A(2),A(3),A(4),A(5));    printf("%s<D>%x:%x:%x:%x:%x:%x\n",blankhead,B(0),B(1),B(2),B(3),B(4),B(5));    if (htons(hdrPtr->ether_type) == ETHERTYPE_IP)       printf("%sether_type = IP\n",blankhead);    else if (htons(hdrPtr->ether_type)  == ETHERTYPE_ARP)#ifdef SIM_PROXY	{	    struct ether_arp *arpHdr;	    u_char *c;	    printf("%sether_type = ARP\n",blankhead);	    arpHdr = (struct ether_arp *) ((char*)hdrPtr + 					   sizeof(struct ether_header));	    c = arpHdr->arp_sha;	    printf("%s<SE>%x:%x:%x:%x:%x:%x\n", blankhead,		   c[0],c[1],c[2],c[3],c[4],c[5]);	    c = arpHdr->arp_spa;	    printf("%s<SIP>%d.%d.%d.%d\n", blankhead,		   c[0],c[1],c[2],c[3]);	    c = arpHdr->arp_tha;	    printf("%s<TE>%x:%x:%x:%x:%x:%x\n", blankhead,		   c[0],c[1],c[2],c[3],c[4],c[5]);	    c = arpHdr->arp_tpa;	    printf("%s<TIP>%d.%d.%d.%d\n", blankhead,		   c[0],c[1],c[2],c[3]);	    return;	}#else       printf("%sether_type = ARP\n",blankhead);#endif    else       printf("%sether_type = %u\n",blankhead,(hdrPtr->ether_type));    ipPtr = (struct ip *) ((char*)hdrPtr + sizeof(struct ether_header));    bcopy((u_char*)& ipPtr->ip_src, (u_char*)& ipsrc.s_addr ,sizeof(u_long));    bcopy((u_char*)& ipPtr->ip_dst, (u_char*)& ipdst.s_addr ,sizeof(u_long));    printf("%s<S>0x%x(%s)\n",blankhead,(ipsrc.s_addr),            inet_ntoa(ipsrc));    printf("%s<D>0x%x(%s)\n",blankhead,(ipdst.s_addr),            inet_ntoa(ipdst));    printf("%sip_len:%d\n",blankhead,(ipPtr->ip_len));    if ( htons(ipPtr->ip_p )== IPPROTO_TCP) {         printf("%sTCP:\n",blankhead);         tcpPtr = (struct tcphdr *) ((char*) ipPtr + sizeof(struct ip));         dataPtr = (char*) ((char*)tcpPtr + sizeof(struct tcphdr));    } else if (htons(ipPtr->ip_p )== IPPROTO_UDP) {         printf("%sUDP:\n",blankhead);         udpPtr = (struct udphdr*) ((char*) ipPtr + sizeof(struct ip));         dataPtr = (char*) ((char*)udpPtr + sizeof(struct udphdr));    } else  if (htons(ipPtr->ip_p) == IPPROTO_ICMP){         printf("%sICMP:\n",blankhead);    } else  if (htons(ipPtr->ip_p) == IPPROTO_IGMP){         printf("%sIGMP:\n",blankhead);    } else  if (htons(ipPtr->ip_p) == IPPROTO_GGP){         printf("%sGGP:\n",blankhead);    } else  if (htons(ipPtr->ip_p) == IPPROTO_RAW){         printf("%sRAW:\n",blankhead);    } else           printf("%sprotocol:%d\n",blankhead,htons(ipPtr->ip_p)); }/* *---------------------------------------------------------------------- * * validPacket --  * *       Check to see if we should accept this packet. * * Results: *      1 if packet ok. *      0 if we should request it. * * Side effects: * *---------------------------------------------------------------------- */intvalidPacket(    char *packet,	/* The contents of the packet. */    int	 size,		/* The size of the packet. */    struct sockaddr *fromAddr, /* Where the packet was from. */    int	  fromlen	       /* The length of fromAddr. */){    struct  ether_header  *hdrPtr;    struct  sockaddr_in   *inaddrPtr;    u_long  srcAddr;    hdrPtr = (struct ether_header *) packet;    if ((size < ETHERMIN + sizeof(struct ether_header)) ||         (size > ETHERMTU + sizeof(struct ether_header))) {	fprintf(stderr, "Bad packet size %d\n", size);	return 0;    }    /*      * XXX - Do security checking here.  Currently we reject all packets      * from hosts outside our network.  We only if we are forwarding     * packets.     */    if (!noipforwarding) { 	if ((fromAddr->sa_family != AF_INET) || 	    (fromlen < offsetof(struct sockaddr_in, sin_zero))) {	    fprintf(stderr, "Packet from bad fromaddr\n");	    return 0;	}	inaddrPtr = (struct sockaddr_in *) fromAddr;	srcAddr = inet_netof(inaddrPtr->sin_addr);	if ((srcAddr != mynetaddr) && (srcAddr != IN_LOOPBACKNET)) {	    fprintf(stderr, "Security violation: Packet from host %s\n",			    inet_ntoa(inaddrPtr->sin_addr));	    return 0;	}    }    return 1;}/* *---------------------------------------------------------------------- * * lookupInterface --  * *       Find the specified interface and read its address and netmask. *	 * * Results: *     0 if we found things, -1 otherwise. * * Side effects: * *---------------------------------------------------------------------- */intlookupInterface(char *interfacename, u_long *inetAddrPtr, u_long *netmaskPtr){    char cmdBuf[256];    char inetString[32], netmaskString[32];    int ch;    FILE *pfile;    /*      * We cheat and use ifconfig to lookup the info. This should probably     * be changed to do all kinds of nasty I/O controls to lookup the info.     */    sprintf(cmdBuf, "/usr/etc/ifconfig %s", interfacename);    pfile = popen(cmdBuf, "r");    if (pfile == (FILE *) NULL) {	fprintf(stderr, "Can't execute %s\n", cmdBuf);	return -1;    }    /*     * Skip the first line which should look something like:     * le0: flags=63<UP,BROADCAST,NOTRAILERS,RUNNING>     */    for (ch = fgetc(pfile); (ch != '\n') && (ch != EOF); ch = fgetc(pfile)) ;    if (fscanf(pfile, "\tinet %s netmask %s ", inetString, netmaskString) != 2){	(void) pclose(pfile);    }    *inetAddrPtr = inet_addr(inetString);    *netmaskPtr = strtoul(netmaskString, (char **)NULL, 16);    if (routeraddr == (u_long) -1) {	routeraddr = ((*inetAddrPtr) & (*netmaskPtr)) | 1; 		/* Default to host 1 on the network */    }    (void) pclose(pfile);    return 0;}unsigned long FindGateway(unsigned long dstaddr){	if ((dstaddr & mynetmask) == (myinetAddr & mynetmask)) 	   return dstaddr;	if ((dstaddr & mynetmask) == subnetaddr) 	   return -1;	return routeraddr;}	

⌨️ 快捷键说明

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