Esempio n. 1
0
/*------------------------------------------------------------------------
 * udp_send - send a UDP packet
 *------------------------------------------------------------------------
 */
status	udp_send (
    uint32	remip,			/* remote IP address or IP_BCAST*/
    /*  for a local broadcast	*/
    uint16	remport,		/* remote UDP protocol port	*/
    uint32	locip,			/* local IP address		*/
    uint16	locport,		/* local UDP protocol port	*/
    char   *buff,			/* buffer of UDP data		*/
    int32	len			/* length of data in buffer	*/
)
{
    struct	eth_packet pkt;		/* ptr to packet being read	*/
    struct ipv4_packet *ippkt = (struct ipv4_packet *)(pkt.net_ethdata);
    struct udp_packet *udppkt = (struct udp_packet *)(ippkt->net_ipdata);
    int32	pktlen;			/* total packet length		*/
    static	uint16 ident = 1;	/* datagram IDENT field		*/
    char	*udataptr;		/* pointer to UDP data		*/
    byte	ethbcast[] = {0xff,0xff,0xff,0xff,0xff,0xff};

    /* Compute packet length as UDP data size + fixed header size	*/

    pktlen = ((char *)(udppkt->net_udpdata) - (char *)&pkt) + len;

    /* Create UDP packet in pkt */

    memcpy(pkt.net_ethsrc, NetData.ethaddr, ETH_ADDR_LEN);
    pkt.net_ethtype = 0x0800;	/* Type is IP */
    ippkt->net_ipvh = 0x45;		/* IP version and hdr length	*/
    ippkt->net_iptos = 0x00;		/* Type of service		*/
    ippkt->net_iplen= pktlen - ETH_HDR_LEN;/* total IP datagram length	*/
    ippkt->net_ipid = ident++;		/* datagram gets next IDENT	*/
    ippkt->net_ipfrag = 0x0000;	/* IP flags & fragment offset	*/
    ippkt->net_ipttl = 0xff;		/* IP time-to-live		*/
    ippkt->net_ipproto = IP_UDP;	/* datagram carries UDP		*/
    ippkt->net_ipcksum = 0x0000;	/* initial checksum		*/
    ippkt->net_ipsrc = locip;		/* IP source address		*/
    ippkt->net_ipdst = remip;		/* IP destination address	*/

    udppkt->net_udpsport = locport;	/* local UDP protocol port	*/
    udppkt->net_udpdport = remport;	/* remote UDP protocol port	*/
    udppkt->net_udplen = (uint16)(UDP_HDR_LEN+len); /* UDP length	*/
    udppkt->net_udpcksum = 0x0000;	/* ignore UDP checksum		*/
    udataptr = (char *) udppkt->net_udpdata;
    for (; len>0; len--) {
        *udataptr++ = *buff++;
    }

    /* Set MAC address in packet, using ARP if needed */

    //kprintf("Udp_send called with ip : %x\r\n", remip);
    if (remip == IP_BCAST) {	/* set mac address to b-cast	*/
        memcpy(pkt.net_ethdst, ethbcast, ETH_ADDR_LEN);

        /* If destination isn't on the same subnet, send to router	*/

    } else if ((locip & NetData.addrmask)
               != (remip & NetData.addrmask)) {
        //kprintf("localip [%08x] NetData.addrmask [%08x] remote ip [%08x] 12 [%08x] 23 [%08x]\r\n",
        //locip, NetData.addrmask, remip, locip&NetData.addrmask, remip & NetData.addrmask);
        if (arp_resolve(NetData.routeraddr, pkt.net_ethdst)!=OK) {
            kprintf("udp_send: cannot resolve router %08x\n\r",
                    NetData.routeraddr);
            return SYSERR;
        }
    } else {
        /* Destination is on local subnet -  get MAC address */

        //kprintf("UDP_Send trying to resolve address : %x\r\n", remip);
        if (arp_resolve(remip, pkt.net_ethdst) != OK) {
            kprintf("udp_send: cannot resolve %08x\n\r",remip);
            return SYSERR;
        }
    }

    /* Convert IP and UDP header fields from net to host byte order */

    udp_hton(udppkt);
    ip_hton(ippkt);
    eth_hton(&pkt);
    //kprintf("Cleared conversion of header fields\r\n");

    /* Compute IP header checksum */
    ippkt->net_ipcksum = 0xffff & ipcksum(ippkt);

    //kprintf("Writing to ethernet device\r\n");
    write(ETHER0, (char *)&pkt, pktlen);

    return OK;
}
/*------------------------------------------------------------------------
 * arp_resolve  -  Use ARP to resolve an IP address to an Ethernet address
 *------------------------------------------------------------------------
 */
status	arp_resolve (
    uint32	nxthop,			/* Next-hop address to resolve	*/
    byte	mac[ETH_ADDR_LEN]	/* Array into which Ethernet	*/
)				/*   address should be placed	*/
{
    intmask	mask;			/* Saved interrupt mask		*/
    struct	arppacket apkt;		/* Local packet buffer		*/
    int32	i;			/* Index into arpcache		*/
    int32	slot;			/* ARP table slot to use	*/
    struct	arpentry  *arptr;	/* Ptr to ARP cache entry	*/
    int32	msg;			/* Message returned by recvtime	*/

    /* Use MAC broadcast address for IP limited broadcast */

    if (nxthop == IP_BCAST) {
        memcpy(mac, NetData.ethbcast, ETH_ADDR_LEN);
        return OK;
    }

    /* Use MAC broadcast address for IP network broadcast */

    if (nxthop == NetData.ipbcast) {
        memcpy(mac, NetData.ethbcast, ETH_ADDR_LEN);
        return OK;
    }

    /* Ensure only one process uses ARP at a time */

    mask = disable();

    /* See if next hop address is already present in ARP cache */

    for (i=0; i<ARP_SIZ; i++) {
        arptr = &arpcache[i];
        if (arptr->arstate == AR_FREE) {
            continue;
        }
        if (arptr->arpaddr == nxthop) { /* Adddress is in cache	*/
            break;
        }
    }

    if (i < ARP_SIZ) {	/* Entry was found */

        /* If entry is resolved - handle and return */

        if (arptr->arstate == AR_RESOLVED) {
            memcpy(mac, arptr->arhaddr, ARP_HALEN);
            restore(mask);
            return OK;
        }

        /* Entry is already pending -  return error because	*/
        /*	only one process can be	waiting at a time	*/

        if (arptr->arstate == AR_PENDING) {
            restore(mask);
            return SYSERR;
        }
    }

    /* IP address not in cache -  allocate a new cache entry and	*/
    /*	send an ARP request to obtain the answer		*/

    slot = arp_alloc();
    if (slot == SYSERR) {
        restore(mask);
        return SYSERR;
    }

    arptr = &arpcache[slot];
    arptr->arstate = AR_PENDING;
    arptr->arpaddr = nxthop;
    arptr->arpid = currpid;

    /* Hand-craft an ARP Request packet */

    memcpy(apkt.arp_ethdst, NetData.ethbcast, ETH_ADDR_LEN);
    memcpy(apkt.arp_ethsrc, NetData.ethucast, ETH_ADDR_LEN);
    apkt.arp_ethtype = ETH_ARP;	  /* Packet type is ARP		*/
    apkt.arp_htype = ARP_HTYPE;	  /* Hardware type is Ethernet	*/
    apkt.arp_ptype = ARP_PTYPE;	  /* Protocol type is IP	*/
    apkt.arp_hlen = 0xff & ARP_HALEN; /* Ethernet MAC size in bytes	*/
    apkt.arp_plen = 0xff & ARP_PALEN; /* IP address size in bytes	*/
    apkt.arp_op = 0xffff & ARP_OP_REQ;/* ARP type is Request	*/
    memcpy(apkt.arp_sndha, NetData.ethucast, ARP_HALEN);
    apkt.arp_sndpa = NetData.ipucast; /* IP address of interface	*/
    memset(apkt.arp_tarha, '\0', ARP_HALEN); /* Target HA is unknown*/
    apkt.arp_tarpa = nxthop;	  /* Target protocol address	*/

    /* Convert ARP packet from host to net byte order */

    arp_hton(&apkt);

    /* Convert Ethernet header from host to net byte order */

    eth_hton((struct netpacket *)&apkt);

    /* Send the packet ARP_RETRY times and await response */

    msg = recvclr();
    for (i=0; i<ARP_RETRY; i++) {
        write(ETHER0, (char *)&apkt, sizeof(struct arppacket));
        msg = recvtime(ARP_TIMEOUT);
        if (msg == TIMEOUT) {
            continue;
        } else if (msg == SYSERR) {
            restore(mask);
            return SYSERR;
        } else {	/* entry is resolved */
            break;
        }
    }

    /* If no response, return TIMEOUT */

    if (msg == TIMEOUT) {
        arptr->arstate = AR_FREE;   /* Invalidate cache entry */
        restore(mask);
        return TIMEOUT;
    }

    /* Return hardware address */

    memcpy(mac, arptr->arhaddr, ARP_HALEN);
    restore(mask);
    return OK;
}
Esempio n. 3
0
status rpl_send_with_ip(char * node_phy_addr, char *src_node, byte msg_type, char *msg, uint32 msg_len, uint32 remip){

        struct eth_packet pkt;
        struct rpl_sim_packet *rpl_sim_pkt  = NULL;
	byte	ethbcast[] = {0xff,0xff,0xff,0xff,0xff,0xff};
#ifdef DEBUG
        kprintf("Simulator is : %04x dest : %04x source : %04x my addr : %04x\r\n", remip, *((uint32*)node_phy_addr), *((uint32*)src_node), NetData.ipaddr);
#endif

        if ( ! NetData.ipvalid){
                getlocalip();
        }
        if(msg_len > 1500-ETH_HDR_LEN-RPL_SIM_HDR_LEN){
                kprintf("WARN : Simulator : Message too big \r\n");
                return SYSERR;
        }
 
	memcpy(pkt.net_ethsrc, NetData.ethaddr, ETH_ADDR_LEN);
        /* FIXME : Needs to be changed to something that is valid */
        pkt.net_ethtype = 0x1000;	
	if (remip == IP_BCAST) {	/* set mac address to b-cast	*/
		memcpy(pkt.net_ethdst, ethbcast, ETH_ADDR_LEN);

	/* If destination isn't on the same subnet, send to router	*/

	} else if ((NetData.ipaddr & NetData.addrmask)
			!= (remip & NetData.addrmask)) {
		if (arp_resolve(NetData.routeraddr, pkt.net_ethdst)!=OK) {
		    kprintf("rpl_send: cannot resolve router %08x\n\r",
				NetData.routeraddr);
		    return SYSERR;
		}
	} else {
		/* Destination is on local subnet -  get MAC address */
		if (arp_resolve(remip, pkt.net_ethdst) != OK) {
			kprintf("rpl_send: cannot resolve %08x\n\r",remip);
			return SYSERR;
		}
	}

        rpl_sim_pkt = (struct rpl_sim_packet *)pkt.net_ethdata;
        memcpy((char *)rpl_sim_pkt->dest_node, (char *)node_phy_addr, RPL_NODE_PHY_ADDR_LEN);
        /*
         * FIXME Change this to my_phsical_address which is 64 bits
         */
        memcpy((char *)rpl_sim_pkt->src_node, (char *)(src_node), RPL_NODE_PHY_ADDR_LEN);
        rpl_sim_pkt->msg_type = msg_type;
        rpl_sim_pkt->msg_len = msg_len;
        memcpy(rpl_sim_pkt->data, msg, msg_len);

        /*
         * FIXME : Perform host to network order translations
         */
#ifdef DEBUG
        kprintf("The packet is destined for : %06x with length : %d\r\n", *(pkt.net_ethdst+4), msg_len);
#endif

        eth_hton(&pkt);

        write(ETHER0, (char *)&pkt, ETH_HDR_LEN + RPL_SIM_HDR_LEN + msg_len); 

        return OK;


}
/*------------------------------------------------------------------------
 * arp_in  -  Handle an incoming ARP packet
 *------------------------------------------------------------------------
 */
void	arp_in (
    struct arppacket *pktptr	/* Ptr to incoming packet	*/
)
{
    intmask	mask;			/* Saved interrupt mask		*/
    struct	arppacket apkt;		/* Local packet buffer		*/
    int32	slot;			/* Slot in cache		*/
    struct	arpentry  *arptr;	/* Ptr to ARP cache entry	*/
    bool8	found;			/* Is the sender's address in	*/
    /*   the cache?			*/

    /* Convert packet from network order to host order */

    arp_ntoh(pktptr);

    /* Verify ARP is for IPv4 and Ethernet */

    if ( (pktptr->arp_htype != ARP_HTYPE) ||
            (pktptr->arp_ptype != ARP_PTYPE) ) {
        freebuf((char *)pktptr);
        return;
    }

    /* Ensure only one process uses ARP at a time */

    mask = disable();

    /* Search cache for sender's IP address */

    found = FALSE;

    for (slot=0; slot < ARP_SIZ; slot++) {
        arptr = &arpcache[slot];

        /* Skip table entries that are unused */

        if (arptr->arstate == AR_FREE) {
            continue;
        }

        /* If sender's address matches, we've found it */

        if (arptr->arpaddr == pktptr->arp_sndpa) {
            found = TRUE;
            break;
        }
    }

    if (found) {

        /* Update sender's hardware address */

        memcpy(arptr->arhaddr, pktptr->arp_sndha, ARP_HALEN);

        /* If a process was waiting, inform the process */

        if (arptr->arstate == AR_PENDING) {
            /* Mark resolved and notify waiting process */
            arptr->arstate = AR_RESOLVED;
            arptr->time = clktime;
            send(arptr->arpid, OK);
        }
    }

    /* For an ARP reply, processing is complete */

    if (pktptr->arp_op == ARP_OP_RPLY) {
        freebuf((char *)pktptr);
        restore(mask);
        return;
    }

    /* The following is for an ARP request packet: if the local	*/
    /*  machine is not the target or the local IP address is not	*/
    /*  yet known, ignore the request (i.e., processing is complete)*/

    if ((!NetData.ipvalid) ||
            (pktptr->arp_tarpa != NetData.ipucast)) {
        freebuf((char *)pktptr);
        restore(mask);
        return;
    }

    /* Request has been sent to the local machine's address.  So,	*/
    /*   add sender's info to cache, if not already present		*/

    if (!found) {
        slot = arp_alloc();
        if (slot == SYSERR) {	/* Cache is full */
            kprintf("ARP cache overflow on interface\n");
            freebuf((char *)pktptr);
            restore(mask);
            return;
        }
        arptr = &arpcache[slot];
        arptr->arpaddr = pktptr->arp_sndpa;
        memcpy(arptr->arhaddr, pktptr->arp_sndha, ARP_HALEN);
        arptr->arstate = AR_RESOLVED;
    }

    /* Hand-craft an ARP reply packet and send back to requester	*/

    memcpy(apkt.arp_ethdst, pktptr->arp_sndha, ARP_HALEN);
    memcpy(apkt.arp_ethsrc, NetData.ethucast, ARP_HALEN);
    apkt.arp_ethtype= ETH_ARP;		/* Frame carries ARP	*/
    apkt.arp_htype	= ARP_HTYPE;		/* Hardware is Ethernet	*/
    apkt.arp_ptype	= ARP_PTYPE;		/* Protocol is IP	*/
    apkt.arp_hlen	= ARP_HALEN;		/* Ethernet address size*/
    apkt.arp_plen	= ARP_PALEN;		/* IP address size	*/
    apkt.arp_op	= ARP_OP_RPLY;		/* Type is Reply	*/

    /* Insert local Ethernet and IP address in sender fields	*/

    memcpy(apkt.arp_sndha, NetData.ethucast, ARP_HALEN);
    apkt.arp_sndpa = NetData.ipucast;

    /* Copy target Ethernet and IP addresses from request packet */

    memcpy(apkt.arp_tarha, pktptr->arp_sndha, ARP_HALEN);
    apkt.arp_tarpa = pktptr->arp_sndpa;

    /* Convert ARP packet from host to network byte order */

    arp_hton(&apkt);

    /* Convert the Ethernet header to network byte order */

    eth_hton((struct netpacket *)&apkt);

    /* Send the reply */

    write(ETHER0, (char *)&apkt, sizeof(struct arppacket));
    freebuf((char *)pktptr);
    restore(mask);
    return;
}