1 /*
2 * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "porting_net_def.h"
16 #include "lwip/tcpip.h"
17 #include "lwip/etharp.h"
18 #include "lwip/netifapi.h"
19 #include "lwip/sockets.h"
20 #include "lwip/netbuf.h"
21 #include "lwip/api.h"
22 #include "lwip/dns.h"
23 #include "netif/ethernet.h"
24 #include "wifi_host_tx.h"
25 #include "dbg_assert.h"
26 #include "lwiphooks.h"
27 #include "lwip/priv/sockets_priv.h"
28
29 #define NX_NB_L2_FILTER 2
30
31 struct l2_filter_tag
32 {
33 struct netif *net_if;
34 int sock;
35 struct netconn *conn;
36 uint16_t ethertype;
37 };
38
39 static struct l2_filter_tag l2_filter[NX_NB_L2_FILTER];
40 static rtos_semaphore l2_semaphore;
41 static rtos_mutex l2_mutex;
42
43 /*
44 * FUNCTIONS
45 ****************************************************************************************
46 */
47 /// Fake function used to detected too small link encapsulation header length
48 void p_buf_link_encapsulation_hlen_too_small(void);
49
50 /// Declaration of the LwIP checksum computation function
51 u16_t lwip_standard_chksum(const void *dataptr, int len);
52
update_etharp_table(struct netif * netif,const ip4_addr_t * ipaddr)53 void update_etharp_table(struct netif *netif, const ip4_addr_t *ipaddr)
54 {
55
56 }
57 /**
58 ****************************************************************************************
59 * @brief Callback used by the networking stack to push a buffer for transmission by the
60 * WiFi interface.
61 *
62 * @param[in] net_if Pointer to the network interface on which the TX is done
63 * @param[in] p_buf Pointer to the buffer to transmit
64 *
65 * @return ERR_OK upon successful pushing of the buffer, ERR_BUF otherwise
66 ****************************************************************************************
67 */
net_if_output(struct netif * net_if,struct pbuf * p_buf)68 static err_t net_if_output(struct netif *net_if, struct pbuf *p_buf)
69 {
70 err_t status = ERR_BUF;
71
72 // Increase the ref count so that the buffer is not freed by the networking stack
73 // until it is actually sent over the WiFi interface
74 pbuf_ref(p_buf);
75
76 // Push the buffer and verify the status
77 if (netif_is_up(net_if) && fhost_tx_start(net_if->state, p_buf, NULL, NULL) == 0)
78 {
79 status = ERR_OK;
80 }
81 else
82 {
83 // Failed to push message to TX task, call pbuf_free only to decrease ref count
84 pbuf_free(p_buf);
85 }
86
87 return (status);
88 }
89
90 /**
91 ****************************************************************************************
92 * @brief Callback used by the networking stack to setup the network interface.
93 * This function should be passed as a parameter to netifapi_netif_add().
94 *
95 * @param[in] net_if Pointer to the network interface to setup
96 * @param[in] p_buf Pointer to the buffer to transmit
97 *
98 * @return ERR_OK upon successful setup of the interface, other status otherwise
99 ****************************************************************************************
100 */
101
net_if_init(struct netif * net_if)102 static err_t net_if_init(struct netif *net_if)
103 {
104 err_t status = ERR_OK;
105 static uint8_t net_num = 1;
106 struct fhost_vif_tag *vif = (struct fhost_vif_tag *)net_if->state;
107
108 #if LWIP_NETIF_HOSTNAME
109 {
110 /* Initialize interface hostname */
111 net_if->hostname = "CsWlan";
112 }
113 #endif /* LWIP_NETIF_HOSTNAME */
114
115 net_if->name[ 0 ] = 'w';
116 net_if->name[ 1 ] = 'l';
117 net_if->full_name[0] = 'w';
118 net_if->full_name[1] = 'l';
119 net_if->full_name[2] = '0' + net_num++;
120 net_if->full_name[3] = '\0';
121
122 net_if->output = etharp_output;
123 net_if->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_IGMP;
124 net_if->hwaddr_len = ETHARP_HWADDR_LEN;
125 net_if->mtu = LLC_ETHER_MTU;
126 net_if->linkoutput = net_if_output;
127 memcpy(net_if->hwaddr, &vif->mac_addr, ETHARP_HWADDR_LEN);
128
129 return status;
130 }
131
net_ip_chksum(const void * dataptr,int len)132 uint16_t net_ip_chksum(const void *dataptr, int len)
133 {
134 // Simply call the LwIP function
135 return lwip_standard_chksum(dataptr, len);
136 }
137
net_if_add(net_if_t * net_if,const uint32_t * ipaddr,const uint32_t * netmask,const uint32_t * gw,struct fhost_vif_tag * vif)138 int net_if_add(net_if_t *net_if,
139 const uint32_t *ipaddr,
140 const uint32_t *netmask,
141 const uint32_t *gw,
142 struct fhost_vif_tag *vif)
143 {
144 err_t status;
145
146 status = netifapi_netif_add(net_if,
147 (const ip4_addr_t *)ipaddr,
148 (const ip4_addr_t *)netmask,
149 (const ip4_addr_t *)gw,
150 vif,
151 net_if_init,
152 tcpip_input);
153
154 return (status == ERR_OK ? 0 : -1);
155 }
156
net_if_get_mac_addr(net_if_t * net_if)157 const uint8_t *net_if_get_mac_addr(net_if_t *net_if)
158 {
159 return net_if->hwaddr;
160 }
161
net_if_find_from_name(const char * name)162 net_if_t *net_if_find_from_name(const char *name)
163 {
164 return netif_find(name);
165 }
166
net_if_find_from_wifi_idx(unsigned int idx)167 net_if_t *net_if_find_from_wifi_idx(unsigned int idx)
168 {
169 if ((idx >= NX_VIRT_DEV_MAX) || (fhost_env.vif[idx].mac_vif == NULL))
170 return NULL;
171
172
173 if (fhost_env.vif[idx].mac_vif->type != VIF_UNKNOWN)
174 {
175 return &fhost_env.vif[idx].net_if;
176 }
177
178 return NULL;
179 }
180
net_if_get_name(net_if_t * net_if,char * buf,int len)181 int net_if_get_name(net_if_t *net_if, char *buf, int len)
182 {
183 if (len > 0)
184 buf[0] = net_if->name[0];
185 if (len > 1)
186 buf[1] = net_if->name[1];
187 if (len > 2)
188 buf[2] = net_if->num + '0';
189 if ( len > 3)
190 buf[3] = '\0';
191
192 return 3;
193 }
194
net_if_get_wifi_idx(net_if_t * net_if)195 int net_if_get_wifi_idx(net_if_t *net_if)
196 {
197 struct fhost_vif_tag *vif;
198 int idx;
199
200 if (!net_if)
201 return -1;
202
203 vif = (struct fhost_vif_tag *)net_if;
204 idx = CO_GET_INDEX(vif, fhost_env.vif);
205
206 /* sanity check */
207 if (&fhost_env.vif[idx].net_if == net_if)
208 return idx;
209
210 return -1;
211 }
212
net_if_up(net_if_t * net_if)213 void net_if_up(net_if_t *net_if)
214 {
215 netifapi_netif_set_up(net_if);
216 }
217
net_if_down(net_if_t * net_if)218 void net_if_down(net_if_t *net_if)
219 {
220 netifapi_netif_set_down(net_if);
221 }
222
net_if_set_default(net_if_t * net_if)223 void net_if_set_default(net_if_t *net_if)
224 {
225 netifapi_netif_set_default(net_if);
226 }
227
net_if_set_ip(net_if_t * net_if,uint32_t ip,uint32_t mask,uint32_t gw)228 void net_if_set_ip(net_if_t *net_if, uint32_t ip, uint32_t mask, uint32_t gw)
229 {
230 if (!net_if)
231 return;
232 netif_set_addr(net_if, (const ip4_addr_t *)&ip, (const ip4_addr_t *)&mask,
233 (const ip4_addr_t *)&gw);
234 }
235
net_if_get_ip(net_if_t * net_if,uint32_t * ip,uint32_t * mask,uint32_t * gw)236 int net_if_get_ip(net_if_t *net_if, uint32_t *ip, uint32_t *mask, uint32_t *gw)
237 {
238 if (!net_if)
239 return -1;
240
241 if (ip)
242 *ip = netif_ip4_addr(net_if)->addr;
243 if (mask)
244 *mask = netif_ip4_netmask(net_if)->addr;
245 if (gw)
246 *gw = netif_ip4_gw(net_if)->addr;
247
248 return 0;
249 }
250
net_if_input(net_buf_rx_t * buf,net_if_t * net_if,void * addr,uint16_t len,net_buf_free_fn free_fn)251 int net_if_input(net_buf_rx_t *buf, net_if_t *net_if, void *addr, uint16_t len, net_buf_free_fn free_fn)
252 {
253 struct pbuf* p;
254
255 buf->custom_free_function = (pbuf_free_custom_fn)free_fn;
256 p = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, buf, addr, len);
257 ASSERT_ERR(p != NULL);
258
259 if (net_if->input(p, net_if))
260 {
261 free_fn(buf);
262 return -1;
263 }
264
265 return 0;
266 }
267
net_if_vif_info(net_if_t * net_if)268 struct fhost_vif_tag *net_if_vif_info(net_if_t *net_if)
269 {
270 return ((struct fhost_vif_tag *)net_if->state);
271 }
272
net_buf_tx_alloc(const uint8_t * payload,uint32_t length)273 net_buf_tx_t *net_buf_tx_alloc(const uint8_t *payload, uint32_t length)
274 {
275 struct pbuf *pbuf;
276
277 pbuf = pbuf_alloc(PBUF_RAW_TX, length, PBUF_RAM);
278 if (pbuf == NULL)
279 return NULL;
280
281 memcpy(pbuf->payload, payload, length);
282 return pbuf;
283 }
284
net_buf_tx_info(net_buf_tx_t * buf,uint16_t * tot_len,uint8_t * seg_cnt)285 void net_buf_tx_info(net_buf_tx_t *buf, uint16_t *tot_len, uint8_t *seg_cnt)
286 {
287 uint8_t idx;
288 uint16_t length = buf->tot_len;
289
290 *tot_len = length;
291
292 idx = 0;
293 while (length && buf)
294 {
295 // Sanity check - the payload shall be in shared RAM
296 //ASSERT_ERR(!TST_SHRAM_PTR(buf->payload));
297
298 length -= buf->len;
299 idx++;
300 // Get info of extra segments if any
301 buf = buf->next;
302 }
303
304 *seg_cnt = idx;
305 if (length != 0)
306 {
307 // The complete buffer must be included in all the segments
308 ASSERT_ERR(0);
309 }
310 }
311
net_buf_tx_free(net_buf_tx_t * buf)312 void net_buf_tx_free(net_buf_tx_t *buf)
313 {
314 // Free the buffer
315 pbuf_free(buf);
316 }
317
net_init(void)318 int net_init(void)
319 {
320 int i;
321
322 for (i = 0; i < NX_NB_L2_FILTER; i++)
323 {
324 l2_filter[i].net_if = NULL;
325 }
326
327 if (rtos_semaphore_create(&l2_semaphore, 1, 0))
328 {
329 ASSERT_ERR(0);
330 }
331
332 if (rtos_mutex_create(&l2_mutex))
333 {
334 ASSERT_ERR(0);
335 }
336
337 // Initialize the TCP/IP stack
338 tcpip_init(NULL, NULL);
339
340 #ifdef DSOFTBUS_ENABLED
341 ipc_host_cntrl_start();
342 #endif
343
344 return 0;
345 }
346
net_l2_send_cfm(uint32_t frame_id,bool acknowledged,void * arg)347 static void net_l2_send_cfm(uint32_t frame_id, bool acknowledged, void *arg)
348 {
349 if (arg)
350 *((bool *)arg) = acknowledged;
351 rtos_semaphore_signal(l2_semaphore, false);
352 }
353
net_l2_send(net_if_t * net_if,const uint8_t * data,int data_len,uint16_t ethertype,const uint8_t * dst_addr,bool * ack)354 int net_l2_send(net_if_t *net_if, const uint8_t *data, int data_len, uint16_t ethertype,
355 const uint8_t *dst_addr, bool *ack)
356 {
357 struct pbuf *pbuf;
358 int res;
359
360 if (net_if == NULL || data == NULL || data_len >= net_if->mtu || !netif_is_up(net_if))
361 return -1;
362
363 pbuf = pbuf_alloc(PBUF_LINK, data_len, PBUF_RAM);
364 if (pbuf == NULL)
365 return -1;
366
367 memcpy(pbuf->payload, data, data_len);
368
369 if (dst_addr)
370 {
371 // Need to add ethernet header as fhost_tx_start is called directly
372 struct eth_hdr* ethhdr;
373 if (pbuf_header(pbuf, SIZEOF_ETH_HDR))
374 {
375 pbuf_free(pbuf);
376 return -1;
377 }
378 ethhdr = (struct eth_hdr*)pbuf->payload;
379 ethhdr->type = htons(ethertype);
380 memcpy(ðhdr->dest, dst_addr, sizeof(struct eth_addr));
381 memcpy(ðhdr->src, net_if->hwaddr, sizeof(struct eth_addr));
382 }
383
384 // Ensure no other thread will program a L2 transmission while this one is waiting
385 // for its confirmation
386 rtos_mutex_lock(l2_mutex, -1);
387
388 // In order to implement this function as blocking until the completion of the frame
389 // transmission, directly call fhost_tx_start with a confirmation callback.
390 res = fhost_tx_start(net_if->state, pbuf, net_l2_send_cfm, ack);
391
392 // Wait for the transmission completion
393 rtos_semaphore_wait(l2_semaphore, -1);
394
395 // Now new L2 transmissions are possible
396 rtos_mutex_unlock(l2_mutex);
397
398 return res;
399 }
400
net_l2_socket_create(net_if_t * net_if,uint16_t ethertype)401 int net_l2_socket_create(net_if_t *net_if, uint16_t ethertype)
402 {
403 struct l2_filter_tag *filter = NULL;
404 socklen_t len = sizeof(filter->conn);
405 int i;
406
407 /* First find free filter and check that socket for this ethertype/net_if couple
408 doesn't already exists */
409 for (i = 0; i < NX_NB_L2_FILTER; i++)
410 {
411 if ((l2_filter[i].net_if == net_if) &&
412 (l2_filter[i].ethertype == ethertype))
413 {
414 return -1;
415 }
416 else if ((filter == NULL) && (l2_filter[i].net_if == NULL))
417 {
418 filter = &l2_filter[i];
419 }
420 }
421
422 if (!filter)
423 return -1;
424
425 /* Note: we create DGRAM socket here but in practice we don't care, net_eth_receive
426 will use the socket as a L2 raw socket */
427 filter->sock = socket(PF_INET, SOCK_DGRAM, 0);
428 if (filter->sock < 0) {
429 return -1;
430 }
431
432
433 if (getsockopt(filter->sock, SOL_SOCKET, SO_CONNINFO, &(filter->conn), &len))
434 {
435 close(filter->sock);
436 return -1;
437 }
438
439 filter->net_if = net_if;
440 filter->ethertype = ethertype;
441
442 return filter->sock;
443 }
444
net_l2_socket_delete(int sock)445 int net_l2_socket_delete(int sock)
446 {
447 int i;
448 for (i = 0; i < NX_NB_L2_FILTER; i++)
449 {
450 if ((l2_filter[i].net_if != NULL) &&
451 (l2_filter[i].sock == sock))
452 {
453 l2_filter[i].net_if = NULL;
454 close(l2_filter[i].sock);
455 l2_filter[i].sock = -1;
456 return 0;
457 }
458 }
459
460 return -1;
461 }
462
net_eth_receive(struct pbuf * pbuf,struct netif * netif)463 err_t net_eth_receive(struct pbuf *pbuf, struct netif *netif)
464 {
465 struct l2_filter_tag *filter = NULL;
466 struct eth_hdr* ethhdr = pbuf->payload;
467 uint16_t ethertype = ntohs(ethhdr->type);
468 struct netconn *conn;
469 struct netbuf *buf;
470 int i;
471
472 for (i = 0; i < NX_NB_L2_FILTER; i++)
473 {
474 if ((l2_filter[i].net_if == netif) &&
475 (l2_filter[i].ethertype == ethertype))
476 {
477 filter = &l2_filter[i];
478 break;
479 }
480 }
481
482 if (!filter)
483 return ERR_VAL;
484
485
486 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
487 if (buf == NULL)
488 {
489 return ERR_MEM;
490 }
491
492 buf->p = pbuf;
493 buf->ptr = pbuf;
494 conn = filter->conn;
495
496 int ret = sys_mbox_trypost(&conn->recvmbox, buf);
497 if (ret != ERR_OK)
498 {
499 netbuf_delete(buf);
500 return ERR_OK;
501 }
502 else
503 {
504 #if LWIP_SO_RCVBUF
505 SYS_ARCH_INC(conn->recv_avail, pbuf->tot_len);
506 #endif /* LWIP_SO_RCVBUF */
507 /* Register event with callback */
508 API_EVENT(conn, NETCONN_EVT_RCVPLUS, pbuf->tot_len);
509 }
510
511 return ERR_OK;
512 }
513
514 static int net_dhcp_started = 0;
net_dhcp_start(net_if_t * net_if)515 int net_dhcp_start(net_if_t *net_if)
516 {
517 #if LWIP_IPV4 && LWIP_DHCP
518 if (netifapi_dhcp_start(net_if) == ERR_OK) {
519 net_dhcp_started = 1;
520 return 0;
521 }
522 #endif //LWIP_IPV4 && LWIP_DHCP
523 return -1;
524 }
525
net_dhcp_stop(net_if_t * net_if)526 void net_dhcp_stop(net_if_t *net_if)
527 {
528 #if LWIP_IPV4 && LWIP_DHCP
529 netifapi_dhcp_stop(net_if);
530 net_dhcp_started = 0;
531 #endif //LWIP_IPV4 && LWIP_DHCP
532 }
533
net_dhcp_start_status(void)534 int net_dhcp_start_status(void)
535 {
536 return net_dhcp_started;
537 }
538
net_dhcp_release(net_if_t * net_if)539 int net_dhcp_release(net_if_t *net_if)
540 {
541 #if LWIP_IPV4 && LWIP_DHCP
542 if (netifapi_dhcp_release(net_if) == ERR_OK)
543 return 0;
544 #endif //LWIP_IPV4 && LWIP_DHCP
545 return -1;
546 }
547
net_dhcp_address_obtained(net_if_t * net_if)548 int net_dhcp_address_obtained(net_if_t *net_if)
549 {
550 #if LWIP_IPV4 && LWIP_DHCP
551 if (dhcp_supplied_address(net_if))
552 return 0;
553 #endif //LWIP_IPV4 && LWIP_DHCP
554 return -1;
555 }
556
net_set_dns(uint32_t dns_server)557 int net_set_dns(uint32_t dns_server)
558 {
559 #if LWIP_DNS
560 ip_addr_t ip;
561 ip_addr_set_ip4_u32(&ip, dns_server);
562 dns_setserver(0, &ip);
563 return 0;
564 #else
565 return -1;
566 #endif
567 }
568
net_get_dns(uint32_t * dns_server)569 int net_get_dns(uint32_t *dns_server)
570 {
571 #if LWIP_DNS
572 const ip_addr_t *ip;
573
574 if (dns_server == NULL)
575 return -1;
576
577 ip = dns_getserver(0);
578 *dns_server = ip_addr_get_ip4_u32(ip);
579 return 0;
580 #else
581 return -1;
582 #endif
583 }
584
lwip_sockopt_hook(int s,struct lwip_sock * sock,int level,int optname,void * optval,uint32_t * optlen,int * err)585 int lwip_sockopt_hook(int s, struct lwip_sock *sock, int level, int optname, void *optval, uint32_t *optlen, int *err)
586 {
587 if (level == SOL_SOCKET && optname == SO_CONNINFO) {
588 if ((sock->conn == NULL) || (*optlen < sizeof(void *))) {
589 return EINVAL;
590 }
591 *(void **)optval = sock->conn;
592 }
593 *err = 0;
594 }
595
596