void
etharp_ip_input(struct netif *netif, struct pbuf *p)
{
  struct ethip_hdr *hdr;

  /* Only insert an entry if the source IP address of the
     incoming IP packet comes from a host on the local network. */
  hdr = p->payload;
  /* source is on local network? */
//Receive another network IP packet. 
#if 0 //20090224
  if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask)) 
#if 0	//ZOT716u2
#ifdef O_AXIS
    /* Open TCP/IP layer hole */
  	   && !TCP_HOLE_FLAG //615wu
#endif// O_AXIS 
#endif	//ZOT716u2
#ifdef RENDEZVOUS
		&& !mRENVEnable
#endif//RENDEZVOUS
  	) {
    /* do nothing */
    return;
  }
#endif //0 //20090224

  LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
  /* update ARP table, ask to insert entry */
  update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ETHARP_CREATE);
}
Esempio n. 2
0
/*-----------------------------------------------------------------------------------*/
struct netif *
ip_route(struct ip_addr *dest)
{
    struct netif *netif;

    for(netif = netif_list; netif != NULL; netif = netif->next) {
        if(ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
            return netif;
        }
    }

    return netif_default;
}
Esempio n. 3
0
/**
 * Updates the ARP table using the given packet.
 *
 * Uses the incoming IP packet's source address to update the
 * ARP cache for the local network. The function does not alter
 * or free the packet. This function must be called before the
 * packet p is passed to the IP layer.
 *
 * @param netif The lwIP network interface on which the IP packet pbuf arrived.
 * @param pbuf The IP packet that arrived on netif.
 * 
 * @return NULL
 *
 * @see pbuf_free()
 */
struct pbuf *
etharp_ip_input(struct netif *netif, struct pbuf *p)
{
  struct ethip_hdr *hdr;
  
  /* Only insert an entry if the source IP address of the
     incoming IP packet comes from a host on the local network. */
  hdr = p->payload;
  /* source is on local network? */
  if (!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
    /* do nothing */
    return NULL;
  }
  
  DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
  /* update ARP table, ask to insert entry */
  update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), ARP_INSERT_FLAG);
  return NULL;
}
Esempio n. 4
0
/*-----------------------------------------------------------------------------------*/
struct pbuf *
etharp_ip_input(struct netif *netif, struct pbuf *p)
{
    struct ethip_hdr *hdr;

    hdr = p->payload;

    /* Only insert/update an entry if the source IP address of the
       incoming IP packet comes from a host on the local network. */
    if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
        return NULL;
    }
    if(ip_addr_isbroadcast(&(hdr->ip.src), &(netif->netmask))) {
        return NULL;
    }
    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));
    if (ip_addr_isbroadcast(&(hdr->ip.dest), &(netif->netmask)))
        return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src), 0);
    else
        return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src), 1);
}
Esempio n. 5
0
/*-----------------------------------------------------------------------------------*/
err_t
ip_input(struct pbuf *p, struct netif *inp) {
    static struct ip_hdr *iphdr;
    static struct netif *netif;
    static u8_t hl;



#ifdef IP_STATS
    ++stats.ip.recv;
#endif /* IP_STATS */

    /* identify the IP header */
    iphdr = p->payload;
    if(IPH_V(iphdr) != 4) {
        DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number %d\n", IPH_V(iphdr)));
#if IP_DEBUG
        ip_debug_print(p);
#endif /* IP_DEBUG */
        pbuf_free(p);
#ifdef IP_STATS
        ++stats.ip.err;
        ++stats.ip.drop;
#endif /* IP_STATS */
        return ERR_OK;
    }

    hl = IPH_HL(iphdr);

    if(hl * 4 > p->len) {
        DEBUGF(IP_DEBUG, ("IP packet dropped due to too short packet %d\n", p->len));

        pbuf_free(p);
#ifdef IP_STATS
        ++stats.ip.lenerr;
        ++stats.ip.drop;
#endif /* IP_STATS */
        return ERR_OK;
    }

    /* verify checksum */
    if(inet_chksum(iphdr, hl * 4) != 0) {

        DEBUGF(IP_DEBUG, ("IP packet dropped due to failing checksum 0x%x\n", inet_chksum(iphdr, hl * 4)));
#if IP_DEBUG
        ip_debug_print(p);
#endif /* IP_DEBUG */
        pbuf_free(p);
#ifdef IP_STATS
        ++stats.ip.chkerr;
        ++stats.ip.drop;
#endif /* IP_STATS */
        return ERR_OK;
    }

    /* Trim pbuf. This should have been done at the netif layer,
       but we'll do it anyway just to be sure that its done. */
    pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));

    /* is this packet for us? */
    for(netif = netif_list; netif != NULL; netif = netif->next) {

        DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
                          iphdr->dest.addr, netif->ip_addr.addr,
                          iphdr->dest.addr & netif->netmask.addr,
                          netif->ip_addr.addr & netif->netmask.addr,
                          iphdr->dest.addr & ~(netif->netmask.addr)));

        if(ip_addr_isany(&(netif->ip_addr)) ||
                ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
                (ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) &&
                 ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
                ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
            break;
        }
    }

#if LWIP_DHCP
    /* If a DHCP packet has arrived on the interface, we pass it up the
       stack regardless of destination IP address. The reason is that
       DHCP replies are sent to the IP adress that will be given to this
       node (as recommended by RFC 1542 section 3.1.1, referred by RFC
       2131). */
    if(IPH_PROTO(iphdr) == IP_PROTO_UDP &&
            ((struct udp_hdr *)((u8_t *)iphdr + IPH_HL(iphdr) * 4/sizeof(u8_t)))->src ==
            DHCP_SERVER_PORT) {
        netif = inp;
    }
#endif /* LWIP_DHCP */

    if(netif == NULL) {
        /* packet not for us, route or discard */
        DEBUGF(IP_DEBUG, ("ip_input: packet not for us.\n"));
#if IP_FORWARD
        if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) {
            ip_forward(p, iphdr, inp);
        }
#endif /* IP_FORWARD */
        pbuf_free(p);
        return ERR_OK;
    }

#if IP_REASSEMBLY
    if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
        p = ip_reass(p);
        if(p == NULL) {
            return ERR_OK;
        }
        iphdr = p->payload;
    }
#else /* IP_REASSEMBLY */
    if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
        pbuf_free(p);
        DEBUGF(IP_DEBUG, ("IP packet dropped since it was fragmented (0x%x).\n",
                          ntohs(IPH_OFFSET(iphdr))));
#ifdef IP_STATS
        ++stats.ip.opterr;
        ++stats.ip.drop;
#endif /* IP_STATS */
        return ERR_OK;
    }
#endif /* IP_REASSEMBLY */

#if IP_OPTIONS == 0
    if(hl * 4 > IP_HLEN) {
        DEBUGF(IP_DEBUG, ("IP packet dropped since there were IP options.\n"));

        pbuf_free(p);
#ifdef IP_STATS
        ++stats.ip.opterr;
        ++stats.ip.drop;
#endif /* IP_STATS */
        return ERR_OK;
    }
#endif /* IP_OPTIONS == 0 */


    /* send to upper layers */
#if IP_DEBUG
    DEBUGF(IP_DEBUG, ("ip_input: \n"));
    ip_debug_print(p);
    DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
#endif /* IP_DEBUG */

    switch(IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
    case IP_PROTO_UDP:
        udp_input(p, inp);
        break;
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
    case IP_PROTO_TCP:
        tcp_input(p, inp);
        break;
#endif /* LWIP_TCP */
    case IP_PROTO_ICMP:
        icmp_input(p, inp);
        break;
    default:
        /* send ICMP destination protocol unreachable unless is was a broadcast */
        if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
                !ip_addr_ismulticast(&(iphdr->dest))) {
            p->payload = iphdr;
            icmp_dest_unreach(p, ICMP_DUR_PROTO);
        }
        pbuf_free(p);

        DEBUGF(IP_DEBUG, ("Unsupported transportation protocol %d\n", IPH_PROTO(iphdr)));

#ifdef IP_STATS
        ++stats.ip.proterr;
        ++stats.ip.drop;
#endif /* IP_STATS */

    }
    return ERR_OK;
}
Esempio n. 6
0
/*-----------------------------------------------------------------------------------*/
struct pbuf *
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
{
    struct eth_addr *dest, *srcaddr, mcastaddr;
    struct eth_hdr *ethhdr;
    struct etharp_hdr *hdr;
    struct pbuf *p;
    u8_t i;

    srcaddr = (struct eth_addr *)netif->hwaddr;

    /* Make room for Ethernet header. */
    if(pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
        /* The pbuf_header() call shouldn't fail, and we'll just bail
           out if it does.. */
        DEBUGF(ETHARP_DEBUG, ("etharp_output: could not allocate room for header.\n"));
#ifdef LINK_STATS
        ++stats.link.lenerr;
#endif /* LINK_STATS */
        return NULL;
    }


    dest = NULL;
    /* Construct Ethernet header. Start with looking up deciding which
       MAC address to use as a destination address. Broadcasts and
       multicasts are special, all other addresses are looked up in the
       ARP table. */
    if(ip_addr_isany(ipaddr) ||
            ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
        dest = (struct eth_addr *)&ethbroadcast;
    } else if(ip_addr_ismulticast(ipaddr)) {
        /* Hash IP multicast address to MAC address. */
        mcastaddr.addr[0] = 0x01;
        mcastaddr.addr[1] = 0x0;
        mcastaddr.addr[2] = 0x5e;
        mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
        mcastaddr.addr[4] = ip4_addr3(ipaddr);
        mcastaddr.addr[5] = ip4_addr4(ipaddr);
        dest = &mcastaddr;
    } else {
#ifdef __PAULOS__
        /* abort on insane conditions */
        if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)))
            return NULL;
        if (ipaddr->addr == netif->ip_addr.addr)
            return NULL;
#else
        if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
            /* Use the IP address of the default gateway if the destination
               is NOT on the same subnet as we are. ("NOT" added 20021113 psheer@) */
            ipaddr = &(netif->gw);
        }
#endif

        /* We try to find a stable mapping. */
        for(i = 0; i < arp_table_last; ++i) {
            if((arp_table[i].state == ETHARP_STATE_STABLE || arp_table[i].state == ETHARP_STATE_STATIC) &&
                    ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
                dest = &arp_table[i].ethaddr;

#if 0
// FIXME: remove this test code
                if (!((int) rand() % 2)) {
                    dest = NULL;
                    arp_table[i].state = ETHARP_STATE_EMPTY;
                    if (arp_table[i].p)
                        pbuf_free (arp_table[i].p);
                    arp_table[i].p = NULL;
                    arp_table[i].payload = NULL;
                    arp_table[i].len = arp_table[0].tot_len = 0;
                }
#endif

                break;
            }
        }
    }

    if(dest == NULL) {
        /* No destination address has been found, so we'll have to send
           out an ARP request for the IP address. The outgoing packet is
           queued unless the queue is full. */

        /* We check if we are already querying for this address. If so,
           we'll bail out. */
        for(i = 0; i < arp_table_last; ++i) {
            if(arp_table[i].state == ETHARP_STATE_PENDING &&
                    ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
                DEBUGF(ETHARP_DEBUG, ("etharp_output: already queued\n"));
                return NULL;
            }
        }

        hdr = q->payload;
        for(i = 0; i < 6; ++i)
            hdr->ethhdr.src.addr[i] = srcaddr->addr[i];
        hdr->ethhdr.type = htons(ETHTYPE_IP);

        i = etharp_new_entry(q, ipaddr, NULL, ETHARP_STATE_PENDING);

        /* We allocate a pbuf for the outgoing ARP request packet. */
        p = pbuf_alloc(PBUF_RAW, sizeof(struct etharp_hdr) + 2, PBUF_RAM);
        if(p == NULL) {
            /* No ARP request packet could be allocated, so we forget about
            the ARP table entry. */
            if(i != ARP_TABLE_SIZE) {
                arp_table[i].state = ETHARP_STATE_EMPTY;
                /* We decrease the reference count of the queued pbuf (which now
                   is dequeued). */
                DEBUGF(ETHARP_DEBUG, ("etharp_output: couldn't alloc pbuf for query, dequeueing %p\n", q));
            }
            return NULL;
        }
        pbuf_header (p, (s16_t) -2);

        hdr = p->payload;

        hdr->opcode = htons(ARP_REQUEST);

        for(i = 0; i < 6; ++i) {
            hdr->dhwaddr.addr[i] = 0x00;
            hdr->shwaddr.addr[i] = srcaddr->addr[i];
        }

        memcpy (&(hdr->dipaddr), ipaddr, sizeof (hdr->dipaddr));
        memcpy (&(hdr->sipaddr), &(netif->ip_addr), sizeof (hdr->sipaddr));

        hdr->hwtype = htons(HWTYPE_ETHERNET);
        ARPH_HWLEN_SET(hdr, 6);

        hdr->proto = htons(ETHTYPE_IP);
        ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));

        for(i = 0; i < 6; ++i) {
            hdr->ethhdr.dest.addr[i] = 0xff;
            hdr->ethhdr.src.addr[i] = srcaddr->addr[i];
        }

        hdr->ethhdr.type = htons(ETHTYPE_ARP);
        return p;	/* (1) */
    } else {
        /* A valid IP->MAC address mapping was found, so we construct the
           Ethernet header for the outgoing packet. */

        ethhdr = q->payload;

        for(i = 0; i < 6; i++) {
            ethhdr->dest.addr[i] = dest->addr[i];
            ethhdr->src.addr[i] = srcaddr->addr[i];
        }

        ethhdr->type = htons(ETHTYPE_IP);

        pbuf_ref (q);  /* <--- this is important, because the reference
must parallel that when returning over here (1). Callers must then
ALWAYS do a pbuf_free on the return value of etharp_output(). */
        return q;
    }


}
Esempio n. 7
0
/** 
 * Resolve and fill-in Ethernet address header for outgoing packet.
 *
 * If ARP has the Ethernet address in cache, the given packet is
 * returned, ready to be sent.
 *
 * If ARP does not have the Ethernet address in cache the packet is
 * queued and a ARP request is sent (on a best-effort basis). This
 * ARP request is returned as a pbuf, which should be sent by the
 * caller.
 *
 * If ARP failed to allocate resources, NULL is returned.
 *
 * A returned non-NULL packet should be sent by the caller.
 *
 * @param netif The lwIP network interface which the IP packet will be sent on.
 * @param ipaddr The IP address of the packet destination.
 * @param pbuf The pbuf(s) containing the IP packet to be sent.
 * 
 * @return If non-NULL, a packet ready to be sent. 
 */
struct pbuf *
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
{
  struct eth_addr *dest, *srcaddr, mcastaddr;
  struct eth_hdr *ethhdr;
  u8_t i;

  /* Make room for Ethernet header. */
  if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {    
    /* The pbuf_header() call shouldn't fail, and we'll just bail
    out if it does.. */
    DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
#ifdef LINK_STATS
    ++lwip_stats.link.lenerr;
#endif /* LINK_STATS */
    return NULL;
  }

  /* obtain source Ethernet address of the given interface */
  srcaddr = (struct eth_addr *)netif->hwaddr;

  /* assume unresolved Ethernet address */
  dest = NULL;
  /* Construct Ethernet header. Start with looking up deciding which
  MAC address to use as a destination address. Broadcasts and
  multicasts are special, all other addresses are looked up in the
  ARP table. */

  /* destination IP address is an IP broadcast address? */
  if (ip_addr_isany(ipaddr) ||
    ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
    /* broadcast on Ethernet also */
    dest = (struct eth_addr *)&ethbroadcast;
  }
  /* destination IP address is an IP multicast address? */
  else if (ip_addr_ismulticast(ipaddr)) {
    /* Hash IP multicast address to MAC address. */
    mcastaddr.addr[0] = 0x01;
    mcastaddr.addr[1] = 0x0;
    mcastaddr.addr[2] = 0x5e;
    mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
    mcastaddr.addr[4] = ip4_addr3(ipaddr);
    mcastaddr.addr[5] = ip4_addr4(ipaddr);
    /* destination Ethernet address is multicast */
    dest = &mcastaddr;
  }
  /* destination IP address is an IP unicast address */
  else {
    /* destination IP network address not on local network? */
    /* this occurs if the packet is routed to the default gateway on this interface */
    if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
      /* gateway available? */
      if (netif->gw.addr != 0)
      {
        /* use the gateway IP address */
        ipaddr = &(netif->gw);
      }
      /* no gateway available? */
      else
      {
        /* IP destination address outside local network, but no gateway available */
        return NULL;
      }
    }

    /* Ethernet address for IP destination address is in ARP cache? */
    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
      /* match found? */    
      if (arp_table[i].state == ETHARP_STATE_STABLE &&
        ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
        dest = &arp_table[i].ethaddr;
        break;
      }
    }
    /* could not find the destination Ethernet address in ARP cache? */
    if (dest == NULL) {
      /* ARP query for the IP address, submit this IP packet for queueing */
      etharp_query(netif, ipaddr, q);
      /* return nothing */
      return NULL;
    }
    /* destination Ethernet address resolved from ARP cache */
    else
    {
      /* fallthrough */
    }
  }

  /* destination Ethernet address known */
  if (dest != NULL) {
    /* A valid IP->MAC address mapping was found, so we construct the
    Ethernet header for the outgoing packet. */
    ethhdr = q->payload;

    for(i = 0; i < netif->hwaddr_len; i++) {
      ethhdr->dest.addr[i] = dest->addr[i];
      ethhdr->src.addr[i] = srcaddr->addr[i];
    }

    ethhdr->type = htons(ETHTYPE_IP);
    /* return the outgoing packet */
    return q;
  }
  /* never reached; here for safety */ 
  return NULL;
}
Esempio n. 8
0
File: ether.c Progetto: HarryR/sanos
err_t ether_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) {
  struct pbuf *q;
  struct eth_hdr *ethhdr;
  struct eth_addr *dest, mcastaddr;
  struct ip_addr *queryaddr;
  err_t err;
  int i;
  int loopback = 0;

  //kprintf("ether: xmit %d bytes, %d bufs\n", p->tot_len, pbuf_clen(p));

  if ((netif->flags & NETIF_UP) == 0) return -ENETDOWN;

  if (pbuf_header(p, ETHER_HLEN)) {
    kprintf(KERN_ERR "ether_output: not enough room for Ethernet header in pbuf\n");
    stats.link.err++;
    return -EBUF;
  }

  // Construct Ethernet header. Start with looking up deciding which
  // MAC address to use as a destination address. Broadcasts and
  // multicasts are special, all other addresses are looked up in the
  // ARP table.

  queryaddr = ipaddr;
  if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, &netif->netmask)) {
    dest = (struct eth_addr *) &ethbroadcast;
  } else if (ip_addr_ismulticast(ipaddr)) {
    // Hash IP multicast address to MAC address.
    mcastaddr.addr[0] = 0x01;
    mcastaddr.addr[1] = 0x0;
    mcastaddr.addr[2] = 0x5e;
    mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
    mcastaddr.addr[4] = ip4_addr3(ipaddr);
    mcastaddr.addr[5] = ip4_addr4(ipaddr);
    dest = &mcastaddr;
  } else if (ip_addr_cmp(ipaddr, &netif->ipaddr)) {
    dest = &netif->hwaddr;
    loopback = 1;
  } else {
    if (ip_addr_maskcmp(ipaddr, &netif->ipaddr, &netif->netmask)) {
      // Use destination IP address if the destination is on the same subnet as we are.
      queryaddr = ipaddr;
    } else {
      // Otherwise we use the default router as the address to send the Ethernet frame to.
      queryaddr = &netif->gw;
    }

    dest = arp_lookup(queryaddr);
  }

  // If the arp_lookup() didn't find an address, we send out an ARP query for the IP address.
  if (dest == NULL) {
    q = arp_query(netif, &netif->hwaddr, queryaddr);
    if (q != NULL) {
      err = dev_transmit((dev_t) netif->state, q);
      if (err < 0) {
        kprintf(KERN_ERR "ether: error %d sending arp packet\n", err);
        pbuf_free(q);
        stats.link.drop++;
        return err;
      }
    }

    // Queue packet for transmission, when the ARP reply returns
    err = arp_queue(netif, p, queryaddr);
    if (err < 0) {
      kprintf(KERN_ERR "ether: error %d queueing packet\n", err);
      stats.link.drop++;
      stats.link.memerr++;
      return err;
    }

    return 0;
  }

  ethhdr = p->payload;

  for (i = 0; i < 6; i++) {
    ethhdr->dest.addr[i] = dest->addr[i];
    ethhdr->src.addr[i] = netif->hwaddr.addr[i];
  }
  ethhdr->type = htons(ETHTYPE_IP);
  
  if (loopback) {
    struct pbuf *q;

    q = pbuf_dup(PBUF_RAW, p);
    if (!q) return -ENOMEM;

    err = ether_input(netif, q);
    if (err < 0) {
      pbuf_free(q);
      return err;
    }
  } else {
    err = dev_transmit((dev_t) netif->state, p);
    if (err < 0) {
      kprintf(KERN_ERR "ether: error %d sending packet\n", err);
      return err;
    }
  }

  return 0;
}
/**
 * Resolve and fill-in Ethernet address header for outgoing packet.
 *
 * If ARP has the Ethernet address in cache, the given packet is
 * returned, ready to be sent.
 *
 * If ARP does not have the Ethernet address in cache the packet is
 * queued (if enabled and space available) and a ARP request is sent.
 * This ARP request is returned as a pbuf, which should be sent by
 * the caller.
 *
 * A returned non-NULL packet should be sent by the caller.
 *
 * If ARP failed to allocate resources, NULL is returned.
 *
 * @param netif The lwIP network interface which the IP packet will be sent on.
 * @param ipaddr The IP address of the packet destination.
 * @param pbuf The pbuf(s) containing the IP packet to be sent.
 *
 * @return If non-NULL, a packet ready to be sent by caller.
 *
 * @return
 * - ERR_BUF Could not make room for Ethernet header.
 * - ERR_MEM Hardware address unknown, and no more ARP entries available
 *   to query for address or queue the packet.
 * - ERR_RTE No route to destination (no gateway to external networks).
 */
err_t
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
{
  struct eth_addr *dest, *srcaddr, mcastaddr;
  struct eth_hdr *ethhdr;
  err_t result = ERR_OK;
  struct ip_hdr *iphdr;  //615wu
	
  iphdr = q->payload;	//615wu	
	
  /* make room for Ethernet header - should not fail */
  if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
    /* bail out */
    LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
    LINK_STATS_INC(link.lenerr);
    return ERR_BUF;
  }

  /* assume unresolved Ethernet address */
  dest = NULL;
  /* Determine on destination hardware address. Broadcasts and multicasts
   * are special, other IP addresses are looked up in the ARP table. */
	
  /* destination IP address is an IP broadcast address? */
  if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif)) {
    /* broadcast on Ethernet also */
    dest = (struct eth_addr *)&ethbroadcast;
  /* destination IP address is an IP multicast address? */
  } else if (ip_addr_ismulticast(ipaddr)) {
    /* Hash IP multicast address to MAC address. */
    mcastaddr.addr[0] = 0x01;
    mcastaddr.addr[1] = 0x00;
    mcastaddr.addr[2] = 0x5e;
    mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
    mcastaddr.addr[4] = ip4_addr3(ipaddr);
    mcastaddr.addr[5] = ip4_addr4(ipaddr);
    /* destination Ethernet address is multicast */
    dest = &mcastaddr;
  /* destination IP address is an IP unicast address */
  } else {
    /* outside local network? */
    if (!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))  
#if 0	//ZOT716u2
#ifdef O_AXIS 
      /* Open TCP/IP layer hole */
        &&  ( !TCP_HOLE_FLAG || ( IPH_PROTO(iphdr) == IP_PROTO_UDP ) )//615wu 
#endif//O_AXIS      
#endif	//ZOT716u2  
#ifdef RENDEZVOUS
		&&  (!mRENVEnable || ( !ip_addr_ismulticast(&(iphdr->dest)) && !is_linklocal((iphdr->dest))) )
#endif//RENDEZVOUS
      ) {
      /* interface has default gateway? */
      if (netif->gw.addr != 0) {
        /* send to hardware address of default gateway IP address */
        ipaddr = &(netif->gw);
      /* no default gateway available */
      } else {
        /* no route to destination error */
        return ERR_RTE;
      }
    }
    /* queue on destination Ethernet address belonging to ipaddr */
    return etharp_query(netif, ipaddr, q);
  }

  /* destination Ethernet address known */
  if (dest != NULL) {
    u8_t i;
    /* obtain source Ethernet address of the given interface */
    srcaddr = (struct eth_addr *)netif->hwaddr;
    /* A valid IP->MAC address mapping was found, fill in the
     * Ethernet header for the outgoing packet */
    ethhdr = q->payload;
    for (i = 0; i < netif->hwaddr_len; i++) {
      ethhdr->dest.addr[i] = dest->addr[i];
      ethhdr->src.addr[i] = srcaddr->addr[i];
    }
    ethhdr->type = htons(ETHTYPE_IP);
    /* send packet */
    result = netif->linkoutput(netif, q);
  }
  return result;
}
Esempio n. 10
0
/*-----------------------------------------------------------------------------------*/
static err_t
tapif_output(struct netif *netif, struct pbuf *p,
		  struct ip_addr *ipaddr)
{
  struct tapif *tapif;
  struct pbuf *q;
  struct eth_hdr *ethhdr;
  struct eth_addr *dest, mcastaddr;
  struct ip_addr *queryaddr;
  err_t err;
  u8_t i;
  
  tapif = netif->state;

  /* Make room for Ethernet header. */
  if(pbuf_header(p, sizeof(struct eth_hdr)) != 0) {
    /* The pbuf_header() call shouldn't fail, but we allocate an extra
       pbuf just in case. */
    q = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr), PBUF_RAM);
    if(q == NULL) {
      return ERR_MEM;
    }
    pbuf_chain(q, p);
    p = q;
  }

  /* Construct Ethernet header. Start with looking up deciding which
     MAC address to use as a destination address. Broadcasts and
     multicasts are special, all other addresses are looked up in the
     ARP table. */
  queryaddr = ipaddr;
  if(ip_addr_isany(ipaddr) ||
     ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
    dest = (struct eth_addr *)&ethbroadcast;
  } else if(ip_addr_ismulticast(ipaddr)) {
    /* Hash IP multicast address to MAC address. */
    mcastaddr.addr[0] = 0x01;
    mcastaddr.addr[1] = 0x0;
    mcastaddr.addr[2] = 0x5e;
    mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
    mcastaddr.addr[4] = ip4_addr3(ipaddr);
    mcastaddr.addr[5] = ip4_addr4(ipaddr);
    dest = &mcastaddr;
  } else {
    if(ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
      /* Use destination IP address if the destination is on the same
         subnet as we are. */
      queryaddr = ipaddr;
    } else {
      /* Otherwise we use the default router as the address to send
         the Ethernet frame to. */
      queryaddr = &(netif->gw);
    }
    dest = arp_lookup(queryaddr);
  }


  /* If the arp_lookup() didn't find an address, we send out an ARP
     query for the IP address. */
  if(dest == NULL) {
    q = arp_query(netif, tapif->ethaddr, queryaddr);
    if(q != NULL) {
      printf("Sending ARP after query\n");
      err = low_level_output(tapif, q);
      pbuf_free(q);
      return err;
    }
    return ERR_MEM;
  }
  ethhdr = p->payload;
  
  for(i = 0; i < 6; i++) {
    ethhdr->dest.addr[i] = dest->addr[i];
    ethhdr->src.addr[i] = tapif->ethaddr->addr[i];
  }
  
  ethhdr->type = htons(ETHTYPE_IP);
  
  return low_level_output(tapif, p);

}