ethersim_output.c 5.05 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_output.c --
 *
 * outputPacket -- 
 *
 *
 * Results:
 *      None.
 *
 * Side effects:
 *
 */
#include "ethersim.h"
extern u_long proxyaddr;

#ifdef sgi
int
outputPacket (
    char *packet,  /* The contents of the packet. */
    int	 size      /* The size of the packet. */
)
{
    struct etherpacket  ep;
    struct ether_header	*hdrPtr;
    struct sockaddr protoheader;
    struct in_addr dstaddr,srcaddr;
    int cc;
    int i;

    /*
     * Fill in the correct ethernet address source. 
     */
    hdrPtr = (struct ether_header *) packet;

    for ( i = 0; i < 6; i++) 
        hdrPtr->ether_shost[i]  = myetheraddr[i];

    bcopy(packet + sizeof(struct ether_header) + offsetof(struct ip, ip_src),
	  (char *) &srcaddr, sizeof(srcaddr));
    bcopy(packet + sizeof(struct ether_header) + offsetof(struct ip, ip_dst),
	  (char *) &dstaddr, sizeof(dstaddr));

    /*
    printf("D<%s,0x%x,%x:%x:%x:%x:%x:%x>", 
        inet_ntoa(dstaddr),dstaddr.s_addr,A(0), A(1), A(2), A(3), A(4), A(5));
    printf("S<%s,0x%x,%x:%x:%x:%x:%x:%x>\n", 
        inet_ntoa(srcaddr),srcaddr.s_addr,B(0), B(1), B(2), B(3), B(4), B(5));
    */

    srcaddr = ntohl(srcaddr);
    dstaddr = ntohl(dstaddr);
    /*
     * Security: 
     *	1) Don't broadcast or send to all zeros.
     *  2) Must be of type IP.
     *  3) Must have a ip_src address on the simulated subnet.
     */

    if (((A(0) == 0xff) && (A(1) == 0xff) && (A(2) == 0xff) &&
	(A(3) == 0xff) && (A(4) == 0xff) && (A(5) == 0xff)) ||
        ((A(0) == 0) && (A(1) == 0) && (A(2) == 0) &&
	(A(3) == 0) && (A(4) == 0) && (A(5) == 0)) ||
	(htons(hdrPtr->ether_type) != ETHERTYPE_IP) ||
#ifdef SIM_PROXY
	(((srcaddr.s_addr & mynetmask) != subnetaddr ) &&
	    proxyaddr == 0)) {
#else
	((srcaddr.s_addr & mynetmask) != subnetaddr)) {
#endif
	fprintf(stderr, 
	    "outputPacket: Tossing packet sent to %x:%x:%x:%x:%x:%x\n",
		A(0), A(1), A(2), A(3), A(4), A(5));
	return 0;
    }

   /* 
    * Send the packet to the snoop device. 
    * Output on a snoop socket, using write or send, takes a buffer
    * address pointing at the link-layer packet to be transmitted.
    * Output buffers may need to begin with RAW_HDRPAD bytes of padding
    * to ensure addressability of structured data, but such padding is
    * not passed to write.
    */  
    if(verbose) {
	printf("outputPacket: sending to 0x%x (%x:%x:%x:%x:%x:%x)\n",
		dstaddr.s_addr, B(0), B(1), B(2), B(3), B(4), B(5));
    }	       
    if ( write(netfd,packet,size ) < size ) {
        perror("outputPacket:send");
        return 0;
    }
#ifdef notdef
    fprintf(stderr, "Not sending packet to %x:%x:%x:%x:%x:%x from %x:%x:%x:%x:%x:%x\n",
	    A(0), A(1), A(2), A(3), A(4), A(5), B(0), B(1), B(2), B(3), B(4), B(5));
#endif	

    return 0;
}
#endif /* sgi */


#ifdef sparc 
int
outputPacket(packet, size)
    char *packet;  /* The contents of the packet. */
    int	 size;     /* The size of the packet. */
{
    struct ether_header	*hdrPtr;
    struct sockaddr protoheader;
    struct strbuf ctlmsgbuf;
    struct strbuf datamsgbuf;
    u_long	dstaddr;

    /*
     * Fill in the correct ethernet address source. 
     */
    hdrPtr = (struct ether_header *) packet;
    hdrPtr->ether_shost = myetheraddr;

    bcopy(packet + sizeof(struct ether_header) + offsetof(struct ip, ip_src),
	  (char *) &dstaddr, sizeof(dstaddr));
    dstaddr = ntohl(dstaddr);

    /*
     * Security: 
     *	1) Don't broadcast or send to all zeros.
     *  2) Must be of type IP.
     *  3) Must have a ip_src address on the simulated subnet.
     */

    if (((A(0) == 0xff) && (A(1) == 0xff) && (A(2) == 0xff) &&
	(A(3) == 0xff) && (A(4) == 0xff) && (A(5) == 0xff)) ||
        ((A(0) == 0) && (A(1) == 0) && (A(2) == 0) &&
	(A(3) == 0) && (A(4) == 0) && (A(5) == 0)) ||
	(htons(hdrPtr->ether_type) != ETHERTYPE_IP) ||
	((dstaddr & mynetmask) != subnetaddr)) {

	fprintf(stderr, 
	    "outputPacket: Tossing packet sent to %x:%x:%x:%x:%x:%x\n",
		A(0), A(1), A(2), A(3), A(4), A(5));
	return 0;
    }

    /*
     * For some reason a write to a NIT device requires that the 
     * ethernet header be passed inside a sockaddr with a AF_UNSPEC
     * family and as a M_PROTO message.
     */
    protoheader.sa_family = AF_UNSPEC;
    bcopy((char *) hdrPtr, protoheader.sa_data, sizeof(struct ether_header));

    ctlmsgbuf.maxlen = sizeof(protoheader);
    ctlmsgbuf.len = sizeof(protoheader);
    ctlmsgbuf.buf = (char *) &protoheader;


    datamsgbuf.maxlen = size - sizeof(struct ether_header);
    datamsgbuf.len = size - sizeof(struct ether_header);
    datamsgbuf.buf = packet + sizeof(struct ether_header);

    if (putmsg(netfd, &ctlmsgbuf, &datamsgbuf, 0) < 0) {
	    perror("outputPacket: putmsg");
	    return (-1);
    }
#ifdef notdef
    fprintf(stderr, "Not sending packet to %x:%x:%x:%x:%x:%x from %x:%x:%x:%x:%x:%x\n", A(0), A(1), A(2), A(3), A(4), A(5), 
	    B(0), B(1), B(2), B(3), B(4), B(5));
#endif	

    return 0;
}

#endif /* sparc */