00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "lwip/opt.h"
00040
00041 #include "lwip/def.h"
00042 #include "lwip/ip_addr.h"
00043 #include "lwip/netif.h"
00044 #include "lwip/tcp_impl.h"
00045 #include "lwip/snmp.h"
00046 #include "lwip/igmp.h"
00047 #include "netif/etharp.h"
00048 #include "lwip/stats.h"
00049 #if ENABLE_LOOPBACK
00050 #include "lwip/sys.h"
00051 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
00052 #include "lwip/tcpip.h"
00053 #endif
00054 #endif
00055
00056 #if LWIP_AUTOIP
00057 #include "lwip/autoip.h"
00058 #endif
00059 #if LWIP_DHCP
00060 #include "lwip/dhcp.h"
00061 #endif
00062
00063 #if LWIP_NETIF_STATUS_CALLBACK
00064 #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
00065 #else
00066 #define NETIF_STATUS_CALLBACK(n)
00067 #endif
00068
00069 #if LWIP_NETIF_LINK_CALLBACK
00070 #define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0)
00071 #else
00072 #define NETIF_LINK_CALLBACK(n)
00073 #endif
00074
00075 struct netif *netif_list;
00076 struct netif *netif_default;
00077
00078 static u8_t netif_num;
00079
00080 #if LWIP_HAVE_LOOPIF
00081 static struct netif loop_netif;
00082
00083
00084
00085
00086
00087
00088
00089
00090 static err_t
00091 netif_loopif_init(struct netif *netif)
00092 {
00093
00094
00095
00096 NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0);
00097
00098 netif->name[0] = 'l';
00099 netif->name[1] = 'o';
00100 netif->output = netif_loop_output;
00101 return ERR_OK;
00102 }
00103 #endif
00104
00105 void
00106 netif_init(void)
00107 {
00108 #if LWIP_HAVE_LOOPIF
00109 ip_addr_t loop_ipaddr, loop_netmask, loop_gw;
00110 IP4_ADDR(&loop_gw, 127,0,0,1);
00111 IP4_ADDR(&loop_ipaddr, 127,0,0,1);
00112 IP4_ADDR(&loop_netmask, 255,0,0,0);
00113
00114 #if NO_SYS
00115 netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input);
00116 #else
00117 netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input);
00118 #endif
00119 netif_set_up(&loop_netif);
00120
00121 #endif
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 struct netif *
00139 netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
00140 ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
00141 {
00142
00143 LWIP_ASSERT("No init function given", init != NULL);
00144
00145
00146 ip_addr_set_zero(&netif->ip_addr);
00147 ip_addr_set_zero(&netif->netmask);
00148 ip_addr_set_zero(&netif->gw);
00149 netif->flags = 0;
00150 #if LWIP_DHCP
00151
00152 netif->dhcp = NULL;
00153 #endif
00154 #if LWIP_AUTOIP
00155
00156 netif->autoip = NULL;
00157 #endif
00158 #if LWIP_NETIF_STATUS_CALLBACK
00159 netif->status_callback = NULL;
00160 #endif
00161 #if LWIP_NETIF_LINK_CALLBACK
00162 netif->link_callback = NULL;
00163 #endif
00164 #if LWIP_IGMP
00165 netif->igmp_mac_filter = NULL;
00166 #endif
00167 #if ENABLE_LOOPBACK
00168 netif->loop_first = NULL;
00169 netif->loop_last = NULL;
00170 #endif
00171
00172
00173 netif->state = state;
00174 netif->num = netif_num++;
00175 netif->input = input;
00176 NETIF_SET_HWADDRHINT(netif, NULL);
00177 #if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
00178 netif->loop_cnt_current = 0;
00179 #endif
00180
00181 netif_set_addr(netif, ipaddr, netmask, gw);
00182
00183
00184 if (init(netif) != ERR_OK) {
00185 return NULL;
00186 }
00187
00188
00189 netif->next = netif_list;
00190 netif_list = netif;
00191 snmp_inc_iflist();
00192
00193 #if LWIP_IGMP
00194
00195 if (netif->flags & NETIF_FLAG_IGMP) {
00196 igmp_start(netif);
00197 }
00198 #endif
00199
00200 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
00201 netif->name[0], netif->name[1]));
00202 ip_addr_debug_print(NETIF_DEBUG, ipaddr);
00203 LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
00204 ip_addr_debug_print(NETIF_DEBUG, netmask);
00205 LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
00206 ip_addr_debug_print(NETIF_DEBUG, gw);
00207 LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
00208 return netif;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 void
00221 netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
00222 ip_addr_t *gw)
00223 {
00224 netif_set_ipaddr(netif, ipaddr);
00225 netif_set_netmask(netif, netmask);
00226 netif_set_gw(netif, gw);
00227 }
00228
00229
00230
00231
00232
00233
00234 void
00235 netif_remove(struct netif *netif)
00236 {
00237 if (netif == NULL) {
00238 return;
00239 }
00240
00241 #if LWIP_IGMP
00242
00243 if (netif->flags & NETIF_FLAG_IGMP) {
00244 igmp_stop(netif);
00245 }
00246 #endif
00247 if (netif_is_up(netif)) {
00248
00249 netif_set_down(netif);
00250 }
00251
00252 snmp_delete_ipaddridx_tree(netif);
00253
00254
00255 if (netif_list == netif) {
00256 netif_list = netif->next;
00257 } else {
00258
00259 struct netif * tmpNetif;
00260 for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {
00261 if (tmpNetif->next == netif) {
00262 tmpNetif->next = netif->next;
00263 break;
00264 }
00265 }
00266 if (tmpNetif == NULL)
00267 return;
00268 }
00269 snmp_dec_iflist();
00270
00271 if (netif_default == netif) {
00272
00273 netif_set_default(NULL);
00274 }
00275 #if LWIP_NETIF_REMOVE_CALLBACK
00276 if (netif->remove_callback) {
00277 netif->remove_callback(netif);
00278 }
00279 #endif
00280 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
00281 }
00282
00283
00284
00285
00286
00287
00288
00289 struct netif *
00290 netif_find(char *name)
00291 {
00292 struct netif *netif;
00293 u8_t num;
00294
00295 if (name == NULL) {
00296 return NULL;
00297 }
00298
00299 num = name[2] - '0';
00300
00301 for(netif = netif_list; netif != NULL; netif = netif->next) {
00302 if (num == netif->num &&
00303 name[0] == netif->name[0] &&
00304 name[1] == netif->name[1]) {
00305 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
00306 return netif;
00307 }
00308 }
00309 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
00310 return NULL;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 void
00323 netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
00324 {
00325
00326
00327 #if LWIP_TCP
00328 struct tcp_pcb *pcb;
00329 struct tcp_pcb_listen *lpcb;
00330
00331
00332 if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) {
00333
00334 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
00335 pcb = tcp_active_pcbs;
00336 while (pcb != NULL) {
00337
00338 if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))
00339 #if LWIP_AUTOIP
00340
00341 && !ip_addr_islinklocal(&(pcb->local_ip))
00342 #endif
00343 ) {
00344
00345 struct tcp_pcb *next = pcb->next;
00346 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
00347 tcp_abort(pcb);
00348 pcb = next;
00349 } else {
00350 pcb = pcb->next;
00351 }
00352 }
00353 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
00354
00355 if ((!(ip_addr_isany(&(lpcb->local_ip)))) &&
00356 (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) {
00357
00358
00359 ip_addr_set(&(lpcb->local_ip), ipaddr);
00360 }
00361 }
00362 }
00363 #endif
00364 snmp_delete_ipaddridx_tree(netif);
00365 snmp_delete_iprteidx_tree(0,netif);
00366
00367 ip_addr_set(&(netif->ip_addr), ipaddr);
00368 snmp_insert_ipaddridx_tree(netif);
00369 snmp_insert_iprteidx_tree(0,netif);
00370
00371 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00372 netif->name[0], netif->name[1],
00373 ip4_addr1_16(&netif->ip_addr),
00374 ip4_addr2_16(&netif->ip_addr),
00375 ip4_addr3_16(&netif->ip_addr),
00376 ip4_addr4_16(&netif->ip_addr)));
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 void
00388 netif_set_gw(struct netif *netif, ip_addr_t *gw)
00389 {
00390 ip_addr_set(&(netif->gw), gw);
00391 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00392 netif->name[0], netif->name[1],
00393 ip4_addr1_16(&netif->gw),
00394 ip4_addr2_16(&netif->gw),
00395 ip4_addr3_16(&netif->gw),
00396 ip4_addr4_16(&netif->gw)));
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 void
00409 netif_set_netmask(struct netif *netif, ip_addr_t *netmask)
00410 {
00411 snmp_delete_iprteidx_tree(0, netif);
00412
00413 ip_addr_set(&(netif->netmask), netmask);
00414 snmp_insert_iprteidx_tree(0, netif);
00415 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00416 netif->name[0], netif->name[1],
00417 ip4_addr1_16(&netif->netmask),
00418 ip4_addr2_16(&netif->netmask),
00419 ip4_addr3_16(&netif->netmask),
00420 ip4_addr4_16(&netif->netmask)));
00421 }
00422
00423
00424
00425
00426
00427
00428
00429 void
00430 netif_set_default(struct netif *netif)
00431 {
00432 if (netif == NULL) {
00433
00434 snmp_delete_iprteidx_tree(1, netif);
00435 } else {
00436
00437 snmp_insert_iprteidx_tree(1, netif);
00438 }
00439 netif_default = netif;
00440 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
00441 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 void netif_set_up(struct netif *netif)
00454 {
00455 if (!(netif->flags & NETIF_FLAG_UP)) {
00456 netif->flags |= NETIF_FLAG_UP;
00457
00458 #if LWIP_SNMP
00459 snmp_get_sysuptime(&netif->ts);
00460 #endif
00461
00462 NETIF_STATUS_CALLBACK(netif);
00463
00464 if (netif->flags & NETIF_FLAG_LINK_UP) {
00465 #if LWIP_ARP
00466
00467 if (netif->flags & (NETIF_FLAG_ETHARP)) {
00468 etharp_gratuitous(netif);
00469 }
00470 #endif
00471
00472 #if LWIP_IGMP
00473
00474 if (netif->flags & NETIF_FLAG_IGMP) {
00475 igmp_report_groups( netif);
00476 }
00477 #endif
00478 }
00479 }
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 void netif_set_down(struct netif *netif)
00491 {
00492 if (netif->flags & NETIF_FLAG_UP) {
00493 netif->flags &= ~NETIF_FLAG_UP;
00494 #if LWIP_SNMP
00495 snmp_get_sysuptime(&netif->ts);
00496 #endif
00497
00498 #if LWIP_ARP
00499 if (netif->flags & NETIF_FLAG_ETHARP) {
00500 etharp_cleanup_netif(netif);
00501 }
00502 #endif
00503 NETIF_STATUS_CALLBACK(netif);
00504 }
00505 }
00506
00507 #if LWIP_NETIF_STATUS_CALLBACK
00508
00509
00510
00511 void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
00512 {
00513 if (netif) {
00514 netif->status_callback = status_callback;
00515 }
00516 }
00517 #endif
00518
00519 #if LWIP_NETIF_REMOVE_CALLBACK
00520
00521
00522
00523 void
00524 netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback)
00525 {
00526 if (netif) {
00527 netif->remove_callback = remove_callback;
00528 }
00529 }
00530 #endif
00531
00532
00533
00534
00535 void netif_set_link_up(struct netif *netif )
00536 {
00537 if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
00538 netif->flags |= NETIF_FLAG_LINK_UP;
00539
00540 #if LWIP_DHCP
00541 if (netif->dhcp) {
00542 dhcp_network_changed(netif);
00543 }
00544 #endif
00545
00546 #if LWIP_AUTOIP
00547 if (netif->autoip) {
00548 autoip_network_changed(netif);
00549 }
00550 #endif
00551
00552 if (netif->flags & NETIF_FLAG_UP) {
00553 #if LWIP_ARP
00554
00555 if (netif->flags & NETIF_FLAG_ETHARP) {
00556 etharp_gratuitous(netif);
00557 }
00558 #endif
00559
00560 #if LWIP_IGMP
00561
00562 if (netif->flags & NETIF_FLAG_IGMP) {
00563 igmp_report_groups( netif);
00564 }
00565 #endif
00566 }
00567 NETIF_LINK_CALLBACK(netif);
00568 }
00569 }
00570
00571
00572
00573
00574 void netif_set_link_down(struct netif *netif )
00575 {
00576 if (netif->flags & NETIF_FLAG_LINK_UP) {
00577 netif->flags &= ~NETIF_FLAG_LINK_UP;
00578 NETIF_LINK_CALLBACK(netif);
00579 }
00580 }
00581
00582 #if LWIP_NETIF_LINK_CALLBACK
00583
00584
00585
00586 void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
00587 {
00588 if (netif) {
00589 netif->link_callback = link_callback;
00590 }
00591 }
00592 #endif
00593
00594 #if ENABLE_LOOPBACK
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 err_t
00610 netif_loop_output(struct netif *netif, struct pbuf *p,
00611 ip_addr_t *ipaddr)
00612 {
00613 struct pbuf *r;
00614 err_t err;
00615 struct pbuf *last;
00616 #if LWIP_LOOPBACK_MAX_PBUFS
00617 u8_t clen = 0;
00618 #endif
00619
00620
00621 #if LWIP_SNMP
00622 #if LWIP_HAVE_LOOPIF
00623 struct netif *stats_if = &loop_netif;
00624 #else
00625 struct netif *stats_if = netif;
00626 #endif
00627 #endif
00628 SYS_ARCH_DECL_PROTECT(lev);
00629 LWIP_UNUSED_ARG(ipaddr);
00630
00631
00632 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
00633 if (r == NULL) {
00634 LINK_STATS_INC(link.memerr);
00635 LINK_STATS_INC(link.drop);
00636 snmp_inc_ifoutdiscards(stats_if);
00637 return ERR_MEM;
00638 }
00639 #if LWIP_LOOPBACK_MAX_PBUFS
00640 clen = pbuf_clen(r);
00641
00642 if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
00643 ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
00644 pbuf_free(r);
00645 LINK_STATS_INC(link.memerr);
00646 LINK_STATS_INC(link.drop);
00647 snmp_inc_ifoutdiscards(stats_if);
00648 return ERR_MEM;
00649 }
00650 netif->loop_cnt_current += clen;
00651 #endif
00652
00653
00654 if ((err = pbuf_copy(r, p)) != ERR_OK) {
00655 pbuf_free(r);
00656 LINK_STATS_INC(link.memerr);
00657 LINK_STATS_INC(link.drop);
00658 snmp_inc_ifoutdiscards(stats_if);
00659 return err;
00660 }
00661
00662
00663
00664
00665
00666 for (last = r; last->next != NULL; last = last->next);
00667
00668 SYS_ARCH_PROTECT(lev);
00669 if(netif->loop_first != NULL) {
00670 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
00671 netif->loop_last->next = r;
00672 netif->loop_last = last;
00673 } else {
00674 netif->loop_first = r;
00675 netif->loop_last = last;
00676 }
00677 SYS_ARCH_UNPROTECT(lev);
00678
00679 LINK_STATS_INC(link.xmit);
00680 snmp_add_ifoutoctets(stats_if, p->tot_len);
00681 snmp_inc_ifoutucastpkts(stats_if);
00682
00683 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
00684
00685 tcpip_callback((tcpip_callback_fn)netif_poll, netif);
00686 #endif
00687
00688 return ERR_OK;
00689 }
00690
00691
00692
00693
00694
00695
00696
00697 void
00698 netif_poll(struct netif *netif)
00699 {
00700 struct pbuf *in;
00701
00702
00703 #if LWIP_SNMP
00704 #if LWIP_HAVE_LOOPIF
00705 struct netif *stats_if = &loop_netif;
00706 #else
00707 struct netif *stats_if = netif;
00708 #endif
00709 #endif
00710 SYS_ARCH_DECL_PROTECT(lev);
00711
00712 do {
00713
00714 SYS_ARCH_PROTECT(lev);
00715 in = netif->loop_first;
00716 if (in != NULL) {
00717 struct pbuf *in_end = in;
00718 #if LWIP_LOOPBACK_MAX_PBUFS
00719 u8_t clen = pbuf_clen(in);
00720
00721 LWIP_ASSERT("netif->loop_cnt_current underflow",
00722 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
00723 netif->loop_cnt_current -= clen;
00724 #endif
00725 while (in_end->len != in_end->tot_len) {
00726 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
00727 in_end = in_end->next;
00728 }
00729
00730 if (in_end == netif->loop_last) {
00731
00732 netif->loop_first = netif->loop_last = NULL;
00733 } else {
00734
00735 netif->loop_first = in_end->next;
00736 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
00737 }
00738
00739 in_end->next = NULL;
00740 }
00741 SYS_ARCH_UNPROTECT(lev);
00742
00743 if (in != NULL) {
00744 LINK_STATS_INC(link.recv);
00745 snmp_add_ifinoctets(stats_if, in->tot_len);
00746 snmp_inc_ifinucastpkts(stats_if);
00747
00748 if (ip_input(in, netif) != ERR_OK) {
00749 pbuf_free(in);
00750 }
00751
00752 in = NULL;
00753 }
00754
00755 } while (netif->loop_first != NULL);
00756 }
00757
00758 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING
00759
00760
00761
00762 void
00763 netif_poll_all(void)
00764 {
00765 struct netif *netif = netif_list;
00766
00767 while (netif != NULL) {
00768 netif_poll(netif);
00769
00770 netif = netif->next;
00771 }
00772 }
00773 #endif
00774 #endif