Skip to content

Commit 07aac8e

Browse files
mip_test.c http fetch (#1851)
* Update mip_test.c * Adding mip_free() function. * Adding mip_free() function. * Added MIP free. * Fixed C++ builds. * Proper C/C++ struct initialization. * Squashed commit of the following: commit 7ba68dd Author: Jean-Francois Simon <[email protected]> Date: Wed Nov 16 16:19:50 2022 +0100 Proper C/C++ struct initialization. commit aeab3ef Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 17:09:29 2022 +0100 Fixed C++ builds. commit 2afd529 Merge: 14710b8 f8445a4 Author: jfsimon1981 <[email protected]> Date: Tue Nov 15 11:33:56 2022 +0100 Merge branch 'cesanta:master' into master commit 14710b8 Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:07:15 2022 +0100 Added MIP free. commit 6393cd1 Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:06:44 2022 +0100 Adding mip_free() function. commit feee81b Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:05:55 2022 +0100 Adding mip_free() function. commit f8445a4 Merge: a39b7dd 71f5be0 Author: Sergio R. Caprile <[email protected]> Date: Fri Nov 11 20:42:38 2022 -0300 Merge pull request #1853 from cesanta/tibaremetaltest Update test.yml commit 71f5be0 Author: Sergio R. Caprile <[email protected]> Date: Fri Nov 11 20:15:01 2022 -0300 Update test.yml commit b53d3cf Merge: 7a71038 a39b7dd Author: jfsimon1981 <[email protected]> Date: Fri Nov 11 16:10:53 2022 +0100 Merge branch 'cesanta:master' into master commit 7a71038 Author: jfsimon1981 <[email protected]> Date: Fri Nov 11 16:09:22 2022 +0100 Update mip_test.c commit a39b7dd Author: cpq <[email protected]> Date: Fri Nov 11 15:03:48 2022 +0000 Fix fuzzer use-after-poison READ 1 * Squashed commit of the following: commit 192ae56 Merge: 7b0509c 7ba68dd Author: Jean-Francois Simon <[email protected]> Date: Wed Nov 16 17:44:03 2022 +0100 Merge branch 'master' of https://github.com/jfsimon1981/mongoose commit 7b0509c Author: Jean-Francois Simon <[email protected]> Date: Wed Nov 16 17:43:33 2022 +0100 Squashed commit of the following: commit 7ba68dd Author: Jean-Francois Simon <[email protected]> Date: Wed Nov 16 16:19:50 2022 +0100 Proper C/C++ struct initialization. commit aeab3ef Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 17:09:29 2022 +0100 Fixed C++ builds. commit 2afd529 Merge: 14710b8 f8445a4 Author: jfsimon1981 <[email protected]> Date: Tue Nov 15 11:33:56 2022 +0100 Merge branch 'cesanta:master' into master commit 14710b8 Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:07:15 2022 +0100 Added MIP free. commit 6393cd1 Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:06:44 2022 +0100 Adding mip_free() function. commit feee81b Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:05:55 2022 +0100 Adding mip_free() function. commit f8445a4 Merge: a39b7dd 71f5be0 Author: Sergio R. Caprile <[email protected]> Date: Fri Nov 11 20:42:38 2022 -0300 Merge pull request #1853 from cesanta/tibaremetaltest Update test.yml commit 71f5be0 Author: Sergio R. Caprile <[email protected]> Date: Fri Nov 11 20:15:01 2022 -0300 Update test.yml commit b53d3cf Merge: 7a71038 a39b7dd Author: jfsimon1981 <[email protected]> Date: Fri Nov 11 16:10:53 2022 +0100 Merge branch 'cesanta:master' into master commit 7a71038 Author: jfsimon1981 <[email protected]> Date: Fri Nov 11 16:09:22 2022 +0100 Update mip_test.c commit a39b7dd Author: cpq <[email protected]> Date: Fri Nov 11 15:03:48 2022 +0000 Fix fuzzer use-after-poison READ 1 commit 7ba68dd Author: Jean-Francois Simon <[email protected]> Date: Wed Nov 16 16:19:50 2022 +0100 Proper C/C++ struct initialization. commit aeab3ef Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 17:09:29 2022 +0100 Fixed C++ builds. commit 2afd529 Merge: 14710b8 f8445a4 Author: jfsimon1981 <[email protected]> Date: Tue Nov 15 11:33:56 2022 +0100 Merge branch 'cesanta:master' into master commit 14710b8 Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:07:15 2022 +0100 Added MIP free. commit 6393cd1 Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:06:44 2022 +0100 Adding mip_free() function. commit feee81b Author: Jean-Francois Simon <[email protected]> Date: Tue Nov 15 11:05:55 2022 +0100 Adding mip_free() function. commit f8445a4 Merge: a39b7dd 71f5be0 Author: Sergio R. Caprile <[email protected]> Date: Fri Nov 11 20:42:38 2022 -0300 Merge pull request #1853 from cesanta/tibaremetaltest Update test.yml commit 71f5be0 Author: Sergio R. Caprile <[email protected]> Date: Fri Nov 11 20:15:01 2022 -0300 Update test.yml commit b53d3cf Merge: 7a71038 a39b7dd Author: jfsimon1981 <[email protected]> Date: Fri Nov 11 16:10:53 2022 +0100 Merge branch 'cesanta:master' into master commit a39b7dd Author: cpq <[email protected]> Date: Fri Nov 11 15:03:48 2022 +0000 Fix fuzzer use-after-poison READ 1 Co-authored-by: Jean-Francois Simon <[email protected]>
1 parent f8445a4 commit 07aac8e

File tree

5 files changed

+213
-3
lines changed

5 files changed

+213
-3
lines changed

mip/mip.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ static size_t tx_tcp(struct mip_if *ifp, uint32_t dst_ip, uint8_t flags,
478478
struct ip *ip = tx_ip(ifp, 6, ifp->ip, dst_ip, sizeof(struct tcp) + len);
479479
struct tcp *tcp = (struct tcp *) (ip + 1);
480480
memset(tcp, 0, sizeof(*tcp));
481-
memmove(tcp + 1, buf, len);
481+
if (buf != NULL && len) memmove(tcp + 1, buf, len);
482482
tcp->sport = sport;
483483
tcp->dport = dport;
484484
tcp->seq = seq;
@@ -845,6 +845,11 @@ void mip_init(struct mg_mgr *mgr, struct mip_if *ifp) {
845845
}
846846
}
847847

848+
void mip_free(struct mip_if * ifp) {
849+
free((char *)ifp->rx.ptr);
850+
free((char *)ifp->tx.ptr);
851+
}
852+
848853
int mg_mkpipe(struct mg_mgr *m, mg_event_handler_t fn, void *d, bool udp) {
849854
(void) m, (void) fn, (void) d, (void) udp;
850855
MG_ERROR(("Not implemented"));

mip/mip.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct mip_if {
5050
};
5151

5252
void mip_init(struct mg_mgr *, struct mip_if *);
53+
void mip_free(struct mip_if *);
5354

5455
extern struct mip_driver mip_driver_stm32;
5556
extern struct mip_driver mip_driver_enc28j60;

mongoose.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7007,7 +7007,7 @@ static size_t tx_tcp(struct mip_if *ifp, uint32_t dst_ip, uint8_t flags,
70077007
struct ip *ip = tx_ip(ifp, 6, ifp->ip, dst_ip, sizeof(struct tcp) + len);
70087008
struct tcp *tcp = (struct tcp *) (ip + 1);
70097009
memset(tcp, 0, sizeof(*tcp));
7010-
memmove(tcp + 1, buf, len);
7010+
if (buf != NULL && len) memmove(tcp + 1, buf, len);
70117011
tcp->sport = sport;
70127012
tcp->dport = dport;
70137013
tcp->seq = seq;
@@ -7374,6 +7374,11 @@ void mip_init(struct mg_mgr *mgr, struct mip_if *ifp) {
73747374
}
73757375
}
73767376

7377+
void mip_free(struct mip_if * ifp) {
7378+
free((char *)ifp->rx.ptr);
7379+
free((char *)ifp->tx.ptr);
7380+
}
7381+
73777382
int mg_mkpipe(struct mg_mgr *m, mg_event_handler_t fn, void *d, bool udp) {
73787383
(void) m, (void) fn, (void) d, (void) udp;
73797384
MG_ERROR(("Not implemented"));

mongoose.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,7 @@ struct mip_if {
14671467
};
14681468

14691469
void mip_init(struct mg_mgr *, struct mip_if *);
1470+
void mip_free(struct mip_if *);
14701471

14711472
extern struct mip_driver mip_driver_stm32;
14721473
extern struct mip_driver mip_driver_enc28j60;

test/mip_test.c

Lines changed: 199 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,25 @@
44
#define MG_ENABLE_PACKED_FS 0
55

66
#include <assert.h>
7+
#include <linux/if.h>
8+
#include <linux/if_tun.h>
9+
#include <sys/ioctl.h>
710
#include "mongoose.c"
811

9-
#include "driver_mock.c"
12+
#include "driver_mock.c"
13+
14+
static int s_num_tests = 0;
15+
16+
#define ASSERT(expr) \
17+
do { \
18+
s_num_tests++; \
19+
if (!(expr)) { \
20+
printf("FAILURE %s:%d: %s\n", __FILE__, __LINE__, #expr); \
21+
abort(); \
22+
} \
23+
} while (0)
24+
25+
1026

1127
static void test_queue(void) {
1228
static uint8_t
@@ -49,9 +65,191 @@ static void test_statechange(void) {
4965
onstatechange(&iface);
5066
}
5167

68+
// MIP TUNTAP driver
69+
static size_t tap_rx(void *buf, size_t len, void *userdata) {
70+
ssize_t received = read(*(int *) userdata, buf, len);
71+
usleep(1); // This is to avoid 100% CPU
72+
if (received < 0) return 0;
73+
return (size_t) received;
74+
}
75+
76+
static size_t tap_tx(const void *buf, size_t len, void *userdata) {
77+
ssize_t res = write(*(int *) userdata, buf, len);
78+
if (res < 0) {
79+
MG_ERROR(("tap_tx failed: %d", errno));
80+
return 0;
81+
}
82+
return (size_t) res;
83+
}
84+
85+
static bool tap_up(void *userdata) {
86+
return userdata ? true : false;
87+
}
88+
89+
// HTTP fetches IOs
90+
struct Post_reply {
91+
char* post; // HTTP POST data
92+
void* http_response; // Server response(s)
93+
unsigned int http_responses_received; // Number responses received
94+
};
95+
96+
char *fetch(struct mg_mgr *mgr, const char *url, const char *post_data);
97+
static void f_http_fetch_query(struct mg_connection *c, int ev, void *ev_data, void *fn_data);
98+
int get_response_code(char *); // Returns HTTP status code from full char* msg
99+
100+
static void f_http_fetch_query(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
101+
static char* http_response = 0;
102+
static bool http_response_allocated = 0; // So that we will update out parameter
103+
unsigned int http_responses_received = 0;
104+
struct Post_reply *post_reply_l;
105+
post_reply_l = (struct Post_reply*)fn_data;
106+
107+
if (ev == MG_EV_CONNECT) {
108+
mg_printf(c, post_reply_l->post);
109+
} else if (ev == MG_EV_HTTP_MSG) {
110+
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
111+
http_responses_received++;
112+
if (!http_response_allocated) {
113+
http_response = (char*)mg_strdup(hm->message).ptr;
114+
http_response_allocated = 1;
115+
}
116+
if (http_responses_received > 0) {
117+
post_reply_l->http_response = http_response;
118+
post_reply_l->http_responses_received = http_responses_received;
119+
}
120+
}
121+
}
122+
123+
// Fetch utility returns message from fetch(..., URL, POST)
124+
char *fetch(struct mg_mgr *mgr, const char *url, const char *fn_data) {
125+
struct Post_reply post_reply;
126+
{
127+
post_reply.post=(char*)fn_data;
128+
post_reply.http_response=0;
129+
post_reply.http_responses_received=0;
130+
}
131+
struct mg_connection *conn;
132+
conn = mg_http_connect(mgr, url, f_http_fetch_query, &post_reply);
133+
ASSERT(conn != NULL); // Assertion on initialisation
134+
for (int i = 0; i < 500 && !post_reply.http_responses_received; i++) {
135+
mg_mgr_poll(mgr, 100);
136+
usleep(10000); // 10 ms. Slow down poll loop to ensure packets transit
137+
}
138+
conn->is_closing = 1;
139+
mg_mgr_poll(mgr, 0);
140+
if (!post_reply.http_responses_received)
141+
return 0;
142+
else
143+
return (char*)post_reply.http_response;
144+
}
145+
146+
// Returns server's HTTP response code
147+
int get_response_code(char * http_msg_raw) {
148+
int http_status = 0;
149+
struct mg_http_message http_msg_parsed;
150+
if (mg_http_parse(http_msg_raw, strlen(http_msg_raw), &http_msg_parsed)) {
151+
http_status = mg_http_status(&http_msg_parsed);
152+
} else {
153+
printf("Error: mg_http_parse()\n");
154+
ASSERT(http_status != 0); // Couldn't parse.
155+
}
156+
return http_status;
157+
}
158+
159+
static void test_http_fetch(void) {
160+
// Setup interface
161+
const char *iface = "tap0"; // Network iface
162+
const char *mac = "00:00:01:02:03:78"; // MAC address
163+
int fd = open("/dev/net/tun", O_RDWR); // Open network interface
164+
165+
struct ifreq ifr;
166+
memset(&ifr, 0, sizeof(ifr));
167+
strncpy(ifr.ifr_name, iface, IFNAMSIZ);
168+
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
169+
if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
170+
MG_ERROR(("Failed to setup TAP interface: %s", ifr.ifr_name));
171+
abort(); // return EXIT_FAILURE;
172+
}
173+
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); // Non-blocking mode
174+
175+
MG_INFO(("Opened TAP interface: %s", iface));
176+
177+
// Events
178+
struct mg_mgr mgr; // Event manager
179+
mg_mgr_init(&mgr); // Initialise event manager
180+
181+
// MIP driver
182+
183+
// Zero init fields required (C/C++ style diverge)
184+
#ifndef __cplusplus
185+
struct mip_driver driver = {.tx = tap_tx, .up = tap_up, .rx = tap_rx};
186+
struct mip_if mif = {.use_dhcp = true, .driver = &driver, .driver_data = &fd};
187+
#else
188+
struct mip_driver driver {};
189+
driver.tx = tap_tx;
190+
driver.up = tap_up;
191+
driver.rx = tap_rx;
192+
struct mip_if mif {};
193+
mif.use_dhcp = true;
194+
mif.driver = &driver;
195+
mif.driver_data = &fd;
196+
#endif
197+
198+
sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mif.mac[0], &mif.mac[1], &mif.mac[2],
199+
&mif.mac[3], &mif.mac[4], &mif.mac[5]);
200+
201+
mip_init(&mgr, &mif);
202+
MG_INFO(("Init done, starting main loop"));
203+
204+
// DHCP lease
205+
{
206+
if (mif.ip) printf("MIF configuration error: not configured for DHCP\n");
207+
ASSERT(!mif.ip); // Check we are set for DHCP
208+
int pc = 500; // Timout on DHCP lease 500 ~ approx 5s (typical delay <1s)
209+
while (((pc--)>0)/* & !mif.ip*/) {
210+
mg_mgr_poll(&mgr, 100);
211+
usleep(10000); // 10 ms
212+
}
213+
if (!mif.ip) printf("DHCP lease failed.\n");
214+
ASSERT(mif.ip); // We have a received lease
215+
}
216+
217+
// Simple HTTP fetch
218+
{
219+
char* http_feedback = (char*)"";
220+
const bool ipv6 = 0;
221+
if (ipv6) {
222+
http_feedback = fetch (&mgr, "ipv6.google.com",\
223+
"GET/ HTTP/1.0\r\nHost: ipv6.google.com\r\n\r\n");
224+
} else {
225+
http_feedback = fetch (&mgr, "http://cesanta.com",\
226+
"GET //robots.txt HTTP/1.0\r\nHost: cesanta.com\r\n\r\n");
227+
}
228+
229+
ASSERT(*http_feedback != '\0'); // Received HTTP response ?
230+
231+
int http_status = get_response_code(http_feedback);
232+
// printf("Server response HTTP status code: %d\n",http_status);
233+
ASSERT(http_status != 0);
234+
ASSERT(http_status == 301); // OK: Permanently moved (HTTP->HTTPS redirect)
235+
236+
if (http_feedback) {
237+
free(http_feedback);
238+
http_feedback = 0;
239+
}
240+
}
241+
242+
// Clear
243+
mip_free(&mif);
244+
mg_mgr_free(&mgr);
245+
ASSERT(mgr.conns == NULL); // Deconstruction OK
246+
close(fd);
247+
}
248+
52249
int main(void) {
53250
test_queue();
54251
test_statechange();
252+
test_http_fetch();
55253
printf("SUCCESS\n");
56254
return 0;
57255
}

0 commit comments

Comments
 (0)