• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  *
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32 
33 #ifndef linux  /* Apparently, this doesn't work under Linux. */
34 
35 #include "lwip/debug.h"
36 
37 #include <fcntl.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/uio.h>
43 #include <sys/socket.h>
44 #include <sys/un.h>
45 #include <sys/stat.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 
49 #include <pcap.h>
50 
51 #include "netif/etharp.h"
52 
53 #include "lwip/stats.h"
54 
55 #include "lwip/def.h"
56 #include "lwip/mem.h"
57 #include "lwip/pbuf.h"
58 #include "lwip/sys.h"
59 
60 #include "lwip/ip.h"
61 
62 
63 struct pcapif {
64   pcap_t *pd;
65   sys_sem_t sem;
66   u8_t pkt[2048];
67   u32_t len;
68   u32_t lasttime;
69   struct pbuf *p;
70   struct eth_addr *ethaddr;
71 };
72 
73 static char errbuf[PCAP_ERRBUF_SIZE];
74 
75 /*-----------------------------------------------------------------------------------*/
76 static err_t
pcapif_output(struct netif * netif,struct pbuf * p,ip_addr_t * ipaddr)77 pcapif_output(struct netif *netif, struct pbuf *p,
78 	      ip_addr_t *ipaddr)
79 {
80   return ERR_OK;
81 }
82 /*-----------------------------------------------------------------------------------*/
83 static void
timeout(void * arg)84 timeout(void *arg)
85 {
86   struct netif *netif;
87   struct pcapif *pcapif;
88   struct pbuf *p;
89   struct eth_hdr *ethhdr;
90 
91   netif = (struct netif *)arg;
92   pcapif = netif->state;
93   ethhdr = (struct eth_hdr *)pcapif->pkt;
94 
95 
96   if (lwip_htons(ethhdr->type) != ETHTYPE_IP ||
97      ip_lookup(pcapif->pkt + 14, netif)) {
98 
99     /* We allocate a pbuf chain of pbufs from the pool. */
100     p = pbuf_alloc(PBUF_LINK, pcapif->len, PBUF_POOL);
101 
102     if (p != NULL) {
103       pbuf_take(p, pcapif->pkt, pcapif->len);
104 
105       ethhdr = p->payload;
106       switch (lwip_htons(ethhdr->type)) {
107       /* IP or ARP packet? */
108       case ETHTYPE_IP:
109       case ETHTYPE_ARP:
110 #if PPPOE_SUPPORT
111       /* PPPoE packet? */
112       case ETHTYPE_PPPOEDISC:
113       case ETHTYPE_PPPOE:
114 #endif /* PPPOE_SUPPORT */
115         /* full packet send to tcpip_thread to process */
116         if (netif->input(p, netif) != ERR_OK) {
117           LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
118           pbuf_free(p);
119           p = NULL;
120         }
121         break;
122       default:
123         pbuf_free(p);
124         break;
125       }
126     }
127   } else {
128     printf("ip_lookup dropped\n");
129   }
130 
131   sys_sem_signal(&pcapif->sem);
132 }
133 /*-----------------------------------------------------------------------------------*/
134 static void
callback(u_char * arg,const struct pcap_pkthdr * hdr,const u_char * pkt)135 callback(u_char *arg, const struct pcap_pkthdr *hdr, const u_char *pkt)
136 {
137   struct netif *netif;
138   struct pcapif *pcapif;
139   u32_t time, lasttime;
140 
141   netif = (struct netif *)arg;
142   pcapif = netif->state;
143 
144   pcapif->len = hdr->len;
145 
146   bcopy(pkt, pcapif->pkt, hdr->len);
147 
148   time = hdr->ts.tv_sec * 1000 + hdr->ts.tv_usec / 1000;
149 
150   lasttime = pcapif->lasttime;
151   pcapif->lasttime = time;
152 
153 
154   if (lasttime == 0) {
155     sys_timeout(1000, timeout, netif);
156   } else {
157     sys_timeout(time - lasttime, timeout, netif);
158   }
159 }
160 /*-----------------------------------------------------------------------------------*/
161 static void
pcapif_thread(void * arg)162 pcapif_thread(void *arg)
163 {
164   struct netif *netif;
165   struct pcapif *pcapif;
166   netif = arg;
167   pcapif = netif->state;
168 
169   while (1) {
170     pcap_loop(pcapif->pd, 1, callback, (u_char *)netif);
171     sys_sem_wait(&pcapif->sem);
172     if (pcapif->p != NULL) {
173       netif->input(pcapif->p, netif);
174     }
175   }
176 }
177 /*-----------------------------------------------------------------------------------*/
178 err_t
pcapif_init(struct netif * netif)179 pcapif_init(struct netif *netif)
180 {
181   struct pcapif *p;
182 
183   p = malloc(sizeof(struct pcapif));
184   if (p == NULL)
185       return ERR_MEM;
186   netif->state = p;
187   netif->name[0] = 'p';
188   netif->name[1] = 'c';
189   netif->output = pcapif_output;
190 
191   p->pd = pcap_open_offline("pcapdump", errbuf);
192   if (p->pd == NULL) {
193     printf("pcapif_init: failed %s\n", errbuf);
194     return ERR_IF;
195   }
196 
197   if(sys_sem_new(&p->sem, 0) != ERR_OK) {
198     LWIP_ASSERT("Failed to create semaphore", 0);
199   }
200   p->p = NULL;
201   p->lasttime = 0;
202 
203   sys_thread_new("pcapif_thread", pcapif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
204   return ERR_OK;
205 }
206 /*-----------------------------------------------------------------------------------*/
207 #endif /* linux */
208