1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * Implementation of raw protocol PCBs for low-level handling of 4195972f6Sopenharmony_ci * different types of protocols besides (or overriding) those 5195972f6Sopenharmony_ci * already available in lwIP.\n 6195972f6Sopenharmony_ci * See also @ref raw_raw 7195972f6Sopenharmony_ci * 8195972f6Sopenharmony_ci * @defgroup raw_raw RAW 9195972f6Sopenharmony_ci * @ingroup callbackstyle_api 10195972f6Sopenharmony_ci * Implementation of raw protocol PCBs for low-level handling of 11195972f6Sopenharmony_ci * different types of protocols besides (or overriding) those 12195972f6Sopenharmony_ci * already available in lwIP.\n 13195972f6Sopenharmony_ci * @see @ref api 14195972f6Sopenharmony_ci */ 15195972f6Sopenharmony_ci 16195972f6Sopenharmony_ci/* 17195972f6Sopenharmony_ci * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 18195972f6Sopenharmony_ci * All rights reserved. 19195972f6Sopenharmony_ci * 20195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 21195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 22195972f6Sopenharmony_ci * 23195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 24195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 25195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 26195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 27195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 28195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 29195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 30195972f6Sopenharmony_ci * 31195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 32195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 33195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 34195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 35195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 36195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 39195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 40195972f6Sopenharmony_ci * OF SUCH DAMAGE. 41195972f6Sopenharmony_ci * 42195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack. 43195972f6Sopenharmony_ci * 44195972f6Sopenharmony_ci * Author: Adam Dunkels <adam@sics.se> 45195972f6Sopenharmony_ci * 46195972f6Sopenharmony_ci */ 47195972f6Sopenharmony_ci 48195972f6Sopenharmony_ci#include "lwip/opt.h" 49195972f6Sopenharmony_ci 50195972f6Sopenharmony_ci#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ 51195972f6Sopenharmony_ci 52195972f6Sopenharmony_ci#include "lwip/def.h" 53195972f6Sopenharmony_ci#include "lwip/memp.h" 54195972f6Sopenharmony_ci#include "lwip/ip_addr.h" 55195972f6Sopenharmony_ci#include "lwip/netif.h" 56195972f6Sopenharmony_ci#include "lwip/raw.h" 57195972f6Sopenharmony_ci#include "lwip/priv/raw_priv.h" 58195972f6Sopenharmony_ci#include "lwip/stats.h" 59195972f6Sopenharmony_ci#include "lwip/ip6.h" 60195972f6Sopenharmony_ci#include "lwip/ip6_addr.h" 61195972f6Sopenharmony_ci#include "lwip/inet_chksum.h" 62195972f6Sopenharmony_ci 63195972f6Sopenharmony_ci#include <string.h> 64195972f6Sopenharmony_ci 65195972f6Sopenharmony_ci/** The list of RAW PCBs */ 66195972f6Sopenharmony_cistatic struct raw_pcb *raw_pcbs; 67195972f6Sopenharmony_ci 68195972f6Sopenharmony_cistatic u8_t 69195972f6Sopenharmony_ciraw_input_local_match(struct raw_pcb *pcb, u8_t broadcast) 70195972f6Sopenharmony_ci{ 71195972f6Sopenharmony_ci LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ 72195972f6Sopenharmony_ci 73195972f6Sopenharmony_ci /* check if PCB is bound to specific netif */ 74195972f6Sopenharmony_ci if ((pcb->netif_idx != NETIF_NO_INDEX) && 75195972f6Sopenharmony_ci (pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) { 76195972f6Sopenharmony_ci return 0; 77195972f6Sopenharmony_ci } 78195972f6Sopenharmony_ci 79195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 80195972f6Sopenharmony_ci /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ 81195972f6Sopenharmony_ci if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { 82195972f6Sopenharmony_ci#if IP_SOF_BROADCAST_RECV 83195972f6Sopenharmony_ci if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { 84195972f6Sopenharmony_ci return 0; 85195972f6Sopenharmony_ci } 86195972f6Sopenharmony_ci#endif /* IP_SOF_BROADCAST_RECV */ 87195972f6Sopenharmony_ci return 1; 88195972f6Sopenharmony_ci } 89195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_IPV6 */ 90195972f6Sopenharmony_ci 91195972f6Sopenharmony_ci /* Only need to check PCB if incoming IP version matches PCB IP version */ 92195972f6Sopenharmony_ci if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { 93195972f6Sopenharmony_ci#if LWIP_IPV4 94195972f6Sopenharmony_ci /* Special case: IPv4 broadcast: receive all broadcasts 95195972f6Sopenharmony_ci * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ 96195972f6Sopenharmony_ci if (broadcast != 0) { 97195972f6Sopenharmony_ci#if IP_SOF_BROADCAST_RECV 98195972f6Sopenharmony_ci if (ip_get_option(pcb, SOF_BROADCAST)) 99195972f6Sopenharmony_ci#endif /* IP_SOF_BROADCAST_RECV */ 100195972f6Sopenharmony_ci { 101195972f6Sopenharmony_ci if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) { 102195972f6Sopenharmony_ci return 1; 103195972f6Sopenharmony_ci } 104195972f6Sopenharmony_ci } 105195972f6Sopenharmony_ci } else 106195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 107195972f6Sopenharmony_ci /* Handle IPv4 and IPv6: catch all or exact match */ 108195972f6Sopenharmony_ci if (ip_addr_isany(&pcb->local_ip) || 109195972f6Sopenharmony_ci ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { 110195972f6Sopenharmony_ci return 1; 111195972f6Sopenharmony_ci } 112195972f6Sopenharmony_ci } 113195972f6Sopenharmony_ci 114195972f6Sopenharmony_ci return 0; 115195972f6Sopenharmony_ci} 116195972f6Sopenharmony_ci 117195972f6Sopenharmony_ci/** 118195972f6Sopenharmony_ci * Determine if in incoming IP packet is covered by a RAW PCB 119195972f6Sopenharmony_ci * and if so, pass it to a user-provided receive callback function. 120195972f6Sopenharmony_ci * 121195972f6Sopenharmony_ci * Given an incoming IP datagram (as a chain of pbufs) this function 122195972f6Sopenharmony_ci * finds a corresponding RAW PCB and calls the corresponding receive 123195972f6Sopenharmony_ci * callback function. 124195972f6Sopenharmony_ci * 125195972f6Sopenharmony_ci * @param p pbuf to be demultiplexed to a RAW PCB. 126195972f6Sopenharmony_ci * @param inp network interface on which the datagram was received. 127195972f6Sopenharmony_ci * @return - 1 if the packet has been eaten by a RAW PCB receive 128195972f6Sopenharmony_ci * callback function. The caller MAY NOT not reference the 129195972f6Sopenharmony_ci * packet any longer, and MAY NOT call pbuf_free(). 130195972f6Sopenharmony_ci * @return - 0 if packet is not eaten (pbuf is still referenced by the 131195972f6Sopenharmony_ci * caller). 132195972f6Sopenharmony_ci * 133195972f6Sopenharmony_ci */ 134195972f6Sopenharmony_ciraw_input_state_t 135195972f6Sopenharmony_ciraw_input(struct pbuf *p, struct netif *inp) 136195972f6Sopenharmony_ci{ 137195972f6Sopenharmony_ci struct raw_pcb *pcb, *prev; 138195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 139195972f6Sopenharmony_ci struct net_group *inp_net_group = get_net_group_from_netif(inp); 140195972f6Sopenharmony_ci#endif 141195972f6Sopenharmony_ci s16_t proto; 142195972f6Sopenharmony_ci raw_input_state_t ret = RAW_INPUT_NONE; 143195972f6Sopenharmony_ci u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); 144195972f6Sopenharmony_ci 145195972f6Sopenharmony_ci LWIP_UNUSED_ARG(inp); 146195972f6Sopenharmony_ci 147195972f6Sopenharmony_ci#if LWIP_IPV6 148195972f6Sopenharmony_ci#if LWIP_IPV4 149195972f6Sopenharmony_ci if (IP_HDR_GET_VERSION(p->payload) == 6) 150195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 151195972f6Sopenharmony_ci { 152195972f6Sopenharmony_ci struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; 153195972f6Sopenharmony_ci proto = IP6H_NEXTH(ip6hdr); 154195972f6Sopenharmony_ci } 155195972f6Sopenharmony_ci#if LWIP_IPV4 156195972f6Sopenharmony_ci else 157195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 158195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 159195972f6Sopenharmony_ci#if LWIP_IPV4 160195972f6Sopenharmony_ci { 161195972f6Sopenharmony_ci proto = IPH_PROTO((struct ip_hdr *)p->payload); 162195972f6Sopenharmony_ci } 163195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 164195972f6Sopenharmony_ci 165195972f6Sopenharmony_ci prev = NULL; 166195972f6Sopenharmony_ci pcb = raw_pcbs; 167195972f6Sopenharmony_ci /* loop through all raw pcbs until the packet is eaten by one */ 168195972f6Sopenharmony_ci /* this allows multiple pcbs to match against the packet by design */ 169195972f6Sopenharmony_ci while (pcb != NULL) { 170195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 171195972f6Sopenharmony_ci if (inp_net_group == get_net_group_from_raw_pcb(pcb) && 172195972f6Sopenharmony_ci (pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) && 173195972f6Sopenharmony_ci#else 174195972f6Sopenharmony_ci if ((pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) && 175195972f6Sopenharmony_ci#endif 176195972f6Sopenharmony_ci (((pcb->flags & RAW_FLAGS_CONNECTED) == 0) || 177195972f6Sopenharmony_ci ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { 178195972f6Sopenharmony_ci /* receive callback function available? */ 179195972f6Sopenharmony_ci if (pcb->recv != NULL) { 180195972f6Sopenharmony_ci u8_t eaten; 181195972f6Sopenharmony_ci#ifndef LWIP_NOASSERT 182195972f6Sopenharmony_ci void *old_payload = p->payload; 183195972f6Sopenharmony_ci#endif 184195972f6Sopenharmony_ci ret = RAW_INPUT_DELIVERED; 185195972f6Sopenharmony_ci /* the receive callback function did not eat the packet? */ 186195972f6Sopenharmony_ci eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()); 187195972f6Sopenharmony_ci if (eaten != 0) { 188195972f6Sopenharmony_ci /* receive function ate the packet */ 189195972f6Sopenharmony_ci p = NULL; 190195972f6Sopenharmony_ci if (prev != NULL) { 191195972f6Sopenharmony_ci /* move the pcb to the front of raw_pcbs so that is 192195972f6Sopenharmony_ci found faster next time */ 193195972f6Sopenharmony_ci prev->next = pcb->next; 194195972f6Sopenharmony_ci pcb->next = raw_pcbs; 195195972f6Sopenharmony_ci raw_pcbs = pcb; 196195972f6Sopenharmony_ci } 197195972f6Sopenharmony_ci return RAW_INPUT_EATEN; 198195972f6Sopenharmony_ci } else { 199195972f6Sopenharmony_ci /* sanity-check that the receive callback did not alter the pbuf */ 200195972f6Sopenharmony_ci LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet", 201195972f6Sopenharmony_ci p->payload == old_payload); 202195972f6Sopenharmony_ci } 203195972f6Sopenharmony_ci } 204195972f6Sopenharmony_ci /* no receive callback function was set for this raw PCB */ 205195972f6Sopenharmony_ci } 206195972f6Sopenharmony_ci /* drop the packet */ 207195972f6Sopenharmony_ci prev = pcb; 208195972f6Sopenharmony_ci pcb = pcb->next; 209195972f6Sopenharmony_ci } 210195972f6Sopenharmony_ci return ret; 211195972f6Sopenharmony_ci} 212195972f6Sopenharmony_ci 213195972f6Sopenharmony_ci/** 214195972f6Sopenharmony_ci * @ingroup raw_raw 215195972f6Sopenharmony_ci * Bind a RAW PCB. 216195972f6Sopenharmony_ci * 217195972f6Sopenharmony_ci * @param pcb RAW PCB to be bound with a local address ipaddr. 218195972f6Sopenharmony_ci * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to 219195972f6Sopenharmony_ci * bind to all local interfaces. 220195972f6Sopenharmony_ci * 221195972f6Sopenharmony_ci * @return lwIP error code. 222195972f6Sopenharmony_ci * - ERR_OK. Successful. No error occurred. 223195972f6Sopenharmony_ci * - ERR_USE. The specified IP address is already bound to by 224195972f6Sopenharmony_ci * another RAW PCB. 225195972f6Sopenharmony_ci * 226195972f6Sopenharmony_ci * @see raw_disconnect() 227195972f6Sopenharmony_ci */ 228195972f6Sopenharmony_cierr_t 229195972f6Sopenharmony_ciraw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) 230195972f6Sopenharmony_ci{ 231195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 232195972f6Sopenharmony_ci if ((pcb == NULL) || (ipaddr == NULL)) { 233195972f6Sopenharmony_ci return ERR_VAL; 234195972f6Sopenharmony_ci } 235195972f6Sopenharmony_ci ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); 236195972f6Sopenharmony_ci#if LWIP_IPV6 && LWIP_IPV6_SCOPES 237195972f6Sopenharmony_ci /* If the given IP address should have a zone but doesn't, assign one now. 238195972f6Sopenharmony_ci * This is legacy support: scope-aware callers should always provide properly 239195972f6Sopenharmony_ci * zoned source addresses. */ 240195972f6Sopenharmony_ci if (IP_IS_V6(&pcb->local_ip) && 241195972f6Sopenharmony_ci ip6_addr_lacks_zone(ip_2_ip6(&pcb->local_ip), IP6_UNKNOWN)) { 242195972f6Sopenharmony_ci ip6_addr_select_zone(ip_2_ip6(&pcb->local_ip), ip_2_ip6(&pcb->local_ip)); 243195972f6Sopenharmony_ci } 244195972f6Sopenharmony_ci#endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */ 245195972f6Sopenharmony_ci return ERR_OK; 246195972f6Sopenharmony_ci} 247195972f6Sopenharmony_ci 248195972f6Sopenharmony_ci/** 249195972f6Sopenharmony_ci * @ingroup raw_raw 250195972f6Sopenharmony_ci * Bind an RAW PCB to a specific netif. 251195972f6Sopenharmony_ci * After calling this function, all packets received via this PCB 252195972f6Sopenharmony_ci * are guaranteed to have come in via the specified netif, and all 253195972f6Sopenharmony_ci * outgoing packets will go out via the specified netif. 254195972f6Sopenharmony_ci * 255195972f6Sopenharmony_ci * @param pcb RAW PCB to be bound with netif. 256195972f6Sopenharmony_ci * @param netif netif to bind to. Can be NULL. 257195972f6Sopenharmony_ci * 258195972f6Sopenharmony_ci * @see raw_disconnect() 259195972f6Sopenharmony_ci */ 260195972f6Sopenharmony_civoid 261195972f6Sopenharmony_ciraw_bind_netif(struct raw_pcb *pcb, const struct netif *netif) 262195972f6Sopenharmony_ci{ 263195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 264195972f6Sopenharmony_ci if (netif != NULL) { 265195972f6Sopenharmony_ci pcb->netif_idx = netif_get_index(netif); 266195972f6Sopenharmony_ci } else { 267195972f6Sopenharmony_ci pcb->netif_idx = NETIF_NO_INDEX; 268195972f6Sopenharmony_ci } 269195972f6Sopenharmony_ci} 270195972f6Sopenharmony_ci 271195972f6Sopenharmony_ci/** 272195972f6Sopenharmony_ci * @ingroup raw_raw 273195972f6Sopenharmony_ci * Connect an RAW PCB. This function is required by upper layers 274195972f6Sopenharmony_ci * of lwip. Using the raw api you could use raw_sendto() instead 275195972f6Sopenharmony_ci * 276195972f6Sopenharmony_ci * This will associate the RAW PCB with the remote address. 277195972f6Sopenharmony_ci * 278195972f6Sopenharmony_ci * @param pcb RAW PCB to be connected with remote address ipaddr and port. 279195972f6Sopenharmony_ci * @param ipaddr remote IP address to connect with. 280195972f6Sopenharmony_ci * 281195972f6Sopenharmony_ci * @return lwIP error code 282195972f6Sopenharmony_ci * 283195972f6Sopenharmony_ci * @see raw_disconnect() and raw_sendto() 284195972f6Sopenharmony_ci */ 285195972f6Sopenharmony_cierr_t 286195972f6Sopenharmony_ciraw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) 287195972f6Sopenharmony_ci{ 288195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 289195972f6Sopenharmony_ci if ((pcb == NULL) || (ipaddr == NULL)) { 290195972f6Sopenharmony_ci return ERR_VAL; 291195972f6Sopenharmony_ci } 292195972f6Sopenharmony_ci ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); 293195972f6Sopenharmony_ci#if LWIP_IPV6 && LWIP_IPV6_SCOPES 294195972f6Sopenharmony_ci /* If the given IP address should have a zone but doesn't, assign one now, 295195972f6Sopenharmony_ci * using the bound address to make a more informed decision when possible. */ 296195972f6Sopenharmony_ci if (IP_IS_V6(&pcb->remote_ip) && 297195972f6Sopenharmony_ci ip6_addr_lacks_zone(ip_2_ip6(&pcb->remote_ip), IP6_UNKNOWN)) { 298195972f6Sopenharmony_ci ip6_addr_select_zone(ip_2_ip6(&pcb->remote_ip), ip_2_ip6(&pcb->local_ip)); 299195972f6Sopenharmony_ci } 300195972f6Sopenharmony_ci#endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */ 301195972f6Sopenharmony_ci raw_set_flags(pcb, RAW_FLAGS_CONNECTED); 302195972f6Sopenharmony_ci return ERR_OK; 303195972f6Sopenharmony_ci} 304195972f6Sopenharmony_ci 305195972f6Sopenharmony_ci/** 306195972f6Sopenharmony_ci * @ingroup raw_raw 307195972f6Sopenharmony_ci * Disconnect a RAW PCB. 308195972f6Sopenharmony_ci * 309195972f6Sopenharmony_ci * @param pcb the raw pcb to disconnect. 310195972f6Sopenharmony_ci */ 311195972f6Sopenharmony_civoid 312195972f6Sopenharmony_ciraw_disconnect(struct raw_pcb *pcb) 313195972f6Sopenharmony_ci{ 314195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 315195972f6Sopenharmony_ci /* reset remote address association */ 316195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 317195972f6Sopenharmony_ci if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { 318195972f6Sopenharmony_ci ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE); 319195972f6Sopenharmony_ci } else { 320195972f6Sopenharmony_ci#endif 321195972f6Sopenharmony_ci ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip); 322195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 323195972f6Sopenharmony_ci } 324195972f6Sopenharmony_ci#endif 325195972f6Sopenharmony_ci pcb->netif_idx = NETIF_NO_INDEX; 326195972f6Sopenharmony_ci /* mark PCB as unconnected */ 327195972f6Sopenharmony_ci raw_clear_flags(pcb, RAW_FLAGS_CONNECTED); 328195972f6Sopenharmony_ci} 329195972f6Sopenharmony_ci 330195972f6Sopenharmony_ci/** 331195972f6Sopenharmony_ci * @ingroup raw_raw 332195972f6Sopenharmony_ci * Set the callback function for received packets that match the 333195972f6Sopenharmony_ci * raw PCB's protocol and binding. 334195972f6Sopenharmony_ci * 335195972f6Sopenharmony_ci * The callback function MUST either 336195972f6Sopenharmony_ci * - eat the packet by calling pbuf_free() and returning non-zero. The 337195972f6Sopenharmony_ci * packet will not be passed to other raw PCBs or other protocol layers. 338195972f6Sopenharmony_ci * - not free the packet, and return zero. The packet will be matched 339195972f6Sopenharmony_ci * against further PCBs and/or forwarded to another protocol layers. 340195972f6Sopenharmony_ci */ 341195972f6Sopenharmony_civoid 342195972f6Sopenharmony_ciraw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) 343195972f6Sopenharmony_ci{ 344195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 345195972f6Sopenharmony_ci /* remember recv() callback and user data */ 346195972f6Sopenharmony_ci pcb->recv = recv; 347195972f6Sopenharmony_ci pcb->recv_arg = recv_arg; 348195972f6Sopenharmony_ci} 349195972f6Sopenharmony_ci 350195972f6Sopenharmony_ci/** 351195972f6Sopenharmony_ci * @ingroup raw_raw 352195972f6Sopenharmony_ci * Send the raw IP packet to the given address. An IP header will be prepended 353195972f6Sopenharmony_ci * to the packet, unless the RAW_FLAGS_HDRINCL flag is set on the PCB. In that 354195972f6Sopenharmony_ci * case, the packet must include an IP header, which will then be sent as is. 355195972f6Sopenharmony_ci * 356195972f6Sopenharmony_ci * @param pcb the raw pcb which to send 357195972f6Sopenharmony_ci * @param p the IP payload to send 358195972f6Sopenharmony_ci * @param ipaddr the destination address of the IP packet 359195972f6Sopenharmony_ci * 360195972f6Sopenharmony_ci */ 361195972f6Sopenharmony_cierr_t 362195972f6Sopenharmony_ciraw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) 363195972f6Sopenharmony_ci{ 364195972f6Sopenharmony_ci struct netif *netif; 365195972f6Sopenharmony_ci const ip_addr_t *src_ip; 366195972f6Sopenharmony_ci 367195972f6Sopenharmony_ci if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { 368195972f6Sopenharmony_ci return ERR_VAL; 369195972f6Sopenharmony_ci } 370195972f6Sopenharmony_ci 371195972f6Sopenharmony_ci LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); 372195972f6Sopenharmony_ci 373195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 374195972f6Sopenharmony_ci struct net_group *group = get_net_group_from_raw_pcb(pcb); 375195972f6Sopenharmony_ci#endif 376195972f6Sopenharmony_ci if (pcb->netif_idx != NETIF_NO_INDEX) { 377195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 378195972f6Sopenharmony_ci netif = netif_get_by_index(pcb->netif_idx, group); 379195972f6Sopenharmony_ci#else 380195972f6Sopenharmony_ci netif = netif_get_by_index(pcb->netif_idx); 381195972f6Sopenharmony_ci#endif 382195972f6Sopenharmony_ci } else { 383195972f6Sopenharmony_ci#if LWIP_MULTICAST_TX_OPTIONS 384195972f6Sopenharmony_ci netif = NULL; 385195972f6Sopenharmony_ci if (ip_addr_ismulticast(ipaddr)) { 386195972f6Sopenharmony_ci /* For multicast-destined packets, use the user-provided interface index to 387195972f6Sopenharmony_ci * determine the outgoing interface, if an interface index is set and a 388195972f6Sopenharmony_ci * matching netif can be found. Otherwise, fall back to regular routing. */ 389195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 390195972f6Sopenharmony_ci netif = netif_get_by_index(pcb->mcast_ifindex, group); 391195972f6Sopenharmony_ci#else 392195972f6Sopenharmony_ci netif = netif_get_by_index(pcb->mcast_ifindex); 393195972f6Sopenharmony_ci#endif 394195972f6Sopenharmony_ci } 395195972f6Sopenharmony_ci 396195972f6Sopenharmony_ci if (netif == NULL) 397195972f6Sopenharmony_ci#endif /* LWIP_MULTICAST_TX_OPTIONS */ 398195972f6Sopenharmony_ci { 399195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 400195972f6Sopenharmony_ci netif = ip_route(&pcb->local_ip, ipaddr, group); 401195972f6Sopenharmony_ci#else 402195972f6Sopenharmony_ci netif = ip_route(&pcb->local_ip, ipaddr); 403195972f6Sopenharmony_ci#endif 404195972f6Sopenharmony_ci } 405195972f6Sopenharmony_ci } 406195972f6Sopenharmony_ci 407195972f6Sopenharmony_ci if (netif == NULL) { 408195972f6Sopenharmony_ci LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); 409195972f6Sopenharmony_ci ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr); 410195972f6Sopenharmony_ci return ERR_RTE; 411195972f6Sopenharmony_ci } 412195972f6Sopenharmony_ci 413195972f6Sopenharmony_ci if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) { 414195972f6Sopenharmony_ci /* use outgoing network interface IP address as source address */ 415195972f6Sopenharmony_ci src_ip = ip_netif_get_local_ip(netif, ipaddr); 416195972f6Sopenharmony_ci#if LWIP_IPV6 417195972f6Sopenharmony_ci if (src_ip == NULL) { 418195972f6Sopenharmony_ci return ERR_RTE; 419195972f6Sopenharmony_ci } 420195972f6Sopenharmony_ci#endif /* LWIP_IPV6 */ 421195972f6Sopenharmony_ci } else { 422195972f6Sopenharmony_ci /* use RAW PCB local IP address as source address */ 423195972f6Sopenharmony_ci src_ip = &pcb->local_ip; 424195972f6Sopenharmony_ci } 425195972f6Sopenharmony_ci 426195972f6Sopenharmony_ci return raw_sendto_if_src(pcb, p, ipaddr, netif, src_ip); 427195972f6Sopenharmony_ci} 428195972f6Sopenharmony_ci 429195972f6Sopenharmony_ci/** 430195972f6Sopenharmony_ci * @ingroup raw_raw 431195972f6Sopenharmony_ci * Send the raw IP packet to the given address, using a particular outgoing 432195972f6Sopenharmony_ci * netif and source IP address. An IP header will be prepended to the packet, 433195972f6Sopenharmony_ci * unless the RAW_FLAGS_HDRINCL flag is set on the PCB. In that case, the 434195972f6Sopenharmony_ci * packet must include an IP header, which will then be sent as is. 435195972f6Sopenharmony_ci * 436195972f6Sopenharmony_ci * @param pcb RAW PCB used to send the data 437195972f6Sopenharmony_ci * @param p chain of pbufs to be sent 438195972f6Sopenharmony_ci * @param dst_ip destination IP address 439195972f6Sopenharmony_ci * @param netif the netif used for sending 440195972f6Sopenharmony_ci * @param src_ip source IP address 441195972f6Sopenharmony_ci */ 442195972f6Sopenharmony_cierr_t 443195972f6Sopenharmony_ciraw_sendto_if_src(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, 444195972f6Sopenharmony_ci struct netif *netif, const ip_addr_t *src_ip) 445195972f6Sopenharmony_ci{ 446195972f6Sopenharmony_ci err_t err; 447195972f6Sopenharmony_ci struct pbuf *q; /* q will be sent down the stack */ 448195972f6Sopenharmony_ci u16_t header_size; 449195972f6Sopenharmony_ci u8_t ttl; 450195972f6Sopenharmony_ci 451195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 452195972f6Sopenharmony_ci 453195972f6Sopenharmony_ci if ((pcb == NULL) || (dst_ip == NULL) || (netif == NULL) || (src_ip == NULL) || 454195972f6Sopenharmony_ci !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { 455195972f6Sopenharmony_ci return ERR_VAL; 456195972f6Sopenharmony_ci } 457195972f6Sopenharmony_ci 458195972f6Sopenharmony_ci header_size = ( 459195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 460195972f6Sopenharmony_ci IP_IS_V6(dst_ip) ? IP6_HLEN : IP_HLEN); 461195972f6Sopenharmony_ci#elif LWIP_IPV4 462195972f6Sopenharmony_ci IP_HLEN); 463195972f6Sopenharmony_ci#else 464195972f6Sopenharmony_ci IP6_HLEN); 465195972f6Sopenharmony_ci#endif 466195972f6Sopenharmony_ci 467195972f6Sopenharmony_ci /* Handle the HDRINCL option as an exception: none of the code below applies 468195972f6Sopenharmony_ci * to this case, and sending the packet needs to be done differently too. */ 469195972f6Sopenharmony_ci if (pcb->flags & RAW_FLAGS_HDRINCL) { 470195972f6Sopenharmony_ci /* A full header *must* be present in the first pbuf of the chain, as the 471195972f6Sopenharmony_ci * output routines may access its fields directly. */ 472195972f6Sopenharmony_ci if (p->len < header_size) { 473195972f6Sopenharmony_ci return ERR_VAL; 474195972f6Sopenharmony_ci } 475195972f6Sopenharmony_ci /* @todo multicast loop support, if at all desired for this scenario.. */ 476195972f6Sopenharmony_ci NETIF_SET_HINTS(netif, &pcb->netif_hints); 477195972f6Sopenharmony_ci err = ip_output_if_hdrincl(p, src_ip, dst_ip, netif); 478195972f6Sopenharmony_ci NETIF_RESET_HINTS(netif); 479195972f6Sopenharmony_ci return err; 480195972f6Sopenharmony_ci } 481195972f6Sopenharmony_ci 482195972f6Sopenharmony_ci /* packet too large to add an IP header without causing an overflow? */ 483195972f6Sopenharmony_ci if ((u16_t)(p->tot_len + header_size) < p->tot_len) { 484195972f6Sopenharmony_ci return ERR_MEM; 485195972f6Sopenharmony_ci } 486195972f6Sopenharmony_ci /* not enough space to add an IP header to first pbuf in given p chain? */ 487195972f6Sopenharmony_ci if (pbuf_add_header(p, header_size)) { 488195972f6Sopenharmony_ci /* allocate header in new pbuf */ 489195972f6Sopenharmony_ci q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); 490195972f6Sopenharmony_ci /* new header pbuf could not be allocated? */ 491195972f6Sopenharmony_ci if (q == NULL) { 492195972f6Sopenharmony_ci LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); 493195972f6Sopenharmony_ci return ERR_MEM; 494195972f6Sopenharmony_ci } 495195972f6Sopenharmony_ci if (p->tot_len != 0) { 496195972f6Sopenharmony_ci /* chain header q in front of given pbuf p */ 497195972f6Sopenharmony_ci pbuf_chain(q, p); 498195972f6Sopenharmony_ci } 499195972f6Sopenharmony_ci /* { first pbuf q points to header pbuf } */ 500195972f6Sopenharmony_ci LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); 501195972f6Sopenharmony_ci } else { 502195972f6Sopenharmony_ci /* first pbuf q equals given pbuf */ 503195972f6Sopenharmony_ci q = p; 504195972f6Sopenharmony_ci if (pbuf_remove_header(q, header_size)) { 505195972f6Sopenharmony_ci LWIP_ASSERT("Can't restore header we just removed!", 0); 506195972f6Sopenharmony_ci return ERR_MEM; 507195972f6Sopenharmony_ci } 508195972f6Sopenharmony_ci } 509195972f6Sopenharmony_ci 510195972f6Sopenharmony_ci#if IP_SOF_BROADCAST 511195972f6Sopenharmony_ci if (IP_IS_V4(dst_ip)) { 512195972f6Sopenharmony_ci /* broadcast filter? */ 513195972f6Sopenharmony_ci if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(dst_ip, netif)) { 514195972f6Sopenharmony_ci LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); 515195972f6Sopenharmony_ci /* free any temporary header pbuf allocated by pbuf_header() */ 516195972f6Sopenharmony_ci if (q != p) { 517195972f6Sopenharmony_ci pbuf_free(q); 518195972f6Sopenharmony_ci } 519195972f6Sopenharmony_ci return ERR_VAL; 520195972f6Sopenharmony_ci } 521195972f6Sopenharmony_ci } 522195972f6Sopenharmony_ci#endif /* IP_SOF_BROADCAST */ 523195972f6Sopenharmony_ci 524195972f6Sopenharmony_ci /* Multicast Loop? */ 525195972f6Sopenharmony_ci#if LWIP_MULTICAST_TX_OPTIONS 526195972f6Sopenharmony_ci if (((pcb->flags & RAW_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) { 527195972f6Sopenharmony_ci q->flags |= PBUF_FLAG_MCASTLOOP; 528195972f6Sopenharmony_ci } 529195972f6Sopenharmony_ci#endif /* LWIP_MULTICAST_TX_OPTIONS */ 530195972f6Sopenharmony_ci 531195972f6Sopenharmony_ci#if LWIP_IPV6 532195972f6Sopenharmony_ci /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, 533195972f6Sopenharmony_ci compute the checksum and update the checksum in the payload. */ 534195972f6Sopenharmony_ci if (IP_IS_V6(dst_ip) && pcb->chksum_reqd) { 535195972f6Sopenharmony_ci u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip)); 536195972f6Sopenharmony_ci LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2)); 537195972f6Sopenharmony_ci SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t)); 538195972f6Sopenharmony_ci } 539195972f6Sopenharmony_ci#endif 540195972f6Sopenharmony_ci 541195972f6Sopenharmony_ci /* Determine TTL to use */ 542195972f6Sopenharmony_ci#if LWIP_MULTICAST_TX_OPTIONS 543195972f6Sopenharmony_ci ttl = (ip_addr_ismulticast(dst_ip) ? raw_get_multicast_ttl(pcb) : pcb->ttl); 544195972f6Sopenharmony_ci#else /* LWIP_MULTICAST_TX_OPTIONS */ 545195972f6Sopenharmony_ci ttl = pcb->ttl; 546195972f6Sopenharmony_ci#endif /* LWIP_MULTICAST_TX_OPTIONS */ 547195972f6Sopenharmony_ci 548195972f6Sopenharmony_ci NETIF_SET_HINTS(netif, &pcb->netif_hints); 549195972f6Sopenharmony_ci err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif); 550195972f6Sopenharmony_ci NETIF_RESET_HINTS(netif); 551195972f6Sopenharmony_ci 552195972f6Sopenharmony_ci /* did we chain a header earlier? */ 553195972f6Sopenharmony_ci if (q != p) { 554195972f6Sopenharmony_ci /* free the header */ 555195972f6Sopenharmony_ci pbuf_free(q); 556195972f6Sopenharmony_ci } 557195972f6Sopenharmony_ci return err; 558195972f6Sopenharmony_ci} 559195972f6Sopenharmony_ci 560195972f6Sopenharmony_ci/** 561195972f6Sopenharmony_ci * @ingroup raw_raw 562195972f6Sopenharmony_ci * Send the raw IP packet to the address given by raw_connect() 563195972f6Sopenharmony_ci * 564195972f6Sopenharmony_ci * @param pcb the raw pcb which to send 565195972f6Sopenharmony_ci * @param p the IP payload to send 566195972f6Sopenharmony_ci * 567195972f6Sopenharmony_ci */ 568195972f6Sopenharmony_cierr_t 569195972f6Sopenharmony_ciraw_send(struct raw_pcb *pcb, struct pbuf *p) 570195972f6Sopenharmony_ci{ 571195972f6Sopenharmony_ci return raw_sendto(pcb, p, &pcb->remote_ip); 572195972f6Sopenharmony_ci} 573195972f6Sopenharmony_ci 574195972f6Sopenharmony_ci/** 575195972f6Sopenharmony_ci * @ingroup raw_raw 576195972f6Sopenharmony_ci * Remove an RAW PCB. 577195972f6Sopenharmony_ci * 578195972f6Sopenharmony_ci * @param pcb RAW PCB to be removed. The PCB is removed from the list of 579195972f6Sopenharmony_ci * RAW PCB's and the data structure is freed from memory. 580195972f6Sopenharmony_ci * 581195972f6Sopenharmony_ci * @see raw_new() 582195972f6Sopenharmony_ci */ 583195972f6Sopenharmony_civoid 584195972f6Sopenharmony_ciraw_remove(struct raw_pcb *pcb) 585195972f6Sopenharmony_ci{ 586195972f6Sopenharmony_ci struct raw_pcb *pcb2; 587195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 588195972f6Sopenharmony_ci /* pcb to be removed is first in list? */ 589195972f6Sopenharmony_ci if (raw_pcbs == pcb) { 590195972f6Sopenharmony_ci /* make list start at 2nd pcb */ 591195972f6Sopenharmony_ci raw_pcbs = raw_pcbs->next; 592195972f6Sopenharmony_ci /* pcb not 1st in list */ 593195972f6Sopenharmony_ci } else { 594195972f6Sopenharmony_ci for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { 595195972f6Sopenharmony_ci /* find pcb in raw_pcbs list */ 596195972f6Sopenharmony_ci if (pcb2->next != NULL && pcb2->next == pcb) { 597195972f6Sopenharmony_ci /* remove pcb from list */ 598195972f6Sopenharmony_ci pcb2->next = pcb->next; 599195972f6Sopenharmony_ci break; 600195972f6Sopenharmony_ci } 601195972f6Sopenharmony_ci } 602195972f6Sopenharmony_ci } 603195972f6Sopenharmony_ci memp_free(MEMP_RAW_PCB, pcb); 604195972f6Sopenharmony_ci} 605195972f6Sopenharmony_ci 606195972f6Sopenharmony_ci#ifdef LOSCFG_NET_CONTAINER 607195972f6Sopenharmony_civoid set_raw_pcb_net_group(struct raw_pcb *pcb, struct net_group *group) 608195972f6Sopenharmony_ci{ 609195972f6Sopenharmony_ci set_ippcb_net_group((struct ip_pcb *)pcb, group); 610195972f6Sopenharmony_ci} 611195972f6Sopenharmony_ci 612195972f6Sopenharmony_cistruct net_group *get_net_group_from_raw_pcb(struct raw_pcb *pcb) { 613195972f6Sopenharmony_ci return get_net_group_from_ippcb((struct ip_pcb *)pcb); 614195972f6Sopenharmony_ci} 615195972f6Sopenharmony_ci#endif 616195972f6Sopenharmony_ci/** 617195972f6Sopenharmony_ci * @ingroup raw_raw 618195972f6Sopenharmony_ci * Create a RAW PCB. 619195972f6Sopenharmony_ci * 620195972f6Sopenharmony_ci * @return The RAW PCB which was created. NULL if the PCB data structure 621195972f6Sopenharmony_ci * could not be allocated. 622195972f6Sopenharmony_ci * 623195972f6Sopenharmony_ci * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) 624195972f6Sopenharmony_ci * 625195972f6Sopenharmony_ci * @see raw_remove() 626195972f6Sopenharmony_ci */ 627195972f6Sopenharmony_cistruct raw_pcb * 628195972f6Sopenharmony_ciraw_new(u8_t proto) 629195972f6Sopenharmony_ci{ 630195972f6Sopenharmony_ci struct raw_pcb *pcb; 631195972f6Sopenharmony_ci 632195972f6Sopenharmony_ci LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); 633195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 634195972f6Sopenharmony_ci 635195972f6Sopenharmony_ci pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); 636195972f6Sopenharmony_ci /* could allocate RAW PCB? */ 637195972f6Sopenharmony_ci if (pcb != NULL) { 638195972f6Sopenharmony_ci /* initialize PCB to all zeroes */ 639195972f6Sopenharmony_ci memset(pcb, 0, sizeof(struct raw_pcb)); 640195972f6Sopenharmony_ci pcb->protocol = proto; 641195972f6Sopenharmony_ci pcb->ttl = RAW_TTL; 642195972f6Sopenharmony_ci#if LWIP_MULTICAST_TX_OPTIONS 643195972f6Sopenharmony_ci raw_set_multicast_ttl(pcb, RAW_TTL); 644195972f6Sopenharmony_ci#endif /* LWIP_MULTICAST_TX_OPTIONS */ 645195972f6Sopenharmony_ci pcb->next = raw_pcbs; 646195972f6Sopenharmony_ci raw_pcbs = pcb; 647195972f6Sopenharmony_ci } 648195972f6Sopenharmony_ci return pcb; 649195972f6Sopenharmony_ci} 650195972f6Sopenharmony_ci 651195972f6Sopenharmony_ci/** 652195972f6Sopenharmony_ci * @ingroup raw_raw 653195972f6Sopenharmony_ci * Create a RAW PCB for specific IP type. 654195972f6Sopenharmony_ci * 655195972f6Sopenharmony_ci * @return The RAW PCB which was created. NULL if the PCB data structure 656195972f6Sopenharmony_ci * could not be allocated. 657195972f6Sopenharmony_ci * 658195972f6Sopenharmony_ci * @param type IP address type, see @ref lwip_ip_addr_type definitions. 659195972f6Sopenharmony_ci * If you want to listen to IPv4 and IPv6 (dual-stack) packets, 660195972f6Sopenharmony_ci * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. 661195972f6Sopenharmony_ci * @param proto the protocol number (next header) of the IPv6 packet payload 662195972f6Sopenharmony_ci * (e.g. IP6_NEXTH_ICMP6) 663195972f6Sopenharmony_ci * 664195972f6Sopenharmony_ci * @see raw_remove() 665195972f6Sopenharmony_ci */ 666195972f6Sopenharmony_cistruct raw_pcb * 667195972f6Sopenharmony_ciraw_new_ip_type(u8_t type, u8_t proto) 668195972f6Sopenharmony_ci{ 669195972f6Sopenharmony_ci struct raw_pcb *pcb; 670195972f6Sopenharmony_ci LWIP_ASSERT_CORE_LOCKED(); 671195972f6Sopenharmony_ci pcb = raw_new(proto); 672195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 673195972f6Sopenharmony_ci if (pcb != NULL) { 674195972f6Sopenharmony_ci IP_SET_TYPE_VAL(pcb->local_ip, type); 675195972f6Sopenharmony_ci IP_SET_TYPE_VAL(pcb->remote_ip, type); 676195972f6Sopenharmony_ci } 677195972f6Sopenharmony_ci#else /* LWIP_IPV4 && LWIP_IPV6 */ 678195972f6Sopenharmony_ci LWIP_UNUSED_ARG(type); 679195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_IPV6 */ 680195972f6Sopenharmony_ci return pcb; 681195972f6Sopenharmony_ci} 682195972f6Sopenharmony_ci 683195972f6Sopenharmony_ci/** This function is called from netif.c when address is changed 684195972f6Sopenharmony_ci * 685195972f6Sopenharmony_ci * @param old_addr IP address of the netif before change 686195972f6Sopenharmony_ci * @param new_addr IP address of the netif after change 687195972f6Sopenharmony_ci */ 688195972f6Sopenharmony_civoid raw_netif_ip_addr_changed(const ip_addr_t *old_addr, const ip_addr_t *new_addr) 689195972f6Sopenharmony_ci{ 690195972f6Sopenharmony_ci struct raw_pcb *rpcb; 691195972f6Sopenharmony_ci 692195972f6Sopenharmony_ci if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { 693195972f6Sopenharmony_ci for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { 694195972f6Sopenharmony_ci /* PCB bound to current local interface address? */ 695195972f6Sopenharmony_ci if (ip_addr_cmp(&rpcb->local_ip, old_addr)) { 696195972f6Sopenharmony_ci /* The PCB is bound to the old ipaddr and 697195972f6Sopenharmony_ci * is set to bound to the new one instead */ 698195972f6Sopenharmony_ci ip_addr_copy(rpcb->local_ip, *new_addr); 699195972f6Sopenharmony_ci } 700195972f6Sopenharmony_ci } 701195972f6Sopenharmony_ci } 702195972f6Sopenharmony_ci} 703195972f6Sopenharmony_ci 704195972f6Sopenharmony_ci#endif /* LWIP_RAW */ 705