From ed201c35d280d0ba41fca04321a8d186b50bfa30 Mon Sep 17 00:00:00 2001 From: likewise Date: Wed, 5 May 2004 13:27:27 +0000 Subject: [PATCH] Made raw_input() more generic allowing multiple matches until someone eats the packet. --- src/core/raw.c | 114 +++++++++++++++++++++++------------------ src/include/lwip/raw.h | 4 +- 2 files changed, 66 insertions(+), 52 deletions(-) diff --git a/src/core/raw.c b/src/core/raw.c index f5792a4f..9dcd8065 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -1,6 +1,9 @@ /** * @file - * Raw Access module + * + * Implementation of raw protocol PCBs for low-level handling of + * different types of protocols besides (or overriding) those + * already available in lwIP. * */ /* @@ -35,13 +38,6 @@ * */ - -/* raw.c - * - * The code for the Raw Access to the IP - * - */ - #include "lwip/opt.h" #include "lwip/def.h" @@ -57,11 +53,10 @@ #include "lwip/snmp.h" #if LWIP_RAW -/* The list of RAW PCBs */ +/** The list of RAW PCBs */ static struct raw_pcb *raw_pcbs = NULL; - void raw_init(void) { @@ -69,42 +64,54 @@ raw_init(void) } /** - * Determine if in incoming IP packet is covered by a RAW pcb and - * and process it if possible + * Determine if in incoming IP packet is covered by a RAW PCB + * and if so, pass it to a user-provided receive callback function. * * Given an incoming IP datagram (as a chain of pbufs) this function - * finds a corresponding RAW PCB and + * finds a corresponding RAW PCB and calls the corresponding receive + * callback function. * * @param pbuf pbuf to be demultiplexed to a RAW PCB. * @param netif network interface on which the datagram was received. - * @return 0 if packet is not eated (pbuf needs to be freed then) - * or 1 if the packet has been eaten (pbuf needs not to be freed - * then) + * @Return - 1 if the packet has been eaten by a RAW PCB receive + * callback function. The caller MAY NOT not reference the + * packet any longer, and MAY NOT call pbuf_free(). + * @return - 0 if packet is not eaten (pbuf is still referenced by the + * caller). * */ -int +u8_t raw_input(struct pbuf *p, struct netif *inp) { struct raw_pcb *pcb; struct ip_hdr *iphdr; int proto; - int rc = 0; + u8_t eaten = 0; iphdr = p->payload; proto = IPH_PROTO(iphdr); - for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) { + pcb = raw_pcbs; + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while ((eaten == 0) && (pcb != NULL)) { if (pcb->protocol == proto) { - if (pcb->recv) { - if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src))) - return 0; + /* receive callback function available? */ + if (pcb->recv != NULL) { + /* the receive callback function did not eat the packet? */ + if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0) + { + /* receive function ate the packet */ + p = NULL; + eaten = 1; + } } - pbuf_free(p); - rc = 1; - break; + /* no receive callback function was set for this raw PCB */ + /* drop the packet */ } + pcb = pcb->next; } - return rc; + return eaten; } /** @@ -116,7 +123,7 @@ raw_input(struct pbuf *p, struct netif *inp) * * @return lwIP error code. * - ERR_OK. Successful. No error occured. - * - ERR_USE. The specified ipaddr is already bound to by + * - ERR_USE. The specified IP address is already bound to by * another RAW PCB. * * @see raw_disconnect() @@ -130,7 +137,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr) /** * Connect an RAW PCB. This function is required by upper layers - * of lwip. Using the raw api you could use raw_send_to() instead + * of lwip. Using the raw api you could use raw_sendto() instead * * This will associate the RAW PCB with the remote address. * @@ -139,7 +146,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr) * * @return lwIP error code * - * @see raw_disconnect() and raw_send_to() + * @see raw_disconnect() and raw_sendto() */ err_t raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr) @@ -150,14 +157,21 @@ raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr) /** - * Set the callback function if a RAW packet with the pcb's protocol - * is received. If the callback function returns a value unequal 0 - * the raw packet is "eaten" and not forwarded to any other raw pcb - * including lwip itself + * Set the callback function for received packets that match the + * raw PCB's protocol and binding. + * + * The callback function MUST either + * - eat the packet by calling pbuf_free() and returning non-zero. The + * packet will not be passed to other raw PCBs or other protocol layers. + * - not free the packet, and return zero. The packet will be matched + * against further PCBs and/or forwarded to another protocol layers. + * + * @return non-zero if the packet was free()d, zero if the packet remains + * available for others. */ void raw_recv(struct raw_pcb *pcb, - int (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p, + u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p, struct ip_addr *addr), void *recv_arg) { @@ -168,25 +182,25 @@ raw_recv(struct raw_pcb *pcb, /** * Send the raw IP packet to the given address. Note that actually you cannot - * modify the IP headers (this is inconsitent with the receive callback where - * you actually get the IP headers), you can only specifiy the ip payload here. - * It requires some more changes in LWIP. (there will be a raw_send() function - * then) + * modify the IP headers (this is inconsistent with the receive callback where + * you actually get the IP headers), you can only specify the IP payload here. + * It requires some more changes in lwIP. (there will be a raw_send() function + * then.) * * @param pcb the raw pcb which to send - * @param p the ip payload to send - * @param ipaddr the destination address of the whole IP packet + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet * */ err_t -raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) +raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) { err_t err; struct netif *netif; struct ip_addr *src_ip; struct pbuf *q; /* q will be sent down the stack */ - LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_send_to\n")); + LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_sendto\n")); /* not enough space to add an IP header to first pbuf in given p chain? */ if (pbuf_header(p, IP_HLEN)) { @@ -194,13 +208,13 @@ raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); /* new header pbuf could not be allocated? */ if (q == NULL) { - LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_send_to: could not allocate header\n")); + LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_sendto: could not allocate header\n")); return ERR_MEM; } /* chain header q in front of given pbuf p */ pbuf_chain(q, p); /* { first pbuf q points to header pbuf } */ - LWIP_DEBUGF(RAW_DEBUG, ("raw_send_to: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); + LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); } else { /* first pbuf q equals given pbuf */ q = p; @@ -208,10 +222,11 @@ raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) } if ((netif = ip_route(ipaddr)) == NULL) { - LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_send_to: No route to 0x%lx\n", ipaddr->addr)); + LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%lx\n", ipaddr->addr)); #if RAW_STATS /* ++lwip_stats.raw.rterr;*/ #endif /* RAW_STATS */ + /* free any temporary header pbuf allocated by pbuf_header() */ if (q != p) { pbuf_free(q); } @@ -240,14 +255,14 @@ raw_send_to(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr) * Send the raw IP packet to the address given by raw_connect() * * @param pcb the raw pcb which to send - * @param p the ip payload to send - * @param ipaddr the destination address of the whole IP packet + * @param p the IP payload to send + * @param ipaddr the destination address of the IP packet * */ err_t raw_send(struct raw_pcb *pcb, struct pbuf *p) { - return raw_send_to(pcb,p,&pcb->remote_ip); + return raw_sendto(pcb, p, &pcb->remote_ip); } /** @@ -266,7 +281,7 @@ raw_remove(struct raw_pcb *pcb) if (raw_pcbs == pcb) { /* make list start at 2nd pcb */ raw_pcbs = raw_pcbs->next; - /* pcb not 1st in list */ + /* pcb not 1st in list */ } else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { /* find pcb in raw_pcbs list */ if (pcb2->next != NULL && pcb2->next == pcb) { @@ -303,7 +318,6 @@ raw_new(u16_t proto) { pcb->next = raw_pcbs; raw_pcbs = pcb; } - return pcb; } diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h index 4ece7901..58b9a867 100644 --- a/src/include/lwip/raw.h +++ b/src/include/lwip/raw.h @@ -63,11 +63,11 @@ void raw_recv (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr), void *recv_arg); -err_t raw_send_to (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr); +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr); err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); /* The following functions are the lower layer interface to RAW. */ -int raw_input (struct pbuf *p, struct netif *inp); +u8_t raw_input (struct pbuf *p, struct netif *inp); void raw_init (void);