Skip to content

Commit fde1c05

Browse files
committed
Revert "remove lwip_src"
This reverts commit 398e912. It fails on LINK without them.
1 parent 398e912 commit fde1c05

File tree

2 files changed

+409
-0
lines changed

2 files changed

+409
-0
lines changed

ports/raspberrypi/lwip_src/ping.c

Lines changed: 384 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,384 @@
1+
/**
2+
* @file
3+
* Ping sender module
4+
*
5+
*/
6+
7+
/*
8+
* Redistribution and use in source and binary forms, with or without modification,
9+
* are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
* 2. Redistributions in binary form must reproduce the above copyright notice,
14+
* this list of conditions and the following disclaimer in the documentation
15+
* and/or other materials provided with the distribution.
16+
* 3. The name of the author may not be used to endorse or promote products
17+
* derived from this software without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
22+
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24+
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27+
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28+
* OF SUCH DAMAGE.
29+
*
30+
* This file is part of the lwIP TCP/IP stack.
31+
*
32+
*/
33+
34+
/**
35+
* This is an example of a "ping" sender (with raw API and socket API).
36+
* It can be used as a start point to maintain opened a network connection, or
37+
* like a network "watchdog" for your device.
38+
*
39+
*/
40+
41+
#include "lwip/opt.h"
42+
43+
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
44+
45+
#include "ping.h"
46+
47+
#include "lwip/mem.h"
48+
#include "lwip/raw.h"
49+
#include "lwip/icmp.h"
50+
#include "lwip/netif.h"
51+
#include "lwip/sys.h"
52+
#include "lwip/timeouts.h"
53+
#include "lwip/inet_chksum.h"
54+
#include "lwip/prot/ip4.h"
55+
56+
#if PING_USE_SOCKETS
57+
#include "lwip/sockets.h"
58+
#include "lwip/inet.h"
59+
#include <string.h>
60+
#endif /* PING_USE_SOCKETS */
61+
62+
63+
/**
64+
* PING_DEBUG: Enable debugging for PING.
65+
*/
66+
#ifndef PING_DEBUG
67+
#define PING_DEBUG LWIP_DBG_ON
68+
#endif
69+
70+
/** ping receive timeout - in milliseconds */
71+
#ifndef PING_RCV_TIMEO
72+
#define PING_RCV_TIMEO 1000
73+
#endif
74+
75+
/** ping delay - in milliseconds */
76+
#ifndef PING_DELAY
77+
#define PING_DELAY 1000
78+
#endif
79+
80+
/** ping identifier - must fit on a u16_t */
81+
#ifndef PING_ID
82+
#define PING_ID 0xAFAF
83+
#endif
84+
85+
/** ping additional data size to include in the packet */
86+
#ifndef PING_DATA_SIZE
87+
#define PING_DATA_SIZE 32
88+
#endif
89+
90+
/** ping result action - no default action */
91+
#ifndef PING_RESULT
92+
#define PING_RESULT(ping_ok)
93+
#endif
94+
95+
/* ping variables */
96+
static const ip_addr_t *ping_target;
97+
u16_t ping_seq_num;
98+
#ifdef LWIP_DEBUG
99+
static u32_t ping_time;
100+
#endif /* LWIP_DEBUG */
101+
#if !PING_USE_SOCKETS
102+
static struct raw_pcb *ping_pcb;
103+
#endif /* PING_USE_SOCKETS */
104+
105+
/** Prepare a echo ICMP request */
106+
void
107+
ping_prepare_echo(struct icmp_echo_hdr *iecho, u16_t len) {
108+
size_t i;
109+
size_t data_len = len - sizeof(struct icmp_echo_hdr);
110+
111+
ICMPH_TYPE_SET(iecho, ICMP_ECHO);
112+
ICMPH_CODE_SET(iecho, 0);
113+
iecho->chksum = 0;
114+
iecho->id = PING_ID;
115+
iecho->seqno = lwip_htons(++ping_seq_num);
116+
117+
/* fill the additional data buffer with some data */
118+
for (i = 0; i < data_len; i++) {
119+
((char *)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
120+
}
121+
122+
iecho->chksum = inet_chksum(iecho, len);
123+
}
124+
125+
#if PING_USE_SOCKETS
126+
127+
/* Ping using the socket ip */
128+
err_t
129+
ping_send(int s, const ip_addr_t *addr) {
130+
int err;
131+
struct icmp_echo_hdr *iecho;
132+
struct sockaddr_storage to;
133+
size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
134+
LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
135+
136+
#if LWIP_IPV6
137+
if (IP_IS_V6(addr) && !ip6_addr_isipv4mappedipv6(ip_2_ip6(addr))) {
138+
/* todo: support ICMP6 echo */
139+
return ERR_VAL;
140+
}
141+
#endif /* LWIP_IPV6 */
142+
143+
iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
144+
if (!iecho) {
145+
return ERR_MEM;
146+
}
147+
148+
ping_prepare_echo(iecho, (u16_t)ping_size);
149+
150+
#if LWIP_IPV4
151+
if (IP_IS_V4(addr)) {
152+
struct sockaddr_in *to4 = (struct sockaddr_in *)&to;
153+
to4->sin_len = sizeof(*to4);
154+
to4->sin_family = AF_INET;
155+
inet_addr_from_ip4addr(&to4->sin_addr, ip_2_ip4(addr));
156+
}
157+
#endif /* LWIP_IPV4 */
158+
159+
#if LWIP_IPV6
160+
if (IP_IS_V6(addr)) {
161+
struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&to;
162+
to6->sin6_len = sizeof(*to6);
163+
to6->sin6_family = AF_INET6;
164+
inet6_addr_from_ip6addr(&to6->sin6_addr, ip_2_ip6(addr));
165+
}
166+
#endif /* LWIP_IPV6 */
167+
168+
err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr *)&to, sizeof(to));
169+
170+
mem_free(iecho);
171+
172+
return err ? ERR_OK : ERR_VAL;
173+
}
174+
175+
static void
176+
ping_recv(int s) {
177+
char buf[64];
178+
int len;
179+
struct sockaddr_storage from;
180+
int fromlen = sizeof(from);
181+
182+
while ((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, (socklen_t *)&fromlen)) > 0) {
183+
if (len >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) {
184+
ip_addr_t fromaddr;
185+
memset(&fromaddr, 0, sizeof(fromaddr));
186+
187+
#if LWIP_IPV4
188+
if (from.ss_family == AF_INET) {
189+
struct sockaddr_in *from4 = (struct sockaddr_in *)&from;
190+
inet_addr_to_ip4addr(ip_2_ip4(&fromaddr), &from4->sin_addr);
191+
IP_SET_TYPE_VAL(fromaddr, IPADDR_TYPE_V4);
192+
}
193+
#endif /* LWIP_IPV4 */
194+
195+
#if LWIP_IPV6
196+
if (from.ss_family == AF_INET6) {
197+
struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from;
198+
inet6_addr_to_ip6addr(ip_2_ip6(&fromaddr), &from6->sin6_addr);
199+
IP_SET_TYPE_VAL(fromaddr, IPADDR_TYPE_V6);
200+
}
201+
#endif /* LWIP_IPV6 */
202+
203+
LWIP_DEBUGF(PING_DEBUG, ("ping: recv "));
204+
ip_addr_debug_print_val(PING_DEBUG, fromaddr);
205+
LWIP_DEBUGF(PING_DEBUG, (" %"U32_F " ms\n", (sys_now() - ping_time)));
206+
207+
/* todo: support ICMP6 echo */
208+
#if LWIP_IPV4
209+
if (IP_IS_V4_VAL(fromaddr)) {
210+
struct ip_hdr *iphdr;
211+
struct icmp_echo_hdr *iecho;
212+
213+
iphdr = (struct ip_hdr *)buf;
214+
iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
215+
if ((iecho->id == PING_ID) && (iecho->seqno == lwip_htons(ping_seq_num))) {
216+
/* do some ping result processing */
217+
PING_RESULT((ICMPH_TYPE(iecho) == ICMP_ER));
218+
return;
219+
} else {
220+
LWIP_DEBUGF(PING_DEBUG, ("ping: drop\n"));
221+
}
222+
}
223+
#endif /* LWIP_IPV4 */
224+
}
225+
fromlen = sizeof(from);
226+
}
227+
228+
if (len == 0) {
229+
LWIP_DEBUGF(PING_DEBUG, ("ping: recv - %"U32_F " ms - timeout\n", (sys_now() - ping_time)));
230+
}
231+
232+
/* do some ping result processing */
233+
PING_RESULT(0);
234+
}
235+
236+
static void
237+
ping_thread(void *arg) {
238+
int s;
239+
int ret;
240+
241+
#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
242+
int timeout = PING_RCV_TIMEO;
243+
#else
244+
struct timeval timeout;
245+
timeout.tv_sec = PING_RCV_TIMEO / 1000;
246+
timeout.tv_usec = (PING_RCV_TIMEO % 1000) * 1000;
247+
#endif
248+
LWIP_UNUSED_ARG(arg);
249+
250+
#if LWIP_IPV6
251+
if (IP_IS_V4(ping_target) || ip6_addr_isipv4mappedipv6(ip_2_ip6(ping_target))) {
252+
s = lwip_socket(AF_INET6, SOCK_RAW, IP_PROTO_ICMP);
253+
} else {
254+
s = lwip_socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6);
255+
}
256+
#else
257+
s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP);
258+
#endif
259+
if (s < 0) {
260+
return;
261+
}
262+
263+
ret = lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
264+
LWIP_ASSERT("setting receive timeout failed", ret == 0);
265+
LWIP_UNUSED_ARG(ret);
266+
267+
while (1) {
268+
if (ping_send(s, ping_target) == ERR_OK) {
269+
LWIP_DEBUGF(PING_DEBUG, ("ping: send "));
270+
ip_addr_debug_print(PING_DEBUG, ping_target);
271+
LWIP_DEBUGF(PING_DEBUG, ("\n"));
272+
273+
#ifdef LWIP_DEBUG
274+
ping_time = sys_now();
275+
#endif /* LWIP_DEBUG */
276+
ping_recv(s);
277+
} else {
278+
LWIP_DEBUGF(PING_DEBUG, ("ping: send "));
279+
ip_addr_debug_print(PING_DEBUG, ping_target);
280+
LWIP_DEBUGF(PING_DEBUG, (" - error\n"));
281+
}
282+
sys_msleep(PING_DELAY);
283+
}
284+
}
285+
286+
#else /* PING_USE_SOCKETS */
287+
288+
/* Ping using the raw ip */
289+
static u8_t
290+
ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) {
291+
struct icmp_echo_hdr *iecho;
292+
LWIP_UNUSED_ARG(arg);
293+
LWIP_UNUSED_ARG(pcb);
294+
LWIP_UNUSED_ARG(addr);
295+
LWIP_ASSERT("p != NULL", p != NULL);
296+
297+
if ((p->tot_len >= (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) &&
298+
pbuf_remove_header(p, PBUF_IP_HLEN) == 0) {
299+
iecho = (struct icmp_echo_hdr *)p->payload;
300+
301+
if ((iecho->id == PING_ID) && (iecho->seqno == lwip_htons(ping_seq_num))) {
302+
LWIP_DEBUGF(PING_DEBUG, ("ping: recv "));
303+
ip_addr_debug_print(PING_DEBUG, addr);
304+
LWIP_DEBUGF(PING_DEBUG, (" %"U32_F " ms\n", (sys_now() - ping_time)));
305+
306+
/* do some ping result processing */
307+
PING_RESULT(1);
308+
pbuf_free(p);
309+
return 1; /* eat the packet */
310+
}
311+
/* not eaten, restore original packet */
312+
pbuf_add_header(p, PBUF_IP_HLEN);
313+
}
314+
315+
return 0; /* don't eat the packet */
316+
}
317+
318+
int
319+
ping_send(struct raw_pcb *raw, const ip_addr_t *addr) {
320+
struct pbuf *p;
321+
struct icmp_echo_hdr *iecho;
322+
size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
323+
324+
LWIP_DEBUGF(PING_DEBUG, ("ping: send "));
325+
ip_addr_debug_print(PING_DEBUG, addr);
326+
LWIP_DEBUGF(PING_DEBUG, ("\n"));
327+
LWIP_ASSERT("ping_size <= 0xffff", ping_size <= 0xffff);
328+
329+
p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM);
330+
if (!p) {
331+
return 0;
332+
}
333+
if ((p->len == p->tot_len) && (p->next == NULL)) {
334+
iecho = (struct icmp_echo_hdr *)p->payload;
335+
336+
ping_prepare_echo(iecho, (u16_t)ping_size);
337+
338+
raw_sendto(raw, p, addr);
339+
#ifdef LWIP_DEBUG
340+
ping_time = sys_now();
341+
#endif /* LWIP_DEBUG */
342+
}
343+
pbuf_free(p);
344+
return 1;
345+
}
346+
347+
static void
348+
ping_timeout(void *arg) {
349+
struct raw_pcb *pcb = (struct raw_pcb *)arg;
350+
351+
LWIP_ASSERT("ping_timeout: no pcb given!", pcb != NULL);
352+
353+
ping_send(pcb, ping_target);
354+
355+
sys_timeout(PING_DELAY, ping_timeout, pcb);
356+
}
357+
358+
static void
359+
ping_raw_init(void) {
360+
if (ping_pcb) {
361+
return;
362+
}
363+
ping_pcb = raw_new(IP_PROTO_ICMP);
364+
LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL);
365+
366+
raw_recv(ping_pcb, ping_recv, NULL);
367+
raw_bind(ping_pcb, IP_ADDR_ANY);
368+
sys_timeout(PING_DELAY, ping_timeout, ping_pcb);
369+
}
370+
371+
#endif /* PING_USE_SOCKETS */
372+
373+
void
374+
ping_init(const ip_addr_t *ping_addr) {
375+
ping_target = ping_addr;
376+
377+
#if PING_USE_SOCKETS
378+
sys_thread_new("ping_thread", ping_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
379+
#else /* PING_USE_SOCKETS */
380+
ping_raw_init();
381+
#endif /* PING_USE_SOCKETS */
382+
}
383+
384+
#endif /* LWIP_RAW */

0 commit comments

Comments
 (0)