err_t jif_init(struct netif *netif) { struct jif *jif; envid_t *output_envid; jif = (struct jif *) mem_malloc(sizeof(struct jif)); if (jif == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("jif_init: out of memory\n")); return ERR_MEM; } output_envid = (envid_t *)netif->state; netif->state = jif; netif->output = jif_output; netif->linkoutput = low_level_output; memcpy(&netif->name[0], "en", 2); jif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); jif->envid = *output_envid; low_level_init(netif); etharp_init(); // qemu user-net is dumb; if the host OS does not send and ARP request // first, the qemu will send packets destined for the host using the mac // addr 00:00:00:00:00; do a arp request for the user-net NAT at 10.0.2.2 uint32_t ipaddr = inet_addr("10.0.2.2"); etharp_query(netif, (struct ip_addr *) &ipaddr, 0); return ERR_OK; }
/** * Bring an interface up, available for processing * traffic. * * @note: Enabling DHCP on a down interface will make it come * up once configured. * * @see dhcp_start() */ void netif_set_up(struct netif *netif) { if ( !(netif->flags & NETIF_FLAG_UP )) { netif->flags |= NETIF_FLAG_UP; #if LWIP_SNMP snmp_get_sysuptime(&netif->ts); #endif /* LWIP_SNMP */ NETIF_LINK_CALLBACK(netif); NETIF_STATUS_CALLBACK(netif); #if LWIP_ARP_GRATUITOUS /** For Ethernet network interfaces, we would like to send a * "gratuitous ARP"; this is an ARP packet sent by a node in order * to spontaneously cause other nodes to update an entry in their * ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ if (netif->flags & NETIF_FLAG_ETHARP) { etharp_query(netif, &(netif->ip_addr), NULL); } #endif /* LWIP_ARP */ } }
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr) { /* TODO: Handling of obsolete pcbs */ /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ #if LWIP_TCP struct tcp_pcb *pcb; struct tcp_pcb_listen *lpcb; /* address is actually being changed? */ if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n")); pcb = tcp_active_pcbs; while (pcb != NULL) { /* PCB bound to current local interface address? */ if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) { /* this connection must be aborted */ struct tcp_pcb *next = pcb->next; LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); tcp_abort(pcb); pcb = next; } else { pcb = pcb->next; } } for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { /* PCB bound to current local interface address? */ if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) { /* The PCB is listening to the old ipaddr and * is set to listen to the new one instead */ ip_addr_set(&(lpcb->local_ip), ipaddr); } } } #endif snmp_delete_ipaddridx_tree(netif); snmp_delete_iprteidx_tree(0,netif); /* set new IP address to netif */ ip_addr_set(&(netif->ip_addr), ipaddr); snmp_insert_ipaddridx_tree(netif); snmp_insert_iprteidx_tree(0,netif); #if 0 /* only allowed for Ethernet interfaces TODO: how can we check? */ /** For Ethernet network interfaces, we would like to send a * "gratuitous ARP"; this is an ARP packet sent by a node in order * to spontaneously cause other nodes to update an entry in their * ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ etharp_query(netif, ipaddr, NULL); #endif LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], ip4_addr1(&netif->ip_addr), ip4_addr2(&netif->ip_addr), ip4_addr3(&netif->ip_addr), ip4_addr4(&netif->ip_addr))); }
int netx_send_to( struct netxsocket_s *rlpsock, const netx_addr_t *destaddr, uint8_t *data, size_t datalen ) { struct pbuf *pkt; /* Outgoing packet */ struct eth_addr *ethaddr_ret; struct ip_addr *ipaddr_ret; int result; int t_begin; struct ip_addr dest_addr; ip4addr_t addr; int arp_index; if (!rlpsock || !rlpsock->nativesock) return -1; /* struct ip_addr *ipaddr, */ addr = NETI_INADDR(destaddr); dest_addr.addr = addr; if (!is_multicast(addr)) { /* We have the arp queue turned off, so we need to make sure we have a ARP entry */ /* else it will fail on first try */ result = -1; arp_index = etharp_find_addr(netxf_default, &dest_addr, ðaddr_ret, &ipaddr_ret); if (arp_index < 0) { result = etharp_query(netxf_default, &dest_addr, NULL); if (result == ERR_OK) { result = -1; t_begin = sys_jiffies(); /* wait 2 seconds (ARP TIMEOUT)*/ while ((unsigned int)sys_jiffies() - t_begin < 2000) { arp_index = etharp_find_addr(netxf_default, &dest_addr, ðaddr_ret, &ipaddr_ret); if (arp_index >= 0) { result = 0; break; } } } else { acnlog(LOG_WARNING | LOG_NETI, "netx_send_to : ARP query failure"); return -1; } } else result = 0; if (result != 0) { acnlog(LOG_WARNING | LOG_NETI, "netx_send_to : ARP failure: %d.%d.%d.%d", ntohl(addr) >> 24 & 0x000000ff, ntohl(addr) >> 16 & 0x000000ff, ntohl(addr) >> 8 & 0x000000ff, ntohl(addr) & 0x000000ff); return result; }
void network_init(void) { printf("\nStarting %s\n", __FUNCTION__); // Initialise the nslu2 hardware ixOsalOemInit(); /* Initialise lwIP */ mem_init(); memp_init(); pbuf_init(); netif_init(); udp_init(); etharp_init(); /* Setup the network interface */ struct ip_addr netmask, ipaddr, gw; IP4_ADDR(&netmask, 255, 255, 255, 0); // Standard net mask IP4_ADDR(&gw, 192, 168, 0, 1); // Your host system IP4_ADDR(&ipaddr, 192, 168, 0, 2); // The Slug's IP address struct netif *netif = netif_add(&ipaddr,&netmask,&gw, sosIfInit, ip_input); netif_set_default(netif); // Generate an arp entry for our gateway // We should only need to do this once, but Linux seems to love ignoring // ARP queries (why??!), so we keep trying until we get a response struct pbuf *p = etharp_query(netif, &netif->gw, NULL); do { (*netif_default->linkoutput)(netif, p); // Direct output sos_usleep(100000); // Wait a while for a reply } while (!etharp_entry_present(&netif->gw)); pbuf_free(p); // Finish the initialisation of the nslu2 hardware ixOsalOSServicesFinaliseInit(); /* Initialise NFS */ int r = nfs_init(gw); assert(!r); mnt_get_export_list(); // Print out the exports on this server const char *msg; if (mnt_mount(NFS_DIR, &mnt_point)) // Mount aos_nfs msg = "%s: Error mounting path '%s'!\n"; else msg = "Successfully mounted '%s'\n"; printf(msg, __FUNCTION__, NFS_DIR); printf("Finished %s\n\n", __FUNCTION__); }
// checks if the offered address is already in use // it does so by sending an ARP query static void dhcp_check(struct dhcp_state *state) { struct pbuf *p; err_t result; u16_t msecs; DEBUGF(DHCP_DEBUG, ("dhcp_check()\n")); p = etharp_query(state->netif, &state->offered_ip_addr, NULL); if(p != NULL) { DEBUGF(DHCP_DEBUG, ("dhcp_check(): sending ARP request len %u\n", p->tot_len)); result = state->netif->linkoutput(state->netif, p); pbuf_free(p); //return /*result*/; } state->tries++; msecs = state->tries * 1000; state->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; DEBUGF(DHCP_DEBUG, ("dhcp_check(): request timeout %u msecs\n", msecs)); dhcp_set_state(state, DHCP_CHECKING); }
/** * Called by a driver when its link goes up */ void netif_set_link_up(struct netif *netif ) { netif->flags |= NETIF_FLAG_LINK_UP; #if LWIP_ARP /** For Ethernet network interfaces, we would like to send a * "gratuitous ARP"; this is an ARP packet sent by a node in order * to spontaneously cause other nodes to update an entry in their * ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ if (netif->flags & NETIF_FLAG_ETHARP) { etharp_query(netif, &(netif->ip_addr), NULL); } #endif /* LWIP_ARP */ #if LWIP_IGMP /* resend IGMP memberships */ if (netif->flags & NETIF_FLAG_IGMP) { igmp_report_groups( netif); } #endif /* LWIP_IGMP */ NETIF_LINK_CALLBACK(netif); }
/** * Resolve and fill-in Ethernet address header for outgoing packet. * * For IP multicast and broadcast, corresponding Ethernet addresses * are selected and the packet is transmitted on the link. * * For unicast addresses, the packet is submitted to etharp_query(). In * case the IP address is outside the local network, the IP address of * the gateway is used. * * @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 * - ERR_RTE No route to destination (no gateway to external networks), * or the return type of either etharp_query() or netif->linkoutput(). */ err_t 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 - 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. */ /* broadcast destination IP address? */ if (ip_addr_isbroadcast(ipaddr, netif)) { /* broadcast on Ethernet also */ dest = (struct eth_addr *)ðbroadcast; /* multicast destination IP 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; /* unicast destination IP address? */ } else { /* outside local network? */ if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { /* 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 (default gateway missing) */ return ERR_RTE; } } /* queue on destination Ethernet address belonging to ipaddr */ return etharp_query(netif, ipaddr, q); } /* continuation for multicast/broadcast destinations */ /* obtain source Ethernet address of the given interface */ srcaddr = (struct eth_addr *)netif->hwaddr; 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 directly on the link */ return netif->linkoutput(netif, q); }
/** * 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 *)ðbroadcast; } /* 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; }
/** * 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 *)ðbroadcast; /* 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; }