ethersim_netport.c 4.76 KB
/*
 * 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_netport.c --
 *
 * serviceNetPort -- 
 *
 *       Service a request that arrives at the network interface tap port.
 *
 * Results:
 *      -1 if problem occur with
 *
 * Side effects:
 *
 */
#include "ethersim.h"

#ifdef sgi
int
serviceNetPort(void)
{
    struct etherpacket ep;
    struct  ether_header  *hdrPtr;
    int	     n;
    u_long	inetAddr;
    Hash_Entry  *entryPtr;
    HostInfoRecord *hostInfoRecord;
    int xfersize;

    n  = read(netfd,(char *) &ep,sizeof(ep));

    if (n  < 0) {
	perror("read of serviceNetPort");
	return -1;
    }
    

    if ((n < ETHERMIN+sizeof(struct ether_header)+sizeof(struct snoopheader) + ETHERHDRPAD)
        || 
	(n > ETHERMTU+sizeof(struct ether_header)+sizeof(struct snoopheader) + ETHERHDRPAD)) {
	fprintf(stderr, "Ethernet: Bad packet size %d\n", n);
	return -1;
    }
    n -= sizeof(struct snoopheader) + ETHERHDRPAD;

    /*
     * Get rid of snoop header and pad to make the curPacket.
     */
    hdrPtr = (struct ether_header *) &(ep.ether);

    if (htons(hdrPtr->ether_type) != ETHERTYPE_IP) {
        fprintf(stderr,"ether_type != ip\n");
	return 0;
    }

    if (verbose) {
	printf("Packet received on ethernet:\n");
	dispEtherPacket(n, hdrPtr, 2);
    }
    bcopy((void *) (((char *) &(ep.data)) + offsetof(struct ip, ip_dst)),
		(void *) &inetAddr, sizeof(inetAddr));

    entryPtr = Hash_FindEntry(&ipaddrTable, (Address)inetAddr);
    if (entryPtr == NULL) {
        fprintf(stderr,"Dhost not in ipaddrTable\n");
	return 0;
    }
    hostInfoRecord = (HostInfoRecord *) Hash_GetValue(entryPtr);
    if (verbose) {
	printf(" Sending packet on UDP to 0x%x\n",
	       ((struct sockaddr_in *) &(hostInfoRecord->fromaddr))->sin_addr.s_addr);
    } 

    xfersize = sendto(simfd, (char *)&(ep.ether), n, 0x0, 
				(struct sockaddr *) &hostInfoRecord->fromaddr,
				hostInfoRecord->fromlen);

    if (xfersize < 0) {
	perror("sendto");
    }

    return 0;
}
#endif /* sgi */


#ifdef sparc
int
serviceNetPort()
{
    struct  ether_header  *hdrPtr;
    int	     n;
    u_long	inetAddr;
    Hash_Entry  *entryPtr;
    HostInfoRecord *hostInfoRecord;
    int xfersize;

    n = read(netfd, curPacket, sizeof(curPacket));
    if (n < 0) {
	perror("read of serviceNetPort");
	return -1;
    }
    if ((n < ETHERMIN + sizeof(struct ether_header)) || 
	(n > ETHERMTU + sizeof(struct ether_header))) {
	fprintf(stderr, "Bad packet size %d\n", n);
	return -1;
    }

    hdrPtr = (struct ether_header *) curPacket;

    if (htons(hdrPtr->ether_type) != ETHERTYPE_IP) {
	return 0;
    }

    bcopy(curPacket + sizeof(struct ether_header) + offsetof(struct ip, ip_dst),
		(char *) &inetAddr, sizeof(inetAddr));
    entryPtr = Hash_FindEntry(&ipaddrTable, (Address)inetAddr);
    if (entryPtr == NULL) {
	return 0;
    }
    hostInfoRecord = (HostInfoRecord *) Hash_GetValue(entryPtr);
    xfersize = sendto(simfd, curPacket, n, 0x0, 
				(struct sockaddr *) &hostInfoRecord->fromaddr,
				hostInfoRecord->fromlen);

    if (xfersize < 0) {
	perror("sendto");
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * validPacket -- 
 *
 *       Check to see if we should accept this packet.
 *
 * Results:
 *      1 if packet ok.
 *      0 if we should request it.
 *
 * Side effects:
 *
 *----------------------------------------------------------------------
 */

int
validPacket(packet, size, fromAddr, fromlen)
    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;
}

#endif /* sparc */