From 751deac9d1d0bd13627dd3ef3a9d2a85bfa2eeed Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Wed, 12 Feb 2014 21:34:19 +0100 Subject: [PATCH 01/23] Another fix to window scaling: support queueing more than 64 KByte in ooseq data --- src/core/pbuf.c | 50 +++++++++++++++++++++++ src/core/tcp.c | 77 +++++++++++++++++++++++------------- src/core/tcp_in.c | 31 +++++++++++++++ src/include/lwip/pbuf.h | 3 ++ test/unit/core/test_pbuf.c | 81 +++++++++++++++++++++++++++++++++++++- test/unit/lwipopts.h | 3 ++ 6 files changed, 216 insertions(+), 29 deletions(-) diff --git a/src/core/pbuf.c b/src/core/pbuf.c index 1e5e53b1..bf313d33 100644 --- a/src/core/pbuf.c +++ b/src/core/pbuf.c @@ -952,6 +952,56 @@ pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) return copied_total; } +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +/** + * This method modifies a 'pbuf chain', so that its total length is + * smaller than 64K. The remainder of the original pbuf chain is stored + * in *rest. + * This function never creates new pbufs, but splits an existing chain + * in two parts. The tot_len of the modified packet queue will likely be + * smaller than 64K. + * 'packet queues' are not supported by this function. + * + * @param p the pbuf queue to be splitted + * @param rest pointer to store the remainder (after the first 64K) + */ +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) +{ + *rest = NULL; + if ((p != NULL) && (p->next != NULL)) { + u16_t tot_len_front = p->len; + struct pbuf *i = p; + struct pbuf *r = p->next; + + /* continue until the total length (summed up as u16_t) overflows */ + while ((r != NULL) && ((u16_t)(tot_len_front + r->len) > tot_len_front)) { + tot_len_front += r->len; + i = r; + r = r->next; + } + /* i now points to last packet of the first segment. Set next + pointer to NULL */ + i->next = NULL; + + if (r != NULL) { + /* Update the tot_len field in the first part */ + for (i = p; i != NULL; i = i->next) { + i->tot_len -= r->tot_len; + LWIP_ASSERT("tot_len/len mismatch in last pbuf", + (i->next != NULL) || (i->tot_len == i->len)); + } + if (p->flags & PBUF_FLAG_TCP_FIN) { + r->flags |= PBUF_FLAG_TCP_FIN; + } + + /* tot_len field in rest does not need modifications */ + /* reference counters do not need modifications */ + *rest = r; + } + } +} +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + /** * Copy application supplied data into a pbuf. * This function can only be used to copy the equivalent of buf->tot_len data. diff --git a/src/core/tcp.c b/src/core/tcp.c index f1fc08b5..1af3d6b3 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -1124,37 +1124,58 @@ tcp_fasttmr_start: err_t tcp_process_refused_data(struct tcp_pcb *pcb) { - err_t err; - u8_t refused_flags = pcb->refused_data->flags; - /* set pcb->refused_data to NULL in case the callback frees it and then - closes the pcb */ - struct pbuf *refused_data = pcb->refused_data; - pcb->refused_data = NULL; - /* Notify again application with data previously received. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); - TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); - if (err == ERR_OK) { - /* did refused_data include a FIN? */ - if (refused_flags & PBUF_FLAG_TCP_FIN) { - /* correct rcv_wnd as the application won't call tcp_recved() - for the FIN's seqno */ - if (pcb->rcv_wnd != TCP_WND) { - pcb->rcv_wnd++; +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + struct pbuf *rest; + while (pcb->refused_data != NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + { + err_t err; + u8_t refused_flags = pcb->refused_data->flags; + /* set pcb->refused_data to NULL in case the callback frees it and then + closes the pcb */ + struct pbuf *refused_data = pcb->refused_data; +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + pbuf_split_64k(refused_data, &rest); + pcb->refused_data = rest; +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = NULL; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + /* Notify again application with data previously received. */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); + TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); + if (err == ERR_OK) { + /* did refused_data include a FIN? */ + if (refused_flags & PBUF_FLAG_TCP_FIN +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + && (rest == NULL) +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + ) { + /* correct rcv_wnd as the application won't call tcp_recved() + for the FIN's seqno */ + if (pcb->rcv_wnd != TCP_WND) { + pcb->rcv_wnd++; + } + TCP_EVENT_CLOSED(pcb, err); + if (err == ERR_ABRT) { + return ERR_ABRT; + } } - TCP_EVENT_CLOSED(pcb, err); - if (err == ERR_ABRT) { - return ERR_ABRT; + } else if (err == ERR_ABRT) { + /* if err == ERR_ABRT, 'pcb' is already deallocated */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); + return ERR_ABRT; + } else { + /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(refused_data, rest); } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + pcb->refused_data = refused_data; + return ERR_INPROGRESS; } - } else if (err == ERR_ABRT) { - /* if err == ERR_ABRT, 'pcb' is already deallocated */ - /* Drop incoming packets because pcb is "full" (only if the incoming - segment contains data). */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); - return ERR_ABRT; - } else { - /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ - pcb->refused_data = refused_data; } return ERR_OK; } diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index b3360f12..9054a757 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -364,12 +364,24 @@ tcp_input(struct pbuf *p, struct netif *inp) } } +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + while (recv_data != NULL) { + struct pbuf *rest = NULL; + pbuf_split_64k(recv_data, &rest); +#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ if (recv_data != NULL) { +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); if (pcb->flags & TF_RXCLOSED) { /* received data although already closed -> abort (send RST) to notify the remote host that not all data has been processed */ pbuf_free(recv_data); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ tcp_abort(pcb); goto aborted; } @@ -377,13 +389,29 @@ tcp_input(struct pbuf *p, struct netif *inp) /* Notify application that data has been received. */ TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); if (err == ERR_ABRT) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_free(rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ goto aborted; } /* If the upper layer can't receive this data, store it */ if (err != ERR_OK) { +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + if (rest != NULL) { + pbuf_cat(recv_data, rest); + } +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ pcb->refused_data = recv_data; LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); +#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE + break; + } else { + /* Upper layer received the data, go on with the rest if > 64K */ + recv_data = rest; +#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ } } @@ -1382,6 +1410,9 @@ tcp_receive(struct tcp_pcb *pcb) if (cseg->p->tot_len > 0) { /* Chain this pbuf onto the pbuf that we will pass to the application. */ + /* With window scaling, this can overflow recv_data->tot_len, but + that's not a problem since we explicitly fix that before passing + recv_data to the application. */ if (recv_data) { pbuf_cat(recv_data, cseg->p); } else { diff --git a/src/include/lwip/pbuf.h b/src/include/lwip/pbuf.h index 4f8dca8a..5b3833a5 100644 --- a/src/include/lwip/pbuf.h +++ b/src/include/lwip/pbuf.h @@ -172,6 +172,9 @@ struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, u16_t len, u16_t *chksum); #endif /* LWIP_CHECKSUM_ON_COPY */ +#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE +void pbuf_split_64k(struct pbuf *p, struct pbuf **rest); +#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ u8_t pbuf_get_at(struct pbuf* p, u16_t offset); u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n); diff --git a/test/unit/core/test_pbuf.c b/test/unit/core/test_pbuf.c index 29110784..2cb2a516 100644 --- a/test/unit/core/test_pbuf.c +++ b/test/unit/core/test_pbuf.c @@ -9,6 +9,9 @@ #if LWIP_DNS #error "This test needs DNS turned off (as it mallocs on init)" #endif +#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !LWIP_WND_SCALE +#error "This test needs TCP OOSEQ queueing and window scaling enabled" +#endif /* Setups/teardown functions */ @@ -23,6 +26,16 @@ pbuf_teardown(void) } +#define TESTBUFSIZE_1 65535 +#define TESTBUFSIZE_2 65530 +#define TESTBUFSIZE_3 50050 +static u8_t testbuf_1[TESTBUFSIZE_1]; +static u8_t testbuf_1a[TESTBUFSIZE_1]; +static u8_t testbuf_2[TESTBUFSIZE_2]; +static u8_t testbuf_2a[TESTBUFSIZE_2]; +static u8_t testbuf_3[TESTBUFSIZE_3]; +static u8_t testbuf_3a[TESTBUFSIZE_3]; + /* Test functions */ /** Call pbuf_copy on a pbuf with zero length */ @@ -61,13 +74,79 @@ START_TEST(test_pbuf_copy_zero_pbuf) } END_TEST +START_TEST(test_pbuf_split_64k_on_small_pbufs) +{ + struct pbuf *p, *rest=NULL; + LWIP_UNUSED_ARG(_i); + + p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL); + pbuf_split_64k(p, &rest); + fail_unless(p->tot_len == 1); + pbuf_free(p); +} +END_TEST + +START_TEST(test_pbuf_queueing_bigger_than_64k) +{ + int i; + err_t err; + struct pbuf *p1, *p2, *p3, *rest2=NULL, *rest3=NULL; + LWIP_UNUSED_ARG(_i); + + for(i = 0; i < TESTBUFSIZE_1; i++) + testbuf_1[i] = rand(); + for(i = 0; i < TESTBUFSIZE_2; i++) + testbuf_2[i] = rand(); + for(i = 0; i < TESTBUFSIZE_3; i++) + testbuf_3[i] = rand(); + + p1 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_1, PBUF_POOL); + fail_unless(p1 != NULL); + p2 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_2, PBUF_POOL); + fail_unless(p2 != NULL); + p3 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_3, PBUF_POOL); + fail_unless(p3 != NULL); + err = pbuf_take(p1, testbuf_1, TESTBUFSIZE_1); + fail_unless(err == ERR_OK); + err = pbuf_take(p2, testbuf_2, TESTBUFSIZE_2); + fail_unless(err == ERR_OK); + err = pbuf_take(p3, testbuf_3, TESTBUFSIZE_3); + fail_unless(err == ERR_OK); + + pbuf_cat(p1, p2); + pbuf_cat(p1, p3); + + pbuf_split_64k(p1, &rest2); + fail_unless(p1->tot_len == TESTBUFSIZE_1); + fail_unless(rest2->tot_len == (u16_t)((TESTBUFSIZE_2+TESTBUFSIZE_3) & 0xFFFF)); + pbuf_split_64k(rest2, &rest3); + fail_unless(rest2->tot_len == TESTBUFSIZE_2); + fail_unless(rest3->tot_len == TESTBUFSIZE_3); + + pbuf_copy_partial(p1, testbuf_1a, TESTBUFSIZE_1, 0); + pbuf_copy_partial(rest2, testbuf_2a, TESTBUFSIZE_2, 0); + pbuf_copy_partial(rest3, testbuf_3a, TESTBUFSIZE_3, 0); + for(i = 0; i < TESTBUFSIZE_1; i++) + fail_unless(testbuf_1[i] == testbuf_1a[i]); + for(i = 0; i < TESTBUFSIZE_2; i++) + fail_unless(testbuf_2[i] == testbuf_2a[i]); + for(i = 0; i < TESTBUFSIZE_3; i++) + fail_unless(testbuf_3[i] == testbuf_3a[i]); + + pbuf_free(p1); + pbuf_free(rest2); + pbuf_free(rest3); +} +END_TEST /** Create the suite including all tests for this module */ Suite * pbuf_suite(void) { TFun tests[] = { - test_pbuf_copy_zero_pbuf + test_pbuf_copy_zero_pbuf, + test_pbuf_split_64k_on_small_pbufs, + test_pbuf_queueing_bigger_than_64k }; return create_suite("PBUF", tests, sizeof(tests)/sizeof(TFun), pbuf_setup, pbuf_teardown); } diff --git a/test/unit/lwipopts.h b/test/unit/lwipopts.h index 00595154..325856d4 100644 --- a/test/unit/lwipopts.h +++ b/test/unit/lwipopts.h @@ -46,6 +46,9 @@ #define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN #define TCP_SND_BUF (12 * TCP_MSS) #define TCP_WND (10 * TCP_MSS) +#define LWIP_WND_SCALE 1 +#define TCP_RCV_SCALE 0 +#define PBUF_POOL_SIZE 400 // pbuf tests need ~200KByte /* Minimal changes to opt.h required for etharp unit tests: */ #define ETHARP_SUPPORT_STATIC_ENTRIES 1 From ad66b2bf133cc6ffb218e3c00e3c97c7740136af Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Thu, 30 Aug 2012 21:57:28 +0200 Subject: [PATCH 02/23] Don't mark arrays as const since they are modified by the test --- test/unit/dhcp/test_dhcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/dhcp/test_dhcp.c b/test/unit/dhcp/test_dhcp.c index 4b40de89..8addfa14 100644 --- a/test/unit/dhcp/test_dhcp.c +++ b/test/unit/dhcp/test_dhcp.c @@ -557,7 +557,7 @@ END_TEST */ START_TEST(test_dhcp_relayed) { - const u8_t relay_offer[] = { + u8_t relay_offer[] = { 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00, @@ -602,7 +602,7 @@ START_TEST(test_dhcp_relayed) 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff }; - const u8_t relay_ack1[] = { + u8_t relay_ack1[] = { 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00, 0x01, 0x38, 0xfd, 0x55, 0x00, 0x00, 0x40, 0x11, @@ -646,7 +646,7 @@ START_TEST(test_dhcp_relayed) 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff }; - const u8_t relay_ack2[] = { + u8_t relay_ack2[] = { 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00, From a80c4d147cc0caa25c61675b972ab617511ae96f Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Wed, 12 Feb 2014 21:52:21 +0100 Subject: [PATCH 03/23] Unit test patch by Erik Ekman: use macro to store correct testcase name --- test/unit/core/test_mem.c | 6 ++--- test/unit/core/test_pbuf.c | 10 ++++---- test/unit/dhcp/test_dhcp.c | 12 ++++----- test/unit/etharp/test_etharp.c | 6 ++--- test/unit/lwip_check.h | 18 ++++++++++--- test/unit/tcp/test_tcp.c | 18 ++++++------- test/unit/tcp/test_tcp_oos.c | 46 +++++++++++++++++----------------- test/unit/udp/test_udp.c | 6 ++--- 8 files changed, 66 insertions(+), 56 deletions(-) diff --git a/test/unit/core/test_mem.c b/test/unit/core/test_mem.c index d3a5d540..af7276d0 100644 --- a/test/unit/core/test_mem.c +++ b/test/unit/core/test_mem.c @@ -66,8 +66,8 @@ END_TEST Suite * mem_suite(void) { - TFun tests[] = { - test_mem_one + testfunc tests[] = { + TESTFUNC(test_mem_one) }; - return create_suite("MEM", tests, sizeof(tests)/sizeof(TFun), mem_setup, mem_teardown); + return create_suite("MEM", tests, sizeof(tests)/sizeof(testfunc), mem_setup, mem_teardown); } diff --git a/test/unit/core/test_pbuf.c b/test/unit/core/test_pbuf.c index 2cb2a516..211465ec 100644 --- a/test/unit/core/test_pbuf.c +++ b/test/unit/core/test_pbuf.c @@ -143,10 +143,10 @@ END_TEST Suite * pbuf_suite(void) { - TFun tests[] = { - test_pbuf_copy_zero_pbuf, - test_pbuf_split_64k_on_small_pbufs, - test_pbuf_queueing_bigger_than_64k + testfunc tests[] = { + TESTFUNC(test_pbuf_copy_zero_pbuf), + TESTFUNC(test_pbuf_split_64k_on_small_pbufs), + TESTFUNC(test_pbuf_queueing_bigger_than_64k) }; - return create_suite("PBUF", tests, sizeof(tests)/sizeof(TFun), pbuf_setup, pbuf_teardown); + return create_suite("PBUF", tests, sizeof(tests)/sizeof(testfunc), pbuf_setup, pbuf_teardown); } diff --git a/test/unit/dhcp/test_dhcp.c b/test/unit/dhcp/test_dhcp.c index 8addfa14..0055b492 100644 --- a/test/unit/dhcp/test_dhcp.c +++ b/test/unit/dhcp/test_dhcp.c @@ -906,11 +906,11 @@ END_TEST Suite * dhcp_suite(void) { - TFun tests[] = { - test_dhcp, - test_dhcp_nak, - test_dhcp_relayed, - test_dhcp_nak_no_endmarker + testfunc tests[] = { + TESTFUNC(test_dhcp), + TESTFUNC(test_dhcp_nak), + TESTFUNC(test_dhcp_relayed), + TESTFUNC(test_dhcp_nak_no_endmarker) }; - return create_suite("DHCP", tests, sizeof(tests)/sizeof(TFun), dhcp_setup, dhcp_teardown); + return create_suite("DHCP", tests, sizeof(tests)/sizeof(testfunc), dhcp_setup, dhcp_teardown); } diff --git a/test/unit/etharp/test_etharp.c b/test/unit/etharp/test_etharp.c index cbbc9502..9c21a4b4 100644 --- a/test/unit/etharp/test_etharp.c +++ b/test/unit/etharp/test_etharp.c @@ -255,8 +255,8 @@ END_TEST Suite * etharp_suite(void) { - TFun tests[] = { - test_etharp_table + testfunc tests[] = { + TESTFUNC(test_etharp_table) }; - return create_suite("ETHARP", tests, sizeof(tests)/sizeof(TFun), etharp_setup, etharp_teardown); + return create_suite("ETHARP", tests, sizeof(tests)/sizeof(testfunc), etharp_setup, etharp_teardown); } diff --git a/test/unit/lwip_check.h b/test/unit/lwip_check.h index e27f55ae..09f8cfe9 100644 --- a/test/unit/lwip_check.h +++ b/test/unit/lwip_check.h @@ -13,22 +13,32 @@ #define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0) #define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL) +typedef struct { + TFun func; + const char *name; +} testfunc; + +#define TESTFUNC(x) {(x), "" # x "" } + +/* Modified function from check.h, supplying function name */ +#define tcase_add_named_test(tc,tf) \ + _tcase_add_test((tc),(tf).func,(tf).name,0, 0, 0, 1) + /** typedef for a function returning a test suite */ typedef Suite* (suite_getter_fn)(void); /** Create a test suite */ -static Suite* create_suite(const char* name, TFun *tests, size_t num_tests, SFun setup, SFun teardown) +static Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown) { size_t i; Suite *s = suite_create(name); for(i = 0; i < num_tests; i++) { - /* Core test case */ - TCase *tc_core = tcase_create("Core"); + TCase *tc_core = tcase_create(name); if ((setup != NULL) || (teardown != NULL)) { tcase_add_checked_fixture(tc_core, setup, teardown); } - tcase_add_test(tc_core, tests[i]); + tcase_add_named_test(tc_core, tests[i]); suite_add_tcase(s, tc_core); } return s; diff --git a/test/unit/tcp/test_tcp.c b/test/unit/tcp/test_tcp.c index 81720984..9982ef45 100644 --- a/test/unit/tcp/test_tcp.c +++ b/test/unit/tcp/test_tcp.c @@ -658,14 +658,14 @@ END_TEST Suite * tcp_suite(void) { - TFun tests[] = { - test_tcp_new_abort, - test_tcp_recv_inseq, - test_tcp_fast_retx_recover, - test_tcp_fast_rexmit_wraparound, - test_tcp_rto_rexmit_wraparound, - test_tcp_tx_full_window_lost_from_unacked, - test_tcp_tx_full_window_lost_from_unsent + testfunc tests[] = { + TESTFUNC(test_tcp_new_abort), + TESTFUNC(test_tcp_recv_inseq), + TESTFUNC(test_tcp_fast_retx_recover), + TESTFUNC(test_tcp_fast_rexmit_wraparound), + TESTFUNC(test_tcp_rto_rexmit_wraparound), + TESTFUNC(test_tcp_tx_full_window_lost_from_unacked), + TESTFUNC(test_tcp_tx_full_window_lost_from_unsent) }; - return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown); + return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown); } diff --git a/test/unit/tcp/test_tcp_oos.c b/test/unit/tcp/test_tcp_oos.c index 612c4680..59d2514b 100644 --- a/test/unit/tcp/test_tcp_oos.c +++ b/test/unit/tcp/test_tcp_oos.c @@ -931,28 +931,28 @@ FIN_TEST(test_tcp_recv_ooseq_double_FIN_15, 15) Suite * tcp_oos_suite(void) { - TFun tests[] = { - test_tcp_recv_ooseq_FIN_OOSEQ, - test_tcp_recv_ooseq_FIN_INSEQ, - test_tcp_recv_ooseq_overrun_rxwin, - test_tcp_recv_ooseq_max_bytes, - test_tcp_recv_ooseq_max_pbufs, - test_tcp_recv_ooseq_double_FIN_0, - test_tcp_recv_ooseq_double_FIN_1, - test_tcp_recv_ooseq_double_FIN_2, - test_tcp_recv_ooseq_double_FIN_3, - test_tcp_recv_ooseq_double_FIN_4, - test_tcp_recv_ooseq_double_FIN_5, - test_tcp_recv_ooseq_double_FIN_6, - test_tcp_recv_ooseq_double_FIN_7, - test_tcp_recv_ooseq_double_FIN_8, - test_tcp_recv_ooseq_double_FIN_9, - test_tcp_recv_ooseq_double_FIN_10, - test_tcp_recv_ooseq_double_FIN_11, - test_tcp_recv_ooseq_double_FIN_12, - test_tcp_recv_ooseq_double_FIN_13, - test_tcp_recv_ooseq_double_FIN_14, - test_tcp_recv_ooseq_double_FIN_15 + testfunc tests[] = { + TESTFUNC(test_tcp_recv_ooseq_FIN_OOSEQ), + TESTFUNC(test_tcp_recv_ooseq_FIN_INSEQ), + TESTFUNC(test_tcp_recv_ooseq_overrun_rxwin), + TESTFUNC(test_tcp_recv_ooseq_max_bytes), + TESTFUNC(test_tcp_recv_ooseq_max_pbufs), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_0), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_1), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_2), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_3), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_4), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_5), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_6), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_7), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_8), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_9), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_10), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_11), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_12), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_13), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_14), + TESTFUNC(test_tcp_recv_ooseq_double_FIN_15) }; - return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown); + return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(testfunc), tcp_oos_setup, tcp_oos_teardown); } diff --git a/test/unit/udp/test_udp.c b/test/unit/udp/test_udp.c index a2f02af0..7de97851 100644 --- a/test/unit/udp/test_udp.c +++ b/test/unit/udp/test_udp.c @@ -61,8 +61,8 @@ END_TEST Suite * udp_suite(void) { - TFun tests[] = { - test_udp_new_remove, + testfunc tests[] = { + TESTFUNC(test_udp_new_remove), }; - return create_suite("UDP", tests, sizeof(tests)/sizeof(TFun), udp_setup, udp_teardown); + return create_suite("UDP", tests, sizeof(tests)/sizeof(testfunc), udp_setup, udp_teardown); } From 5eaef50a7755e0be58fd6695a132c44520a4762a Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Sun, 4 Nov 2012 12:11:41 +0100 Subject: [PATCH 04/23] Remove newlines in LWIP_ERROR calls --- src/core/pbuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/pbuf.c b/src/core/pbuf.c index bf313d33..0e5981bd 100644 --- a/src/core/pbuf.c +++ b/src/core/pbuf.c @@ -890,12 +890,12 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) if((p_from != NULL) && (p_from->len == p_from->tot_len)) { /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + LWIP_ERROR("pbuf_copy() does not allow packet queues!", (p_from->next == NULL), return ERR_VAL;); } if((p_to != NULL) && (p_to->len == p_to->tot_len)) { /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!\n", + LWIP_ERROR("pbuf_copy() does not allow packet queues!", (p_to->next == NULL), return ERR_VAL;); } } while (p_from); From c0b534e5318baf870e2152c70d4d11a3a86181f3 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Wed, 12 Feb 2014 22:20:25 +0100 Subject: [PATCH 05/23] Minor fixes to init.c preprocessor checks --- src/core/init.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/core/init.c b/src/core/init.c index 61cf3327..52d7baa0 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -73,9 +73,6 @@ #if (!LWIP_UDP && LWIP_UDPLITE) #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" #endif -#if (!LWIP_UDP && LWIP_SNMP) - #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif #if (!LWIP_UDP && LWIP_DHCP) #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" #endif @@ -142,7 +139,7 @@ #if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" #endif -#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)) +#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))) #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" #endif #if (LWIP_NETIF_API && (NO_SYS==1)) @@ -184,7 +181,7 @@ #if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" #endif -#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT +#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT #error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on" #endif #if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) From 2f02120fee4d709636c6979a70dd2a5c83a3e948 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 15:43:51 +0100 Subject: [PATCH 06/23] Fixed typo. --- src/core/tcp_in.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 9054a757..bf921a84 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -348,7 +348,7 @@ tcp_input(struct pbuf *p, struct netif *inp) u16_t acked; #if LWIP_WND_SCALE /* pcb->acked is u32_t but the sent callback only takes a u16_t, - so we might have to call it multiple timess. */ + so we might have to call it multiple times. */ u32_t pcb_acked = pcb->acked; while(pcb_acked > 0) { acked = (u16_t)LWIP_MIN(pcb_acked, 0xffffu); From cffe54d09470b7dd5b5afbe114b63757859fb40d Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 16:10:55 +0100 Subject: [PATCH 07/23] Patch #7815 by James Smith: added inet_ntop/inet_pton --- src/include/lwip/sockets.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h index 853beea8..74cd252c 100644 --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -423,6 +423,20 @@ int lwip_fcntl(int s, int cmd, int val); #define fcntl(a,b,c) lwip_fcntl(a,b,c) #endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ +#if LWIP_IPV6 +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET6) ? ip6addr_ntoa_r((src),(dst),(size)) \ + : (((af) == AF_INET) ? ipaddr_ntoa_r((src),(dst),(size)) : NULL)) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET6) ? inet6_aton((src),(dst)) \ + : (((af) == AF_INET) ? inet_aton((src),(dst)) : 0)) +#else /* LWIP_IPV6 */ +#define inet_ntop(af,src,dst,size) \ + (((af) == AF_INET) ? ipaddr_ntoa_r((src),(dst),(size)) : NULL) +#define inet_pton(af,src,dst) \ + (((af) == AF_INET) ? inet_aton((src),(dst)) : 0) +#endif /* LWIP_IPV6 */ + #endif /* LWIP_COMPAT_SOCKETS */ #ifdef __cplusplus From e2c2afbbe01762345ef99561a40b05033e166941 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 19:50:17 +0100 Subject: [PATCH 08/23] patch #7885: modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads) (based on patch by Artem Pisarenko) --- CHANGELOG | 4 + src/api/api_lib.c | 227 ++++++++++++++++++++++++------------ src/api/api_msg.c | 54 ++++----- src/api/netifapi.c | 108 ++++++++++++----- src/api/sockets.c | 81 +++++++------ src/api/tcpip.c | 31 +++-- src/core/init.c | 3 - src/core/memp.c | 1 + src/include/lwip/api_msg.h | 22 ++-- src/include/lwip/memp_std.h | 12 ++ src/include/lwip/netifapi.h | 12 +- src/include/lwip/opt.h | 37 ++++++ src/include/lwip/sockets.h | 25 ++++ src/include/lwip/tcpip.h | 29 +++++ 14 files changed, 444 insertions(+), 202 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 300b3d50..8d6c2333 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,10 @@ HISTORY ++ New features: + 2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko) + * patch #7885: modification of api modules to support FreeRTOS-MPU + (don't pass stack-pointers to other threads) + 2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab") * patch #6537/#7858: TCP window scaling support diff --git a/src/api/api_lib.c b/src/api/api_lib.c index adaaad43..971fe918 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -54,6 +54,12 @@ #include +#define API_MSG_VAR_REF(name) API_VAR_REF(name) +#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name) +#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name) +#define API_MSG_VAR_ALLOC_DONTFAIL(name) API_VAR_ALLOC_DONTFAIL(struct api_msg, MEMP_API_MSG, name) +#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name) + /** * Create a new netconn (of a specific type) that has a callback function. * The corresponding pcb is also created. @@ -68,14 +74,16 @@ struct netconn* netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) { struct netconn *conn; - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); conn = netconn_alloc(t, callback); if (conn != NULL) { err_t err; - msg.msg.msg.n.proto = proto; - msg.msg.conn = conn; - TCPIP_APIMSG((&msg), lwip_netconn_do_newconn, err); + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.msg.n.proto = proto; + API_MSG_VAR_REF(msg).msg.conn = conn; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_newconn, err); + API_MSG_VAR_FREE(msg); if (err != ERR_OK) { LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); @@ -103,16 +111,18 @@ netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_cal err_t netconn_delete(struct netconn *conn) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ if (conn == NULL) { return ERR_OK; } - msg.function = lwip_netconn_do_delconn; - msg.msg.conn = conn; - tcpip_apimsg(&msg); + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).function = lwip_netconn_do_delconn; + API_MSG_VAR_REF(msg).msg.conn = conn; + tcpip_apimsg(&API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); netconn_free(conn); @@ -135,18 +145,26 @@ netconn_delete(struct netconn *conn) err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); - msg.msg.conn = conn; + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.ad.local = local; +#if LWIP_MPU_COMPATIBLE + TCPIP_APIMSG(msg, lwip_netconn_do_getaddr, err); + *addr = *ipX_2_ip(&(msg->msg.msg.ad.ipaddr)); + *port = msg->msg.msg.ad.port; +#else /* LWIP_MPU_COMPATIBLE */ msg.msg.msg.ad.ipaddr = ip_2_ipX(addr); msg.msg.msg.ad.port = port; - msg.msg.msg.ad.local = local; TCPIP_APIMSG(&msg, lwip_netconn_do_getaddr, err); +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -165,15 +183,22 @@ netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); - msg.msg.conn = conn; - msg.msg.msg.bc.ipaddr = addr; - msg.msg.msg.bc.port = port; - TCPIP_APIMSG(&msg, lwip_netconn_do_bind, err); + API_MSG_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (addr == NULL) { + addr = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.msg.bc.port = port; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_bind, err); + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -190,14 +215,20 @@ netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port) err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); - msg.msg.conn = conn; - msg.msg.msg.bc.ipaddr = addr; - msg.msg.msg.bc.port = port; + API_MSG_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (addr == NULL) { + addr = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.msg.bc.port = port; #if LWIP_TCP #if (LWIP_UDP || LWIP_RAW) if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) @@ -205,8 +236,8 @@ netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) { /* The TCP version waits for the connect to succeed, so always needs to use message passing. */ - msg.function = lwip_netconn_do_connect; - err = tcpip_apimsg(&msg); + API_MSG_VAR_REF(msg).function = lwip_netconn_do_connect; + err = tcpip_apimsg(&API_MSG_VAR_REF(msg)); } #endif /* LWIP_TCP */ #if (LWIP_UDP || LWIP_RAW) && LWIP_TCP @@ -215,9 +246,10 @@ netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) #if (LWIP_UDP || LWIP_RAW) { /* UDP and RAW only set flags, so we can use core-locking. */ - TCPIP_APIMSG(&msg, lwip_netconn_do_connect, err); + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_connect, err); } #endif /* (LWIP_UDP || LWIP_RAW) */ + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -232,13 +264,15 @@ netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port) err_t netconn_disconnect(struct netconn *conn) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); - msg.msg.conn = conn; - TCPIP_APIMSG(&msg, lwip_netconn_do_disconnect, err); + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_disconnect, err); + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -256,7 +290,7 @@ err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) { #if LWIP_TCP - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ @@ -264,11 +298,13 @@ netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); - msg.msg.conn = conn; + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; #if TCP_LISTEN_BACKLOG - msg.msg.msg.lb.backlog = backlog; + API_MSG_VAR_REF(msg).msg.msg.lb.backlog = backlog; #endif /* TCP_LISTEN_BACKLOG */ - TCPIP_APIMSG(&msg, lwip_netconn_do_listen, err); + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_listen, err); + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -294,7 +330,7 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn) struct netconn *newconn; err_t err; #if TCP_LISTEN_BACKLOG - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); #endif /* TCP_LISTEN_BACKLOG */ LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); @@ -327,9 +363,11 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn) } #if TCP_LISTEN_BACKLOG /* Let the stack know that we have accepted the connection. */ - msg.msg.conn = conn; + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; /* don't care for the return value of lwip_netconn_do_recv */ - TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv); + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); #endif /* TCP_LISTEN_BACKLOG */ *new_conn = newconn; @@ -358,7 +396,7 @@ netconn_recv_data(struct netconn *conn, void **new_buf) u16_t len; err_t err; #if LWIP_TCP - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); #endif /* LWIP_TCP */ LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); @@ -393,14 +431,16 @@ netconn_recv_data(struct netconn *conn, void **new_buf) /* Let the stack know that we have taken the data. */ /* TODO: Speedup: Don't block and wait for the answer here (to prevent multiple thread-switches). */ - msg.msg.conn = conn; + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; if (buf != NULL) { - msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len; + API_MSG_VAR_REF(msg).msg.msg.r.len = ((struct pbuf *)buf)->tot_len; } else { - msg.msg.msg.r.len = 1; + API_MSG_VAR_REF(msg).msg.msg.r.len = 1; } /* don't care for the return value of lwip_netconn_do_recv */ - TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv); + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); } /* If we are closed, we indicate that we no longer wish to use the socket */ @@ -531,14 +571,16 @@ netconn_recved(struct netconn *conn, u32_t length) #if LWIP_TCP if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (netconn_get_noautorecved(conn))) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); /* Let the stack know that we have taken the data. */ /* TODO: Speedup: Don't block and wait for the answer here (to prevent multiple thread-switches). */ - msg.msg.conn = conn; - msg.msg.msg.r.len = length; + API_MSG_VAR_ALLOC_DONTFAIL(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.r.len = length; /* don't care for the return value of lwip_netconn_do_recv */ - TCPIP_APIMSG_NOERR(&msg, lwip_netconn_do_recv); + TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv); + API_MSG_VAR_FREE(msg); } #else /* LWIP_TCP */ LWIP_UNUSED_ARG(conn); @@ -577,15 +619,17 @@ netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t err_t netconn_send(struct netconn *conn, struct netbuf *buf) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); - msg.msg.conn = conn; - msg.msg.msg.b = buf; - TCPIP_APIMSG(&msg, lwip_netconn_do_send, err); + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.b = buf; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_send, err); + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -608,7 +652,7 @@ err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags, size_t *bytes_written) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; u8_t dontblock; @@ -624,25 +668,26 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, return ERR_VAL; } + API_MSG_VAR_ALLOC(msg); /* non-blocking write sends as much */ - msg.msg.conn = conn; - msg.msg.msg.w.dataptr = dataptr; - msg.msg.msg.w.apiflags = apiflags; - msg.msg.msg.w.len = size; + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.w.dataptr = dataptr; + API_MSG_VAR_REF(msg).msg.msg.w.apiflags = apiflags; + API_MSG_VAR_REF(msg).msg.msg.w.len = size; #if LWIP_SO_SNDTIMEO if (conn->send_timeout != 0) { /* get the time we started, which is later compared to sys_now() + conn->send_timeout */ - msg.msg.msg.w.time_started = sys_now(); + API_MSG_VAR_REF(msg).msg.msg.w.time_started = sys_now(); } else { - msg.msg.msg.w.time_started = 0; + API_MSG_VAR_REF(msg).msg.msg.w.time_started = 0; } #endif /* LWIP_SO_SNDTIMEO */ /* For locking the core: this _can_ be delayed on low memory/low send buffer, but if it is, this is done inside api_msg.c:do_write(), so we can use the non-blocking version here. */ - TCPIP_APIMSG(&msg, lwip_netconn_do_write, err); + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_write, err); if ((err == ERR_OK) && (bytes_written != NULL)) { if (dontblock #if LWIP_SO_SNDTIMEO @@ -650,12 +695,13 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, #endif /* LWIP_SO_SNDTIMEO */ ) { /* nonblocking write: maybe the data has been sent partly */ - *bytes_written = msg.msg.msg.w.len; + *bytes_written = API_MSG_VAR_REF(msg).msg.msg.w.len; } else { /* blocking call succeeded: all data has been sent if it */ *bytes_written = size; } } + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -671,18 +717,20 @@ netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, static err_t netconn_close_shutdown(struct netconn *conn, u8_t how) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); - msg.function = lwip_netconn_do_close; - msg.msg.conn = conn; + API_MSG_VAR_ALLOC(msg); + API_MSG_VAR_REF(msg).function = lwip_netconn_do_close; + API_MSG_VAR_REF(msg).msg.conn = conn; /* shutting down both ends is the same as closing */ - msg.msg.msg.sd.shut = how; + API_MSG_VAR_REF(msg).msg.msg.sd.shut = how; /* because of the LWIP_TCPIP_CORE_LOCKING implementation of lwip_netconn_do_close, don't use TCPIP_APIMSG here */ - err = tcpip_apimsg(&msg); + err = tcpip_apimsg(&API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -730,16 +778,26 @@ netconn_join_leave_group(struct netconn *conn, ip_addr_t *netif_addr, enum netconn_igmp join_or_leave) { - struct api_msg msg; + API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); - msg.msg.conn = conn; - msg.msg.msg.jl.multiaddr = ip_2_ipX(multiaddr); - msg.msg.msg.jl.netif_addr = ip_2_ipX(netif_addr); - msg.msg.msg.jl.join_or_leave = join_or_leave; - TCPIP_APIMSG(&msg, lwip_netconn_do_join_leave_group, err); + API_MSG_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (multiaddr == NULL) { + multiaddr = IP_ADDR_ANY; + } + if (netif_addr == NULL) { + netif_addr = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + API_MSG_VAR_REF(msg).msg.conn = conn; + API_MSG_VAR_REF(msg).msg.msg.jl.multiaddr = API_MSG_VAR_REF(ip_2_ipX(multiaddr)); + API_MSG_VAR_REF(msg).msg.msg.jl.netif_addr = API_MSG_VAR_REF(ip_2_ipX(netif_addr)); + API_MSG_VAR_REF(msg).msg.msg.jl.join_or_leave = join_or_leave; + TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_join_leave_group, err); + API_MSG_VAR_FREE(msg); NETCONN_SET_SAFE_ERR(conn, err); return err; @@ -760,27 +818,42 @@ netconn_join_leave_group(struct netconn *conn, err_t netconn_gethostbyname(const char *name, ip_addr_t *addr) { - struct dns_api_msg msg; - err_t err; + API_VAR_DECLARE(struct dns_api_msg, msg); +#if !LWIP_MPU_COMPATIBLE sys_sem_t sem; +#endif /* LWIP_MPU_COMPATIBLE */ + err_t err; LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); - err = sys_sem_new(&sem, 0); - if (err != ERR_OK) { - return err; + API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg); +#if LWIP_MPU_COMPATIBLE + if (addr == NULL) { + addr = IP_ADDR_ANY; } - - msg.name = name; - msg.addr = addr; +#else msg.err = &err; msg.sem = &sem; + API_VAR_REF(msg).addr = API_VAR_REF(addr); +#endif /* LWIP_MPU_COMPATIBLE */ + err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0); + if (err != ERR_OK) { + API_VAR_FREE(MEMP_DNS_API_MSG, msg); + return err; + } + API_VAR_REF(msg).name = name; - tcpip_callback(lwip_netconn_do_gethostbyname, &msg); - sys_sem_wait(&sem); - sys_sem_free(&sem); + tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg)); + sys_sem_wait(API_EXPR_REF(API_VAR_REF(msg).sem)); + sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); +#if LWIP_MPU_COMPATIBLE + *addr = msg->addr; + err = msg->err; +#endif /* LWIP_MPU_COMPATIBLE */ + + API_VAR_FREE(MEMP_DNS_API_MSG, msg); return err; } #endif /* LWIP_DNS*/ diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 02973389..7f7138ed 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -907,17 +907,17 @@ lwip_netconn_do_bind(struct api_msg_msg *msg) switch (NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: - msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr); + msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); break; #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: - msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); + msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: - msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port); + msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); break; #endif /* LWIP_TCP */ default: @@ -997,12 +997,12 @@ lwip_netconn_do_connect(struct api_msg_msg *msg) switch (NETCONNTYPE_GROUP(msg->conn->type)) { #if LWIP_RAW case NETCONN_RAW: - msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr); + msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); break; #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: - msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port); + msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); break; #endif /* LWIP_UDP */ #if LWIP_TCP @@ -1012,7 +1012,7 @@ lwip_netconn_do_connect(struct api_msg_msg *msg) msg->err = ERR_ISCONN; } else { setup_tcp(msg->conn); - msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, + msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port, lwip_netconn_do_connected); if (msg->err == ERR_OK) { u8_t non_blocking = netconn_is_nonblocking(msg->conn); @@ -1422,10 +1422,10 @@ lwip_netconn_do_getaddr(struct api_msg_msg *msg) { if (msg->conn->pcb.ip != NULL) { if (msg->msg.ad.local) { - ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), *(msg->msg.ad.ipaddr), + ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), API_EXPR_DEREF(msg->msg.ad.ipaddr), msg->conn->pcb.ip->local_ip); } else { - ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), *(msg->msg.ad.ipaddr), + ipX_addr_copy(PCB_ISIPV6(msg->conn->pcb.ip), API_EXPR_DEREF(msg->msg.ad.ipaddr), msg->conn->pcb.ip->remote_ip); } msg->err = ERR_OK; @@ -1433,7 +1433,7 @@ lwip_netconn_do_getaddr(struct api_msg_msg *msg) #if LWIP_RAW case NETCONN_RAW: if (msg->msg.ad.local) { - *(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; } else { /* return an error as connecting is only a helper for upper layers */ msg->err = ERR_CONN; @@ -1443,19 +1443,19 @@ lwip_netconn_do_getaddr(struct api_msg_msg *msg) #if LWIP_UDP case NETCONN_UDP: if (msg->msg.ad.local) { - *(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; } else { if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { msg->err = ERR_CONN; } else { - *(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; + API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; } } break; #endif /* LWIP_UDP */ #if LWIP_TCP case NETCONN_TCP: - *(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port); + API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local?msg->conn->pcb.tcp->local_port:msg->conn->pcb.tcp->remote_port); break; #endif /* LWIP_TCP */ default: @@ -1528,11 +1528,11 @@ lwip_netconn_do_join_leave_group(struct api_msg_msg *msg) #if LWIP_IPV6 && LWIP_IPV6_MLD if (PCB_ISIPV6(msg->conn->pcb.udp)) { if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { - msg->err = mld6_joingroup(ipX_2_ip6(msg->msg.jl.netif_addr), - ipX_2_ip6(msg->msg.jl.multiaddr)); + msg->err = mld6_joingroup(ipX_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ipX_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); } else { - msg->err = mld6_leavegroup(ipX_2_ip6(msg->msg.jl.netif_addr), - ipX_2_ip6(msg->msg.jl.multiaddr)); + msg->err = mld6_leavegroup(ipX_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), + ipX_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); } } else @@ -1540,11 +1540,11 @@ lwip_netconn_do_join_leave_group(struct api_msg_msg *msg) { #if LWIP_IGMP if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { - msg->err = igmp_joingroup(ipX_2_ip(msg->msg.jl.netif_addr), - ipX_2_ip(msg->msg.jl.multiaddr)); + msg->err = igmp_joingroup(ipX_2_ip(API_EXPR_REF(msg->msg.jl.netif_addr)), + ipX_2_ip(API_EXPR_REF(msg->msg.jl.multiaddr))); } else { - msg->err = igmp_leavegroup(ipX_2_ip(msg->msg.jl.netif_addr), - ipX_2_ip(msg->msg.jl.multiaddr)); + msg->err = igmp_leavegroup(ipX_2_ip(API_EXPR_REF(msg->msg.jl.netif_addr)), + ipX_2_ip(API_EXPR_REF(msg->msg.jl.multiaddr))); } #endif /* LWIP_IGMP */ } @@ -1578,14 +1578,14 @@ lwip_netconn_do_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) if (ipaddr == NULL) { /* timeout or memory error */ - *msg->err = ERR_VAL; + API_EXPR_DEREF(msg->err) = ERR_VAL; } else { /* address was resolved */ - *msg->err = ERR_OK; - *msg->addr = *ipaddr; + API_EXPR_DEREF(msg->err) = ERR_OK; + API_EXPR_DEREF(msg->addr) = *ipaddr; } /* wake up the application task waiting in netconn_gethostbyname */ - sys_sem_signal(msg->sem); + sys_sem_signal(API_EXPR_REF(msg->sem)); } /** @@ -1599,11 +1599,11 @@ lwip_netconn_do_gethostbyname(void *arg) { struct dns_api_msg *msg = (struct dns_api_msg*)arg; - *msg->err = dns_gethostbyname(msg->name, msg->addr, lwip_netconn_do_dns_found, msg); - if (*msg->err != ERR_INPROGRESS) { + API_EXPR_DEREF(msg->err) = dns_gethostbyname(msg->name, API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg); + if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { /* on error or immediate success, wake up the application * task waiting in netconn_gethostbyname */ - sys_sem_signal(msg->sem); + sys_sem_signal(API_EXPR_REF(msg->sem)); } } #endif /* LWIP_DNS */ diff --git a/src/api/netifapi.c b/src/api/netifapi.c index 81403f82..715d515e 100644 --- a/src/api/netifapi.c +++ b/src/api/netifapi.c @@ -37,6 +37,12 @@ #include "lwip/netifapi.h" #include "lwip/tcpip.h" +#include "lwip/memp.h" + +#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) +#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) +#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name) +#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) /** * Call netif_add() inside the tcpip_thread context. @@ -45,9 +51,9 @@ static void netifapi_do_netif_add(struct netifapi_msg_msg *msg) { if (!netif_add( msg->netif, - msg->msg.add.ipaddr, - msg->msg.add.netmask, - msg->msg.add.gw, + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw), msg->msg.add.state, msg->msg.add.init, msg->msg.add.input)) { @@ -65,9 +71,9 @@ static void netifapi_do_netif_set_addr(struct netifapi_msg_msg *msg) { netif_set_addr( msg->netif, - msg->msg.add.ipaddr, - msg->msg.add.netmask, - msg->msg.add.gw); + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), + API_EXPR_REF(msg->msg.add.gw)); msg->err = ERR_OK; TCPIP_NETIFAPI_ACK(msg); } @@ -103,17 +109,33 @@ netifapi_netif_add(struct netif *netif, netif_init_fn init, netif_input_fn input) { - struct netifapi_msg msg; - msg.function = netifapi_do_netif_add; - msg.msg.netif = netif; - msg.msg.msg.add.ipaddr = ipaddr; - msg.msg.msg.add.netmask = netmask; - msg.msg.msg.add.gw = gw; - msg.msg.msg.add.state = state; - msg.msg.msg.add.init = init; - msg.msg.msg.add.input = input; - TCPIP_NETIFAPI(&msg); - return msg.msg.err; + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (ipaddr == NULL) { + ipaddr = IP_ADDR_ANY; + } + if (netmask == NULL) { + netmask = IP_ADDR_ANY; + } + if (gw == NULL) { + gw = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + NETIFAPI_VAR_REF(msg).function = netifapi_do_netif_add; + NETIFAPI_VAR_REF(msg).msg.netif = netif; + NETIFAPI_VAR_REF(msg).msg.msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.msg.add.gw = NETIFAPI_VAR_REF(gw); + NETIFAPI_VAR_REF(msg).msg.msg.add.state = state; + NETIFAPI_VAR_REF(msg).msg.msg.add.init = init; + NETIFAPI_VAR_REF(msg).msg.msg.add.input = input; + TCPIP_NETIFAPI(&API_VAR_REF(msg)); + + err = NETIFAPI_VAR_REF(msg).msg.err; + NETIFAPI_VAR_FREE(msg); + return err; } /** @@ -128,14 +150,30 @@ netifapi_netif_set_addr(struct netif *netif, ip_addr_t *netmask, ip_addr_t *gw) { - struct netifapi_msg msg; - msg.function = netifapi_do_netif_set_addr; - msg.msg.netif = netif; - msg.msg.msg.add.ipaddr = ipaddr; - msg.msg.msg.add.netmask = netmask; - msg.msg.msg.add.gw = gw; - TCPIP_NETIFAPI(&msg); - return msg.msg.err; + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); +#if LWIP_MPU_COMPATIBLE + if (ipaddr == NULL) { + ipaddr = IP_ADDR_ANY; + } + if (netmask == NULL) { + netmask = IP_ADDR_ANY; + } + if (gw == NULL) { + gw = IP_ADDR_ANY; + } +#endif /* LWIP_MPU_COMPATIBLE */ + NETIFAPI_VAR_REF(msg).function = netifapi_do_netif_set_addr; + NETIFAPI_VAR_REF(msg).msg.netif = netif; + NETIFAPI_VAR_REF(msg).msg.msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); + NETIFAPI_VAR_REF(msg).msg.msg.add.netmask = NETIFAPI_VAR_REF(netmask); + NETIFAPI_VAR_REF(msg).msg.msg.add.gw = NETIFAPI_VAR_REF(gw); + TCPIP_NETIFAPI(&API_VAR_REF(msg)); + + err = NETIFAPI_VAR_REF(msg).msg.err; + NETIFAPI_VAR_FREE(msg); + return err; } /** @@ -148,13 +186,19 @@ err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, netifapi_errt_fn errtfunc) { - struct netifapi_msg msg; - msg.function = netifapi_do_netif_common; - msg.msg.netif = netif; - msg.msg.msg.common.voidfunc = voidfunc; - msg.msg.msg.common.errtfunc = errtfunc; - TCPIP_NETIFAPI(&msg); - return msg.msg.err; + err_t err; + NETIFAPI_VAR_DECLARE(msg); + NETIFAPI_VAR_ALLOC(msg); + + NETIFAPI_VAR_REF(msg).function = netifapi_do_netif_common; + NETIFAPI_VAR_REF(msg).msg.netif = netif; + NETIFAPI_VAR_REF(msg).msg.msg.common.voidfunc = voidfunc; + NETIFAPI_VAR_REF(msg).msg.msg.common.errtfunc = errtfunc; + TCPIP_NETIFAPI(&API_VAR_REF(msg)); + + err = NETIFAPI_VAR_REF(msg).msg.err; + NETIFAPI_VAR_FREE(msg); + return err; } #endif /* LWIP_NETIF_API */ diff --git a/src/api/sockets.c b/src/api/sockets.c index 66036712..22905539 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -51,6 +51,7 @@ #include "lwip/raw.h" #include "lwip/udp.h" #include "lwip/tcpip.h" +#include "lwip/memp.h" #include "lwip/pbuf.h" #if LWIP_CHECKSUM_ON_COPY #include "lwip/inet_chksum.h" @@ -117,6 +118,20 @@ #define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) +#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) +#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) +#if LWIP_MPU_COMPATIBLE +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ + name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ + if (name == NULL) { \ + sock_set_errno(sock, ERR_MEM); \ + return -1; \ + } }while(0) +#else /* LWIP_MPU_COMPATIBLE */ +#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) +#endif /* LWIP_MPU_COMPATIBLE */ + #define NUM_SOCKETS MEMP_NUM_NETCONN @@ -160,28 +175,6 @@ struct lwip_select_cb { sys_sem_t sem; }; -/** This struct is used to pass data to the set/getsockopt_internal - * functions running in tcpip_thread context (only a void* is allowed) */ -struct lwip_setgetsockopt_data { - /** socket struct for which to change options */ - struct lwip_sock *sock; -#ifdef LWIP_DEBUG - /** socket index for which to change options */ - int s; -#endif /* LWIP_DEBUG */ - /** level of the option to process */ - int level; - /** name of the option to process */ - int optname; - /** set: value to set the option to - * get: value of the option is stored here */ - void *optval; - /** size of *optval */ - socklen_t *optlen; - /** if an error occures, it is temporarily stored here */ - err_t err; -}; - /** A struct sockaddr replacement that has the same alignment as sockaddr_in/ * sockaddr_in6 if instantiated. */ @@ -1526,7 +1519,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) { err_t err = ERR_OK; struct lwip_sock *sock = get_socket(s); - struct lwip_setgetsockopt_data data; + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); if (!sock) { return -1; @@ -1724,19 +1717,21 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) } /* Now do the actual option processing */ - data.sock = sock; + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).sock = sock; #ifdef LWIP_DEBUG - data.s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; #endif /* LWIP_DEBUG */ - data.level = level; - data.optname = optname; - data.optval = optval; - data.optlen = optlen; - data.err = err; - tcpip_callback(lwip_getsockopt_internal, &data); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval = optval; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = err; + tcpip_callback(lwip_getsockopt_internal, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); sys_arch_sem_wait(&sock->conn->op_completed, 0); /* maybe lwip_getsockopt_internal has changed err */ - err = data.err; + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); sock_set_errno(sock, err); return err ? -1 : 0; @@ -1972,7 +1967,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt { struct lwip_sock *sock = get_socket(s); err_t err = ERR_OK; - struct lwip_setgetsockopt_data data; + LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); if (!sock) { return -1; @@ -2181,19 +2176,21 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt /* Now do the actual option processing */ - data.sock = sock; + LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).sock = sock; #ifdef LWIP_DEBUG - data.s = s; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; #endif /* LWIP_DEBUG */ - data.level = level; - data.optname = optname; - data.optval = (void*)optval; - data.optlen = &optlen; - data.err = err; - tcpip_callback(lwip_setsockopt_internal, &data); + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval = (void*)optval; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = &optlen; + LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = err; + tcpip_callback(lwip_setsockopt_internal, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); sys_arch_sem_wait(&sock->conn->op_completed, 0); /* maybe lwip_setsockopt_internal has changed err */ - err = data.err; + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); sock_set_errno(sock, err); return err ? -1 : 0; diff --git a/src/api/tcpip.c b/src/api/tcpip.c index 2c0032c2..31e7c924 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -50,6 +50,11 @@ #include "netif/etharp.h" #include "netif/ppp_oe.h" +#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name) +#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name) +#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name) +#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name) + /* global variables */ static tcpip_init_done_fn tcpip_init_done; static void *tcpip_init_done_arg; @@ -311,17 +316,19 @@ tcpip_untimeout(sys_timeout_handler h, void *arg) err_t tcpip_apimsg(struct api_msg *apimsg) { - struct tcpip_msg msg; + TCPIP_MSG_VAR_DECLARE(msg); #ifdef LWIP_DEBUG /* catch functions that don't set err */ apimsg->msg.err = ERR_VAL; #endif if (sys_mbox_valid(&mbox)) { - msg.type = TCPIP_MSG_API; - msg.msg.apimsg = apimsg; - sys_mbox_post(&mbox, &msg); + TCPIP_MSG_VAR_ALLOC(msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; + TCPIP_MSG_VAR_REF(msg).msg.apimsg = apimsg; + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0); + TCPIP_MSG_VAR_FREE(msg); return apimsg->msg.err; } return ERR_VAL; @@ -341,20 +348,24 @@ tcpip_apimsg(struct api_msg *apimsg) err_t tcpip_netifapi(struct netifapi_msg* netifapimsg) { - struct tcpip_msg msg; - + TCPIP_MSG_VAR_DECLARE(msg); + if (sys_mbox_valid(&mbox)) { - err_t err = sys_sem_new(&netifapimsg->msg.sem, 0); + err_t err; + TCPIP_MSG_VAR_ALLOC(msg); + + err = sys_sem_new(&netifapimsg->msg.sem, 0); if (err != ERR_OK) { netifapimsg->msg.err = err; return err; } - msg.type = TCPIP_MSG_NETIFAPI; - msg.msg.netifapimsg = netifapimsg; - sys_mbox_post(&mbox, &msg); + TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_NETIFAPI; + TCPIP_MSG_VAR_REF(msg).msg.netifapimsg = netifapimsg; + sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_sem_wait(&netifapimsg->msg.sem); sys_sem_free(&netifapimsg->msg.sem); + TCPIP_MSG_VAR_FREE(msg); return netifapimsg->msg.err; } return ERR_VAL; diff --git a/src/core/init.c b/src/core/init.c index 52d7baa0..3095bd38 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -232,9 +232,6 @@ #ifdef MEMP_NUM_TCPIP_MSG #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." #endif -#ifdef MEMP_NUM_API_MSG - #error "MEMP_NUM_API_MSG option is deprecated. Remove it from your lwipopts.h." -#endif #ifdef TCP_REXMIT_DEBUG #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." #endif diff --git a/src/core/memp.c b/src/core/memp.c index cc967981..992b2307 100644 --- a/src/core/memp.c +++ b/src/core/memp.c @@ -48,6 +48,7 @@ #include "lwip/igmp.h" #include "lwip/api.h" #include "lwip/api_msg.h" +#include "lwip/sockets.h" #include "lwip/tcpip.h" #include "lwip/sys.h" #include "lwip/timers.h" diff --git a/src/include/lwip/api_msg.h b/src/include/lwip/api_msg.h index 8268036a..95614b7a 100644 --- a/src/include/lwip/api_msg.h +++ b/src/include/lwip/api_msg.h @@ -48,6 +48,12 @@ extern "C" { #endif +#if LWIP_MPU_COMPATIBLE +#define API_MSG_M_DEF(m) m +#else /* LWIP_MPU_COMPATIBLE */ +#define API_MSG_M_DEF(m) *m +#endif /* LWIP_MPU_COMPATIBLE */ + /* For the netconn API, these values are use as a bitmask! */ #define NETCONN_SHUT_RD 1 #define NETCONN_SHUT_WR 2 @@ -75,13 +81,13 @@ struct api_msg_msg { } n; /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ struct { - ip_addr_t *ipaddr; + ip_addr_t API_MSG_M_DEF(ipaddr); u16_t port; } bc; /** used for lwip_netconn_do_getaddr */ struct { - ipX_addr_t *ipaddr; - u16_t *port; + ipX_addr_t API_MSG_M_DEF(ipaddr); + u16_t API_MSG_M_DEF(port); u8_t local; } ad; /** used for lwip_netconn_do_write */ @@ -104,8 +110,8 @@ struct api_msg_msg { #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) /** used for lwip_netconn_do_join_leave_group */ struct { - ipX_addr_t *multiaddr; - ipX_addr_t *netif_addr; + ipX_addr_t API_MSG_M_DEF(multiaddr); + ipX_addr_t API_MSG_M_DEF(netif_addr); enum netconn_igmp join_or_leave; } jl; #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ @@ -136,12 +142,12 @@ struct dns_api_msg { /** Hostname to query or dotted IP address string */ const char *name; /** Rhe resolved address is stored here */ - ip_addr_t *addr; + ip_addr_t API_MSG_M_DEF(addr); /** This semaphore is posted when the name is resolved, the application thread should wait on it. */ - sys_sem_t *sem; + sys_sem_t API_MSG_M_DEF(sem); /** Errors are given back here */ - err_t *err; + err_t API_MSG_M_DEF(err); }; #endif /* LWIP_DNS */ diff --git a/src/include/lwip/memp_std.h b/src/include/lwip/memp_std.h index 8e1c99c4..18afe7c6 100644 --- a/src/include/lwip/memp_std.h +++ b/src/include/lwip/memp_std.h @@ -58,6 +58,18 @@ LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), #if NO_SYS==0 LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if LWIP_MPU_COMPATIBLE +LWIP_MEMPOOL(API_MSG, MEMP_NUM_API_MSG, sizeof(struct api_msg), "API_MSG") +#if LWIP_DNS +LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg), "DNS_API_MSG") +#endif +#if LWIP_SOCKET +LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA") +#endif +#if LWIP_NETIF_API +LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG") +#endif +#endif /* LWIP_MPU_COMPATIBLE */ #if !LWIP_TCPIP_CORE_LOCKING_INPUT LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ diff --git a/src/include/lwip/netifapi.h b/src/include/lwip/netifapi.h index 648151b6..37a6743f 100644 --- a/src/include/lwip/netifapi.h +++ b/src/include/lwip/netifapi.h @@ -41,6 +41,12 @@ extern "C" { #endif +#if LWIP_MPU_COMPATIBLE +#define NETIFAPI_IPADDR_DEF(m) m +#else /* LWIP_MPU_COMPATIBLE */ +#define NETIFAPI_IPADDR_DEF(m) *m +#endif /* LWIP_MPU_COMPATIBLE */ + typedef void (*netifapi_void_fn)(struct netif *netif); typedef err_t (*netifapi_errt_fn)(struct netif *netif); @@ -52,9 +58,9 @@ struct netifapi_msg_msg { struct netif *netif; union { struct { - ip_addr_t *ipaddr; - ip_addr_t *netmask; - ip_addr_t *gw; + ip_addr_t NETIFAPI_IPADDR_DEF(ipaddr); + ip_addr_t NETIFAPI_IPADDR_DEF(netmask); + ip_addr_t NETIFAPI_IPADDR_DEF(gw); void *state; netif_init_fn init; netif_input_fn input; diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 82946d0f..2becda85 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -92,6 +92,16 @@ #define SMEMCPY(dst,src,len) memcpy(dst,src,len) #endif +/** + * LWIP_MPU_COMPATIBLE: enables special memory management mechanism + * which makes lwip able to work on MPU (Memory Protection Unit) system + * by not passing stack-pointers to other threads + * (this decreases performance) + */ +#ifndef LWIP_MPU_COMPATIBLE +#define LWIP_MPU_COMPATIBLE 0 +#endif + /* ------------------------------------ ---------- Memory options ---------- @@ -414,6 +424,33 @@ #define PBUF_POOL_SIZE 16 #endif +/** MEMP_NUM_API_MSG: the number of concurrently active calls to various + * socket, netconn, and tcpip functions + */ +#ifndef MEMP_NUM_API_MSG +#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_DNS_API_MSG: the number of concurrently active calls to netconn_gethostbyname + */ +#ifndef MEMP_NUM_DNS_API_MSG +#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA: the number of concurrently active calls + * to getsockopt/setsockopt + */ +#ifndef MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA +#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_NETIFAPI_MSG: the number of concurrently active calls to the + * netifapi functions + */ +#ifndef MEMP_NUM_NETIFAPI_MSG +#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API +#endif + /* --------------------------------- ---------- ARP options ---------- diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h index 74cd252c..ba4ca7b6 100644 --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -41,6 +41,7 @@ #include /* for size_t */ #include "lwip/ip_addr.h" +#include "lwip/err.h" #include "lwip/inet.h" #include "lwip/inet6.h" @@ -105,6 +106,30 @@ struct sockaddr_storage { typedef u32_t socklen_t; #endif +struct lwip_sock; + +/** This struct is used to pass data to the set/getsockopt_internal + * functions running in tcpip_thread context (only a void* is allowed) */ +struct lwip_setgetsockopt_data { + /** socket struct for which to change options */ + struct lwip_sock *sock; +#ifdef LWIP_DEBUG + /** socket index for which to change options */ + int s; +#endif /* LWIP_DEBUG */ + /** level of the option to process */ + int level; + /** name of the option to process */ + int optname; + /** set: value to set the option to + * get: value of the option is stored here */ + void *optval; + /** size of *optval */ + socklen_t *optlen; + /** if an error occures, it is temporarily stored here */ + err_t err; +}; + /* Socket protocol types (TCP/UDP/RAW) */ #define SOCK_STREAM 1 #define SOCK_DGRAM 2 diff --git a/src/include/lwip/tcpip.h b/src/include/lwip/tcpip.h index 04567f2c..5b71cf1b 100644 --- a/src/include/lwip/tcpip.h +++ b/src/include/lwip/tcpip.h @@ -87,6 +87,35 @@ extern sys_mutex_t lock_tcpip_core; #define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem) #endif /* LWIP_TCPIP_CORE_LOCKING */ + +#if LWIP_MPU_COMPATIBLE +#define API_VAR_REF(name) (*(name)) +#define API_VAR_DECLARE(type, name) type * name +#define API_VAR_ALLOC(type, pool, name) do { \ + name = (type *)memp_malloc(pool); \ + if (name == NULL) { \ + return ERR_MEM; \ + } \ + } while(0) +#define API_VAR_ALLOC_DONTFAIL(type, pool, name) do { \ + name = (type *)memp_malloc(pool); \ + LWIP_ASSERT("pool empty", name != NULL); \ + } while(0) +#define API_VAR_FREE(pool, name) memp_free(pool, name) +#define API_EXPR_REF(expr) &(expr) +#define API_EXPR_DEREF(expr) expr +#else /* LWIP_MPU_COMPATIBLE */ +#define API_VAR_REF(name) name +#define API_VAR_DECLARE(type, name) type name +#define API_VAR_ALLOC(type, pool, name) +#define API_VAR_ALLOC_DONTFAIL(type, pool, name) +#define API_VAR_FREE(pool, name) +#define API_EXPR_REF(expr) expr +#define API_EXPR_DEREF(expr) *(expr) +#endif /* LWIP_MPU_COMPATIBLE */ + + + /** Function prototype for the init_done function passed to tcpip_init */ typedef void (*tcpip_init_done_fn)(void *arg); /** Function prototype for functions passed to tcpip_callback() */ From d74464e0919ce6f2e7b16712fac6e641cfdf2cf8 Mon Sep 17 00:00:00 2001 From: Grant Erickson Date: Wed, 19 Dec 2012 18:21:07 -0800 Subject: [PATCH 09/23] Add RFC3542-style checksum compuation on raw, IPv6 sockets This patch adds support for RFC3542-style checksum computation on raw, IPv6 sockets via the IPV6_CHECKSUM socket option. This allows the development of application-layer utilities such as ping6 which are unable to compute the raw packet checksum without a prior knowledge of the source address selection. --- src/api/sockets.c | 84 ++++++++++++++++++++++++++++++++++++++ src/core/raw.c | 11 +++++ src/include/lwip/raw.h | 5 +++ src/include/lwip/sockets.h | 3 +- 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/api/sockets.c b/src/api/sockets.c index 22905539..096b9c5c 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -1703,6 +1703,22 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) } /* switch (optname) */ break; #endif /* LWIP_UDP && LWIP_UDPLITE*/ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 + case IPV6_CHECKSUM: + if (*optlen < sizeof(int)) { + err = EINVAL; + break; + } +#endif /* LWIP_IPV6 */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; /* UNDEFINED LEVEL */ default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", @@ -1955,6 +1971,24 @@ lwip_getsockopt_internal(void *arg) } /* switch (optname) */ break; #endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 + case IPV6_CHECKSUM: + if (sock->conn->pcb.raw->chksum_reqd == 0) + *(int *)optval = -1; + else + *(int *)optval = sock->conn->pcb.raw->chksum_offset; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", + s, (*(int*)optval)) ); + break; +#endif /* LWIP_IPV6 */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; default: LWIP_ASSERT("unhandled level", 0); break; @@ -2129,12 +2163,26 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt return 0; break; + case IPV6_CHECKSUM: + err = EINVAL; + break; default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", s, optname)); err = ENOPROTOOPT; } /* switch (optname) */ break; + case IPPROTO_ICMPV6: + switch (optname) { + case IPV6_CHECKSUM: + err = EINVAL; + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_ICMPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; #endif /* LWIP_IPV6 */ #if LWIP_UDP && LWIP_UDPLITE @@ -2161,6 +2209,22 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt } /* switch (optname) */ break; #endif /* LWIP_UDP && LWIP_UDPLITE */ +/* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 + case IPV6_CHECKSUM: + /* Per RFC3542, odd offsets are not allowed */ + if ((*(int *)optval > 0) && (*(int *)optval & 1)) + err = EINVAL; + break; +#endif /* LWIP_IPV6 */ + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; + } /* switch (optname) */ + break; /* UNDEFINED LEVEL */ default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", @@ -2419,6 +2483,26 @@ lwip_setsockopt_internal(void *arg) } /* switch (optname) */ break; #endif /* LWIP_UDP */ + /* Level: IPPROTO_RAW */ + case IPPROTO_RAW: + switch (optname) { +#if LWIP_IPV6 + case IPV6_CHECKSUM: + if (*(int *)optval < 0) { + sock->conn->pcb.raw->chksum_reqd = 0; + } else { + sock->conn->pcb.raw->chksum_reqd = 1; + sock->conn->pcb.raw->chksum_offset = *(int *)optval; + } + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", + s, sock->conn->pcb.raw->chksum_reqd)); + break; +#endif /* LWIP_IPV6 */ + default: + LWIP_ASSERT("unhandled optname", 0); + break; + } /* switch (optname) */ + break; default: LWIP_ASSERT("unhandled level", 0); break; diff --git a/src/core/raw.c b/src/core/raw.c index 68b23c61..90eda30b 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -51,6 +51,7 @@ #include "arch/perf.h" #include "lwip/ip6.h" #include "lwip/ip6_addr.h" +#include "lwip/inet_chksum.h" #include @@ -313,6 +314,16 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) src_ip = &pcb->local_ip; } +#if LWIP_IPV6 + /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, */ + /* compute the checksum and update the checksum in the payload. */ + if (PCB_ISIPV6(pcb) && pcb->chksum_reqd) { + u16_t chksum; + chksum = ip6_chksum_pseudo(q, pcb->protocol, q->tot_len, ipX_2_ip6(src_ip), ipX_2_ip6(dst_ip)); + *(u16_t *)(((u8_t *)q->payload) + pcb->chksum_offset) = chksum; + } +#endif + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); err = ipX_output_if(PCB_ISIPV6(pcb), q, ipX_2_ip(src_ip), ipX_2_ip(dst_ip), pcb->ttl, pcb->tos, pcb->protocol, netif); NETIF_SET_HWADDRHINT(netif, NULL); diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h index f0c8ed47..e1412489 100644 --- a/src/include/lwip/raw.h +++ b/src/include/lwip/raw.h @@ -97,6 +97,11 @@ struct raw_pcb { } recv; /* user-supplied argument for the recv callback */ void *recv_arg; +#if LWIP_IPV6 + /* fields for handling checksum computations as per RFC3542. */ + u8_t chksum_reqd; + u16_t chksum_offset; +#endif }; /* The following functions is the application layer interface to the diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h index ba4ca7b6..e2a36a46 100644 --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -230,7 +230,8 @@ struct linger { /* * Options for level IPPROTO_IPV6 */ -#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ +#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ +#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ #endif /* LWIP_IPV6 */ #if LWIP_UDP && LWIP_UDPLITE From a375ea4ee2f4146816ce7c757011bab28fb1dfef Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 20:09:33 +0100 Subject: [PATCH 10/23] Minor: coding style cleanups... --- src/api/sockets.c | 56 ++++++++++++++++++++++-------------------- src/core/raw.c | 10 ++++---- src/include/lwip/raw.h | 2 +- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/api/sockets.c b/src/api/sockets.c index 096b9c5c..9f6b5277 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -1721,9 +1721,9 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) break; /* UNDEFINED LEVEL */ default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", - s, level, optname)); - err = ENOPROTOOPT; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", + s, level, optname)); + err = ENOPROTOOPT; } /* switch */ @@ -1976,10 +1976,11 @@ lwip_getsockopt_internal(void *arg) switch (optname) { #if LWIP_IPV6 case IPV6_CHECKSUM: - if (sock->conn->pcb.raw->chksum_reqd == 0) + if (sock->conn->pcb.raw->chksum_reqd == 0) { *(int *)optval = -1; - else + } else { *(int *)optval = sock->conn->pcb.raw->chksum_offset; + } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", s, (*(int*)optval)) ); break; @@ -1988,7 +1989,7 @@ lwip_getsockopt_internal(void *arg) LWIP_ASSERT("unhandled optname", 0); break; } /* switch (optname) */ - break; + break; default: LWIP_ASSERT("unhandled level", 0); break; @@ -2159,28 +2160,29 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt } /* @todo: this does not work for datagram sockets, yet */ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { return 0; + } break; case IPV6_CHECKSUM: - err = EINVAL; - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; + err = EINVAL; + break; + default: + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; } /* switch (optname) */ break; case IPPROTO_ICMPV6: switch (optname) { case IPV6_CHECKSUM: - err = EINVAL; - break; + err = EINVAL; + break; default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_ICMPV6, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_ICMPV6, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; } /* switch (optname) */ break; #endif /* LWIP_IPV6 */ @@ -2194,8 +2196,9 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt } /* If this is no UDP lite socket, ignore any options. */ - if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) + if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { return 0; + } switch (optname) { case UDPLITE_SEND_CSCOV: @@ -2215,16 +2218,17 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt #if LWIP_IPV6 case IPV6_CHECKSUM: /* Per RFC3542, odd offsets are not allowed */ - if ((*(int *)optval > 0) && (*(int *)optval & 1)) - err = EINVAL; - break; + if ((*(int *)optval > 0) && (*(int *)optval & 1)) { + err = EINVAL; + } + break; #endif /* LWIP_IPV6 */ default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", + s, optname)); + err = ENOPROTOOPT; } /* switch (optname) */ - break; + break; /* UNDEFINED LEVEL */ default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", diff --git a/src/core/raw.c b/src/core/raw.c index 90eda30b..a3ee94b9 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -315,12 +315,12 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) } #if LWIP_IPV6 - /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, */ - /* compute the checksum and update the checksum in the payload. */ + /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, + compute the checksum and update the checksum in the payload. */ if (PCB_ISIPV6(pcb) && pcb->chksum_reqd) { - u16_t chksum; - chksum = ip6_chksum_pseudo(q, pcb->protocol, q->tot_len, ipX_2_ip6(src_ip), ipX_2_ip6(dst_ip)); - *(u16_t *)(((u8_t *)q->payload) + pcb->chksum_offset) = chksum; + u16_t chksum; + chksum = ip6_chksum_pseudo(q, pcb->protocol, q->tot_len, ipX_2_ip6(src_ip), ipX_2_ip6(dst_ip)); + *(u16_t *)(((u8_t *)q->payload) + pcb->chksum_offset) = chksum; } #endif diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h index e1412489..9fa8c315 100644 --- a/src/include/lwip/raw.h +++ b/src/include/lwip/raw.h @@ -99,8 +99,8 @@ struct raw_pcb { void *recv_arg; #if LWIP_IPV6 /* fields for handling checksum computations as per RFC3542. */ - u8_t chksum_reqd; u16_t chksum_offset; + u8_t chksum_reqd; #endif }; From 6dcc85dcf4b6f28fe2f528bae12ee7253e9b8440 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 21:08:50 +0100 Subject: [PATCH 11/23] patch #7993: Added support for transmitting packets with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them via hook function LWIP_HOOK_VLAN_CHECK --- CHANGELOG | 5 +++ src/include/lwip/opt.h | 31 +++++++++++++++- src/include/netif/etharp.h | 8 +++- src/netif/etharp.c | 75 +++++++++++++++++++++++++++++++------- 4 files changed, 103 insertions(+), 16 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8d6c2333..8f7b50df 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,11 @@ HISTORY ++ New features: + 2013-04-20: Fatih Asici + * opt.h, etharp.h/.c: patch #7993: Added support for transmitting packets + with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them + via hook function LWIP_HOOK_VLAN_CHECK + 2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko) * patch #7885: modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads) diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 2becda85..5d7ff630 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -496,7 +496,9 @@ #endif /** - * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with + * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and + * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. @@ -1145,7 +1147,11 @@ * Ethernet. */ #ifndef PBUF_LINK_HLEN +#ifdef LWIP_HOOK_VLAN_SET +#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) +#else /* LWIP_HOOK_VLAN_SET */ #define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif /* LWIP_HOOK_VLAN_SET */ #endif /** @@ -2213,6 +2219,29 @@ * that case, ip_route() continues as normal. */ +/** + * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): + * - called from ethernet_input() if VLAN support is enabled + * - netif: struct netif on which the packet has been received + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet must be dropped. + * - != 0: Packet must be accepted. + */ + +/** + * LWIP_HOOK_VLAN_SET(netif, eth_hdr, vlan_hdr): + * - called from etharp_raw() and etharp_send_ip() if VLAN support is enabled + * - netif: struct netif that the packet will be sent through + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet shall not contain VLAN header. + * - != 0: Packet shall contain VLAN header. + * Hook can be used to set prio_vid field of vlan_hdr. + */ + /* --------------------------------------- ---------- Debugging options ---------- diff --git a/src/include/netif/etharp.h b/src/include/netif/etharp.h index 92d57ae4..6ef5ad1b 100644 --- a/src/include/netif/etharp.h +++ b/src/include/netif/etharp.h @@ -129,7 +129,13 @@ PACK_STRUCT_END #endif #define SIZEOF_ETHARP_HDR 28 -#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) + +#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR) +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) +#define SIZEOF_ETHARP_PACKET_TX (SIZEOF_ETHARP_PACKET + SIZEOF_VLAN_HDR) +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ +#define SIZEOF_ETHARP_PACKET_TX SIZEOF_ETHARP_PACKET +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ /** 5 seconds period */ #define ARP_TMR_INTERVAL 5000 diff --git a/src/netif/etharp.c b/src/netif/etharp.c index 1b7eb988..60417474 100644 --- a/src/netif/etharp.c +++ b/src/netif/etharp.c @@ -416,12 +416,28 @@ static err_t etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) { struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + struct eth_vlan_hdr *vlanhdr; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", (netif->hwaddr_len == ETHARP_HWADDR_LEN)); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + ethhdr->type = PP_HTONS(ETHTYPE_VLAN); + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR); + vlanhdr->prio_vid = 0; + vlanhdr->tpid = PP_HTONS(ETHTYPE_IP); + if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) { + /* packet shall not contain VLAN header, so hide it and set correct ethertype */ + pbuf_header(p, -SIZEOF_VLAN_HDR); + ethhdr = (struct eth_hdr *)p->payload; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + ethhdr->type = PP_HTONS(ETHTYPE_IP); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + } +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ ETHADDR32_COPY(ðhdr->dest, dst); ETHADDR16_COPY(ðhdr->src, src); - ethhdr->type = PP_HTONS(ETHTYPE_IP); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); /* send the packet */ return netif->linkoutput(netif, p); @@ -888,7 +904,11 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); /* make room for Ethernet header - should not fail */ +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + if (pbuf_header(q, sizeof(struct eth_hdr) + SIZEOF_VLAN_HDR) != 0) { +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) { +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ /* bail out */ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("etharp_output: could not allocate room for header.\n")); @@ -923,6 +943,9 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) !ip_addr_islinklocal(ipaddr)) { #if LWIP_AUTOIP struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload + +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + SIZEOF_VLAN_HDR + +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ sizeof(struct eth_hdr)); /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with a link-local source address must always be "directly to its destination @@ -1182,6 +1205,9 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, struct pbuf *p; err_t result = ERR_OK; struct eth_hdr *ethhdr; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + struct eth_vlan_hdr *vlanhdr; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ struct etharp_hdr *hdr; #if LWIP_AUTOIP const u8_t * ethdst_hwaddr; @@ -1190,7 +1216,7 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, LWIP_ASSERT("netif != NULL", netif != NULL); /* allocate a pbuf for the outgoing ARP request packet */ - p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM); + p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET_TX, PBUF_RAM); /* could allocate a pbuf for an ARP request? */ if (p == NULL) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, @@ -1199,10 +1225,15 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, return ERR_MEM; } LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", - (p->len >= SIZEOF_ETHARP_PACKET)); + (p->len >= SIZEOF_ETHARP_PACKET_TX)); ethhdr = (struct eth_hdr *)p->payload; +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR); + hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); +#else /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); hdr->opcode = htons(opcode); @@ -1217,13 +1248,6 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, /* Write the ARP MAC-Addresses */ ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); - /* Write the Ethernet MAC-Addresses */ -#if LWIP_AUTOIP - ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); -#else /* LWIP_AUTOIP */ - ETHADDR16_COPY(ðhdr->dest, ethdst_addr); -#endif /* LWIP_AUTOIP */ - ETHADDR16_COPY(ðhdr->src, ethsrc_addr); /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without * structure packing. */ IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); @@ -1235,7 +1259,28 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, hdr->hwlen = ETHARP_HWADDR_LEN; hdr->protolen = sizeof(ip_addr_t); - ethhdr->type = PP_HTONS(ETHTYPE_ARP); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + ethhdr->type = PP_HTONS(ETHTYPE_VLAN); + vlanhdr->tpid = PP_HTONS(ETHTYPE_ARP); + vlanhdr->prio_vid = 0; + if (!LWIP_HOOK_VLAN_SET(netif, ethhdr, vlanhdr)) { + /* packet shall not contain VLAN header, so hide it and set correct ethertype */ + pbuf_header(p, -SIZEOF_VLAN_HDR); + ethhdr = (struct eth_hdr *)p->payload; +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + ethhdr->type = PP_HTONS(ETHTYPE_ARP); +#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) + } +#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ + + /* Write the Ethernet MAC-Addresses */ +#if LWIP_AUTOIP + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); +#else /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->dest, ethdst_addr); +#endif /* LWIP_AUTOIP */ + ETHADDR16_COPY(ðhdr->src, ethsrc_addr); + /* send ARP query */ result = netif->linkoutput(netif, p); ETHARP_STATS_INC(etharp.xmit); @@ -1310,8 +1355,10 @@ ethernet_input(struct pbuf *p, struct netif *netif) ETHARP_STATS_INC(etharp.drop); goto free_and_return; } -#if defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ -#ifdef ETHARP_VLAN_CHECK_FN +#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ +#ifdef LWIP_HOOK_VLAN_CHECK + if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { +#elif defined(ETHARP_VLAN_CHECK_FN) if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { #elif defined(ETHARP_VLAN_CHECK) if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { @@ -1320,7 +1367,7 @@ ethernet_input(struct pbuf *p, struct netif *netif) pbuf_free(p); return ERR_OK; } -#endif /* defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ +#endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ type = vlan->tpid; ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; } From a89db9872dc6851d953e2c1e717f57b3b48270b3 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 21:13:13 +0100 Subject: [PATCH 12/23] Added missing IPPROTO_RAW --- src/include/lwip/sockets.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h index e2a36a46..8bbebb84 100644 --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -192,7 +192,7 @@ struct linger { #define PF_UNSPEC AF_UNSPEC #define IPPROTO_IP 0 -#define IPPROTO_ICMP 1 +#define IPPROTO_ICMP 1 #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 #if LWIP_IPV6 @@ -200,6 +200,7 @@ struct linger { #define IPPROTO_ICMPV6 58 #endif /* LWIP_IPV6 */ #define IPPROTO_UDPLITE 136 +#define IPPROTO_RAW 255 /* Flags we can use with send and recv. */ #define MSG_PEEK 0x01 /* Peeks at an incoming message */ From e432014a8828c0b5bbe775d5b8aa8a75a8a6c05f Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Mon, 10 Feb 2014 13:04:09 +0100 Subject: [PATCH 13/23] netif: Update header file documentation IPv6 output method referenced old method name. --- src/include/lwip/netif.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h index b2c8d87a..35fee3c8 100644 --- a/src/include/lwip/netif.h +++ b/src/include/lwip/netif.h @@ -123,7 +123,7 @@ typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr); #if LWIP_IPV6 /** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet - * shall be sent. For ethernet netif, set this to 'nd_output' and set + * shall be sent. For ethernet netif, set this to 'ethip6_output' and set * 'linkoutput'. * * @param netif The netif which shall send a packet From 7a77917df6d7a5cfc77759f3093a06b8dabeb76f Mon Sep 17 00:00:00 2001 From: Freddie Chopin Date: Sat, 26 Oct 2013 20:15:21 +0200 Subject: [PATCH 14/23] SNMP: use MEMCPY() instead of ocstrncpy() and objectidncpy() Signed-off-by: Freddie Chopin --- src/core/snmp/mib2.c | 60 +++++++++++--------------------------------- 1 file changed, 14 insertions(+), 46 deletions(-) diff --git a/src/core/snmp/mib2.c b/src/core/snmp/mib2.c index fe1bf6d7..c5369509 100644 --- a/src/core/snmp/mib2.c +++ b/src/core/snmp/mib2.c @@ -51,6 +51,8 @@ #include "lwip/sys.h" #include "netif/etharp.h" +#include + /** * IANA assigned enterprise ID for lwIP is 26381 * @see http://www.iana.org/assignments/enterprise-numbers @@ -893,40 +895,6 @@ static u32_t snmpinpkts = 0, snmpouttraps = 0; - -/* prototypes of the following functions are in lwip/src/include/lwip/snmp.h */ -/** - * Copy octet string. - * - * @param dst points to destination - * @param src points to source - * @param n number of octets to copy. - */ -static void ocstrncpy(u8_t *dst, const u8_t *src, u16_t n) -{ - u16_t i = n; - while (i > 0) { - i--; - *dst++ = *src++; - } -} - -/** - * Copy object identifier (s32_t) array. - * - * @param dst points to destination - * @param src points to source - * @param n number of sub identifiers to copy. - */ -void objectidncpy(s32_t *dst, const s32_t *src, u8_t n) -{ - u8_t i = n; - while(i > 0) { - i--; - *dst++ = *src++; - } -} - /** * Initializes sysDescr pointers. * @@ -2204,10 +2172,10 @@ system_get_value(struct obj_def *od, u16_t len, void *value) switch (id) { case 1: /* sysDescr */ - ocstrncpy((u8_t*)value, sysdescr_ptr, len); + MEMCPY(value, sysdescr_ptr, len); break; case 2: /* sysObjectID */ - objectidncpy((s32_t*)value, (s32_t*)sysobjid.id, (u8_t)(len / sizeof(s32_t))); + MEMCPY(value, sysobjid.id, len); break; case 3: /* sysUpTime */ { @@ -2215,13 +2183,13 @@ system_get_value(struct obj_def *od, u16_t len, void *value) } break; case 4: /* sysContact */ - ocstrncpy((u8_t*)value, syscontact_ptr, len); + MEMCPY(value, syscontact_ptr, len); break; case 5: /* sysName */ - ocstrncpy((u8_t*)value, sysname_ptr, len); + MEMCPY(value, sysname_ptr, len); break; case 6: /* sysLocation */ - ocstrncpy((u8_t*)value, syslocation_ptr, len); + MEMCPY(value, syslocation_ptr, len); break; case 7: /* sysServices */ { @@ -2279,15 +2247,15 @@ system_set_value(struct obj_def *od, u16_t len, void *value) switch (id) { case 4: /* sysContact */ - ocstrncpy(syscontact_ptr, (u8_t*)value, len); + MEMCPY(syscontact_ptr, value, len); *syscontact_len_ptr = (u8_t)len; break; case 5: /* sysName */ - ocstrncpy(sysname_ptr, (u8_t*)value, len); + MEMCPY(sysname_ptr, value, len); *sysname_len_ptr = (u8_t)len; break; case 6: /* sysLocation */ - ocstrncpy(syslocation_ptr, (u8_t*)value, len); + MEMCPY(syslocation_ptr, value, len); *syslocation_len_ptr = (u8_t)len; break; }; @@ -2475,7 +2443,7 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value) } break; case 2: /* ifDescr */ - ocstrncpy((u8_t*)value, (u8_t*)netif->name, len); + MEMCPY(value, netif->name, len); break; case 3: /* ifType */ { @@ -2496,7 +2464,7 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value) } break; case 6: /* ifPhysAddress */ - ocstrncpy((u8_t*)value, netif->hwaddr, len); + MEMCPY(value, netif->hwaddr, len); break; case 7: /* ifAdminStatus */ { @@ -2608,7 +2576,7 @@ ifentry_get_value(struct obj_def *od, u16_t len, void *value) } break; case 22: /* ifSpecific */ - objectidncpy((s32_t*)value, (s32_t*)ifspecific.id, (u8_t)(len / sizeof(s32_t))); + MEMCPY(value, ifspecific.id, len); break; }; } @@ -3352,7 +3320,7 @@ ip_rteentry_get_value(struct obj_def *od, u16_t len, void *value) } break; case 13: /* ipRouteInfo */ - objectidncpy((s32_t*)value, (s32_t*)iprouteinfo.id, (u8_t)(len / sizeof(s32_t))); + MEMCPY(value, iprouteinfo.id, len); break; } } From 08b56e8180a1e3f498f76f2c932552dd075c82af Mon Sep 17 00:00:00 2001 From: Freddie Chopin Date: Sat, 26 Oct 2013 22:30:46 +0200 Subject: [PATCH 15/23] SNMP: mib-2.system.sysObjectID is read-only, so make the object "static const" and modify just the pointer; snmp_get_sysobjid_ptr() and snmp_set_sysobjid() take a pointer to "const" object now Signed-off-by: Freddie Chopin --- src/core/snmp/mib2.c | 15 ++++++++------- src/include/lwip/snmp.h | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/core/snmp/mib2.c b/src/core/snmp/mib2.c index c5369509..0c9ba9f2 100644 --- a/src/core/snmp/mib2.c +++ b/src/core/snmp/mib2.c @@ -765,7 +765,8 @@ const struct mib_array_node internet = { #endif /** mib-2.system.sysObjectID */ -static struct snmp_obj_id sysobjid = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; +static const struct snmp_obj_id sysobjid_default = {SNMP_SYSOBJID_LEN, SNMP_SYSOBJID}; +static const struct snmp_obj_id* sysobjid_ptr = &sysobjid_default; /** enterprise ID for generic TRAPs, .iso.org.dod.internet.mgmt.mib-2.snmp */ static struct snmp_obj_id snmpgrp_id = {7,{1,3,6,1,2,1,11}}; /** mib-2.system.sysServices */ @@ -910,9 +911,9 @@ void snmp_set_sysdescr(const u8_t *str, const u8_t *len) } } -void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid) +void snmp_get_sysobjid_ptr(const struct snmp_obj_id **oid) { - *oid = &sysobjid; + *oid = sysobjid_ptr; } /** @@ -920,9 +921,9 @@ void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid) * * @param oid points to stuct snmp_obj_id to copy */ -void snmp_set_sysobjid(struct snmp_obj_id *oid) +void snmp_set_sysobjid(const struct snmp_obj_id *oid) { - sysobjid = *oid; + sysobjid_ptr = oid; } /** @@ -2109,7 +2110,7 @@ system_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) od->instance = MIB_OBJECT_SCALAR; od->access = MIB_OBJECT_READ_ONLY; od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID); - od->v_len = sysobjid.len * sizeof(s32_t); + od->v_len = sysobjid_ptr->len * sizeof(s32_t); break; case 3: /* sysUpTime */ od->instance = MIB_OBJECT_SCALAR; @@ -2175,7 +2176,7 @@ system_get_value(struct obj_def *od, u16_t len, void *value) MEMCPY(value, sysdescr_ptr, len); break; case 2: /* sysObjectID */ - MEMCPY(value, sysobjid.id, len); + MEMCPY(value, sysobjid_ptr->id, len); break; case 3: /* sysUpTime */ { diff --git a/src/include/lwip/snmp.h b/src/include/lwip/snmp.h index 7844cc11..a592e6cb 100644 --- a/src/include/lwip/snmp.h +++ b/src/include/lwip/snmp.h @@ -99,8 +99,8 @@ struct snmp_obj_id /* system */ void snmp_set_sysdescr(const u8_t* str, const u8_t* len); -void snmp_set_sysobjid(struct snmp_obj_id *oid); -void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); +void snmp_set_sysobjid(const struct snmp_obj_id *oid); +void snmp_get_sysobjid_ptr(const struct snmp_obj_id **oid); void snmp_inc_sysuptime(void); void snmp_add_sysuptime(u32_t value); void snmp_get_sysuptime(u32_t *value); From a2d6a50dff4ff7a2ffe634b4f78912c92d4cd9df Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 21:55:11 +0100 Subject: [PATCH 16/23] fixed bug #41499 netconn::recv_avail can overflow --- CHANGELOG | 3 +++ src/api/sockets.c | 4 ++-- src/include/lwip/api.h | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8f7b50df..af7a5bf4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -96,6 +96,9 @@ HISTORY ++ Bugfixes: + 2014-02-20: Simon Goldschmidt + * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow + 2014-01-08: Stathis Voukelatos * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool creation macro diff --git a/src/api/sockets.c b/src/api/sockets.c index 9f6b5277..2fd8847d 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -2521,7 +2521,7 @@ lwip_ioctl(int s, long cmd, void *argp) u8_t val; #if LWIP_SO_RCVBUF u16_t buflen = 0; - s16_t recv_avail; + int recv_avail; #endif /* LWIP_SO_RCVBUF */ if (!sock) { @@ -2565,7 +2565,7 @@ lwip_ioctl(int s, long cmd, void *argp) if (recv_avail < 0) { recv_avail = 0; } - *((u16_t*)argp) = (u16_t)recv_avail; + *((int*)argp) = recv_avail; /* Check if there is data left from the last recv operation. /maq 041215 */ if (sock->lastdata) { diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index ac58eebb..78bf0c52 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -203,7 +203,7 @@ struct netconn { /** number of bytes currently in recvmbox to be received, tested against recv_bufsize to limit bytes on recvmbox for UDP and RAW, used for FIONREAD */ - s16_t recv_avail; + int recv_avail; #endif /* LWIP_SO_RCVBUF */ /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ u8_t flags; From 4d774e275dc3729ae825b647c16ffe7347ef23eb Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 22:01:13 +0100 Subject: [PATCH 17/23] netconn::recv_avail: forgot one line --- src/api/sockets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/sockets.c b/src/api/sockets.c index 2fd8847d..fda702ac 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -2576,7 +2576,7 @@ lwip_ioctl(int s, long cmd, void *argp) buflen = p->tot_len; buflen -= sock->lastoffset; - *((u16_t*)argp) += buflen; + *((int*)argp) += buflen; } LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); From 0f24fba28aa53b46b40dd5d069da072edea5f2af Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 22:07:58 +0100 Subject: [PATCH 18/23] IGMP: fixed !define LWIP_RAND case --- src/core/ipv4/igmp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/ipv4/igmp.c b/src/core/ipv4/igmp.c index 9cb4c0c6..107c0e9a 100644 --- a/src/core/ipv4/igmp.c +++ b/src/core/ipv4/igmp.c @@ -696,12 +696,18 @@ static void igmp_start_timer(struct igmp_group *group, u8_t max_time) { /* ensure the input value is > 0 */ +#ifdef LWIP_RAND if (max_time == 0) { max_time = 1; } -#ifdef LWIP_RAND /* ensure the random value is > 0 */ group->timer = (LWIP_RAND() % max_time); +#else /* LWIP_RAND */ + /* ATTENTION: use this only if absolutely necessary! */ + group->timer = max_time / 2; + if (group->timer == 0) { + group->timer = 1; + } #endif /* LWIP_RAND */ } From a58083b11e87d4a3b8b72ff60602198f048bc8b2 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 22:09:38 +0100 Subject: [PATCH 19/23] Fixed comment on LWIP_HAVE_LOOPIF --- src/include/lwip/opt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 5d7ff630..d8cf3491 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -1270,7 +1270,7 @@ ------------------------------------ */ /** - * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) */ #ifndef LWIP_HAVE_LOOPIF #define LWIP_HAVE_LOOPIF 0 From c1dc1a20d61798615a99065a8359ffc09d5b065a Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 22:14:10 +0100 Subject: [PATCH 20/23] fixed bug #40050 SNMP problem with MIB arrays > 255 --- CHANGELOG | 3 +++ src/core/snmp/mib_structs.c | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index af7a5bf4..2682b9f4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -96,6 +96,9 @@ HISTORY ++ Bugfixes: + 2014-02-20: Simon Goldschmidt + * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255 + 2014-02-20: Simon Goldschmidt * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow diff --git a/src/core/snmp/mib_structs.c b/src/core/snmp/mib_structs.c index 2f185cb4..67c1f941 100644 --- a/src/core/snmp/mib_structs.c +++ b/src/core/snmp/mib_structs.c @@ -737,13 +737,13 @@ snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snm } else { - u8_t j; + u16_t j; struct nse cur_node; LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); /* non-leaf, store right child ptr and id */ LWIP_ASSERT("i < 0xff", i < 0xff); - j = (u8_t)i + 1; + j = i + 1; while ((j < an->maxlength) && (empty_table(an->nptr[j]))) { j++; @@ -781,7 +781,7 @@ snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snm } else { - u8_t j; + u16_t j; /* ident_len == 0, complete with leftmost '.thing' */ j = 0; while ((j < an->maxlength) && empty_table(an->nptr[j])) @@ -980,13 +980,13 @@ snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snm } else { - u8_t j; + u16_t j; struct nse cur_node; LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n")); /* non-leaf, store right child ptr and id */ LWIP_ASSERT("i < 0xff", i < 0xff); - j = (u8_t)i + 1; + j = i + 1; if (j < len) { /* right node is the current external node */ From 515e4b9187d5b40e4e036e7d25e0b7d8f805dd8d Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 22:23:40 +0100 Subject: [PATCH 21/23] fixed bug #39882 No function shall set errno to 0 --- CHANGELOG | 3 +++ src/api/sockets.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 2682b9f4..c42f4602 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -96,6 +96,9 @@ HISTORY ++ Bugfixes: + 2014-02-20: Simon Goldschmidt + * sockets.c: fixed bug #39882 No function shall set errno to 0 + 2014-02-20: Simon Goldschmidt * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255 diff --git a/src/api/sockets.c b/src/api/sockets.c index fda702ac..e77bb8b4 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -225,7 +225,7 @@ static const int err_to_errno_table[] = { #ifdef ERRNO #ifndef set_errno -#define set_errno(err) errno = (err) +#define set_errno(err) do { if (err) { errno = (err); } } while(0) #endif #else /* ERRNO */ #define set_errno(err) From 9572db262cb9ac578b6cf5ee87a0e1e2095f2e61 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 22:32:57 +0100 Subject: [PATCH 22/23] Fixed bug #39718: disconnecting an UDP socket reports an error --- src/api/sockets.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/api/sockets.c b/src/api/sockets.c index e77bb8b4..a298869d 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -550,10 +550,6 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) return -1; } - /* check size, familiy and alignment of 'name' */ - LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); LWIP_UNUSED_ARG(namelen); if (name->sa_family == AF_UNSPEC) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); @@ -561,6 +557,12 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) } else { ipX_addr_t remote_addr; u16_t remote_port; + + /* check size, familiy and alignment of 'name' */ + LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), + sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); + SOCKADDR_TO_IPXADDR_PORT((name->sa_family == AF_INET6), name, &remote_addr, remote_port); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); ipX_addr_debug_print(name->sa_family == AF_INET6, SOCKETS_DEBUG, &remote_addr); From 2225b8add7a0f758236de533a3bcb34de415a625 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Thu, 20 Feb 2014 22:35:37 +0100 Subject: [PATCH 23/23] fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with MEM_ALIGNMENT = 8 --- CHANGELOG | 4 ++++ src/core/tcp_out.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index c42f4602..3191a970 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -96,6 +96,10 @@ HISTORY ++ Bugfixes: + 2014-02-20: Simon Goldschmidt + * tcp_out.c: fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with + MEM_ALIGNMENT = 8 + 2014-02-20: Simon Goldschmidt * sockets.c: fixed bug #39882 No function shall set errno to 0 diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index bc67e09f..6eb2d64f 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -789,7 +789,7 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) TCP_STATS_INC(tcp.memerr); return ERR_MEM; } - LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % 4) == 0); LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,