Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
raw.c
00001 /** 00002 * @file 00003 * Implementation of raw protocol PCBs for low-level handling of 00004 * different types of protocols besides (or overriding) those 00005 * already available in lwIP. 00006 * 00007 */ 00008 00009 /* 00010 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 2. Redistributions in binary form must reproduce the above copyright notice, 00019 * this list of conditions and the following disclaimer in the documentation 00020 * and/or other materials provided with the distribution. 00021 * 3. The name of the author may not be used to endorse or promote products 00022 * derived from this software without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00025 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00026 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00027 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00028 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00029 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00030 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00031 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00032 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00033 * OF SUCH DAMAGE. 00034 * 00035 * This file is part of the lwIP TCP/IP stack. 00036 * 00037 * Author: Adam Dunkels <adam@sics.se> 00038 * 00039 */ 00040 00041 #include "lwip/opt.h" 00042 00043 #if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ 00044 00045 #include "lwip/def.h" 00046 #include "lwip/memp.h" 00047 #include "lwip/ip_addr.h" 00048 #include "lwip/netif.h" 00049 #include "lwip/raw.h" 00050 #include "lwip/stats.h" 00051 #include "arch/perf.h" 00052 00053 #include <string.h> 00054 00055 /** The list of RAW PCBs */ 00056 static struct raw_pcb *raw_pcbs; 00057 00058 /** 00059 * Determine if in incoming IP packet is covered by a RAW PCB 00060 * and if so, pass it to a user-provided receive callback function. 00061 * 00062 * Given an incoming IP datagram (as a chain of pbufs) this function 00063 * finds a corresponding RAW PCB and calls the corresponding receive 00064 * callback function. 00065 * 00066 * @param p pbuf to be demultiplexed to a RAW PCB. 00067 * @param inp network interface on which the datagram was received. 00068 * @return - 1 if the packet has been eaten by a RAW PCB receive 00069 * callback function. The caller MAY NOT not reference the 00070 * packet any longer, and MAY NOT call pbuf_free(). 00071 * @return - 0 if packet is not eaten (pbuf is still referenced by the 00072 * caller). 00073 * 00074 */ 00075 u8_t 00076 raw_input(struct pbuf *p, struct netif *inp) 00077 { 00078 struct raw_pcb *pcb, *prev; 00079 struct ip_hdr *iphdr; 00080 s16_t proto; 00081 u8_t eaten = 0; 00082 00083 LWIP_UNUSED_ARG(inp); 00084 00085 iphdr = (struct ip_hdr *)p->payload; 00086 proto = IPH_PROTO(iphdr); 00087 00088 prev = NULL; 00089 pcb = raw_pcbs; 00090 /* loop through all raw pcbs until the packet is eaten by one */ 00091 /* this allows multiple pcbs to match against the packet by design */ 00092 while ((eaten == 0) && (pcb != NULL)) { 00093 if ((pcb->protocol == proto) && 00094 (ip_addr_isany(&pcb->local_ip) || 00095 ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest))) { 00096 #if IP_SOF_BROADCAST_RECV 00097 /* broadcast filter? */ 00098 if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(¤t_iphdr_dest, inp)) 00099 #endif /* IP_SOF_BROADCAST_RECV */ 00100 { 00101 /* receive callback function available? */ 00102 if (pcb->recv != NULL) { 00103 /* the receive callback function did not eat the packet? */ 00104 if (pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()) != 0) { 00105 /* receive function ate the packet */ 00106 p = NULL; 00107 eaten = 1; 00108 if (prev != NULL) { 00109 /* move the pcb to the front of raw_pcbs so that is 00110 found faster next time */ 00111 prev->next = pcb->next; 00112 pcb->next = raw_pcbs; 00113 raw_pcbs = pcb; 00114 } 00115 } 00116 } 00117 /* no receive callback function was set for this raw PCB */ 00118 } 00119 /* drop the packet */ 00120 } 00121 prev = pcb; 00122 pcb = pcb->next; 00123 } 00124 return eaten; 00125 } 00126 00127 /** 00128 * Bind a RAW PCB. 00129 * 00130 * @param pcb RAW PCB to be bound with a local address ipaddr. 00131 * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to 00132 * bind to all local interfaces. 00133 * 00134 * @return lwIP error code. 00135 * - ERR_OK. Successful. No error occured. 00136 * - ERR_USE. The specified IP address is already bound to by 00137 * another RAW PCB. 00138 * 00139 * @see raw_disconnect() 00140 */ 00141 err_t 00142 raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr) 00143 { 00144 ip_addr_set(&pcb->local_ip, ipaddr); 00145 return ERR_OK; 00146 } 00147 00148 /** 00149 * Connect an RAW PCB. This function is required by upper layers 00150 * of lwip. Using the raw api you could use raw_sendto() instead 00151 * 00152 * This will associate the RAW PCB with the remote address. 00153 * 00154 * @param pcb RAW PCB to be connected with remote address ipaddr and port. 00155 * @param ipaddr remote IP address to connect with. 00156 * 00157 * @return lwIP error code 00158 * 00159 * @see raw_disconnect() and raw_sendto() 00160 */ 00161 err_t 00162 raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr) 00163 { 00164 ip_addr_set(&pcb->remote_ip, ipaddr); 00165 return ERR_OK; 00166 } 00167 00168 00169 /** 00170 * Set the callback function for received packets that match the 00171 * raw PCB's protocol and binding. 00172 * 00173 * The callback function MUST either 00174 * - eat the packet by calling pbuf_free() and returning non-zero. The 00175 * packet will not be passed to other raw PCBs or other protocol layers. 00176 * - not free the packet, and return zero. The packet will be matched 00177 * against further PCBs and/or forwarded to another protocol layers. 00178 * 00179 * @return non-zero if the packet was free()d, zero if the packet remains 00180 * available for others. 00181 */ 00182 void 00183 raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) 00184 { 00185 /* remember recv() callback and user data */ 00186 pcb->recv = recv; 00187 pcb->recv_arg = recv_arg; 00188 } 00189 00190 /** 00191 * Send the raw IP packet to the given address. Note that actually you cannot 00192 * modify the IP headers (this is inconsistent with the receive callback where 00193 * you actually get the IP headers), you can only specify the IP payload here. 00194 * It requires some more changes in lwIP. (there will be a raw_send() function 00195 * then.) 00196 * 00197 * @param pcb the raw pcb which to send 00198 * @param p the IP payload to send 00199 * @param ipaddr the destination address of the IP packet 00200 * 00201 */ 00202 err_t 00203 raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) 00204 { 00205 err_t err; 00206 struct netif *netif; 00207 ip_addr_t *src_ip; 00208 struct pbuf *q; /* q will be sent down the stack */ 00209 00210 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); 00211 00212 /* not enough space to add an IP header to first pbuf in given p chain? */ 00213 if (pbuf_header(p, IP_HLEN)) { 00214 /* allocate header in new pbuf */ 00215 q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); 00216 /* new header pbuf could not be allocated? */ 00217 if (q == NULL) { 00218 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); 00219 return ERR_MEM; 00220 } 00221 if (p->tot_len != 0) { 00222 /* chain header q in front of given pbuf p */ 00223 pbuf_chain(q, p); 00224 } 00225 /* { first pbuf q points to header pbuf } */ 00226 LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); 00227 } else { 00228 /* first pbuf q equals given pbuf */ 00229 q = p; 00230 if(pbuf_header(q, -IP_HLEN)) { 00231 LWIP_ASSERT("Can't restore header we just removed!", 0); 00232 return ERR_MEM; 00233 } 00234 } 00235 00236 if ((netif = ip_route(ipaddr)) == NULL) { 00237 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00238 ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); 00239 /* free any temporary header pbuf allocated by pbuf_header() */ 00240 if (q != p) { 00241 pbuf_free(q); 00242 } 00243 return ERR_RTE; 00244 } 00245 00246 #if IP_SOF_BROADCAST 00247 /* broadcast filter? */ 00248 if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) { 00249 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); 00250 /* free any temporary header pbuf allocated by pbuf_header() */ 00251 if (q != p) { 00252 pbuf_free(q); 00253 } 00254 return ERR_VAL; 00255 } 00256 #endif /* IP_SOF_BROADCAST */ 00257 00258 if (ip_addr_isany(&pcb->local_ip)) { 00259 /* use outgoing network interface IP address as source address */ 00260 src_ip = &(netif->ip_addr); 00261 } else { 00262 /* use RAW PCB local IP address as source address */ 00263 src_ip = &(pcb->local_ip); 00264 } 00265 00266 #if LWIP_NETIF_HWADDRHINT 00267 netif->addr_hint = &(pcb->addr_hint); 00268 #endif /* LWIP_NETIF_HWADDRHINT*/ 00269 err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); 00270 #if LWIP_NETIF_HWADDRHINT 00271 netif->addr_hint = NULL; 00272 #endif /* LWIP_NETIF_HWADDRHINT*/ 00273 00274 /* did we chain a header earlier? */ 00275 if (q != p) { 00276 /* free the header */ 00277 pbuf_free(q); 00278 } 00279 return err; 00280 } 00281 00282 /** 00283 * Send the raw IP packet to the address given by raw_connect() 00284 * 00285 * @param pcb the raw pcb which to send 00286 * @param p the IP payload to send 00287 * 00288 */ 00289 err_t 00290 raw_send(struct raw_pcb *pcb, struct pbuf *p) 00291 { 00292 return raw_sendto(pcb, p, &pcb->remote_ip); 00293 } 00294 00295 /** 00296 * Remove an RAW PCB. 00297 * 00298 * @param pcb RAW PCB to be removed. The PCB is removed from the list of 00299 * RAW PCB's and the data structure is freed from memory. 00300 * 00301 * @see raw_new() 00302 */ 00303 void 00304 raw_remove(struct raw_pcb *pcb) 00305 { 00306 struct raw_pcb *pcb2; 00307 /* pcb to be removed is first in list? */ 00308 if (raw_pcbs == pcb) { 00309 /* make list start at 2nd pcb */ 00310 raw_pcbs = raw_pcbs->next; 00311 /* pcb not 1st in list */ 00312 } else { 00313 for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { 00314 /* find pcb in raw_pcbs list */ 00315 if (pcb2->next != NULL && pcb2->next == pcb) { 00316 /* remove pcb from list */ 00317 pcb2->next = pcb->next; 00318 } 00319 } 00320 } 00321 memp_free(MEMP_RAW_PCB, pcb); 00322 } 00323 00324 /** 00325 * Create a RAW PCB. 00326 * 00327 * @return The RAW PCB which was created. NULL if the PCB data structure 00328 * could not be allocated. 00329 * 00330 * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) 00331 * 00332 * @see raw_remove() 00333 */ 00334 struct raw_pcb * 00335 raw_new(u8_t proto) 00336 { 00337 struct raw_pcb *pcb; 00338 00339 LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); 00340 00341 pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); 00342 /* could allocate RAW PCB? */ 00343 if (pcb != NULL) { 00344 /* initialize PCB to all zeroes */ 00345 memset(pcb, 0, sizeof(struct raw_pcb)); 00346 pcb->protocol = proto; 00347 pcb->ttl = RAW_TTL; 00348 pcb->next = raw_pcbs; 00349 raw_pcbs = pcb; 00350 } 00351 return pcb; 00352 } 00353 00354 #endif /* LWIP_RAW */
Generated on Tue Jul 12 2022 17:34:52 by
