1*5d5fbe79SDavid van Moolenbroek /**
2*5d5fbe79SDavid van Moolenbroek * @file
3*5d5fbe79SDavid van Moolenbroek * Implementation of raw protocol PCBs for low-level handling of
4*5d5fbe79SDavid van Moolenbroek * different types of protocols besides (or overriding) those
5*5d5fbe79SDavid van Moolenbroek * already available in lwIP.\n
6*5d5fbe79SDavid van Moolenbroek * See also @ref raw_raw
7*5d5fbe79SDavid van Moolenbroek *
8*5d5fbe79SDavid van Moolenbroek * @defgroup raw_raw RAW
9*5d5fbe79SDavid van Moolenbroek * @ingroup callbackstyle_api
10*5d5fbe79SDavid van Moolenbroek * Implementation of raw protocol PCBs for low-level handling of
11*5d5fbe79SDavid van Moolenbroek * different types of protocols besides (or overriding) those
12*5d5fbe79SDavid van Moolenbroek * already available in lwIP.\n
13*5d5fbe79SDavid van Moolenbroek * @see @ref raw_api
14*5d5fbe79SDavid van Moolenbroek */
15*5d5fbe79SDavid van Moolenbroek
16*5d5fbe79SDavid van Moolenbroek /*
17*5d5fbe79SDavid van Moolenbroek * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
18*5d5fbe79SDavid van Moolenbroek * All rights reserved.
19*5d5fbe79SDavid van Moolenbroek *
20*5d5fbe79SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without modification,
21*5d5fbe79SDavid van Moolenbroek * are permitted provided that the following conditions are met:
22*5d5fbe79SDavid van Moolenbroek *
23*5d5fbe79SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright notice,
24*5d5fbe79SDavid van Moolenbroek * this list of conditions and the following disclaimer.
25*5d5fbe79SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright notice,
26*5d5fbe79SDavid van Moolenbroek * this list of conditions and the following disclaimer in the documentation
27*5d5fbe79SDavid van Moolenbroek * and/or other materials provided with the distribution.
28*5d5fbe79SDavid van Moolenbroek * 3. The name of the author may not be used to endorse or promote products
29*5d5fbe79SDavid van Moolenbroek * derived from this software without specific prior written permission.
30*5d5fbe79SDavid van Moolenbroek *
31*5d5fbe79SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
32*5d5fbe79SDavid van Moolenbroek * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33*5d5fbe79SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
34*5d5fbe79SDavid van Moolenbroek * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35*5d5fbe79SDavid van Moolenbroek * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
36*5d5fbe79SDavid van Moolenbroek * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37*5d5fbe79SDavid van Moolenbroek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38*5d5fbe79SDavid van Moolenbroek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
39*5d5fbe79SDavid van Moolenbroek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
40*5d5fbe79SDavid van Moolenbroek * OF SUCH DAMAGE.
41*5d5fbe79SDavid van Moolenbroek *
42*5d5fbe79SDavid van Moolenbroek * This file is part of the lwIP TCP/IP stack.
43*5d5fbe79SDavid van Moolenbroek *
44*5d5fbe79SDavid van Moolenbroek * Author: Adam Dunkels <adam@sics.se>
45*5d5fbe79SDavid van Moolenbroek *
46*5d5fbe79SDavid van Moolenbroek */
47*5d5fbe79SDavid van Moolenbroek
48*5d5fbe79SDavid van Moolenbroek #include "lwip/opt.h"
49*5d5fbe79SDavid van Moolenbroek
50*5d5fbe79SDavid van Moolenbroek #if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
51*5d5fbe79SDavid van Moolenbroek
52*5d5fbe79SDavid van Moolenbroek #include "lwip/def.h"
53*5d5fbe79SDavid van Moolenbroek #include "lwip/memp.h"
54*5d5fbe79SDavid van Moolenbroek #include "lwip/ip_addr.h"
55*5d5fbe79SDavid van Moolenbroek #include "lwip/netif.h"
56*5d5fbe79SDavid van Moolenbroek #include "lwip/raw.h"
57*5d5fbe79SDavid van Moolenbroek #include "lwip/stats.h"
58*5d5fbe79SDavid van Moolenbroek #include "lwip/ip6.h"
59*5d5fbe79SDavid van Moolenbroek #include "lwip/ip6_addr.h"
60*5d5fbe79SDavid van Moolenbroek #include "lwip/inet_chksum.h"
61*5d5fbe79SDavid van Moolenbroek
62*5d5fbe79SDavid van Moolenbroek #include <string.h>
63*5d5fbe79SDavid van Moolenbroek
64*5d5fbe79SDavid van Moolenbroek /** The list of RAW PCBs */
65*5d5fbe79SDavid van Moolenbroek static struct raw_pcb *raw_pcbs;
66*5d5fbe79SDavid van Moolenbroek
67*5d5fbe79SDavid van Moolenbroek static u8_t
raw_input_local_match(struct raw_pcb * pcb,u8_t broadcast)68*5d5fbe79SDavid van Moolenbroek raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast)
69*5d5fbe79SDavid van Moolenbroek {
70*5d5fbe79SDavid van Moolenbroek LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */
71*5d5fbe79SDavid van Moolenbroek
72*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4 && LWIP_IPV6
73*5d5fbe79SDavid van Moolenbroek /* Dual-stack: PCBs listening to any IP type also listen to any IP address */
74*5d5fbe79SDavid van Moolenbroek if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
75*5d5fbe79SDavid van Moolenbroek #if IP_SOF_BROADCAST_RECV
76*5d5fbe79SDavid van Moolenbroek if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) {
77*5d5fbe79SDavid van Moolenbroek return 0;
78*5d5fbe79SDavid van Moolenbroek }
79*5d5fbe79SDavid van Moolenbroek #endif /* IP_SOF_BROADCAST_RECV */
80*5d5fbe79SDavid van Moolenbroek return 1;
81*5d5fbe79SDavid van Moolenbroek }
82*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV4 && LWIP_IPV6 */
83*5d5fbe79SDavid van Moolenbroek
84*5d5fbe79SDavid van Moolenbroek /* Only need to check PCB if incoming IP version matches PCB IP version */
85*5d5fbe79SDavid van Moolenbroek if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) {
86*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4
87*5d5fbe79SDavid van Moolenbroek /* Special case: IPv4 broadcast: receive all broadcasts
88*5d5fbe79SDavid van Moolenbroek * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */
89*5d5fbe79SDavid van Moolenbroek if (broadcast != 0) {
90*5d5fbe79SDavid van Moolenbroek #if IP_SOF_BROADCAST_RECV
91*5d5fbe79SDavid van Moolenbroek if (ip_get_option(pcb, SOF_BROADCAST))
92*5d5fbe79SDavid van Moolenbroek #endif /* IP_SOF_BROADCAST_RECV */
93*5d5fbe79SDavid van Moolenbroek {
94*5d5fbe79SDavid van Moolenbroek if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) {
95*5d5fbe79SDavid van Moolenbroek return 1;
96*5d5fbe79SDavid van Moolenbroek }
97*5d5fbe79SDavid van Moolenbroek }
98*5d5fbe79SDavid van Moolenbroek } else
99*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV4 */
100*5d5fbe79SDavid van Moolenbroek /* Handle IPv4 and IPv6: catch all or exact match */
101*5d5fbe79SDavid van Moolenbroek if (ip_addr_isany(&pcb->local_ip) ||
102*5d5fbe79SDavid van Moolenbroek ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
103*5d5fbe79SDavid van Moolenbroek return 1;
104*5d5fbe79SDavid van Moolenbroek }
105*5d5fbe79SDavid van Moolenbroek }
106*5d5fbe79SDavid van Moolenbroek
107*5d5fbe79SDavid van Moolenbroek return 0;
108*5d5fbe79SDavid van Moolenbroek }
109*5d5fbe79SDavid van Moolenbroek
110*5d5fbe79SDavid van Moolenbroek /**
111*5d5fbe79SDavid van Moolenbroek * Determine if in incoming IP packet is covered by a RAW PCB
112*5d5fbe79SDavid van Moolenbroek * and if so, pass it to a user-provided receive callback function.
113*5d5fbe79SDavid van Moolenbroek *
114*5d5fbe79SDavid van Moolenbroek * Given an incoming IP datagram (as a chain of pbufs) this function
115*5d5fbe79SDavid van Moolenbroek * finds a corresponding RAW PCB and calls the corresponding receive
116*5d5fbe79SDavid van Moolenbroek * callback function.
117*5d5fbe79SDavid van Moolenbroek *
118*5d5fbe79SDavid van Moolenbroek * @param p pbuf to be demultiplexed to a RAW PCB.
119*5d5fbe79SDavid van Moolenbroek * @param inp network interface on which the datagram was received.
120*5d5fbe79SDavid van Moolenbroek * @return - 1 if the packet has been eaten by a RAW PCB receive
121*5d5fbe79SDavid van Moolenbroek * callback function. The caller MAY NOT not reference the
122*5d5fbe79SDavid van Moolenbroek * packet any longer, and MAY NOT call pbuf_free().
123*5d5fbe79SDavid van Moolenbroek * @return - 0 if packet is not eaten (pbuf is still referenced by the
124*5d5fbe79SDavid van Moolenbroek * caller).
125*5d5fbe79SDavid van Moolenbroek *
126*5d5fbe79SDavid van Moolenbroek */
127*5d5fbe79SDavid van Moolenbroek u8_t
raw_input(struct pbuf * p,struct netif * inp)128*5d5fbe79SDavid van Moolenbroek raw_input(struct pbuf *p, struct netif *inp)
129*5d5fbe79SDavid van Moolenbroek {
130*5d5fbe79SDavid van Moolenbroek struct raw_pcb *pcb, *prev;
131*5d5fbe79SDavid van Moolenbroek s16_t proto;
132*5d5fbe79SDavid van Moolenbroek u8_t eaten = 0;
133*5d5fbe79SDavid van Moolenbroek u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif());
134*5d5fbe79SDavid van Moolenbroek
135*5d5fbe79SDavid van Moolenbroek LWIP_UNUSED_ARG(inp);
136*5d5fbe79SDavid van Moolenbroek
137*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV6
138*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4
139*5d5fbe79SDavid van Moolenbroek if (IP_HDR_GET_VERSION(p->payload) == 6)
140*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV4 */
141*5d5fbe79SDavid van Moolenbroek {
142*5d5fbe79SDavid van Moolenbroek struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
143*5d5fbe79SDavid van Moolenbroek proto = IP6H_NEXTH(ip6hdr);
144*5d5fbe79SDavid van Moolenbroek }
145*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4
146*5d5fbe79SDavid van Moolenbroek else
147*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV4 */
148*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV6 */
149*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4
150*5d5fbe79SDavid van Moolenbroek {
151*5d5fbe79SDavid van Moolenbroek proto = IPH_PROTO((struct ip_hdr *)p->payload);
152*5d5fbe79SDavid van Moolenbroek }
153*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV4 */
154*5d5fbe79SDavid van Moolenbroek
155*5d5fbe79SDavid van Moolenbroek prev = NULL;
156*5d5fbe79SDavid van Moolenbroek pcb = raw_pcbs;
157*5d5fbe79SDavid van Moolenbroek /* loop through all raw pcbs until the packet is eaten by one */
158*5d5fbe79SDavid van Moolenbroek /* this allows multiple pcbs to match against the packet by design */
159*5d5fbe79SDavid van Moolenbroek while ((eaten == 0) && (pcb != NULL)) {
160*5d5fbe79SDavid van Moolenbroek if ((pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) &&
161*5d5fbe79SDavid van Moolenbroek (((pcb->flags & RAW_FLAGS_CONNECTED) == 0) ||
162*5d5fbe79SDavid van Moolenbroek ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) {
163*5d5fbe79SDavid van Moolenbroek /* receive callback function available? */
164*5d5fbe79SDavid van Moolenbroek if (pcb->recv != NULL) {
165*5d5fbe79SDavid van Moolenbroek #ifndef LWIP_NOASSERT
166*5d5fbe79SDavid van Moolenbroek void* old_payload = p->payload;
167*5d5fbe79SDavid van Moolenbroek #endif
168*5d5fbe79SDavid van Moolenbroek /* the receive callback function did not eat the packet? */
169*5d5fbe79SDavid van Moolenbroek eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
170*5d5fbe79SDavid van Moolenbroek if (eaten != 0) {
171*5d5fbe79SDavid van Moolenbroek /* receive function ate the packet */
172*5d5fbe79SDavid van Moolenbroek p = NULL;
173*5d5fbe79SDavid van Moolenbroek eaten = 1;
174*5d5fbe79SDavid van Moolenbroek if (prev != NULL) {
175*5d5fbe79SDavid van Moolenbroek /* move the pcb to the front of raw_pcbs so that is
176*5d5fbe79SDavid van Moolenbroek found faster next time */
177*5d5fbe79SDavid van Moolenbroek prev->next = pcb->next;
178*5d5fbe79SDavid van Moolenbroek pcb->next = raw_pcbs;
179*5d5fbe79SDavid van Moolenbroek raw_pcbs = pcb;
180*5d5fbe79SDavid van Moolenbroek }
181*5d5fbe79SDavid van Moolenbroek } else {
182*5d5fbe79SDavid van Moolenbroek /* sanity-check that the receive callback did not alter the pbuf */
183*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet",
184*5d5fbe79SDavid van Moolenbroek p->payload == old_payload);
185*5d5fbe79SDavid van Moolenbroek }
186*5d5fbe79SDavid van Moolenbroek }
187*5d5fbe79SDavid van Moolenbroek /* no receive callback function was set for this raw PCB */
188*5d5fbe79SDavid van Moolenbroek }
189*5d5fbe79SDavid van Moolenbroek /* drop the packet */
190*5d5fbe79SDavid van Moolenbroek prev = pcb;
191*5d5fbe79SDavid van Moolenbroek pcb = pcb->next;
192*5d5fbe79SDavid van Moolenbroek }
193*5d5fbe79SDavid van Moolenbroek return eaten;
194*5d5fbe79SDavid van Moolenbroek }
195*5d5fbe79SDavid van Moolenbroek
196*5d5fbe79SDavid van Moolenbroek /**
197*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
198*5d5fbe79SDavid van Moolenbroek * Bind a RAW PCB.
199*5d5fbe79SDavid van Moolenbroek *
200*5d5fbe79SDavid van Moolenbroek * @param pcb RAW PCB to be bound with a local address ipaddr.
201*5d5fbe79SDavid van Moolenbroek * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to
202*5d5fbe79SDavid van Moolenbroek * bind to all local interfaces.
203*5d5fbe79SDavid van Moolenbroek *
204*5d5fbe79SDavid van Moolenbroek * @return lwIP error code.
205*5d5fbe79SDavid van Moolenbroek * - ERR_OK. Successful. No error occurred.
206*5d5fbe79SDavid van Moolenbroek * - ERR_USE. The specified IP address is already bound to by
207*5d5fbe79SDavid van Moolenbroek * another RAW PCB.
208*5d5fbe79SDavid van Moolenbroek *
209*5d5fbe79SDavid van Moolenbroek * @see raw_disconnect()
210*5d5fbe79SDavid van Moolenbroek */
211*5d5fbe79SDavid van Moolenbroek err_t
raw_bind(struct raw_pcb * pcb,const ip_addr_t * ipaddr)212*5d5fbe79SDavid van Moolenbroek raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
213*5d5fbe79SDavid van Moolenbroek {
214*5d5fbe79SDavid van Moolenbroek if ((pcb == NULL) || (ipaddr == NULL)) {
215*5d5fbe79SDavid van Moolenbroek return ERR_VAL;
216*5d5fbe79SDavid van Moolenbroek }
217*5d5fbe79SDavid van Moolenbroek ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
218*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV6 && LWIP_IPV6_SCOPES
219*5d5fbe79SDavid van Moolenbroek /* If the given IP address should have a zone but doesn't, assign one now.
220*5d5fbe79SDavid van Moolenbroek * This is legacy support: scope-aware callers should always provide properly
221*5d5fbe79SDavid van Moolenbroek * zoned source addresses. */
222*5d5fbe79SDavid van Moolenbroek if (IP_IS_V6(&pcb->local_ip) &&
223*5d5fbe79SDavid van Moolenbroek ip6_addr_lacks_zone(ip_2_ip6(&pcb->local_ip), IP6_UNKNOWN)) {
224*5d5fbe79SDavid van Moolenbroek ip6_addr_select_zone(ip_2_ip6(&pcb->local_ip), ip_2_ip6(&pcb->local_ip));
225*5d5fbe79SDavid van Moolenbroek }
226*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */
227*5d5fbe79SDavid van Moolenbroek return ERR_OK;
228*5d5fbe79SDavid van Moolenbroek }
229*5d5fbe79SDavid van Moolenbroek
230*5d5fbe79SDavid van Moolenbroek /**
231*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
232*5d5fbe79SDavid van Moolenbroek * Connect an RAW PCB. This function is required by upper layers
233*5d5fbe79SDavid van Moolenbroek * of lwip. Using the raw api you could use raw_sendto() instead
234*5d5fbe79SDavid van Moolenbroek *
235*5d5fbe79SDavid van Moolenbroek * This will associate the RAW PCB with the remote address.
236*5d5fbe79SDavid van Moolenbroek *
237*5d5fbe79SDavid van Moolenbroek * @param pcb RAW PCB to be connected with remote address ipaddr and port.
238*5d5fbe79SDavid van Moolenbroek * @param ipaddr remote IP address to connect with.
239*5d5fbe79SDavid van Moolenbroek *
240*5d5fbe79SDavid van Moolenbroek * @return lwIP error code
241*5d5fbe79SDavid van Moolenbroek *
242*5d5fbe79SDavid van Moolenbroek * @see raw_disconnect() and raw_sendto()
243*5d5fbe79SDavid van Moolenbroek */
244*5d5fbe79SDavid van Moolenbroek err_t
raw_connect(struct raw_pcb * pcb,const ip_addr_t * ipaddr)245*5d5fbe79SDavid van Moolenbroek raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
246*5d5fbe79SDavid van Moolenbroek {
247*5d5fbe79SDavid van Moolenbroek if ((pcb == NULL) || (ipaddr == NULL)) {
248*5d5fbe79SDavid van Moolenbroek return ERR_VAL;
249*5d5fbe79SDavid van Moolenbroek }
250*5d5fbe79SDavid van Moolenbroek ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
251*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV6 && LWIP_IPV6_SCOPES
252*5d5fbe79SDavid van Moolenbroek /* If the given IP address should have a zone but doesn't, assign one now,
253*5d5fbe79SDavid van Moolenbroek * using the bound address to make a more informed decision when possible. */
254*5d5fbe79SDavid van Moolenbroek if (IP_IS_V6(&pcb->remote_ip) &&
255*5d5fbe79SDavid van Moolenbroek ip6_addr_lacks_zone(ip_2_ip6(&pcb->remote_ip), IP6_UNKNOWN)) {
256*5d5fbe79SDavid van Moolenbroek ip6_addr_select_zone(ip_2_ip6(&pcb->remote_ip), ip_2_ip6(&pcb->local_ip));
257*5d5fbe79SDavid van Moolenbroek }
258*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */
259*5d5fbe79SDavid van Moolenbroek pcb->flags |= RAW_FLAGS_CONNECTED;
260*5d5fbe79SDavid van Moolenbroek return ERR_OK;
261*5d5fbe79SDavid van Moolenbroek }
262*5d5fbe79SDavid van Moolenbroek
263*5d5fbe79SDavid van Moolenbroek /**
264*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
265*5d5fbe79SDavid van Moolenbroek * Disconnect a RAW PCB.
266*5d5fbe79SDavid van Moolenbroek *
267*5d5fbe79SDavid van Moolenbroek * @param pcb the raw pcb to disconnect.
268*5d5fbe79SDavid van Moolenbroek */
269*5d5fbe79SDavid van Moolenbroek void
raw_disconnect(struct raw_pcb * pcb)270*5d5fbe79SDavid van Moolenbroek raw_disconnect(struct raw_pcb *pcb)
271*5d5fbe79SDavid van Moolenbroek {
272*5d5fbe79SDavid van Moolenbroek /* reset remote address association */
273*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4 && LWIP_IPV6
274*5d5fbe79SDavid van Moolenbroek if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
275*5d5fbe79SDavid van Moolenbroek ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE);
276*5d5fbe79SDavid van Moolenbroek } else {
277*5d5fbe79SDavid van Moolenbroek #endif
278*5d5fbe79SDavid van Moolenbroek ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip);
279*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4 && LWIP_IPV6
280*5d5fbe79SDavid van Moolenbroek }
281*5d5fbe79SDavid van Moolenbroek #endif
282*5d5fbe79SDavid van Moolenbroek /* mark PCB as unconnected */
283*5d5fbe79SDavid van Moolenbroek pcb->flags &= ~RAW_FLAGS_CONNECTED;
284*5d5fbe79SDavid van Moolenbroek }
285*5d5fbe79SDavid van Moolenbroek
286*5d5fbe79SDavid van Moolenbroek /**
287*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
288*5d5fbe79SDavid van Moolenbroek * Set the callback function for received packets that match the
289*5d5fbe79SDavid van Moolenbroek * raw PCB's protocol and binding.
290*5d5fbe79SDavid van Moolenbroek *
291*5d5fbe79SDavid van Moolenbroek * The callback function MUST either
292*5d5fbe79SDavid van Moolenbroek * - eat the packet by calling pbuf_free() and returning non-zero. The
293*5d5fbe79SDavid van Moolenbroek * packet will not be passed to other raw PCBs or other protocol layers.
294*5d5fbe79SDavid van Moolenbroek * - not free the packet, and return zero. The packet will be matched
295*5d5fbe79SDavid van Moolenbroek * against further PCBs and/or forwarded to another protocol layers.
296*5d5fbe79SDavid van Moolenbroek */
297*5d5fbe79SDavid van Moolenbroek void
raw_recv(struct raw_pcb * pcb,raw_recv_fn recv,void * recv_arg)298*5d5fbe79SDavid van Moolenbroek raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
299*5d5fbe79SDavid van Moolenbroek {
300*5d5fbe79SDavid van Moolenbroek /* remember recv() callback and user data */
301*5d5fbe79SDavid van Moolenbroek pcb->recv = recv;
302*5d5fbe79SDavid van Moolenbroek pcb->recv_arg = recv_arg;
303*5d5fbe79SDavid van Moolenbroek }
304*5d5fbe79SDavid van Moolenbroek
305*5d5fbe79SDavid van Moolenbroek /**
306*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
307*5d5fbe79SDavid van Moolenbroek * Send the raw IP packet to the given address. An IP header will be prepended
308*5d5fbe79SDavid van Moolenbroek * to the packet, unless the RAW_FLAGS_HDRINCL flag is set on the PCB. In that
309*5d5fbe79SDavid van Moolenbroek * case, the packet must include an IP header, which will then be sent as is.
310*5d5fbe79SDavid van Moolenbroek *
311*5d5fbe79SDavid van Moolenbroek * @param pcb the raw pcb which to send
312*5d5fbe79SDavid van Moolenbroek * @param p the IP payload to send
313*5d5fbe79SDavid van Moolenbroek * @param ipaddr the destination address of the IP packet
314*5d5fbe79SDavid van Moolenbroek *
315*5d5fbe79SDavid van Moolenbroek */
316*5d5fbe79SDavid van Moolenbroek err_t
raw_sendto(struct raw_pcb * pcb,struct pbuf * p,const ip_addr_t * ipaddr)317*5d5fbe79SDavid van Moolenbroek raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
318*5d5fbe79SDavid van Moolenbroek {
319*5d5fbe79SDavid van Moolenbroek struct netif *netif;
320*5d5fbe79SDavid van Moolenbroek const ip_addr_t *src_ip;
321*5d5fbe79SDavid van Moolenbroek
322*5d5fbe79SDavid van Moolenbroek if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
323*5d5fbe79SDavid van Moolenbroek return ERR_VAL;
324*5d5fbe79SDavid van Moolenbroek }
325*5d5fbe79SDavid van Moolenbroek
326*5d5fbe79SDavid van Moolenbroek LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
327*5d5fbe79SDavid van Moolenbroek
328*5d5fbe79SDavid van Moolenbroek #if LWIP_MULTICAST_TX_OPTIONS
329*5d5fbe79SDavid van Moolenbroek netif = NULL;
330*5d5fbe79SDavid van Moolenbroek if (ip_addr_ismulticast(ipaddr)) {
331*5d5fbe79SDavid van Moolenbroek /* For multicast-destined packets, use the user-provided interface index to
332*5d5fbe79SDavid van Moolenbroek * determine the outgoing interface, if an interface index is set and a
333*5d5fbe79SDavid van Moolenbroek * matching netif can be found. Otherwise, fall back to regular routing. */
334*5d5fbe79SDavid van Moolenbroek netif = netif_get_by_index(pcb->mcast_ifindex);
335*5d5fbe79SDavid van Moolenbroek }
336*5d5fbe79SDavid van Moolenbroek
337*5d5fbe79SDavid van Moolenbroek if (netif == NULL)
338*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_MULTICAST_TX_OPTIONS */
339*5d5fbe79SDavid van Moolenbroek {
340*5d5fbe79SDavid van Moolenbroek if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
341*5d5fbe79SDavid van Moolenbroek /* Don't call ip_route() with IP_ANY_TYPE */
342*5d5fbe79SDavid van Moolenbroek netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr);
343*5d5fbe79SDavid van Moolenbroek } else {
344*5d5fbe79SDavid van Moolenbroek netif = ip_route(&pcb->local_ip, ipaddr);
345*5d5fbe79SDavid van Moolenbroek }
346*5d5fbe79SDavid van Moolenbroek }
347*5d5fbe79SDavid van Moolenbroek
348*5d5fbe79SDavid van Moolenbroek if (netif == NULL) {
349*5d5fbe79SDavid van Moolenbroek LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
350*5d5fbe79SDavid van Moolenbroek ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr);
351*5d5fbe79SDavid van Moolenbroek return ERR_RTE;
352*5d5fbe79SDavid van Moolenbroek }
353*5d5fbe79SDavid van Moolenbroek
354*5d5fbe79SDavid van Moolenbroek if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) {
355*5d5fbe79SDavid van Moolenbroek /* use outgoing network interface IP address as source address */
356*5d5fbe79SDavid van Moolenbroek src_ip = ip_netif_get_local_ip(netif, ipaddr);
357*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV6
358*5d5fbe79SDavid van Moolenbroek if (src_ip == NULL) {
359*5d5fbe79SDavid van Moolenbroek return ERR_RTE;
360*5d5fbe79SDavid van Moolenbroek }
361*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV6 */
362*5d5fbe79SDavid van Moolenbroek } else {
363*5d5fbe79SDavid van Moolenbroek /* use RAW PCB local IP address as source address */
364*5d5fbe79SDavid van Moolenbroek src_ip = &pcb->local_ip;
365*5d5fbe79SDavid van Moolenbroek }
366*5d5fbe79SDavid van Moolenbroek
367*5d5fbe79SDavid van Moolenbroek return raw_sendto_if_src(pcb, p, ipaddr, netif, src_ip);
368*5d5fbe79SDavid van Moolenbroek }
369*5d5fbe79SDavid van Moolenbroek
370*5d5fbe79SDavid van Moolenbroek /**
371*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
372*5d5fbe79SDavid van Moolenbroek * Send the raw IP packet to the given address, using a particular outgoing
373*5d5fbe79SDavid van Moolenbroek * netif and source IP address. An IP header will be prepended to the packet,
374*5d5fbe79SDavid van Moolenbroek * unless the RAW_FLAGS_HDRINCL flag is set on the PCB. In that case, the
375*5d5fbe79SDavid van Moolenbroek * packet must include an IP header, which will then be sent as is.
376*5d5fbe79SDavid van Moolenbroek *
377*5d5fbe79SDavid van Moolenbroek * @param pcb RAW PCB used to send the data
378*5d5fbe79SDavid van Moolenbroek * @param p chain of pbufs to be sent
379*5d5fbe79SDavid van Moolenbroek * @param dst_ip destination IP address
380*5d5fbe79SDavid van Moolenbroek * @param netif the netif used for sending
381*5d5fbe79SDavid van Moolenbroek * @param src_ip source IP address
382*5d5fbe79SDavid van Moolenbroek */
383*5d5fbe79SDavid van Moolenbroek err_t
raw_sendto_if_src(struct raw_pcb * pcb,struct pbuf * p,const ip_addr_t * dst_ip,struct netif * netif,const ip_addr_t * src_ip)384*5d5fbe79SDavid van Moolenbroek raw_sendto_if_src(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
385*5d5fbe79SDavid van Moolenbroek struct netif *netif, const ip_addr_t *src_ip)
386*5d5fbe79SDavid van Moolenbroek {
387*5d5fbe79SDavid van Moolenbroek err_t err;
388*5d5fbe79SDavid van Moolenbroek struct pbuf *q; /* q will be sent down the stack */
389*5d5fbe79SDavid van Moolenbroek s16_t header_size;
390*5d5fbe79SDavid van Moolenbroek u8_t ttl;
391*5d5fbe79SDavid van Moolenbroek
392*5d5fbe79SDavid van Moolenbroek if ((pcb == NULL) || (dst_ip == NULL) || (netif == NULL) || (src_ip == NULL) ||
393*5d5fbe79SDavid van Moolenbroek !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) {
394*5d5fbe79SDavid van Moolenbroek return ERR_VAL;
395*5d5fbe79SDavid van Moolenbroek }
396*5d5fbe79SDavid van Moolenbroek
397*5d5fbe79SDavid van Moolenbroek header_size = (
398*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4 && LWIP_IPV6
399*5d5fbe79SDavid van Moolenbroek IP_IS_V6(dst_ip) ? IP6_HLEN : IP_HLEN);
400*5d5fbe79SDavid van Moolenbroek #elif LWIP_IPV4
401*5d5fbe79SDavid van Moolenbroek IP_HLEN);
402*5d5fbe79SDavid van Moolenbroek #else
403*5d5fbe79SDavid van Moolenbroek IP6_HLEN);
404*5d5fbe79SDavid van Moolenbroek #endif
405*5d5fbe79SDavid van Moolenbroek
406*5d5fbe79SDavid van Moolenbroek /* Handle the HDRINCL option as an exception: none of the code below applies
407*5d5fbe79SDavid van Moolenbroek * to this case, and sending the packet needs to be done differently too. */
408*5d5fbe79SDavid van Moolenbroek if (pcb->flags & RAW_FLAGS_HDRINCL) {
409*5d5fbe79SDavid van Moolenbroek /* A full header *must* be present in the first pbuf of the chain, as the
410*5d5fbe79SDavid van Moolenbroek * output routines may access its fields directly. */
411*5d5fbe79SDavid van Moolenbroek if (p->len < header_size) {
412*5d5fbe79SDavid van Moolenbroek return ERR_VAL;
413*5d5fbe79SDavid van Moolenbroek }
414*5d5fbe79SDavid van Moolenbroek /* @todo multicast loop support, if at all desired for this scenario.. */
415*5d5fbe79SDavid van Moolenbroek NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
416*5d5fbe79SDavid van Moolenbroek err = ip_output_if_hdrincl(p, src_ip, dst_ip, netif);
417*5d5fbe79SDavid van Moolenbroek NETIF_SET_HWADDRHINT(netif, NULL);
418*5d5fbe79SDavid van Moolenbroek return err;
419*5d5fbe79SDavid van Moolenbroek }
420*5d5fbe79SDavid van Moolenbroek
421*5d5fbe79SDavid van Moolenbroek /* packet too large to add an IP header without causing an overflow? */
422*5d5fbe79SDavid van Moolenbroek if ((u16_t)(p->tot_len + header_size) < p->tot_len) {
423*5d5fbe79SDavid van Moolenbroek return ERR_MEM;
424*5d5fbe79SDavid van Moolenbroek }
425*5d5fbe79SDavid van Moolenbroek /* not enough space to add an IP header to first pbuf in given p chain? */
426*5d5fbe79SDavid van Moolenbroek if (pbuf_header(p, header_size)) {
427*5d5fbe79SDavid van Moolenbroek /* allocate header in new pbuf */
428*5d5fbe79SDavid van Moolenbroek q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
429*5d5fbe79SDavid van Moolenbroek /* new header pbuf could not be allocated? */
430*5d5fbe79SDavid van Moolenbroek if (q == NULL) {
431*5d5fbe79SDavid van Moolenbroek LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
432*5d5fbe79SDavid van Moolenbroek return ERR_MEM;
433*5d5fbe79SDavid van Moolenbroek }
434*5d5fbe79SDavid van Moolenbroek if (p->tot_len != 0) {
435*5d5fbe79SDavid van Moolenbroek /* chain header q in front of given pbuf p */
436*5d5fbe79SDavid van Moolenbroek pbuf_chain(q, p);
437*5d5fbe79SDavid van Moolenbroek }
438*5d5fbe79SDavid van Moolenbroek /* { first pbuf q points to header pbuf } */
439*5d5fbe79SDavid van Moolenbroek LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
440*5d5fbe79SDavid van Moolenbroek } else {
441*5d5fbe79SDavid van Moolenbroek /* first pbuf q equals given pbuf */
442*5d5fbe79SDavid van Moolenbroek q = p;
443*5d5fbe79SDavid van Moolenbroek if (pbuf_header(q, -header_size)) {
444*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("Can't restore header we just removed!", 0);
445*5d5fbe79SDavid van Moolenbroek return ERR_MEM;
446*5d5fbe79SDavid van Moolenbroek }
447*5d5fbe79SDavid van Moolenbroek }
448*5d5fbe79SDavid van Moolenbroek
449*5d5fbe79SDavid van Moolenbroek #if IP_SOF_BROADCAST
450*5d5fbe79SDavid van Moolenbroek if (IP_IS_V4(dst_ip))
451*5d5fbe79SDavid van Moolenbroek {
452*5d5fbe79SDavid van Moolenbroek /* broadcast filter? */
453*5d5fbe79SDavid van Moolenbroek if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(dst_ip, netif)) {
454*5d5fbe79SDavid van Moolenbroek LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
455*5d5fbe79SDavid van Moolenbroek /* free any temporary header pbuf allocated by pbuf_header() */
456*5d5fbe79SDavid van Moolenbroek if (q != p) {
457*5d5fbe79SDavid van Moolenbroek pbuf_free(q);
458*5d5fbe79SDavid van Moolenbroek }
459*5d5fbe79SDavid van Moolenbroek return ERR_VAL;
460*5d5fbe79SDavid van Moolenbroek }
461*5d5fbe79SDavid van Moolenbroek }
462*5d5fbe79SDavid van Moolenbroek #endif /* IP_SOF_BROADCAST */
463*5d5fbe79SDavid van Moolenbroek
464*5d5fbe79SDavid van Moolenbroek /* Multicast Loop? */
465*5d5fbe79SDavid van Moolenbroek #if LWIP_MULTICAST_TX_OPTIONS
466*5d5fbe79SDavid van Moolenbroek if (((pcb->flags & RAW_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) {
467*5d5fbe79SDavid van Moolenbroek q->flags |= PBUF_FLAG_MCASTLOOP;
468*5d5fbe79SDavid van Moolenbroek }
469*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_MULTICAST_TX_OPTIONS */
470*5d5fbe79SDavid van Moolenbroek
471*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV6
472*5d5fbe79SDavid van Moolenbroek /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542,
473*5d5fbe79SDavid van Moolenbroek compute the checksum and update the checksum in the payload. */
474*5d5fbe79SDavid van Moolenbroek if (IP_IS_V6(dst_ip) && pcb->chksum_reqd) {
475*5d5fbe79SDavid van Moolenbroek u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip));
476*5d5fbe79SDavid van Moolenbroek LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2));
477*5d5fbe79SDavid van Moolenbroek SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t));
478*5d5fbe79SDavid van Moolenbroek }
479*5d5fbe79SDavid van Moolenbroek #endif
480*5d5fbe79SDavid van Moolenbroek
481*5d5fbe79SDavid van Moolenbroek /* Determine TTL to use */
482*5d5fbe79SDavid van Moolenbroek #if LWIP_MULTICAST_TX_OPTIONS
483*5d5fbe79SDavid van Moolenbroek ttl = (ip_addr_ismulticast(dst_ip) ? raw_get_multicast_ttl(pcb) : pcb->ttl);
484*5d5fbe79SDavid van Moolenbroek #else /* LWIP_MULTICAST_TX_OPTIONS */
485*5d5fbe79SDavid van Moolenbroek ttl = pcb->ttl;
486*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_MULTICAST_TX_OPTIONS */
487*5d5fbe79SDavid van Moolenbroek
488*5d5fbe79SDavid van Moolenbroek NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
489*5d5fbe79SDavid van Moolenbroek err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif);
490*5d5fbe79SDavid van Moolenbroek NETIF_SET_HWADDRHINT(netif, NULL);
491*5d5fbe79SDavid van Moolenbroek
492*5d5fbe79SDavid van Moolenbroek /* did we chain a header earlier? */
493*5d5fbe79SDavid van Moolenbroek if (q != p) {
494*5d5fbe79SDavid van Moolenbroek /* free the header */
495*5d5fbe79SDavid van Moolenbroek pbuf_free(q);
496*5d5fbe79SDavid van Moolenbroek }
497*5d5fbe79SDavid van Moolenbroek return err;
498*5d5fbe79SDavid van Moolenbroek }
499*5d5fbe79SDavid van Moolenbroek
500*5d5fbe79SDavid van Moolenbroek /**
501*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
502*5d5fbe79SDavid van Moolenbroek * Send the raw IP packet to the address given by raw_connect()
503*5d5fbe79SDavid van Moolenbroek *
504*5d5fbe79SDavid van Moolenbroek * @param pcb the raw pcb which to send
505*5d5fbe79SDavid van Moolenbroek * @param p the IP payload to send
506*5d5fbe79SDavid van Moolenbroek *
507*5d5fbe79SDavid van Moolenbroek */
508*5d5fbe79SDavid van Moolenbroek err_t
raw_send(struct raw_pcb * pcb,struct pbuf * p)509*5d5fbe79SDavid van Moolenbroek raw_send(struct raw_pcb *pcb, struct pbuf *p)
510*5d5fbe79SDavid van Moolenbroek {
511*5d5fbe79SDavid van Moolenbroek return raw_sendto(pcb, p, &pcb->remote_ip);
512*5d5fbe79SDavid van Moolenbroek }
513*5d5fbe79SDavid van Moolenbroek
514*5d5fbe79SDavid van Moolenbroek /**
515*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
516*5d5fbe79SDavid van Moolenbroek * Remove an RAW PCB.
517*5d5fbe79SDavid van Moolenbroek *
518*5d5fbe79SDavid van Moolenbroek * @param pcb RAW PCB to be removed. The PCB is removed from the list of
519*5d5fbe79SDavid van Moolenbroek * RAW PCB's and the data structure is freed from memory.
520*5d5fbe79SDavid van Moolenbroek *
521*5d5fbe79SDavid van Moolenbroek * @see raw_new()
522*5d5fbe79SDavid van Moolenbroek */
523*5d5fbe79SDavid van Moolenbroek void
raw_remove(struct raw_pcb * pcb)524*5d5fbe79SDavid van Moolenbroek raw_remove(struct raw_pcb *pcb)
525*5d5fbe79SDavid van Moolenbroek {
526*5d5fbe79SDavid van Moolenbroek struct raw_pcb *pcb2;
527*5d5fbe79SDavid van Moolenbroek /* pcb to be removed is first in list? */
528*5d5fbe79SDavid van Moolenbroek if (raw_pcbs == pcb) {
529*5d5fbe79SDavid van Moolenbroek /* make list start at 2nd pcb */
530*5d5fbe79SDavid van Moolenbroek raw_pcbs = raw_pcbs->next;
531*5d5fbe79SDavid van Moolenbroek /* pcb not 1st in list */
532*5d5fbe79SDavid van Moolenbroek } else {
533*5d5fbe79SDavid van Moolenbroek for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
534*5d5fbe79SDavid van Moolenbroek /* find pcb in raw_pcbs list */
535*5d5fbe79SDavid van Moolenbroek if (pcb2->next != NULL && pcb2->next == pcb) {
536*5d5fbe79SDavid van Moolenbroek /* remove pcb from list */
537*5d5fbe79SDavid van Moolenbroek pcb2->next = pcb->next;
538*5d5fbe79SDavid van Moolenbroek break;
539*5d5fbe79SDavid van Moolenbroek }
540*5d5fbe79SDavid van Moolenbroek }
541*5d5fbe79SDavid van Moolenbroek }
542*5d5fbe79SDavid van Moolenbroek memp_free(MEMP_RAW_PCB, pcb);
543*5d5fbe79SDavid van Moolenbroek }
544*5d5fbe79SDavid van Moolenbroek
545*5d5fbe79SDavid van Moolenbroek /**
546*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
547*5d5fbe79SDavid van Moolenbroek * Create a RAW PCB.
548*5d5fbe79SDavid van Moolenbroek *
549*5d5fbe79SDavid van Moolenbroek * @return The RAW PCB which was created. NULL if the PCB data structure
550*5d5fbe79SDavid van Moolenbroek * could not be allocated.
551*5d5fbe79SDavid van Moolenbroek *
552*5d5fbe79SDavid van Moolenbroek * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
553*5d5fbe79SDavid van Moolenbroek *
554*5d5fbe79SDavid van Moolenbroek * @see raw_remove()
555*5d5fbe79SDavid van Moolenbroek */
556*5d5fbe79SDavid van Moolenbroek struct raw_pcb *
raw_new(u8_t proto)557*5d5fbe79SDavid van Moolenbroek raw_new(u8_t proto)
558*5d5fbe79SDavid van Moolenbroek {
559*5d5fbe79SDavid van Moolenbroek struct raw_pcb *pcb;
560*5d5fbe79SDavid van Moolenbroek
561*5d5fbe79SDavid van Moolenbroek LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n"));
562*5d5fbe79SDavid van Moolenbroek
563*5d5fbe79SDavid van Moolenbroek pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB);
564*5d5fbe79SDavid van Moolenbroek /* could allocate RAW PCB? */
565*5d5fbe79SDavid van Moolenbroek if (pcb != NULL) {
566*5d5fbe79SDavid van Moolenbroek /* initialize PCB to all zeroes */
567*5d5fbe79SDavid van Moolenbroek memset(pcb, 0, sizeof(struct raw_pcb));
568*5d5fbe79SDavid van Moolenbroek pcb->protocol = proto;
569*5d5fbe79SDavid van Moolenbroek pcb->ttl = RAW_TTL;
570*5d5fbe79SDavid van Moolenbroek #if LWIP_MULTICAST_TX_OPTIONS
571*5d5fbe79SDavid van Moolenbroek raw_set_multicast_ttl(pcb, RAW_TTL);
572*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_MULTICAST_TX_OPTIONS */
573*5d5fbe79SDavid van Moolenbroek pcb->next = raw_pcbs;
574*5d5fbe79SDavid van Moolenbroek raw_pcbs = pcb;
575*5d5fbe79SDavid van Moolenbroek }
576*5d5fbe79SDavid van Moolenbroek return pcb;
577*5d5fbe79SDavid van Moolenbroek }
578*5d5fbe79SDavid van Moolenbroek
579*5d5fbe79SDavid van Moolenbroek /**
580*5d5fbe79SDavid van Moolenbroek * @ingroup raw_raw
581*5d5fbe79SDavid van Moolenbroek * Create a RAW PCB for specific IP type.
582*5d5fbe79SDavid van Moolenbroek *
583*5d5fbe79SDavid van Moolenbroek * @return The RAW PCB which was created. NULL if the PCB data structure
584*5d5fbe79SDavid van Moolenbroek * could not be allocated.
585*5d5fbe79SDavid van Moolenbroek *
586*5d5fbe79SDavid van Moolenbroek * @param type IP address type, see @ref lwip_ip_addr_type definitions.
587*5d5fbe79SDavid van Moolenbroek * If you want to listen to IPv4 and IPv6 (dual-stack) packets,
588*5d5fbe79SDavid van Moolenbroek * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
589*5d5fbe79SDavid van Moolenbroek * @param proto the protocol number (next header) of the IPv6 packet payload
590*5d5fbe79SDavid van Moolenbroek * (e.g. IP6_NEXTH_ICMP6)
591*5d5fbe79SDavid van Moolenbroek *
592*5d5fbe79SDavid van Moolenbroek * @see raw_remove()
593*5d5fbe79SDavid van Moolenbroek */
594*5d5fbe79SDavid van Moolenbroek struct raw_pcb *
raw_new_ip_type(u8_t type,u8_t proto)595*5d5fbe79SDavid van Moolenbroek raw_new_ip_type(u8_t type, u8_t proto)
596*5d5fbe79SDavid van Moolenbroek {
597*5d5fbe79SDavid van Moolenbroek struct raw_pcb *pcb;
598*5d5fbe79SDavid van Moolenbroek pcb = raw_new(proto);
599*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV4 && LWIP_IPV6
600*5d5fbe79SDavid van Moolenbroek if (pcb != NULL) {
601*5d5fbe79SDavid van Moolenbroek IP_SET_TYPE_VAL(pcb->local_ip, type);
602*5d5fbe79SDavid van Moolenbroek IP_SET_TYPE_VAL(pcb->remote_ip, type);
603*5d5fbe79SDavid van Moolenbroek }
604*5d5fbe79SDavid van Moolenbroek #else /* LWIP_IPV4 && LWIP_IPV6 */
605*5d5fbe79SDavid van Moolenbroek LWIP_UNUSED_ARG(type);
606*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV4 && LWIP_IPV6 */
607*5d5fbe79SDavid van Moolenbroek return pcb;
608*5d5fbe79SDavid van Moolenbroek }
609*5d5fbe79SDavid van Moolenbroek
610*5d5fbe79SDavid van Moolenbroek /** This function is called from netif.c when address is changed
611*5d5fbe79SDavid van Moolenbroek *
612*5d5fbe79SDavid van Moolenbroek * @param old_addr IP address of the netif before change
613*5d5fbe79SDavid van Moolenbroek * @param new_addr IP address of the netif after change
614*5d5fbe79SDavid van Moolenbroek */
raw_netif_ip_addr_changed(const ip_addr_t * old_addr,const ip_addr_t * new_addr)615*5d5fbe79SDavid van Moolenbroek void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr)
616*5d5fbe79SDavid van Moolenbroek {
617*5d5fbe79SDavid van Moolenbroek struct raw_pcb* rpcb;
618*5d5fbe79SDavid van Moolenbroek
619*5d5fbe79SDavid van Moolenbroek if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) {
620*5d5fbe79SDavid van Moolenbroek for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) {
621*5d5fbe79SDavid van Moolenbroek /* PCB bound to current local interface address? */
622*5d5fbe79SDavid van Moolenbroek if (ip_addr_cmp(&rpcb->local_ip, old_addr)) {
623*5d5fbe79SDavid van Moolenbroek /* The PCB is bound to the old ipaddr and
624*5d5fbe79SDavid van Moolenbroek * is set to bound to the new one instead */
625*5d5fbe79SDavid van Moolenbroek ip_addr_copy(rpcb->local_ip, *new_addr);
626*5d5fbe79SDavid van Moolenbroek }
627*5d5fbe79SDavid van Moolenbroek }
628*5d5fbe79SDavid van Moolenbroek }
629*5d5fbe79SDavid van Moolenbroek }
630*5d5fbe79SDavid van Moolenbroek
631*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_RAW */
632