source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/contrib-2.1.0/ports/win32/pcapif.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 32.9 KB
Line 
1/**
2 * pcapif.c - This file is part of lwIP pcapif
3 *
4 ****************************************************************************
5 *
6 * This file is derived from an example in lwIP with the following license:
7 *
8 * Copyright (c) 2001, Swedish Institute of Computer Science.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36
37/* include the port-dependent configuration */
38#include "lwipcfg.h"
39
40#include <stdlib.h>
41#include <stdio.h>
42
43#ifdef _MSC_VER
44#pragma warning( push, 3 )
45#include "pcap.h"
46#pragma warning ( pop )
47#else
48/* e.g. mingw */
49#define _MSC_VER 1500
50#include "pcap.h"
51#undef _MSC_VER
52#endif
53
54#include "lwip/opt.h"
55
56#if LWIP_ETHERNET
57
58#include "pcapif.h"
59
60#include <stdlib.h>
61#include <stdio.h>
62#include <string.h>
63
64#include "lwip/debug.h"
65
66#include "lwip/def.h"
67#include "lwip/mem.h"
68#include "lwip/pbuf.h"
69#include "lwip/stats.h"
70#include "lwip/sys.h"
71#include "lwip/ip.h"
72#include "lwip/snmp.h"
73#include "lwip/tcpip.h"
74#include "lwip/timeouts.h"
75#include "lwip/ethip6.h"
76
77#include "lwip/etharp.h"
78
79/* For compatibility with old pcap */
80#ifndef PCAP_OPENFLAG_PROMISCUOUS
81#define PCAP_OPENFLAG_PROMISCUOUS 1
82#endif
83
84/** Set this to 0 to receive all multicast ethernet destination addresses */
85#ifndef PCAPIF_FILTER_GROUP_ADDRESSES
86#define PCAPIF_FILTER_GROUP_ADDRESSES 1
87#endif
88
89/** Set this to 1 to receive all frames (also unicast to other addresses)
90 * In this mode, filtering out our own tx packets from loopback receiving
91 * is done via matching rx against recent tx (memcmp).
92 */
93#ifndef PCAPIF_RECEIVE_PROMISCUOUS
94#define PCAPIF_RECEIVE_PROMISCUOUS 0
95#endif
96
97/* Define those to better describe your network interface.
98 For now, we use 'e0', 'e1', 'e2' and so on */
99#define IFNAME0 'e'
100#define IFNAME1 '0'
101
102/** index of the network adapter to use for lwIP */
103#ifndef PACKET_LIB_ADAPTER_NR
104#define PACKET_LIB_ADAPTER_NR 0
105#endif
106
107/** If 1, check link state and report it to lwIP.
108 * If 0, don't check link state (lwIP link state is always UP).
109 */
110#ifndef PCAPIF_HANDLE_LINKSTATE
111#define PCAPIF_HANDLE_LINKSTATE 1
112#endif
113
114/** If 1, use PBUF_REF for RX (for testing purposes mainly).
115 * For this, LWIP_SUPPORT_CUSTOM_PBUF must be enabled.
116 */
117#ifndef PCAPIF_RX_REF
118#define PCAPIF_RX_REF 0
119#endif
120
121/** This can be used when netif->state is used for something else in your
122 * application (e.g. when wrapping a class around this interface). Just
123 * make sure this define returns the state pointer set by
124 * pcapif_low_level_init() (e.g. by using an offset or a callback).
125 */
126#ifndef PCAPIF_GET_STATE_PTR
127#define PCAPIF_GET_STATE_PTR(netif) ((netif)->state)
128#endif
129
130#if PCAPIF_HANDLE_LINKSTATE
131#include "pcapif_helper.h"
132
133/* Define "PHY" delay when "link up" */
134#ifndef PCAPIF_LINKUP_DELAY
135#define PCAPIF_LINKUP_DELAY 0
136#endif
137
138#define PCAPIF_LINKCHECK_INTERVAL_MS 500
139
140/* link state notification macro */
141#if PCAPIF_LINKUP_DELAY
142#define PCAPIF_NOTIFY_LINKSTATE(netif, linkfunc) sys_timeout(PCAPIF_LINKUP_DELAY, (sys_timeout_handler)linkfunc, netif)
143#else /* PHY_LINKUP_DELAY */
144#define PCAPIF_NOTIFY_LINKSTATE(netif, linkfunc) linkfunc(netif)
145#endif /* PHY_LINKUP_DELAY */
146
147#endif /* PCAPIF_HANDLE_LINKSTATE */
148
149/* Define PCAPIF_RX_LOCK_LWIP and PCAPIF_RX_UNLOCK_LWIP if you need to lock the lwIP core
150 before/after pbuf_alloc() or netif->input() are called on RX. */
151#ifndef PCAPIF_RX_LOCK_LWIP
152#define PCAPIF_RX_LOCK_LWIP()
153#endif
154#ifndef PCAPIF_RX_UNLOCK_LWIP
155#define PCAPIF_RX_UNLOCK_LWIP()
156#endif
157
158#define ETH_MIN_FRAME_LEN 60U
159#define ETH_MAX_FRAME_LEN 1518U
160
161#define ADAPTER_NAME_LEN 128
162#define ADAPTER_DESC_LEN 128
163
164#if PCAPIF_RECEIVE_PROMISCUOUS
165#ifndef PCAPIF_LOOPBACKFILTER_NUM_TX_PACKETS
166#define PCAPIF_LOOPBACKFILTER_NUM_TX_PACKETS 128
167#endif
168struct pcapipf_pending_packet {
169 struct pcapipf_pending_packet *next;
170 u16_t len;
171 u8_t data[ETH_MAX_FRAME_LEN];
172};
173#endif /* PCAPIF_RECEIVE_PROMISCUOUS */
174
175/* Packet Adapter informations */
176struct pcapif_private {
177 void *input_fn_arg;
178 pcap_t *adapter;
179 char name[ADAPTER_NAME_LEN];
180 char description[ADAPTER_DESC_LEN];
181 int shutdown_called;
182#if PCAPIF_RX_USE_THREAD
183 volatile int rx_run;
184 volatile int rx_running;
185#endif /* PCAPIF_RX_USE_THREAD */
186#if PCAPIF_HANDLE_LINKSTATE
187 struct pcapifh_linkstate *link_state;
188 enum pcapifh_link_event last_link_event;
189#endif /* PCAPIF_HANDLE_LINKSTATE */
190#if PCAPIF_RECEIVE_PROMISCUOUS
191 struct pcapipf_pending_packet packets[PCAPIF_LOOPBACKFILTER_NUM_TX_PACKETS];
192 struct pcapipf_pending_packet *tx_packets;
193 struct pcapipf_pending_packet *free_packets;
194#endif /* PCAPIF_RECEIVE_PROMISCUOUS */
195};
196
197#if PCAPIF_RECEIVE_PROMISCUOUS
198static void
199pcapif_init_tx_packets(struct pcapif_private *priv)
200{
201 int i;
202 priv->tx_packets = NULL;
203 priv->free_packets = NULL;
204 for (i = 0; i < PCAPIF_LOOPBACKFILTER_NUM_TX_PACKETS; i++) {
205 struct pcapipf_pending_packet *pack = &priv->packets[i];
206 pack->len = 0;
207 pack->next = priv->free_packets;
208 priv->free_packets = pack;
209 }
210}
211
212static void
213pcapif_add_tx_packet(struct pcapif_private *priv, unsigned char *buf, u16_t tot_len)
214{
215 struct pcapipf_pending_packet *tx;
216 struct pcapipf_pending_packet *pack;
217 SYS_ARCH_DECL_PROTECT(lev);
218
219 /* get a free packet (locked) */
220 SYS_ARCH_PROTECT(lev);
221 pack = priv->free_packets;
222 if ((pack == NULL) && (priv->tx_packets != NULL)) {
223 /* no free packets, reuse the oldest */
224 pack = priv->tx_packets;
225 priv->tx_packets = pack->next;
226 }
227 LWIP_ASSERT("no free packet", pack != NULL);
228 priv->free_packets = pack->next;
229 pack->next = NULL;
230 SYS_ARCH_UNPROTECT(lev);
231
232 /* set up the packet (unlocked) */
233 pack->len = tot_len;
234 memcpy(pack->data, buf, tot_len);
235
236 /* put the packet on the list (locked) */
237 SYS_ARCH_PROTECT(lev);
238 if (priv->tx_packets != NULL) {
239 for (tx = priv->tx_packets; tx->next != NULL; tx = tx->next);
240 LWIP_ASSERT("bug", tx != NULL);
241 tx->next = pack;
242 } else {
243 priv->tx_packets = pack;
244 }
245 SYS_ARCH_UNPROTECT(lev);
246}
247
248static int
249pcapif_compare_packets(struct pcapipf_pending_packet *pack, const void *packet, int packet_len)
250{
251 if (pack->len == packet_len) {
252 if (!memcmp(pack->data, packet, packet_len)) {
253 return 1;
254 }
255 }
256 return 0;
257}
258
259static int
260pcaipf_is_tx_packet(struct netif *netif, const void *packet, int packet_len)
261{
262 struct pcapif_private *priv = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
263 struct pcapipf_pending_packet *iter, *last;
264 SYS_ARCH_DECL_PROTECT(lev);
265
266 last = priv->tx_packets;
267 if (last == NULL) {
268 /* list is empty */
269 return 0;
270 }
271 /* compare the first packet */
272 if (pcapif_compare_packets(last, packet, packet_len)) {
273 SYS_ARCH_PROTECT(lev);
274 LWIP_ASSERT("list has changed", last == priv->tx_packets);
275 priv->tx_packets = last->next;
276 last->next = priv->free_packets;
277 priv->free_packets = last;
278 last->len = 0;
279 SYS_ARCH_UNPROTECT(lev);
280 return 1;
281 }
282 SYS_ARCH_PROTECT(lev);
283 for (iter = last->next; iter != NULL; last = iter, iter = iter->next) {
284 /* unlock while comparing (this works because we have a clean threading separation
285 of adding and removing items and adding is only done at the end) */
286 SYS_ARCH_UNPROTECT(lev);
287 if (pcapif_compare_packets(iter, packet, packet_len)) {
288 SYS_ARCH_PROTECT(lev);
289 LWIP_ASSERT("last != NULL", last != NULL);
290 last->next = iter->next;
291 iter->next = priv->free_packets;
292 priv->free_packets = iter;
293 last->len = 0;
294 SYS_ARCH_UNPROTECT(lev);
295 return 1;
296 }
297 SYS_ARCH_PROTECT(lev);
298 }
299 SYS_ARCH_UNPROTECT(lev);
300 return 0;
301}
302#else /* PCAPIF_RECEIVE_PROMISCUOUS */
303#define pcapif_init_tx_packets(priv)
304#define pcapif_add_tx_packet(priv, buf, tot_len)
305static int
306pcaipf_is_tx_packet(struct netif *netif, const void *packet, int packet_len)
307{
308 const struct eth_addr *src = (const struct eth_addr *)packet + 1;
309 if (packet_len >= (ETH_HWADDR_LEN * 2)) {
310 /* Don't let feedback packets through (limitation in winpcap?) */
311 if(!memcmp(src, netif->hwaddr, ETH_HWADDR_LEN)) {
312 return 1;
313 }
314 }
315 return 0;
316}
317#endif /* PCAPIF_RECEIVE_PROMISCUOUS */
318
319#if PCAPIF_RX_REF
320struct pcapif_pbuf_custom
321{
322 struct pbuf_custom pc;
323 struct pbuf* p;
324};
325#endif /* PCAPIF_RX_REF */
326
327/* Forward declarations. */
328static void pcapif_input(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *packet);
329
330#ifdef PACKET_LIB_GET_ADAPTER_NETADDRESS
331/** Get the index of an adapter by its network address
332 *
333 * @param netaddr network address of the adapter (e.g. 192.168.1.0)
334 * @return index of the adapter or negative on error
335 */
336static int
337get_adapter_index_from_addr(struct in_addr *netaddr, char *guid, size_t guid_len)
338{
339 pcap_if_t *alldevs;
340 pcap_if_t *d;
341 char errbuf[PCAP_ERRBUF_SIZE+1];
342 int index = 0;
343
344 memset(guid, 0, guid_len);
345
346 /* Retrieve the interfaces list */
347 if (pcap_findalldevs(&alldevs, errbuf) == -1) {
348 printf("Error in pcap_findalldevs: %s\n", errbuf);
349 return -1;
350 }
351 /* Scan the list printing every entry */
352 for (d = alldevs; d != NULL; d = d->next, index++) {
353 pcap_addr_t *a;
354 for(a = d->addresses; a != NULL; a = a->next) {
355 if (a->addr->sa_family == AF_INET) {
356 ULONG a_addr = ((struct sockaddr_in *)a->addr)->sin_addr.s_addr;
357 ULONG a_netmask = ((struct sockaddr_in *)a->netmask)->sin_addr.s_addr;
358 ULONG a_netaddr = a_addr & a_netmask;
359 ULONG addr = (*netaddr).s_addr;
360 if (a_netaddr == addr) {
361 int ret = -1;
362 char name[128];
363 char *start, *end;
364 size_t len = strlen(d->name);
365 if(len > 127) {
366 len = 127;
367 }
368 MEMCPY(name, d->name, len);
369 name[len] = 0;
370 start = strstr(name, "{");
371 if (start != NULL) {
372 end = strstr(start, "}");
373 if (end != NULL) {
374 size_t len = end - start + 1;
375 MEMCPY(guid, start, len);
376 ret = index;
377 }
378 }
379 pcap_freealldevs(alldevs);
380 return ret;
381 }
382 }
383 }
384 }
385 printf("Network address not found.\n");
386
387 pcap_freealldevs(alldevs);
388 return -1;
389}
390#endif /* PACKET_LIB_GET_ADAPTER_NETADDRESS */
391
392#if defined(PACKET_LIB_GET_ADAPTER_NETADDRESS) || defined(PACKET_LIB_ADAPTER_GUID)
393/** Get the index of an adapter by its GUID
394 *
395 * @param adapter_guid GUID of the adapter
396 * @return index of the adapter or negative on error
397 */
398static int
399get_adapter_index(const char* adapter_guid)
400{
401 pcap_if_t *alldevs;
402 pcap_if_t *d;
403 char errbuf[PCAP_ERRBUF_SIZE+1];
404 int idx = 0;
405
406 /* Retrieve the interfaces list */
407 if (pcap_findalldevs(&alldevs, errbuf) == -1) {
408 printf("Error in pcap_findalldevs: %s\n", errbuf);
409 return -1;
410 }
411 /* Scan the list and compare name vs. adapter_guid */
412 for (d = alldevs; d != NULL; d = d->next, idx++) {
413 if(strstr(d->name, adapter_guid)) {
414 pcap_freealldevs(alldevs);
415 return idx;
416 }
417 }
418 /* not found, dump all adapters */
419 printf("%d available adapters:\n", idx);
420 for (d = alldevs, idx = 0; d != NULL; d = d->next, idx++) {
421 printf("- %d: %s\n", idx, d->name);
422 }
423 pcap_freealldevs(alldevs);
424 return -1;
425}
426#endif /* defined(PACKET_LIB_GET_ADAPTER_NETADDRESS) || defined(PACKET_LIB_ADAPTER_GUID) */
427
428static pcap_t*
429pcapif_open_adapter(const char* adapter_name, char* errbuf)
430{
431 pcap_t* adapter = pcap_open_live(adapter_name,/* name of the device */
432 65536, /* portion of the packet to capture */
433 /* 65536 guarantees that the whole packet will be captured on all the link layers */
434 PCAP_OPENFLAG_PROMISCUOUS,/* promiscuous mode */
435#if PCAPIF_RX_USE_THREAD
436 /*-*/1, /* don't wait at all for lower latency */
437#else
438 1, /* wait 1 ms in ethernetif_poll */
439#endif
440 errbuf); /* error buffer */
441 return adapter;
442}
443
444#if !PCAPIF_RX_USE_THREAD
445static void
446pcap_reopen_adapter(struct pcapif_private *pa)
447{
448 char errbuf[PCAP_ERRBUF_SIZE+1];
449 pcap_if_t *alldevs;
450 if (pa->adapter != NULL) {
451 pcap_close(pa->adapter);
452 pa->adapter = NULL;
453 }
454 if (pcap_findalldevs(&alldevs, errbuf) != -1) {
455 pcap_if_t *d;
456 for (d = alldevs; d != NULL; d = d->next) {
457 if (!strcmp(d->name, pa->name)) {
458 pa->adapter = pcapif_open_adapter(pa->name, errbuf);
459 if (pa->adapter == NULL) {
460 printf("failed to reopen pcap adapter after failure: %s\n", errbuf);
461 }
462 break;
463 }
464 }
465 pcap_freealldevs(alldevs);
466 }
467}
468#endif
469
470/**
471 * Open a network adapter and set it up for packet input
472 *
473 * @param adapter_num the index of the adapter to use
474 * @param arg argument to pass to input
475 * @return an adapter handle on success, NULL on failure
476 */
477static struct pcapif_private*
478pcapif_init_adapter(int adapter_num, void *arg)
479{
480 int i;
481 int number_of_adapters;
482 struct pcapif_private *pa;
483 char errbuf[PCAP_ERRBUF_SIZE+1];
484
485 pcap_if_t *alldevs;
486 pcap_if_t *d;
487 pcap_if_t *used_adapter = NULL;
488
489 pa = (struct pcapif_private *)malloc(sizeof(struct pcapif_private));
490 if (!pa) {
491 printf("Unable to alloc the adapter!\n");
492 return NULL;
493 }
494
495 memset(pa, 0, sizeof(struct pcapif_private));
496 pcapif_init_tx_packets(pa);
497 pa->input_fn_arg = arg;
498
499 /* Retrieve the interfaces list */
500 if (pcap_findalldevs(&alldevs, errbuf) == -1) {
501 free(pa);
502 return NULL; /* no adapters found */
503 }
504 /* get number of adapters and adapter pointer */
505 for (d = alldevs, number_of_adapters = 0; d != NULL; d = d->next, number_of_adapters++) {
506 if (number_of_adapters == adapter_num) {
507 char *desc = d->description;
508 size_t len;
509
510 len = strlen(d->name);
511 LWIP_ASSERT("len < ADAPTER_NAME_LEN", len < ADAPTER_NAME_LEN);
512 strcpy(pa->name, d->name);
513
514 used_adapter = d;
515 /* format vendor description */
516 if (desc != NULL) {
517 len = strlen(desc);
518 if (strstr(desc, " ' on local host") != NULL) {
519 len -= 16;
520 }
521 else if (strstr(desc, "' on local host") != NULL) {
522 len -= 15;
523 }
524 if (strstr(desc, "Network adapter '") == desc) {
525 len -= 17;
526 desc += 17;
527 }
528 len = LWIP_MIN(len, ADAPTER_DESC_LEN-1);
529 while ((desc[len-1] == ' ') || (desc[len-1] == '\t')) {
530 /* don't copy trailing whitespace */
531 len--;
532 }
533 strncpy(pa->description, desc, len);
534 pa->description[len] = 0;
535 } else {
536 strcpy(pa->description, "<no_desc>");
537 }
538 }
539 }
540
541#ifndef PCAPIF_LIB_QUIET
542 /* Scan the list printing every entry */
543 for (d = alldevs, i = 0; d != NULL; d = d->next, i++) {
544 char *desc = d->description;
545 char descBuf[128];
546 size_t len;
547 const char* devname = d->name;
548 if (d->name == NULL) {
549 devname = "<unnamed>";
550 } else {
551 if (strstr(devname, "\\Device\\") == devname) {
552 /* windows: strip the first part */
553 devname += 8;
554 }
555 }
556 printf("%2i: %s\n", i, devname);
557 if (desc != NULL) {
558 /* format vendor description */
559 len = strlen(desc);
560 if (strstr(desc, " ' on local host") != NULL) {
561 len -= 16;
562 }
563 else if (strstr(desc, "' on local host") != NULL) {
564 len -= 15;
565 }
566 if (strstr(desc, "Network adapter '") == desc) {
567 len -= 17;
568 desc += 17;
569 }
570 len = LWIP_MIN(len, 127);
571 while ((desc[len-1] == ' ') || (desc[len-1] == '\t')) {
572 /* don't copy trailing whitespace */
573 len--;
574 }
575 strncpy(descBuf, desc, len);
576 descBuf[len] = 0;
577 printf(" Desc: \"%s\"\n", descBuf);
578 }
579 }
580#endif /* PCAPIF_LIB_QUIET */
581
582 /* invalid adapter index -> check this after printing the adapters */
583 if (adapter_num < 0) {
584 printf("Invalid adapter_num: %d\n", adapter_num);
585 free(pa);
586 pcap_freealldevs(alldevs);
587 return NULL;
588 }
589 /* adapter index out of range */
590 if (adapter_num >= number_of_adapters) {
591 printf("Invalid adapter_num: %d\n", adapter_num);
592 free(pa);
593 pcap_freealldevs(alldevs);
594 return NULL;
595 }
596#ifndef PCAPIF_LIB_QUIET
597 printf("Using adapter_num: %d\n", adapter_num);
598#endif /* PCAPIF_LIB_QUIET */
599 /* set up the selected adapter */
600
601 LWIP_ASSERT("used_adapter != NULL", used_adapter != NULL);
602
603 /* Open the device */
604 pa->adapter = pcapif_open_adapter(used_adapter->name, errbuf);
605 if (pa->adapter == NULL) {
606 printf("\nUnable to open the adapter. %s is not supported by pcap (\"%s\").\n", used_adapter->name, errbuf);
607 /* Free the device list */
608 pcap_freealldevs(alldevs);
609 free(pa);
610 return NULL;
611 }
612 printf("Using adapter: \"%s\"\n", pa->description);
613 pcap_freealldevs(alldevs);
614
615#if PCAPIF_HANDLE_LINKSTATE
616 pa->link_state = pcapifh_linkstate_init(pa->name);
617 pa->last_link_event = PCAPIF_LINKEVENT_UNKNOWN;
618#endif /* PCAPIF_HANDLE_LINKSTATE */
619
620 return pa;
621}
622
623#if PCAPIF_HANDLE_LINKSTATE
624static void
625pcapif_check_linkstate(void *netif_ptr)
626{
627 struct netif *netif = (struct netif*)netif_ptr;
628 struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
629 enum pcapifh_link_event le;
630
631 le = pcapifh_linkstate_get(pa->link_state);
632
633 if (pa->last_link_event != le) {
634 pa->last_link_event = le;
635 switch (le) {
636 case PCAPIF_LINKEVENT_UP: {
637 PCAPIF_NOTIFY_LINKSTATE(netif, netif_set_link_up);
638 break;
639 }
640 case PCAPIF_LINKEVENT_DOWN: {
641 PCAPIF_NOTIFY_LINKSTATE(netif, netif_set_link_down);
642 break;
643 }
644 case PCAPIF_LINKEVENT_UNKNOWN: /* fall through */
645 default:
646 break;
647 }
648 }
649 sys_timeout(PCAPIF_LINKCHECK_INTERVAL_MS, pcapif_check_linkstate, netif);
650}
651#endif /* PCAPIF_HANDLE_LINKSTATE */
652
653
654/**
655 * Close the adapter (no more packets can be sent or received)
656 *
657 * @param netif netif to shutdown
658 */
659void
660pcapif_shutdown(struct netif *netif)
661{
662 struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
663 if (pa) {
664#if PCAPIF_RX_USE_THREAD
665 pa->rx_run = 0;
666#endif /* PCAPIF_RX_USE_THREAD */
667 if (pa->adapter) {
668 pcap_breakloop(pa->adapter);
669 pcap_close(pa->adapter);
670 }
671#if PCAPIF_RX_USE_THREAD
672 /* wait for rxthread to end */
673 while(pa->rx_running);
674#endif /* PCAPIF_RX_USE_THREAD */
675#if PCAPIF_HANDLE_LINKSTATE
676 pcapifh_linkstate_close(pa->link_state);
677#endif /* PCAPIF_HANDLE_LINKSTATE */
678 free(pa);
679 }
680}
681
682#if PCAPIF_RX_USE_THREAD
683/** RX running in its own thread */
684static void
685pcapif_input_thread(void *arg)
686{
687 struct netif *netif = (struct netif *)arg;
688 struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
689 do
690 {
691 struct pcap_pkthdr pkt_header;
692 const u_char *packet = pcap_next(pa->adapter, &pkt_header);
693 if(packet != NULL) {
694 pcapif_input((u_char*)pa, &pkt_header, packet);
695 }
696 } while (pa->rx_run);
697 pa->rx_running = 0;
698}
699#endif /* PCAPIF_RX_USE_THREAD */
700
701/** Low-level initialization: find the correct adapter and initialize it.
702 */
703static void
704pcapif_low_level_init(struct netif *netif)
705{
706 u8_t my_mac_addr[ETH_HWADDR_LEN] = LWIP_MAC_ADDR_BASE;
707 int adapter_num = PACKET_LIB_ADAPTER_NR;
708 struct pcapif_private *pa;
709#ifdef PACKET_LIB_GET_ADAPTER_NETADDRESS
710 ip4_addr_t netaddr;
711#define GUID_LEN 128
712 char guid[GUID_LEN + 1];
713#endif /* PACKET_LIB_GET_ADAPTER_NETADDRESS */
714
715 /* If 'state' is != NULL at this point, we assume it is an 'int' giving
716 the index of the adapter to use (+ 1 because 0==NULL is invalid).
717 This can be used to instantiate multiple PCAP drivers. */
718 if (netif->state != NULL) {
719 adapter_num = (LWIP_PTR_NUMERIC_CAST(int, netif->state)) - 1;
720 if (adapter_num < 0) {
721 printf("ERROR: invalid adapter index \"%d\"!\n", adapter_num);
722 LWIP_ASSERT("ERROR initializing network adapter!\n", 0);
723 return;
724 }
725 }
726
727#ifdef PACKET_LIB_GET_ADAPTER_NETADDRESS
728 memset(&guid, 0, sizeof(guid));
729 PACKET_LIB_GET_ADAPTER_NETADDRESS(&netaddr);
730 if (get_adapter_index_from_addr((struct in_addr *)&netaddr, guid, GUID_LEN) < 0) {
731 printf("ERROR initializing network adapter, failed to get GUID for network address %s\n", ip4addr_ntoa(&netaddr));
732 LWIP_ASSERT("ERROR initializing network adapter, failed to get GUID for network address!", 0);
733 return;
734 }
735 adapter_num = get_adapter_index(guid);
736 if (adapter_num < 0) {
737 printf("ERROR finding network adapter with GUID \"%s\"!\n", guid);
738 LWIP_ASSERT("ERROR finding network adapter with expected GUID!", 0);
739 return;
740 }
741
742#else /* PACKET_LIB_GET_ADAPTER_NETADDRESS */
743#ifdef PACKET_LIB_ADAPTER_GUID
744 /* get adapter index for guid string */
745 adapter_num = get_adapter_index(PACKET_LIB_ADAPTER_GUID);
746 if (adapter_num < 0) {
747 printf("ERROR finding network adapter with GUID \"%s\"!\n", PACKET_LIB_ADAPTER_GUID);
748 LWIP_ASSERT("ERROR initializing network adapter!\n", 0);
749 return;
750 }
751#endif /* PACKET_LIB_ADAPTER_GUID */
752#endif /* PACKET_LIB_GET_ADAPTER_NETADDRESS */
753
754 /* Do whatever else is needed to initialize interface. */
755 pa = pcapif_init_adapter(adapter_num, netif);
756 if (pa == NULL) {
757 printf("ERROR initializing network adapter %d!\n", adapter_num);
758 LWIP_ASSERT("ERROR initializing network adapter!", 0);
759 return;
760 }
761 netif->state = pa;
762
763 /* change the MAC address to a unique value
764 so that multiple ethernetifs are supported */
765 /* @todo: this does NOT support multiple processes using this adapter! */
766 my_mac_addr[ETH_HWADDR_LEN - 1] += netif->num;
767 /* Copy MAC addr */
768 SMEMCPY(&netif->hwaddr, my_mac_addr, ETH_HWADDR_LEN);
769
770 /* get the initial link state of the selected interface */
771#if PCAPIF_HANDLE_LINKSTATE
772 pa->last_link_event = pcapifh_linkstate_get(pa->link_state);
773 if (pa->last_link_event == PCAPIF_LINKEVENT_DOWN) {
774 netif_set_link_down(netif);
775 } else {
776 netif_set_link_up(netif);
777 }
778 sys_timeout(PCAPIF_LINKCHECK_INTERVAL_MS, pcapif_check_linkstate, netif);
779#else /* PCAPIF_HANDLE_LINKSTATE */
780 /* just set the link up so that lwIP can transmit */
781 netif_set_link_up(netif);
782#endif /* PCAPIF_HANDLE_LINKSTATE */
783
784#if PCAPIF_RX_USE_THREAD
785 pa->rx_run = 1;
786 pa->rx_running = 1;
787 sys_thread_new("pcapif_rxthread", pcapif_input_thread, netif, 0, 0);
788#endif
789
790 LWIP_DEBUGF(NETIF_DEBUG, ("pcapif: eth_addr %02X%02X%02X%02X%02X%02X\n",netif->hwaddr[0],netif->hwaddr[1],netif->hwaddr[2],netif->hwaddr[3],netif->hwaddr[4],netif->hwaddr[5]));
791}
792
793/** low_level_output():
794 * Transmit a packet. The packet is contained in the pbuf that is passed to
795 * the function. This pbuf might be chained.
796 */
797static err_t
798pcapif_low_level_output(struct netif *netif, struct pbuf *p)
799{
800 struct pbuf *q;
801 unsigned char buffer[ETH_MAX_FRAME_LEN + ETH_PAD_SIZE];
802 unsigned char *buf = buffer;
803 unsigned char *ptr;
804 struct eth_hdr *ethhdr;
805 u16_t tot_len = p->tot_len - ETH_PAD_SIZE;
806 struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
807
808#if defined(LWIP_DEBUG) && LWIP_NETIF_TX_SINGLE_PBUF && !(LWIP_IPV4 && IP_FRAG) && (LWIP_IPV6 && LWIP_IPV6_FRAG)
809 LWIP_ASSERT("p->next == NULL && p->len == p->tot_len", p->next == NULL && p->len == p->tot_len);
810#endif
811
812 /* initiate transfer */
813 if ((p->len == p->tot_len) && (p->len >= ETH_MIN_FRAME_LEN + ETH_PAD_SIZE)) {
814 /* no pbuf chain, don't have to copy -> faster */
815 buf = &((unsigned char*)p->payload)[ETH_PAD_SIZE];
816 } else {
817 /* pbuf chain, copy into contiguous buffer */
818 if (p->tot_len >= sizeof(buffer)) {
819 LINK_STATS_INC(link.lenerr);
820 LINK_STATS_INC(link.drop);
821 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
822 return ERR_BUF;
823 }
824 ptr = buffer;
825 for(q = p; q != NULL; q = q->next) {
826 /* Send the data from the pbuf to the interface, one pbuf at a
827 time. The size of the data in each pbuf is kept in the ->len
828 variable. */
829 /* send data from(q->payload, q->len); */
830 LWIP_DEBUGF(NETIF_DEBUG, ("netif: send ptr %p q->payload %p q->len %i q->next %p\n", ptr, q->payload, (int)q->len, (void*)q->next));
831 if (q == p) {
832 MEMCPY(ptr, &((char*)q->payload)[ETH_PAD_SIZE], q->len - ETH_PAD_SIZE);
833 ptr += q->len - ETH_PAD_SIZE;
834 } else {
835 MEMCPY(ptr, q->payload, q->len);
836 ptr += q->len;
837 }
838 }
839 }
840
841 if (tot_len < ETH_MIN_FRAME_LEN) {
842 /* ensure minimal frame length */
843 memset(&buf[tot_len], 0, ETH_MIN_FRAME_LEN - tot_len);
844 tot_len = ETH_MIN_FRAME_LEN;
845 }
846
847 /* signal that packet should be sent */
848 if (pcap_sendpacket(pa->adapter, buf, tot_len) < 0) {
849 LINK_STATS_INC(link.memerr);
850 LINK_STATS_INC(link.drop);
851 MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
852 return ERR_BUF;
853 }
854 if (netif_is_link_up(netif)) {
855 pcapif_add_tx_packet(pa, buf, tot_len);
856 }
857
858 LINK_STATS_INC(link.xmit);
859 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, tot_len);
860 ethhdr = (struct eth_hdr *)p->payload;
861 if ((ethhdr->dest.addr[0] & 1) != 0) {
862 /* broadcast or multicast packet*/
863 MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
864 } else {
865 /* unicast packet */
866 MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
867 }
868 return ERR_OK;
869}
870
871/** low_level_input(): Allocate a pbuf and transfer the bytes of the incoming
872 * packet from the interface into the pbuf.
873 */
874static struct pbuf *
875pcapif_low_level_input(struct netif *netif, const void *packet, int packet_len)
876{
877 struct pbuf *p, *q;
878 int start;
879 int length = packet_len;
880 const struct eth_addr *dest = (const struct eth_addr*)packet;
881 int unicast;
882#if PCAPIF_FILTER_GROUP_ADDRESSES && !PCAPIF_RECEIVE_PROMISCUOUS
883 const u8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
884 const u8_t ipv4mcast[] = {0x01, 0x00, 0x5e};
885 const u8_t ipv6mcast[] = {0x33, 0x33};
886#endif /* PCAPIF_FILTER_GROUP_ADDRESSES && !PCAPIF_RECEIVE_PROMISCUOUS */
887
888 if (pcaipf_is_tx_packet(netif, packet, packet_len)) {
889 /* don't update counters here! */
890 return NULL;
891 }
892
893 unicast = ((dest->addr[0] & 0x01) == 0);
894#if !PCAPIF_RECEIVE_PROMISCUOUS
895 /* MAC filter: only let my MAC or non-unicast through (pcap receives loopback traffic, too) */
896 if (memcmp(dest, &netif->hwaddr, ETH_HWADDR_LEN) &&
897#if PCAPIF_FILTER_GROUP_ADDRESSES
898 (memcmp(dest, ipv4mcast, 3) || ((dest->addr[3] & 0x80) != 0)) &&
899 memcmp(dest, ipv6mcast, 2) &&
900 memcmp(dest, bcast, 6)
901#else /* PCAPIF_FILTER_GROUP_ADDRESSES */
902 unicast
903#endif /* PCAPIF_FILTER_GROUP_ADDRESSES */
904 ) {
905 /* don't update counters here! */
906 return NULL;
907 }
908#endif /* !PCAPIF_RECEIVE_PROMISCUOUS */
909
910 /* We allocate a pbuf chain of pbufs from the pool. */
911 p = pbuf_alloc(PBUF_RAW, (u16_t)length + ETH_PAD_SIZE, PBUF_POOL);
912 LWIP_DEBUGF(NETIF_DEBUG, ("netif: recv length %i p->tot_len %i\n", length, (int)p->tot_len));
913
914 if (p != NULL) {
915 /* We iterate over the pbuf chain until we have read the entire
916 packet into the pbuf. */
917 start = 0;
918 for (q = p; q != NULL; q = q->next) {
919 u16_t copy_len = q->len;
920 /* Read enough bytes to fill this pbuf in the chain. The
921 available data in the pbuf is given by the q->len
922 variable. */
923 /* read data into(q->payload, q->len); */
924 LWIP_DEBUGF(NETIF_DEBUG, ("netif: recv start %i length %i q->payload %p q->len %i q->next %p\n", start, length, q->payload, (int)q->len, (void*)q->next));
925 if (q == p) {
926#if ETH_PAD_SIZE
927 LWIP_ASSERT("q->len >= ETH_PAD_SIZE", q->len >= ETH_PAD_SIZE);
928 copy_len -= ETH_PAD_SIZE;
929#endif /* ETH_PAD_SIZE*/
930 MEMCPY(&((char*)q->payload)[ETH_PAD_SIZE], &((const char*)packet)[start], copy_len);
931 } else {
932 MEMCPY(q->payload, &((const char*)packet)[start], copy_len);
933 }
934 start += copy_len;
935 length -= copy_len;
936 if (length <= 0) {
937 break;
938 }
939 }
940 LINK_STATS_INC(link.recv);
941 MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len - ETH_PAD_SIZE);
942 if (unicast) {
943 MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
944 } else {
945 MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
946 }
947 } else {
948 /* drop packet */
949 LINK_STATS_INC(link.memerr);
950 LINK_STATS_INC(link.drop);
951 MIB2_STATS_NETIF_INC(netif, ifindiscards);
952 }
953
954 return p;
955}
956
957#if PCAPIF_RX_REF
958static void
959pcapif_rx_pbuf_free_custom(struct pbuf *p)
960{
961 struct pcapif_pbuf_custom* ppc;
962 LWIP_ASSERT("NULL pointer", p != NULL);
963 ppc = (struct pcapif_pbuf_custom*)p;
964 LWIP_ASSERT("NULL pointer", ppc->p != NULL);
965 pbuf_free(ppc->p);
966 ppc->p = NULL;
967 mem_free(p);
968}
969
970static struct pbuf*
971pcapif_rx_ref(struct pbuf* p)
972{
973 struct pcapif_pbuf_custom* ppc;
974 struct pbuf* q;
975
976 LWIP_ASSERT("NULL pointer", p != NULL);
977 LWIP_ASSERT("chained pbuf not supported here", p->next == NULL);
978
979 ppc = (struct pcapif_pbuf_custom*)mem_malloc(sizeof(struct pcapif_pbuf_custom));
980 LWIP_ASSERT("out of memory for RX", ppc != NULL);
981 ppc->pc.custom_free_function = pcapif_rx_pbuf_free_custom;
982 ppc->p = p;
983
984 q = pbuf_alloced_custom(PBUF_RAW, p->tot_len, PBUF_REF, &ppc->pc, p->payload, p->tot_len);
985 LWIP_ASSERT("pbuf_alloced_custom returned NULL", q != NULL);
986 return q;
987}
988#endif /* PCAPIF_RX_REF */
989
990/** pcapif_input: This function is called when a packet is ready to be read
991 * from the interface. It uses the function low_level_input() that should
992 * handle the actual reception of bytes from the network interface.
993 */
994static void
995pcapif_input(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *packet)
996{
997 struct pcapif_private *pa = (struct pcapif_private*)user;
998 int packet_len = pkt_header->caplen;
999 struct netif *netif = (struct netif *)pa->input_fn_arg;
1000 struct pbuf *p;
1001
1002 PCAPIF_RX_LOCK_LWIP();
1003
1004 /* move received packet into a new pbuf */
1005 p = pcapif_low_level_input(netif, packet, packet_len);
1006 /* if no packet could be read, silently ignore this */
1007 if (p != NULL) {
1008#if PCAPIF_RX_REF
1009 p = pcapif_rx_ref(p);
1010#endif
1011 /* pass all packets to ethernet_input, which decides what packets it supports */
1012 if (netif->input(p, netif) != ERR_OK) {
1013 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
1014 pbuf_free(p);
1015 }
1016 }
1017 PCAPIF_RX_UNLOCK_LWIP();
1018}
1019
1020/**
1021 * pcapif_init(): initialization function, pass to netif_add().
1022 */
1023err_t
1024pcapif_init(struct netif *netif)
1025{
1026 static int ethernetif_index;
1027
1028 int local_index;
1029 SYS_ARCH_DECL_PROTECT(lev);
1030 SYS_ARCH_PROTECT(lev);
1031 local_index = ethernetif_index++;
1032 SYS_ARCH_UNPROTECT(lev);
1033
1034 LWIP_ASSERT("pcapif needs an input callback", netif->input != NULL);
1035
1036 netif->name[0] = IFNAME0;
1037 netif->name[1] = (char)(IFNAME1 + local_index);
1038 netif->linkoutput = pcapif_low_level_output;
1039#if LWIP_IPV4
1040#if LWIP_ARP
1041 netif->output = etharp_output;
1042#else /* LWIP_ARP */
1043 netif->output = NULL; /* not used for PPPoE */
1044#endif /* LWIP_ARP */
1045#endif /* LWIP_IPV4 */
1046#if LWIP_IPV6
1047 netif->output_ip6 = ethip6_output;
1048#endif /* LWIP_IPV6 */
1049#if LWIP_NETIF_HOSTNAME
1050 /* Initialize interface hostname */
1051 netif_set_hostname(netif, "lwip");
1052#endif /* LWIP_NETIF_HOSTNAME */
1053
1054 netif->mtu = 1500;
1055 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
1056#if LWIP_IPV6 && LWIP_IPV6_MLD
1057 netif->flags |= NETIF_FLAG_MLD6;
1058#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
1059 netif->hwaddr_len = ETH_HWADDR_LEN;
1060
1061 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
1062
1063 /* sets link up or down based on current status */
1064 pcapif_low_level_init(netif);
1065
1066 return ERR_OK;
1067}
1068
1069#if !PCAPIF_RX_USE_THREAD
1070void
1071pcapif_poll(struct netif *netif)
1072{
1073 struct pcapif_private *pa = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
1074
1075 int ret;
1076 do {
1077 if (pa->adapter != NULL) {
1078 ret = pcap_dispatch(pa->adapter, -1, pcapif_input, (u_char*)pa);
1079 } else {
1080 ret = -1;
1081 }
1082 if (ret < 0) {
1083 /* error (e.g. adapter removed or resume from standby), try to reopen the adapter */
1084 pcap_reopen_adapter(pa);
1085 }
1086 } while (ret > 0);
1087
1088}
1089#endif /* !PCAPIF_RX_USE_THREAD */
1090
1091#endif /* LWIP_ETHERNET */
Note: See TracBrowser for help on using the repository browser.