1/** 2 * @file 3 * Ethernet Interface Skeleton 4 * 5 */ 6 7/* 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without modification, 12 * are permitted provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, 15 * this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 * 33 * This file is part of the lwIP TCP/IP stack. 34 * 35 * Author: Adam Dunkels <adam@sics.se> 36 * Author: H. Peter Anvin <hpa@@zytor.com> 37 * Author: Eric Biederman <ebiederm@xmission.com> 38 * 39 */ 40 41/* 42 * This file is a skeleton for developing Ethernet network interface 43 * drivers for lwIP. Add code to the low_level functions and do a 44 * search-and-replace for the word "ethernetif" to replace it with 45 * something that better describes your network interface. 46 */ 47 48/* other headers include deprintf.h too early */ 49#define UNDIIF_ID_FULL_DEBUG (UNDIIF_ID_DEBUG | UNDIIF_DEBUG) 50 51#if UNDIIF_ID_FULL_DEBUG 52# ifndef DEBUG 53# define DEBUG 1 54# endif 55# ifndef DEBUG_PORT 56# define DEBUG_PORT 0x3f8 57# endif 58#endif /* UNDIIF_ID_FULL_DEBUG */ 59 60#include <core.h> 61 62#include "lwip/opt.h" 63 64#define LWIP_UNDIIF_DBG(debug) \ 65 ( ((debug) & LWIP_DBG_ON) && \ 66 ((debug) & LWIP_DBG_TYPES_ON) && \ 67 (((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL) ) 68 69#include "lwip/def.h" 70#include "lwip/mem.h" 71#include "lwip/pbuf.h" 72#include "lwip/sys.h" 73#include <lwip/stats.h> 74#include <lwip/snmp.h> 75#include "netif/etharp.h" 76#include "netif/ppp_oe.h" 77#include "lwip/netifapi.h" 78#include "lwip/tcpip.h" 79#include "../../../fs/pxe/pxe.h" 80 81#include <inttypes.h> 82#include <string.h> 83#include <syslinux/pxe_api.h> 84#include <dprintf.h> 85 86/* debug extras */ 87#include "ipv4/lwip/icmp.h" 88#include "lwip/tcp_impl.h" 89#include "lwip/udp.h" 90 91#if LWIP_AUTOIP 92#error "AUTOIP not supported" 93#endif 94#if ETH_PAD_SIZE 95#error "ETH_PAD_SIZE not supported" 96#endif 97#if NETIF_MAX_HWADDR_LEN != MAC_MAX 98#error "hwaddr_len mismatch" 99#endif 100 101/** the time an ARP entry stays valid after its last update, 102 * for ARP_TMR_INTERVAL = 5000, this is 103 * (240 * 5) seconds = 20 minutes. 104 */ 105#define UNDIARP_MAXAGE 240 106/** the time an ARP entry stays pending after first request, 107 * for ARP_TMR_INTERVAL = 5000, this is 108 * (2 * 5) seconds = 10 seconds. 109 * 110 * @internal Keep this number at least 2, otherwise it might 111 * run out instantly if the timeout occurs directly after a request. 112 */ 113#define UNDIARP_MAXPENDING 2 114 115typedef u8_t hwaddr_t[NETIF_MAX_HWADDR_LEN]; 116 117#ifdef PACK_STRUCT_USE_INCLUDES 118# include "arch/bpstruct.h" 119#endif 120PACK_STRUCT_BEGIN 121/** the ARP message */ 122struct arp_hdr { 123 PACK_STRUCT_FIELD(u16_t hwtype); 124 PACK_STRUCT_FIELD(u16_t proto); 125 PACK_STRUCT_FIELD(u8_t hwlen); 126 PACK_STRUCT_FIELD(u8_t protolen); 127 PACK_STRUCT_FIELD(u16_t opcode); 128} PACK_STRUCT_STRUCT; 129PACK_STRUCT_END 130#ifdef PACK_STRUCT_USE_INCLUDES 131# include "arch/epstruct.h" 132#endif 133 134static inline int arp_hdr_len(struct netif *netif) 135{ 136 return sizeof(struct arp_hdr) + (netif->hwaddr_len + sizeof(uint32_t))*2; 137} 138 139enum undiarp_state { 140 UNDIARP_STATE_EMPTY = 0, 141 UNDIARP_STATE_PENDING, 142 UNDIARP_STATE_STABLE 143}; 144 145struct undiarp_entry { 146#if ARP_QUEUEING 147 /** 148 * Pointer to queue of pending outgoing packets on this ARP entry. 149 */ 150 struct etharp_q_entry *q; 151#endif 152 struct ip_addr ipaddr; 153 u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; 154 enum undiarp_state state; 155 u8_t ctime; 156 struct netif *netif; 157}; 158 159#define PKTBUF_SIZE 2048 160 161/* Define those to better describe your network interface. */ 162#define IFNAME0 'u' 163#define IFNAME1 'n' 164 165static struct netif undi_netif; 166static struct undiarp_entry arp_table[ARP_TABLE_SIZE]; 167#if !LWIP_NETIF_HWADDRHINT 168static u8_t undiarp_cached_entry; 169#endif 170 171/** 172 * Try hard to create a new entry - we want the IP address to appear in 173 * the cache (even if this means removing an active entry or so). */ 174#define UNDIARP_TRY_HARD 1 175#define UNDIARP_FIND_ONLY 2 176 177#define UNIDIF_ID_STRLEN 300 178 179 180static inline bool undi_is_ethernet(struct netif *netif) 181{ 182 (void)netif; 183 return MAC_type == ETHER_TYPE; 184} 185 186#if 0 187static void print_pbuf(struct pbuf *p) 188{ 189 struct pbuf *q; 190 int off; 191 192 for( off = 0, q = p; q != NULL; q = q->next) { 193 unsigned char *byte, *end; 194 byte = q->payload; 195 end = byte + q->len; 196 for (; byte < end; byte++, off++ ) { 197 if ((off & 0xf) == 0) { 198 printf("%04x: ", off); 199 } 200 printf("%02x ", *byte); 201 if ((off & 0xf) == 0xf) { 202 printf("\n"); 203 } 204 } 205 } 206 printf("\n"); 207} 208#endif 209 210#if 0 211static void print_arp_pbuf(struct netif *netif, struct pbuf *p) 212{ 213 struct arp_hdr *hdr; 214 u8_t *hdr_ptr; 215 int i; 216 217 hdr = p->payload; 218 hdr_ptr = (unsigned char *)(hdr + 1); 219 /* Fixed fields */ 220 printf("arp: %04x %04x %04x %04x ", 221 hdr->hwtype, 222 hdr->proto, 223 hdr->_hwlen_protolen); 224 /* Source hardware address */ 225 for(i = 0; i < netif->hwaddr_len; i++, hdr_ptr++) { 226 printf("%02x%c", *hdr_ptr,(i +1) == netif->hwaddr_len?' ':':'); 227 } 228 /* Source ip address */ 229 printf("%d.%d.%d.%d ", hdr_ptr[0], hdr_ptr[1], hdr_ptr[2], hdr_ptr[3]); 230 hdr_ptr += 4; 231 /* Destination hardware address */ 232 for(i = 0; i < netif->hwaddr_len; i++, hdr_ptr++) { 233 printf("%02x%c", *hdr_ptr, (i +1) == netif->hwaddr_len?' ':':'); 234 } 235 /* Destination ip address */ 236 printf("%d.%d.%d.%d ", hdr_ptr[0], hdr_ptr[1], hdr_ptr[2], hdr_ptr[3]); 237 hdr_ptr += 4; 238} 239#endif 240 241#if LWIP_UNDIIF_DBG(UNDIIF_ID_FULL_DEBUG) 242int snprintf_eth_hdr(char *str, size_t size, char head[], 243 struct eth_hdr *ethhdr, char dir, char status, 244 char tail[]) 245{ 246 u8_t *d = ethhdr->dest.addr; 247 u8_t *s = ethhdr->src.addr; 248 return snprintf(str, size, 249 "%s: d:%02x:%02x:%02x:%02x:%02x:%02x" 250 " s:%02x:%02x:%02x:%02x:%02x:%02x" 251 " t:%4hx %c%c%s\n", head, 252 d[0], d[1], d[2], d[3], d[4], d[5], 253 s[0], s[1], s[2], s[3], s[4], s[5], 254 (unsigned)htons(ethhdr->type), 255 dir, status, tail); 256} 257 258int snprintf_arp_hdr(char *str, size_t size, char head[], 259 struct eth_hdr *ethhdr, char dir, 260 char status, char tail[]) 261{ 262 struct etharp_hdr *arphdr; 263 u8_t *d, *s; 264 struct ip_addr *sip, *dip; 265 if (ntohs(ethhdr->type) == ETHTYPE_ARP) { 266 arphdr = (struct etharp_hdr *)((void *)ethhdr + 14); 267 d = arphdr->dhwaddr.addr; 268 s = arphdr->shwaddr.addr; 269 sip = (struct ip_addr *) &(arphdr->sipaddr); 270 dip = (struct ip_addr *) &(arphdr->dipaddr); 271 return snprintf(str, size, 272 "%s: s:%02x:%02x:%02x:%02x:%02x:%02x" 273 " %3d.%3d.%3d.%3d" 274 " %02x:%02x:%02x:%02x:%02x:%02x" 275 " %3d.%3d.%3d.%3d" 276 " %c%c%s\n", head, 277 s[0], s[1], s[2], s[3], s[4], s[5], 278 ip4_addr1(sip), ip4_addr2(sip), 279 ip4_addr3(sip), ip4_addr4(sip), 280 d[0], d[1], d[2], d[3], d[4], d[5], 281 ip4_addr1(dip), ip4_addr2(dip), 282 ip4_addr3(dip), ip4_addr4(dip), 283 dir, status, tail); 284 } else { 285 return 0; 286 } 287} 288 289int snprintf_ip_hdr(char *str, size_t size, char head[], 290 struct eth_hdr *ethhdr, char dir, 291 char status, char tail[]) 292{ 293 struct ip_hdr *iphdr; 294 if (ntohs(ethhdr->type) == ETHTYPE_IP) { 295 iphdr = (struct ip_hdr *)((void *)ethhdr + 14); 296 return snprintf(str, size, 297 "%s: s:%3d.%3d.%3d.%3d %3d.%3d.%3d.%3d l:%5d" 298 " i:%04x p:%04x c:%04x hl:%3d" 299 " %c%c%s\n", head, 300 ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src), 301 ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), 302 ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest), 303 ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), 304 ntohs(IPH_LEN(iphdr)), ntohs(IPH_ID(iphdr)), 305 IPH_PROTO(iphdr), ntohs(IPH_CHKSUM(iphdr)), 306 (IPH_HL(iphdr) << 2), 307 dir, status, tail); 308 } else { 309 return 0; 310 } 311} 312 313int snprintf_icmp_hdr(char *str, size_t size, char head[], 314 struct eth_hdr *ethhdr, char dir, 315 char status, char tail[]) 316{ 317 struct ip_hdr *iphdr; 318 struct icmp_echo_hdr *icmphdr; 319 if (ntohs(ethhdr->type) == ETHTYPE_IP) { 320 iphdr = (struct ip_hdr *)((void *)ethhdr + 14); 321 if (IPH_PROTO(iphdr) == IP_PROTO_ICMP) { 322 icmphdr = (struct icmp_echo_hdr *)((void *)iphdr + (IPH_HL(iphdr) << 2)); 323 return snprintf(str, size, 324 "%s: t:%02x c:%02x k:%04x" 325 " i:%04x s:%04x " 326 " %c%c%s\n", head, 327 icmphdr->type, icmphdr->code, ntohs(icmphdr->chksum), 328 ntohs(icmphdr->id), ntohs(icmphdr->seqno), 329 dir, status, tail); 330 } else { 331 return 0; 332 } 333 } else { 334 return 0; 335 } 336} 337 338int snprintf_tcp_hdr(char *str, size_t size, char head[], 339 struct eth_hdr *ethhdr, char dir, 340 char status, char tail[]) 341{ 342 struct ip_hdr *iphdr; 343 struct tcp_hdr *tcphdr; 344 if (ntohs(ethhdr->type) == ETHTYPE_IP) { 345 iphdr = (struct ip_hdr *)((void *)ethhdr + 14); 346 if (IPH_PROTO(iphdr) == IP_PROTO_TCP) { 347 tcphdr = (struct tcp_hdr *)((void *)iphdr + (IPH_HL(iphdr) << 2)); 348 u16_t lenfl = ntohs(tcphdr->_hdrlen_rsvd_flags); 349 return snprintf(str, size, 350 "%s: s:%5d %5d q:%08x a:%08x lf:%04x k:%04x" 351 " %c%c%s\n", head, 352 ntohs(tcphdr->src), ntohs(tcphdr->dest), 353 ntohl(tcphdr->seqno), ntohl(tcphdr->ackno), 354 lenfl, ntohs(tcphdr->chksum), 355 dir, status, tail); 356 } else { 357 return 0; 358 } 359 } else { 360 return 0; 361 } 362} 363 364int snprintf_udp_hdr(char *str, size_t size, char head[], 365 struct eth_hdr *ethhdr, char dir, 366 char status, char tail[]) 367{ 368 struct ip_hdr *iphdr; 369 struct udp_hdr *udphdr; 370 if (ntohs(ethhdr->type) == ETHTYPE_IP) { 371 iphdr = (struct ip_hdr *)((void *)ethhdr + 14); 372 if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { 373 udphdr = (struct udp_hdr *)((void *)iphdr + (IPH_HL(iphdr) << 2)); 374 return snprintf(str, size, 375 "%s: s:%5d %5d l:%d c:%04x" 376 " %c%c%s\n", head, 377 ntohs(udphdr->src), ntohs(udphdr->dest), 378 ntohs(udphdr->len), ntohs(udphdr->chksum), 379 dir, status, tail); 380 } else { 381 return 0; 382 } 383 } else { 384 return 0; 385 } 386} 387#endif /* UNDIIF_ID_FULL_DEBUG */ 388 389/** 390 * In this function, the hardware should be initialized. 391 * Called from undiif_init(). 392 * 393 * @param netif the already initialized lwip network interface structure 394 * for this undiif 395 */ 396static void 397low_level_init(struct netif *netif) 398{ 399 static __lowmem t_PXENV_UNDI_OPEN undi_open; 400 int i; 401 402 /* MAC_type and MAC_len should always match what is returned by 403 * PXENV_UNDI_GET_INFORMATION. At the moment the both seem to be 404 * reliable but if they disagree that is a sign of a nasty bug 405 * somewhere so abort. 406 */ 407 /* If we are in conflict abort */ 408 if (MAC_type != pxe_undi_info.HwType) { 409 printf("HwType conflicit: %u != %u\n", 410 MAC_type, pxe_undi_info.HwType); 411 kaboom(); 412 } 413 if (MAC_len != pxe_undi_info.HwAddrLen) { 414 printf("HwAddrLen conflict: %u != %u\n", 415 MAC_len, pxe_undi_info.HwAddrLen); 416 kaboom(); 417 } 418 419 /* set MAC hardware address length */ 420 netif->hwaddr_len = MAC_len; 421 422 /* set MAC hardware address */ 423 memcpy(netif->hwaddr, MAC, MAC_len); 424 425 /* maximum transfer unit */ 426 netif->mtu = pxe_undi_info.MaxTranUnit; 427 428 dprintf("UNDI: hw address"); 429 for (i = 0; i < netif->hwaddr_len; i++) 430 dprintf("%c%02x", i ? ':' : ' ', (uint8_t)netif->hwaddr[i]); 431 dprintf("\n"); 432 433 /* device capabilities */ 434 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP; 435 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ 436 if (undi_is_ethernet(netif)) 437 netif->flags |= NETIF_FLAG_ETHARP; 438 439 /* Install the interrupt vector */ 440 pxe_start_isr(); 441 442 /* Open the UNDI stack - you'd think the BC would have done this... */ 443 undi_open.PktFilter = 0x0003; /* FLTR_DIRECTED | FLTR_BRDCST */ 444 pxe_call(PXENV_UNDI_OPEN, &undi_open); 445} 446 447/** 448 * This function should do the actual transmission of the packet. The packet is 449 * contained in the pbuf that is passed to the function. This pbuf 450 * might be chained. 451 * 452 * @param netif the lwip network interface structure for this undiif 453 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) 454 * @return ERR_OK if the packet could be sent 455 * an err_t value if the packet couldn't be sent 456 * 457 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to 458 * strange results. You might consider waiting for space in the DMA queue 459 * to become availale since the stack doesn't retry to send a packet 460 * dropped because of memory failure (except for the TCP timers). 461 */ 462extern volatile uint32_t pxe_irq_count; 463extern volatile uint8_t pxe_need_poll; 464 465static err_t 466undi_transmit(struct netif *netif, struct pbuf *pbuf, 467 hwaddr_t *dest, uint16_t undi_protocol) 468{ 469 struct pxe_xmit { 470 t_PXENV_UNDI_TRANSMIT xmit; 471 t_PXENV_UNDI_TBD tbd; 472 }; 473 static __lowmem struct pxe_xmit pxe; 474 static __lowmem hwaddr_t low_dest; 475 static __lowmem char pkt_buf[PKTBUF_SIZE]; 476 uint32_t now; 477 static uint32_t first_xmit; 478#if LWIP_UNDIIF_DBG(UNDIIF_ID_FULL_DEBUG) 479 char *str = malloc(UNIDIF_ID_STRLEN); 480 int strpos = 0; 481 struct eth_hdr *ethhdr = pbuf->payload; 482 483 484 strpos += snprintf(str + strpos, UNIDIF_ID_STRLEN - strpos, 485 "undi xmit thd '%s'\n", current()->name); 486 strpos += snprintf_eth_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 487 "undi", ethhdr, 'x', '0', ""); 488 strpos += snprintf_arp_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 489 " arp", ethhdr, 'x', '0', ""); 490 strpos += snprintf_ip_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 491 " ip", ethhdr, 'x', '0', ""); 492 strpos += snprintf_icmp_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 493 " icmp", ethhdr, 'x', '0', ""); 494 strpos += snprintf_tcp_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 495 " tcp", ethhdr, 'x', '0', ""); 496 strpos += snprintf_udp_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 497 " udp", ethhdr, 'x', '0', ""); 498 LWIP_DEBUGF(UNDIIF_ID_FULL_DEBUG, ("%s", str)); 499 free(str); 500#endif /* UNDIIF_ID_FULL_DEBUG */ 501 502 /* Drop jumbo frames */ 503 if ((pbuf->tot_len > sizeof(pkt_buf)) || (pbuf->tot_len > netif->mtu)) 504 return ERR_ARG; 505 506 if (__unlikely(!pxe_irq_count)) { 507 now = ms_timer(); 508 if (!first_xmit) { 509 first_xmit = now; 510 } else if (now - first_xmit > 3000) { 511 /* 3 seconds after first transmit, and no interrupts */ 512 LWIP_PLATFORM_DIAG(("undiif: forcing polling\n")); 513 asm volatile("orb $1,%0" : "+m" (pxe_need_poll)); 514 asm volatile("incl %0" : "+m" (pxe_irq_count)); 515 } 516 } 517 518 pbuf_copy_partial( pbuf, pkt_buf, pbuf->tot_len, 0); 519 if (dest) 520 memcpy(low_dest, dest, netif->hwaddr_len); 521 522 do { 523 memset(&pxe, 0, sizeof pxe); 524 525 pxe.xmit.Protocol = undi_protocol; 526 pxe.xmit.XmitFlag = dest? XMT_DESTADDR : XMT_BROADCAST; 527 pxe.xmit.DestAddr = FAR_PTR(&low_dest); 528 pxe.xmit.TBD = FAR_PTR(&pxe.tbd); 529 pxe.tbd.ImmedLength = pbuf->tot_len; 530 pxe.tbd.Xmit = FAR_PTR(pkt_buf); 531 532 pxe_call(PXENV_UNDI_TRANSMIT, &pxe.xmit); 533 } while (pxe.xmit.Status == PXENV_STATUS_OUT_OF_RESOURCES); 534 535 LINK_STATS_INC(link.xmit); 536 537 return ERR_OK; 538} 539 540static err_t 541undi_send_unknown(struct netif *netif, struct pbuf *pbuf) 542{ 543 return undi_transmit(netif, pbuf, NULL, P_UNKNOWN); 544} 545 546static err_t 547undi_send_ip(struct netif *netif, struct pbuf *pbuf, hwaddr_t *dst) 548{ 549 return undi_transmit(netif, pbuf, dst, P_IP); 550} 551 552static err_t 553undi_send_arp(struct netif *netif, struct pbuf *pbuf, hwaddr_t *dst) 554{ 555 return undi_transmit(netif, pbuf, dst, P_ARP); 556} 557 558/** 559 * Send an ARP request packet asking for ipaddr. 560 * 561 * @param netif the lwip network interface on which to send the request 562 * @param ipaddr the IP address for which to ask 563 * @return ERR_OK if the request has been sent 564 * ERR_MEM if the ARP packet couldn't be allocated 565 * any other err_t on failure 566 */ 567static err_t 568undiarp_request(struct netif *netif, struct ip_addr *ipaddr) 569{ 570 struct pbuf *p; 571 err_t result = ERR_OK; 572 struct arp_hdr *hdr; 573 u8_t *hdr_ptr; 574 575 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_request: sending ARP request.\n")); 576 577 /* allocate a pbuf for the outgoing ARP request packet */ 578 p = pbuf_alloc(PBUF_RAW, arp_hdr_len(netif), PBUF_RAM); 579 /* could allocate a pbuf for an ARP request? */ 580 if (p == NULL) { 581 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, 582 ("undiarp_raw: could not allocate pbuf for ARP request.\n")); 583 ETHARP_STATS_INC(etharp.memerr); 584 return ERR_MEM; 585 } 586 LWIP_ASSERT("check that first pbuf can hold arp_hdr_len bytesr", 587 (p->len >= arp_hdr_len(netif))); 588 589 hdr = p->payload; 590 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_request: sending raw ARP packet.\n")); 591 hdr->opcode = htons(ARP_REQUEST); 592 hdr->hwtype = htons(MAC_type); 593 hdr->proto = htons(ETHTYPE_IP); 594 hdr->hwlen = netif->hwaddr_len; 595 hdr->protolen = sizeof(struct ip_addr); 596 597 hdr_ptr = (unsigned char *)(hdr + 1); 598 memcpy(hdr_ptr, netif->hwaddr, netif->hwaddr_len); 599 hdr_ptr += netif->hwaddr_len; 600 memcpy(hdr_ptr, &netif->ip_addr, 4); 601 hdr_ptr += 4; 602 memset(hdr_ptr, 0, netif->hwaddr_len); 603 hdr_ptr += netif->hwaddr_len; 604 memcpy(hdr_ptr, ipaddr, 4); 605 606 /* send ARP query */ 607 result = undi_send_arp(netif, p, NULL); 608 ETHARP_STATS_INC(etharp.xmit); 609 /* free ARP query packet */ 610 pbuf_free(p); 611 p = NULL; 612 /* could not allocate pbuf for ARP request */ 613 614 return result; 615} 616 617#if ARP_QUEUEING 618/** 619 * Free a complete queue of etharp entries 620 * 621 * @param q a qeueue of etharp_q_entry's to free 622 */ 623static void 624free_undiarp_q(struct etharp_q_entry *q) 625{ 626 struct etharp_q_entry *r; 627 LWIP_ASSERT("q != NULL", q != NULL); 628 LWIP_ASSERT("q->p != NULL", q->p != NULL); 629 while (q) { 630 r = q; 631 q = q->next; 632 LWIP_ASSERT("r->p != NULL", (r->p != NULL)); 633 pbuf_free(r->p); 634 memp_free(MEMP_ARP_QUEUE, r); 635 } 636} 637#endif 638 639/** 640 * Clears expired entries in the ARP table. 641 * 642 * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds), 643 * in order to expire entries in the ARP table. 644 */ 645void 646undiarp_tmr(void) 647{ 648 u8_t i; 649 650 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG, ("undiarp_timer\n")); 651 /* remove expired entries from the ARP table */ 652 for (i = 0; i < ARP_TABLE_SIZE; ++i) { 653 arp_table[i].ctime++; 654 if (((arp_table[i].state == UNDIARP_STATE_STABLE) && 655 (arp_table[i].ctime >= UNDIARP_MAXAGE)) || 656 ((arp_table[i].state == UNDIARP_STATE_PENDING) && 657 (arp_table[i].ctime >= UNDIARP_MAXPENDING))) { 658 /* pending or stable entry has become old! */ 659 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG , ("undiarp_timer: expired %s entry %"U16_F".\n", 660 arp_table[i].state == UNDIARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); 661 /* clean up entries that have just been expired */ 662 /* remove from SNMP ARP index tree */ 663 snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); 664#if ARP_QUEUEING 665 /* and empty packet queue */ 666 if (arp_table[i].q != NULL) { 667 /* remove all queued packets */ 668 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG , ("undiarp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); 669 free_undiarp_q(arp_table[i].q); 670 arp_table[i].q = NULL; 671 } 672#endif 673 /* recycle entry for re-use */ 674 arp_table[i].state = UNDIARP_STATE_EMPTY; 675 } 676#if ARP_QUEUEING 677 /* still pending entry? (not expired) */ 678 if (arp_table[i].state == UNDIARP_STATE_PENDING) { 679 /* resend an ARP query here? */ 680 } 681#endif 682 } 683} 684 685/** 686 * Search the ARP table for a matching or new entry. 687 * 688 * If an IP address is given, return a pending or stable ARP entry that matches 689 * the address. If no match is found, create a new entry with this address set, 690 * but in state ETHARP_EMPTY. The caller must check and possibly change the 691 * state of the returned entry. 692 * 693 * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. 694 * 695 * In all cases, attempt to create new entries from an empty entry. If no 696 * empty entries are available and UNDIARP_TRY_HARD flag is set, recycle 697 * old entries. Heuristic choose the least important entry for recycling. 698 * 699 * @param ipaddr IP address to find in ARP cache, or to add if not found. 700 * @param flags 701 * - UNDIARP_TRY_HARD: Try hard to create a entry by allowing recycling of 702 * active (stable or pending) entries. 703 * 704 * @return The ARP entry index that matched or is created, ERR_MEM if no 705 * entry is found or could be recycled. 706 */ 707static s8_t 708#if LWIP_NETIF_HWADDRHINT 709find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif) 710#else /* LWIP_NETIF_HWADDRHINT */ 711find_entry(struct ip_addr *ipaddr, u8_t flags) 712#endif /* LWIP_NETIF_HWADDRHINT */ 713{ 714 s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; 715 s8_t empty = ARP_TABLE_SIZE; 716 u8_t i = 0, age_pending = 0, age_stable = 0; 717#if ARP_QUEUEING 718 /* oldest entry with packets on queue */ 719 s8_t old_queue = ARP_TABLE_SIZE; 720 /* its age */ 721 u8_t age_queue = 0; 722#endif 723 724 /* First, test if the last call to this function asked for the 725 * same address. If so, we're really fast! */ 726 if (ipaddr) { 727 /* ipaddr to search for was given */ 728#if LWIP_NETIF_HWADDRHINT 729 if ((netif != NULL) && (netif->addr_hint != NULL)) { 730 /* per-pcb cached entry was given */ 731 u8_t per_pcb_cache = *(netif->addr_hint); 732 if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == UNDIARP_STATE_STABLE) { 733 /* the per-pcb-cached entry is stable */ 734 if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) { 735 /* per-pcb cached entry was the right one! */ 736 ETHARP_STATS_INC(etharp.cachehit); 737 return per_pcb_cache; 738 } 739 } 740 } 741#else /* #if LWIP_NETIF_HWADDRHINT */ 742 if (arp_table[undiarp_cached_entry].state == UNDIARP_STATE_STABLE) { 743 /* the cached entry is stable */ 744 if (ip_addr_cmp(ipaddr, &arp_table[undiarp_cached_entry].ipaddr)) { 745 /* cached entry was the right one! */ 746 ETHARP_STATS_INC(etharp.cachehit); 747 return undiarp_cached_entry; 748 } 749 } 750#endif /* #if LWIP_NETIF_HWADDRHINT */ 751 } 752 753 /** 754 * a) do a search through the cache, remember candidates 755 * b) select candidate entry 756 * c) create new entry 757 */ 758 759 /* a) in a single search sweep, do all of this 760 * 1) remember the first empty entry (if any) 761 * 2) remember the oldest stable entry (if any) 762 * 3) remember the oldest pending entry without queued packets (if any) 763 * 4) remember the oldest pending entry with queued packets (if any) 764 * 5) search for a matching IP entry, either pending or stable 765 * until 5 matches, or all entries are searched for. 766 */ 767 768 for (i = 0; i < ARP_TABLE_SIZE; ++i) { 769 /* no empty entry found yet and now we do find one? */ 770 if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == UNDIARP_STATE_EMPTY)) { 771 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG , ("find_entry: found empty entry %"U16_F"\n", (u16_t)i)); 772 /* remember first empty entry */ 773 empty = i; 774 } 775 /* pending entry? */ 776 else if (arp_table[i].state == UNDIARP_STATE_PENDING) { 777 /* if given, does IP address match IP address in ARP entry? */ 778 if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 779 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i)); 780 /* found exact IP address match, simply bail out */ 781#if LWIP_NETIF_HWADDRHINT 782 NETIF_SET_HINT(netif, i); 783#else /* #if LWIP_NETIF_HWADDRHINT */ 784 undiarp_cached_entry = i; 785#endif /* #if LWIP_NETIF_HWADDRHINT */ 786 return i; 787#if ARP_QUEUEING 788 /* pending with queued packets? */ 789 } else if (arp_table[i].q != NULL) { 790 if (arp_table[i].ctime >= age_queue) { 791 old_queue = i; 792 age_queue = arp_table[i].ctime; 793 } 794#endif 795 /* pending without queued packets? */ 796 } else { 797 if (arp_table[i].ctime >= age_pending) { 798 old_pending = i; 799 age_pending = arp_table[i].ctime; 800 } 801 } 802 } 803 /* stable entry? */ 804 else if (arp_table[i].state == UNDIARP_STATE_STABLE) { 805 /* if given, does IP address match IP address in ARP entry? */ 806 if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { 807 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i)); 808 /* found exact IP address match, simply bail out */ 809#if LWIP_NETIF_HWADDRHINT 810 NETIF_SET_HINT(netif, i); 811#else /* #if LWIP_NETIF_HWADDRHINT */ 812 undiarp_cached_entry = i; 813#endif /* #if LWIP_NETIF_HWADDRHINT */ 814 return i; 815 /* remember entry with oldest stable entry in oldest, its age in maxtime */ 816 } else if (arp_table[i].ctime >= age_stable) { 817 old_stable = i; 818 age_stable = arp_table[i].ctime; 819 } 820 } 821 } 822 /* { we have no match } => try to create a new entry */ 823 824 /* no empty entry found and not allowed to recycle? */ 825 if (((empty == ARP_TABLE_SIZE) && ((flags & UNDIARP_TRY_HARD) == 0)) 826 /* or don't create new entry, only search? */ 827 || ((flags & UNDIARP_FIND_ONLY) != 0)) { 828 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n")); 829 return (s8_t)ERR_MEM; 830 } 831 832 /* b) choose the least destructive entry to recycle: 833 * 1) empty entry 834 * 2) oldest stable entry 835 * 3) oldest pending entry without queued packets 836 * 4) oldest pending entry with queued packets 837 * 838 * { UNDIARP_TRY_HARD is set at this point } 839 */ 840 841 /* 1) empty entry available? */ 842 if (empty < ARP_TABLE_SIZE) { 843 i = empty; 844 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); 845 } 846 /* 2) found recyclable stable entry? */ 847 else if (old_stable < ARP_TABLE_SIZE) { 848 /* recycle oldest stable*/ 849 i = old_stable; 850 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); 851#if ARP_QUEUEING 852 /* no queued packets should exist on stable entries */ 853 LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); 854#endif 855 /* 3) found recyclable pending entry without queued packets? */ 856 } else if (old_pending < ARP_TABLE_SIZE) { 857 /* recycle oldest pending */ 858 i = old_pending; 859 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); 860#if ARP_QUEUEING 861 /* 4) found recyclable pending entry with queued packets? */ 862 } else if (old_queue < ARP_TABLE_SIZE) { 863 /* recycle oldest pending */ 864 i = old_queue; 865 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); 866 free_undiarp_q(arp_table[i].q); 867 arp_table[i].q = NULL; 868#endif 869 /* no empty or recyclable entries found */ 870 } else { 871 return (s8_t)ERR_MEM; 872 } 873 874 /* { empty or recyclable entry found } */ 875 LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); 876 877 if (arp_table[i].state != UNDIARP_STATE_EMPTY) 878 { 879 snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); 880 } 881 /* recycle entry (no-op for an already empty entry) */ 882 arp_table[i].state = UNDIARP_STATE_EMPTY; 883 884 /* IP address given? */ 885 if (ipaddr != NULL) { 886 /* set IP address */ 887 ip_addr_set(&arp_table[i].ipaddr, ipaddr); 888 } 889 arp_table[i].ctime = 0; 890#if LWIP_NETIF_HWADDRHINT 891 NETIF_SET_HINT(netif, i); 892#else /* #if LWIP_NETIF_HWADDRHINT */ 893 undiarp_cached_entry = i; 894#endif /* #if LWIP_NETIF_HWADDRHINT */ 895 return (err_t)i; 896} 897 898 899/** 900 * Send an ARP request for the given IP address and/or queue a packet. 901 * 902 * If the IP address was not yet in the cache, a pending ARP cache entry 903 * is added and an ARP request is sent for the given address. The packet 904 * is queued on this entry. 905 * 906 * If the IP address was already pending in the cache, a new ARP request 907 * is sent for the given address. The packet is queued on this entry. 908 * 909 * If the IP address was already stable in the cache, and a packet is 910 * given, it is directly sent and no ARP request is sent out. 911 * 912 * If the IP address was already stable in the cache, and no packet is 913 * given, an ARP request is sent out. 914 * 915 * @param netif The lwIP network interface on which ipaddr 916 * must be queried for. 917 * @param ipaddr The IP address to be resolved. 918 * @param q If non-NULL, a pbuf that must be delivered to the IP address. 919 * q is not freed by this function. 920 * 921 * @note q must only be ONE packet, not a packet queue! 922 * 923 * @return 924 * - ERR_BUF Could not make room for Ethernet header. 925 * - ERR_MEM Hardware address unknown, and no more ARP entries available 926 * to query for address or queue the packet. 927 * - ERR_MEM Could not queue packet due to memory shortage. 928 * - ERR_RTE No route to destination (no gateway to external networks). 929 * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. 930 * 931 */ 932static err_t 933undiarp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) 934{ 935 err_t result = ERR_MEM; 936 s8_t i; /* ARP entry index */ 937 938 /* non-unicast address? */ 939 if (ip_addr_isbroadcast(ipaddr, netif) || 940 ip_addr_ismulticast(ipaddr) || 941 ip_addr_isany(ipaddr)) { 942 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_query: will not add non-unicast IP address to ARP cache\n")); 943 return ERR_ARG; 944 } 945 946 /* find entry in ARP cache, ask to create entry if queueing packet */ 947#if LWIP_NETIF_HWADDRHINT 948 i = find_entry(ipaddr, UNDIARP_TRY_HARD, netif); 949#else /* LWIP_NETIF_HWADDRHINT */ 950 i = find_entry(ipaddr, UNDIARP_TRY_HARD); 951#endif /* LWIP_NETIF_HWADDRHINT */ 952 953 /* could not find or create entry? */ 954 if (i < 0) { 955 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_query: could not create ARP entry\n")); 956 if (q) { 957 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_query: packet dropped\n")); 958 ETHARP_STATS_INC(etharp.memerr); 959 } 960 return (err_t)i; 961 } 962 963 /* mark a fresh entry as pending (we just sent a request) */ 964 if (arp_table[i].state == UNDIARP_STATE_EMPTY) { 965 arp_table[i].state = UNDIARP_STATE_PENDING; 966 } 967 968 /* { i is either a STABLE or (new or existing) PENDING entry } */ 969 LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", 970 ((arp_table[i].state == UNDIARP_STATE_PENDING) || 971 (arp_table[i].state == UNDIARP_STATE_STABLE))); 972 973 /* do we have a pending entry? or an implicit query request? */ 974 if ((arp_table[i].state == UNDIARP_STATE_PENDING) || (q == NULL)) { 975 /* try to resolve it; send out ARP request */ 976 result = undiarp_request(netif, ipaddr); 977 if (result != ERR_OK) { 978 /* ARP request couldn't be sent */ 979 /* We don't re-send arp request in undiarp_tmr, but we still queue packets, 980 since this failure could be temporary, and the next packet calling 981 etharp_query again could lead to sending the queued packets. */ 982 } 983 } 984 985 /* packet given? */ 986 if (q != NULL) { 987 /* stable entry? */ 988 if (arp_table[i].state == UNDIARP_STATE_STABLE) { 989 /* we have a valid IP->hardware address mapping */ 990 /* send the packet */ 991 result = undi_send_ip(netif, q, &(arp_table[i].hwaddr)); 992 /* pending entry? (either just created or already pending */ 993 } else if (arp_table[i].state == UNDIARP_STATE_PENDING) { 994#if ARP_QUEUEING /* queue the given q packet */ 995 struct pbuf *p; 996 int copy_needed = 0; 997 /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but 998 * to copy the whole queue into a new PBUF_RAM (see bug #11400) 999 * PBUF_ROMs can be left as they are, since ROM must not get changed. */ 1000 p = q; 1001 while (p) { 1002 LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); 1003 if(p->type != PBUF_ROM) { 1004 copy_needed = 1; 1005 break; 1006 } 1007 p = p->next; 1008 } 1009 if(copy_needed) { 1010 /* copy the whole packet into new pbufs */ 1011 p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 1012 if(p != NULL) { 1013 if (pbuf_copy(p, q) != ERR_OK) { 1014 pbuf_free(p); 1015 p = NULL; 1016 } 1017 } 1018 } else { 1019 /* referencing the old pbuf is enough */ 1020 p = q; 1021 pbuf_ref(p); 1022 } 1023 /* packet could be taken over? */ 1024 if (p != NULL) { 1025 /* queue packet ... */ 1026 struct etharp_q_entry *new_entry; 1027 /* allocate a new arp queue entry */ 1028 new_entry = memp_malloc(MEMP_ARP_QUEUE); 1029 if (new_entry != NULL) { 1030 new_entry->next = 0; 1031 new_entry->p = p; 1032 if(arp_table[i].q != NULL) { 1033 /* queue was already existent, append the new entry to the end */ 1034 struct etharp_q_entry *r; 1035 r = arp_table[i].q; 1036 while (r->next != NULL) { 1037 r = r->next; 1038 } 1039 r->next = new_entry; 1040 } else { 1041 /* queue did not exist, first item in queue */ 1042 arp_table[i].q = new_entry; 1043 } 1044 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); 1045 result = ERR_OK; 1046 } else { 1047 /* the pool MEMP_ARP_QUEUE is empty */ 1048 pbuf_free(p); 1049 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); 1050 /* { result == ERR_MEM } through initialization */ 1051 } 1052 } else { 1053 ETHARP_STATS_INC(etharp.memerr); 1054 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); 1055 /* { result == ERR_MEM } through initialization */ 1056 } 1057#else /* ARP_QUEUEING == 0 */ 1058 /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */ 1059 /* { result == ERR_MEM } through initialization */ 1060 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q)); 1061#endif 1062 } 1063 } 1064 return result; 1065} 1066 1067/** 1068 * Resolve and fill-in address header for outgoing IP packet. 1069 * 1070 * For IP multicast and broadcast, corresponding Ethernet addresses 1071 * are selected and the packet is transmitted on the link. 1072 * 1073 * For unicast addresses, the packet is submitted to etharp_query(). In 1074 * case the IP address is outside the local network, the IP address of 1075 * the gateway is used. 1076 * 1077 * @param netif The lwIP network interface which the IP packet will be sent on. 1078 * @param q The pbuf(s) containing the IP packet to be sent. 1079 * @param ipaddr The IP address of the packet destination. 1080 * 1081 * @return 1082 * - ERR_RTE No route to destination (no gateway to external networks), 1083 * or the return type of either etharp_query() or etharp_send_ip(). 1084 */ 1085static err_t 1086undiarp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr) 1087{ 1088 static __lowmem t_PXENV_UNDI_GET_MCAST_ADDR get_mcast; 1089 hwaddr_t *dest; 1090 1091 if (undi_is_ethernet(netif)) 1092 return etharp_output(netif, q, ipaddr); 1093 1094 /* Assume unresolved hardware address */ 1095 dest = NULL; 1096 1097 /* Determine on destination hardware address. Broadcasts and multicasts 1098 * are special, other IP addresses are looked up in the ARP table. 1099 */ 1100 if (ip_addr_isbroadcast(ipaddr, netif)) { 1101 dest = NULL; 1102 } 1103 else if (ip_addr_ismulticast(ipaddr)) { 1104 memset(&get_mcast, 0, sizeof get_mcast); 1105 memcpy(&get_mcast.InetAddr, ipaddr, sizeof(get_mcast.InetAddr)); 1106 pxe_call(PXENV_UNDI_GET_MCAST_ADDR, &get_mcast); 1107 dest = (hwaddr_t *)&get_mcast.MediaAddr; 1108 } 1109 else { 1110 /* outside local network? */ 1111 if (!ip_addr_netcmp(ipaddr, &netif->ip_addr, &netif->netmask)) { 1112 /* interface has default gateway? */ 1113 if (netif->gw.addr != 0) { 1114 /* send to hardware address of default gateway IP address */ 1115 ipaddr = &(netif->gw); 1116 /* no default gateway available */ 1117 } else { 1118 /* no route to destination error (default gateway missing) */ 1119 return ERR_RTE; 1120 } 1121 } 1122 /* queue on destination Ethernet address belonging to ipaddr */ 1123 return undiarp_query(netif, ipaddr, q); 1124 } 1125 1126 /* continuation for multicast/broadcast destinations */ 1127 /* obtain source Ethernet address of the given interface */ 1128 /* send packet directly on the link */ 1129 return undi_send_ip(netif, q, dest); 1130} 1131 1132static void get_packet_fragment(t_PXENV_UNDI_ISR *isr) 1133{ 1134 do { 1135 isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; 1136 pxe_call(PXENV_UNDI_ISR, &isr); 1137 } while (isr->FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE); 1138} 1139 1140/** 1141 * Should allocate a pbuf and transfer the bytes of the incoming 1142 * packet from the interface into the pbuf. 1143 * 1144 * @param netif the lwip network interface structure for this undiif 1145 * @return a pbuf filled with the received packet (including MAC header) 1146 * NULL on memory error 1147 */ 1148static struct pbuf * 1149low_level_input(t_PXENV_UNDI_ISR *isr) 1150{ 1151 struct pbuf *p, *q; 1152 const char *r; 1153 int len; 1154 1155 /* Obtain the size of the packet and put it into the "len" 1156 variable. */ 1157 len = isr->FrameLength; 1158 1159 //printf("undiif_input, len = %d\n", len); 1160 1161 /* We allocate a pbuf chain of pbufs from the pool. */ 1162 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); 1163 1164 if (p != NULL) { 1165 /* 1166 * We iterate over the pbuf chain until we have read the entire 1167 * packet into the pbuf. 1168 */ 1169 r = GET_PTR(isr->Frame); 1170 for (q = p; q != NULL; q = q->next) { 1171 /* 1172 * Read enough bytes to fill this pbuf in the chain. The 1173 * available data in the pbuf is given by the q->len 1174 * variable. 1175 */ 1176 char *s = q->payload; 1177 int ql = q->len; 1178 1179 while (ql) { 1180 int qb = isr->BufferLength < ql ? isr->BufferLength : ql; 1181 1182 if (!qb) { 1183 /* 1184 * Only received a partial frame, must get the next one... 1185 */ 1186 get_packet_fragment(isr); 1187 r = GET_PTR(isr->Frame); 1188 } else { 1189 memcpy(s, r, qb); 1190 s += qb; 1191 r += qb; 1192 ql -= qb; 1193 } 1194 } 1195 } 1196 1197 LINK_STATS_INC(link.recv); 1198 } else { 1199 /* 1200 * Dropped packet: we really should make sure we drain any partial 1201 * frame here... 1202 */ 1203 while ((len -= isr->BufferLength) > 0) 1204 get_packet_fragment(isr); 1205 1206 LINK_STATS_INC(link.memerr); 1207 LINK_STATS_INC(link.drop); 1208 } 1209 1210 return p; 1211} 1212 1213 1214/** 1215 * Update (or insert) a IP/MAC address pair in the ARP cache. 1216 * 1217 * If a pending entry is resolved, any queued packets will be sent 1218 * at this point. 1219 * 1220 * @param ipaddr IP address of the inserted ARP entry. 1221 * @param ethaddr Ethernet address of the inserted ARP entry. 1222 * @param flags Defines behaviour: 1223 * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified, 1224 * only existing ARP entries will be updated. 1225 * 1226 * @return 1227 * - ERR_OK Succesfully updated ARP cache. 1228 * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set. 1229 * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. 1230 * 1231 * @see pbuf_free() 1232 */ 1233static err_t 1234update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, 1235 hwaddr_t *lladdr, u8_t flags) 1236{ 1237 s8_t i; 1238 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiif:update_arp_entry()\n")); 1239 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiif:update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", 1240 ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr), 1241 (*lladdr)[0], (*lladdr)[1], (*lladdr)[2], 1242 (*lladdr)[3], (*lladdr)[4], (*lladdr)[5])); 1243 /* non-unicast address? */ 1244 if (ip_addr_isany(ipaddr) || 1245 ip_addr_isbroadcast(ipaddr, netif) || 1246 ip_addr_ismulticast(ipaddr)) { 1247 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiif:update_arp_entry: will not add non-unicast IP address to ARP cache\n")); 1248 return ERR_ARG; 1249 } 1250 /* find or create ARP entry */ 1251#if LWIP_NETIF_HWADDRHINT 1252 i = find_entry(ipaddr, flags, netif); 1253#else /* LWIP_NETIF_HWADDRHINT */ 1254 i = find_entry(ipaddr, flags); 1255#endif /* LWIP_NETIF_HWADDRHINT */ 1256 /* bail out if no entry could be found */ 1257 if (i < 0) 1258 return (err_t)i; 1259 1260 /* mark it stable */ 1261 arp_table[i].state = UNDIARP_STATE_STABLE; 1262 /* record network interface */ 1263 arp_table[i].netif = netif; 1264 1265 /* insert in SNMP ARP index tree */ 1266 snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); 1267 1268 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiif:update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); 1269 /* update address */ 1270 memcpy(arp_table[i].hwaddr, lladdr, netif->hwaddr_len); 1271 1272 /* reset time stamp */ 1273 arp_table[i].ctime = 0; 1274#if ARP_QUEUEING 1275 /* this is where we will send out queued packets! */ 1276 while (arp_table[i].q != NULL) { 1277 struct pbuf *p; 1278 /* remember remainder of queue */ 1279 struct etharp_q_entry *q = arp_table[i].q; 1280 /* pop first item off the queue */ 1281 arp_table[i].q = q->next; 1282 /* get the packet pointer */ 1283 p = q->p; 1284 /* now queue entry can be freed */ 1285 memp_free(MEMP_ARP_QUEUE, q); 1286 /* send the queued IP packet */ 1287 undi_send_ip(netif, p, lladdr); 1288 /* free the queued IP packet */ 1289 pbuf_free(p); 1290 } 1291#endif 1292 return ERR_OK; 1293} 1294 1295/** 1296 * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache 1297 * send out queued IP packets. Updates cache with snooped address pairs. 1298 * 1299 * Should be called for incoming ARP packets. The pbuf in the argument 1300 * is freed by this function. 1301 * 1302 * @param netif The lwIP network interface on which the ARP packet pbuf arrived. 1303 * @param ethaddr Ethernet address of netif. 1304 * @param p The ARP packet that arrived on netif. Is freed by this function. 1305 * 1306 * @return NULL 1307 * 1308 * @see pbuf_free() 1309 */ 1310static void 1311undiarp_input(struct netif *netif, struct pbuf *p) 1312{ 1313 struct arp_hdr *hdr; 1314 /* these are aligned properly, whereas the ARP header fields might not be */ 1315 struct ip_addr sipaddr, dipaddr; 1316 hwaddr_t hwaddr_remote; 1317 u8_t *hdr_ptr; 1318 u8_t for_us; 1319 1320 LWIP_ERROR("netif != NULL", (netif != NULL), return;); 1321 1322 /* drop short ARP packets: we have to check for p->len instead of p->tot_len here 1323 since a struct arp_hdr is pointed to p->payload, so it musn't be chained! */ 1324 if (p->len < arp_hdr_len(netif)) { 1325 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 1326 ("undiarp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, 1327 (s16_t)SIZEOF_ETHARP_PACKET)); 1328 printf("short arp packet\n"); 1329 ETHARP_STATS_INC(etharp.lenerr); 1330 ETHARP_STATS_INC(etharp.drop); 1331 pbuf_free(p); 1332 return; 1333 } 1334 1335 hdr = p->payload; 1336 /* RFC 826 "Packet Reception": */ 1337 if ((hdr->hwtype != htons(MAC_type)) || 1338 (hdr->hwlen != netif->hwaddr_len) || 1339 (hdr->protolen != sizeof(struct ip_addr)) || 1340 (hdr->proto != htons(ETHTYPE_IP))) { 1341 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, 1342 ("undiarp_input: packet dropped, wrong hw type, hwlen, proto, or protolen (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", 1343 hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen)); 1344 ETHARP_STATS_INC(etharp.proterr); 1345 ETHARP_STATS_INC(etharp.drop); 1346 printf("malformed arp packet\n"); 1347 pbuf_free(p); 1348 return; 1349 } 1350 ETHARP_STATS_INC(etharp.recv); 1351 1352 /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without 1353 * structure packing (not using structure copy which breaks strict-aliasing rules). */ 1354 hdr_ptr = (unsigned char *)(hdr + 1); 1355 memcpy(hwaddr_remote, hdr_ptr, netif->hwaddr_len); 1356 hdr_ptr += netif->hwaddr_len; 1357 memcpy(&sipaddr, hdr_ptr, sizeof(sipaddr)); 1358 hdr_ptr += sizeof(sipaddr); 1359 hdr_ptr += netif->hwaddr_len; 1360 memcpy(&dipaddr, hdr_ptr, sizeof(dipaddr)); 1361 1362 /* this interface is not configured? */ 1363 if (netif->ip_addr.addr == 0) { 1364 for_us = 0; 1365 } else { 1366 /* ARP packet directed to us? */ 1367 for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr)); 1368 } 1369 1370 /* ARP message directed to us? */ 1371 if (for_us) { 1372 /* add IP address in ARP cache; assume requester wants to talk to us. 1373 * can result in directly sending the queued packets for this host. */ 1374 update_arp_entry(netif, &sipaddr, &hwaddr_remote, UNDIARP_TRY_HARD); 1375 /* ARP message not directed to us? */ 1376 } else { 1377 /* update the source IP address in the cache, if present */ 1378 update_arp_entry(netif, &sipaddr, &hwaddr_remote, 0); 1379 } 1380 1381 /* now act on the message itself */ 1382 switch (htons(hdr->opcode)) { 1383 /* ARP request? */ 1384 case ARP_REQUEST: 1385 /* ARP request. If it asked for our address, we send out a 1386 * reply. In any case, we time-stamp any existing ARP entry, 1387 * and possiby send out an IP packet that was queued on it. */ 1388 1389 LWIP_DEBUGF (UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_input: incoming ARP request\n")); 1390 /* ARP request for our address? */ 1391 if (for_us) { 1392 1393 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_input: replying to ARP request for our IP address\n")); 1394 /* Re-use pbuf to send ARP reply. 1395 Since we are re-using an existing pbuf, we can't call etharp_raw since 1396 that would allocate a new pbuf. */ 1397 hdr->opcode = htons(ARP_REPLY); 1398 hdr_ptr = (unsigned char *)(hdr + 1); 1399 memcpy(hdr_ptr, &netif->hwaddr, netif->hwaddr_len); 1400 hdr_ptr += netif->hwaddr_len; 1401 memcpy(hdr_ptr, &dipaddr, sizeof(dipaddr)); 1402 hdr_ptr += sizeof(dipaddr); 1403 memcpy(hdr_ptr, &hwaddr_remote, netif->hwaddr_len); 1404 hdr_ptr += netif->hwaddr_len; 1405 memcpy(hdr_ptr, &sipaddr, sizeof(sipaddr)); 1406 1407 /* return ARP reply */ 1408 undi_send_arp(netif, p, &hwaddr_remote); 1409 /* we are not configured? */ 1410 } else if (netif->ip_addr.addr == 0) { 1411 /* { for_us == 0 and netif->ip_addr.addr == 0 } */ 1412 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_input: we are unconfigured, ARP request ignored.\n")); 1413 /* request was not directed to us */ 1414 } else { 1415 /* { for_us == 0 and netif->ip_addr.addr != 0 } */ 1416 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_input: ARP request was not for us.\n")); 1417 } 1418 break; 1419 case ARP_REPLY: 1420 /* ARP reply. We already updated the ARP cache earlier. */ 1421 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_input: incoming ARP reply\n")); 1422#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) 1423 /* DHCP wants to know about ARP replies from any host with an 1424 * IP address also offered to us by the DHCP server. We do not 1425 * want to take a duplicate IP address on a single network. 1426 * @todo How should we handle redundant (fail-over) interfaces? */ 1427 dhcp_arp_reply(netif, &sipaddr); 1428#endif 1429 break; 1430 default: 1431 LWIP_DEBUGF(UNDIIF_ARP_DEBUG | UNDIIF_DEBUG | LWIP_DBG_TRACE, ("undiarp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); 1432 ETHARP_STATS_INC(etharp.err); 1433 break; 1434 } 1435 /* free ARP packet */ 1436 pbuf_free(p); 1437} 1438 1439/** 1440 * This function should be called when a packet is ready to be read 1441 * from the interface. It uses the function low_level_input() that 1442 * should handle the actual reception of bytes from the network 1443 * interface. Then the type of the received packet is determined and 1444 * the appropriate input function is called. 1445 * 1446 * @param netif the lwip network interface structure for this undiif 1447 */ 1448void undiif_input(t_PXENV_UNDI_ISR *isr) 1449{ 1450 struct pbuf *p; 1451 u8_t undi_prot; 1452 u16_t llhdr_len; 1453 1454 /* From the first isr capture the essential information */ 1455 undi_prot = isr->ProtType; 1456 llhdr_len = isr->FrameHeaderLength; 1457 1458 /* move received packet into a new pbuf */ 1459 p = low_level_input(isr); 1460 /* no packet could be read, silently ignore this */ 1461 if (p == NULL) return; 1462 1463 if (undi_is_ethernet(&undi_netif)) { 1464 /* points to packet payload, which starts with an Ethernet header */ 1465 struct eth_hdr *ethhdr = p->payload; 1466#if LWIP_UNDIIF_DBG(UNDIIF_ID_FULL_DEBUG) 1467 char *str = malloc(UNIDIF_ID_STRLEN); 1468 int strpos = 0; 1469 1470 strpos += snprintf(str + strpos, UNIDIF_ID_STRLEN - strpos, 1471 "undi recv thd '%s'\n", current()->name); 1472 strpos += snprintf_eth_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 1473 "undi", ethhdr, 'r', '0', ""); 1474 strpos += snprintf_arp_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 1475 " arp", ethhdr, 'r', '0', ""); 1476 strpos += snprintf_ip_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 1477 " ip", ethhdr, 'r', '0', ""); 1478 strpos += snprintf_icmp_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 1479 " icmp", ethhdr, 'r', '0', ""); 1480 strpos += snprintf_tcp_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 1481 " tcp", ethhdr, 'r', '0', ""); 1482 strpos += snprintf_udp_hdr(str + strpos, UNIDIF_ID_STRLEN - strpos, 1483 " udp", ethhdr, 'r', '0', ""); 1484 LWIP_DEBUGF(UNDIIF_ID_FULL_DEBUG, ("%s", str)); 1485 free(str); 1486#endif /* UNDIIF_ID_FULL_DEBUG */ 1487 1488 switch (htons(ethhdr->type)) { 1489 /* IP or ARP packet? */ 1490 case ETHTYPE_IP: 1491 case ETHTYPE_ARP: 1492#if PPPOE_SUPPORT 1493 /* PPPoE packet? */ 1494 case ETHTYPE_PPPOEDISC: 1495 case ETHTYPE_PPPOE: 1496#endif /* PPPOE_SUPPORT */ 1497 /* full packet send to tcpip_thread to process */ 1498 if (tcpip_input(p, &undi_netif)!=ERR_OK) 1499 { LWIP_DEBUGF(UNDIIF_NET_DEBUG | UNDIIF_DEBUG, ("undiif_input: IP input error\n")); 1500 pbuf_free(p); 1501 p = NULL; 1502 } 1503 break; 1504 1505 default: 1506 pbuf_free(p); 1507 p = NULL; 1508 break; 1509 } 1510 } else { 1511 if (pbuf_header(p, -(s16_t)llhdr_len)) { 1512 LWIP_ASSERT("Can't move link level header in packet", 0); 1513 pbuf_free(p); 1514 p = NULL; 1515 } else { 1516 switch(undi_prot) { 1517 case P_IP: 1518 /* pass to IP layer */ 1519 tcpip_input(p, &undi_netif); 1520 break; 1521 1522 case P_ARP: 1523 /* pass p to ARP module */ 1524 undiarp_input(&undi_netif, p); 1525 break; 1526 1527 default: 1528 ETHARP_STATS_INC(etharp.proterr); 1529 ETHARP_STATS_INC(etharp.drop); 1530 pbuf_free(p); 1531 p = NULL; 1532 break; 1533 } 1534 } 1535 } 1536} 1537 1538/** 1539 * Should be called at the beginning of the program to set up the 1540 * network interface. It calls the function low_level_init() to do the 1541 * actual setup of the hardware. 1542 * 1543 * This function should be passed as a parameter to netif_add(). 1544 * 1545 * @param netif the lwip network interface structure for this undiif 1546 * @return ERR_OK if the loopif is initialized 1547 * ERR_MEM if private data couldn't be allocated 1548 * any other err_t on error 1549 */ 1550static err_t 1551undiif_init(struct netif *netif) 1552{ 1553 LWIP_ASSERT("netif != NULL", (netif != NULL)); 1554#if LWIP_NETIF_HOSTNAME 1555 /* Initialize interface hostname */ 1556 netif->hostname = "undi"; 1557#endif /* LWIP_NETIF_HOSTNAME */ 1558 1559 /* 1560 * Initialize the snmp variables and counters inside the struct netif. 1561 * The last argument should be replaced with your link speed, in units 1562 * of bits per second. 1563 */ 1564 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); 1565 1566 netif->state = NULL; /* Private pointer if we need it */ 1567 netif->name[0] = IFNAME0; 1568 netif->name[1] = IFNAME1; 1569 netif->output = undiarp_output; 1570 netif->linkoutput = undi_send_unknown; 1571 1572 /* initialize the hardware */ 1573 low_level_init(netif); 1574 1575 return ERR_OK; 1576} 1577 1578int undiif_start(uint32_t ip, uint32_t netmask, uint32_t gw) 1579{ 1580 err_t err; 1581 1582 // This should be done *after* the threading system and receive thread 1583 // have both been started. 1584 dprintf("undi_netif: ip %d.%d.%d.%d netmask %d.%d.%d.%d gw %d.%d.%d.%d\n", 1585 ((uint8_t *)&ip)[0], 1586 ((uint8_t *)&ip)[1], 1587 ((uint8_t *)&ip)[2], 1588 ((uint8_t *)&ip)[3], 1589 ((uint8_t *)&netmask)[0], 1590 ((uint8_t *)&netmask)[1], 1591 ((uint8_t *)&netmask)[2], 1592 ((uint8_t *)&netmask)[3], 1593 ((uint8_t *)&gw)[0], 1594 ((uint8_t *)&gw)[1], 1595 ((uint8_t *)&gw)[2], 1596 ((uint8_t *)&gw)[3]); 1597 err = netifapi_netif_add(&undi_netif, 1598 (struct ip_addr *)&ip, (struct ip_addr *)&netmask, (struct ip_addr *)&gw, 1599 NULL, undiif_init, tcpip_input); 1600 if (err) 1601 return err; 1602 1603 netif_set_up(&undi_netif); 1604 netif_set_default(&undi_netif); /* Make this interface the default route */ 1605 1606 return ERR_OK; 1607} 1608