1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2012-11-05 Bernard the first version
9 * 2012-11-13 Bernard merge prife's patch for exclusive
10 * access pcap driver.
11 */
12
13 #ifdef _TIME_T_DEFINED
14 #undef _TIME_T_DEFINED
15 #endif
16
17 #ifdef _MSC_VER
18 /*
19 * we do not want the warnings about the old deprecated and unsecure CRT functions
20 * since these examples can be compiled under *nix as well
21 */
22 #define _CRT_SECURE_NO_WARNINGS
23 #endif
24 #include <pcap.h>
25
26 #include <rtthread.h>
27 #include <netif/ethernetif.h>
28
29 #define DBG_TAG "pcap.netif"
30 #define DBG_LVL DBG_INFO
31 #include <rtdbg.h>
32
33 #define MAX_ADDR_LEN 6
34
35 #define NETIF_DEVICE(netif) ((struct pcap_netif*)(netif))
36 #define NETIF_PCAP(netif) (NETIF_DEVICE(netif)->tap)
37
38 struct pcap_netif
39 {
40 /* inherit from ethernet device */
41 struct eth_device parent;
42
43 pcap_t *tap;
44 /* interface address info. */
45 rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
46 };
47 static struct pcap_netif pcap_netif_device;
48 static struct rt_semaphore sem_lock;
49 static rt_mailbox_t packet_mb = RT_NULL;
50
pcap_thread_entry(void * parameter)51 static void pcap_thread_entry(void* parameter)
52 {
53 pcap_if_t *netif;
54 pcap_t *tap;
55 char errbuf[PCAP_ERRBUF_SIZE];
56 struct pcap_pkthdr *header;
57 const u_char *pkt_data;
58 int res;
59
60 netif = (pcap_if_t *) parameter;
61
62 /* Open the adapter */
63 if ((tap = pcap_open_live(netif->name,
64 65536, // portion of the packet to capture.
65 1, // promiscuous mode (nonzero means promiscuous)
66 1, // read timeout, 0 blocked, -1 no timeout
67 errbuf )) == NULL)
68 {
69 rt_kprintf("Unable to open the adapter. %s is not supported by WinPcap\n", netif->name);
70 return;
71 }
72
73 NETIF_PCAP(&pcap_netif_device) = tap;
74
75 /* Read the packets */
76 while (1)
77 {
78 struct eth_device* eth;
79 struct pbuf *p;
80
81 rt_enter_critical();
82 res = pcap_next_ex(tap, &header, &pkt_data);
83 rt_exit_critical();
84
85 if (res == 0) continue;
86
87 eth = (struct eth_device*) &pcap_netif_device;
88
89 p = pbuf_alloc(PBUF_LINK, header->len, PBUF_RAM);
90 pbuf_take(p, pkt_data, header->len);
91
92 /* send to packet mailbox */
93 rt_mb_send_wait(packet_mb, (rt_uint32_t)p, RT_WAITING_FOREVER);
94 /* notify eth rx thread to receive packet */
95 eth_device_ready(eth);
96 }
97 }
98
pcap_netif_init(rt_device_t dev)99 static rt_err_t pcap_netif_init(rt_device_t dev)
100 {
101 rt_thread_t tid;
102 pcap_if_t *alldevs;
103 pcap_if_t *d;
104 pcap_t *tap;
105 int inum, i=0;
106 char errbuf[PCAP_ERRBUF_SIZE];
107
108 /* Retrieve the device list */
109 if(pcap_findalldevs(&alldevs, errbuf) == -1)
110 {
111 rt_kprintf("Error in pcap_findalldevs: %s\n", errbuf);
112 return -RT_ERROR;
113 }
114
115 /* Print the list */
116 for(d = alldevs; d; d = d->next)
117 {
118 rt_kprintf("%d. %s", ++i, d->name);
119 if (d->description)
120 rt_kprintf(" (%s)\n", d->description);
121 else
122 rt_kprintf(" (No description available)\n");
123 }
124 if(i == 0)
125 {
126 rt_kprintf("\nNo interfaces found! Make sure WinPcap is installed.\n");
127 return -RT_ERROR;
128 }
129
130 inum = 1;
131 /* Jump to the selected adapter */
132 for(d = alldevs, i = 0; i < inum-1 ;d = d->next, i++);
133
134 {
135 rt_kprintf("Select (%s) as network interface\n", d->description);
136 packet_mb = rt_mb_create("pcap", 64, RT_IPC_FLAG_FIFO);
137 tid = rt_thread_create("pcap", pcap_thread_entry, d,
138 2048, RT_THREAD_PRIORITY_MAX - 1, 10);
139 if (tid != RT_NULL)
140 {
141 rt_thread_startup(tid);
142 }
143
144 rt_thread_delay(100);
145 }
146
147 pcap_freealldevs(alldevs);
148
149 return RT_EOK;
150 }
151
pcap_netif_open(rt_device_t dev,rt_uint16_t oflag)152 static rt_err_t pcap_netif_open(rt_device_t dev, rt_uint16_t oflag)
153 {
154 return RT_EOK;
155 }
156
pcap_netif_close(rt_device_t dev)157 static rt_err_t pcap_netif_close(rt_device_t dev)
158 {
159 pcap_t *tap;
160
161 tap = NETIF_PCAP(dev);
162
163 pcap_close(tap);
164 return RT_EOK;
165 }
166
pcap_netif_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)167 static rt_ssize_t pcap_netif_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
168 {
169 rt_set_errno(-RT_ENOSYS);
170 return 0;
171 }
172
pcap_netif_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)173 static rt_ssize_t pcap_netif_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
174 {
175 rt_set_errno(-RT_ENOSYS);
176 return 0;
177 }
178
pcap_netif_control(rt_device_t dev,int cmd,void * args)179 static rt_err_t pcap_netif_control(rt_device_t dev, int cmd, void *args)
180 {
181 switch (cmd)
182 {
183 case NIOCTL_GADDR:
184 /* get mac address */
185 if (args) rt_memcpy(args, pcap_netif_device.dev_addr, 6);
186 else return -RT_ERROR;
187 break;
188
189 default :
190 break;
191 }
192
193 return RT_EOK;
194 }
195
pcap_netif_tx(rt_device_t dev,struct pbuf * p)196 rt_err_t pcap_netif_tx( rt_device_t dev, struct pbuf* p)
197 {
198 struct pbuf *q;
199 rt_uint8_t *ptr;
200 rt_uint8_t buf[2048];
201 rt_err_t result = RT_EOK;
202 pcap_t *tap;
203 int res;
204
205 tap = NETIF_PCAP(dev);
206
207 /* lock EMAC device */
208 rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
209
210 /* check if the total length of pbuf exceeds the size of buf */
211 if(p->tot_len > 2048)
212 {
213 LOG_E("Sending the packet: send data exceed max len 2048!");
214 rt_sem_release(&sem_lock);
215 return -RT_ERROR;
216 }
217
218 /* copy data to tx buffer */
219 q = p;
220 ptr = (rt_uint8_t*)buf;
221 while (q)
222 {
223 memcpy(ptr, q->payload, q->len);
224 ptr += q->len;
225 q = q->next;
226 }
227
228 rt_enter_critical();
229 res = pcap_sendpacket(tap, buf, p->tot_len);
230 rt_exit_critical();
231
232 if (res != 0)
233 {
234 LOG_E("Sending the packet: %s", pcap_geterr(tap));
235 result = -RT_ERROR;
236 }
237
238 /* unlock EMAC device */
239 rt_sem_release(&sem_lock);
240
241 return result;
242 }
243
pcap_netif_rx(rt_device_t dev)244 struct pbuf *pcap_netif_rx(rt_device_t dev)
245 {
246 struct pbuf* p = RT_NULL;
247
248 rt_mb_recv(packet_mb, (rt_uint32_t*)&p, 0);
249
250 return p;
251 }
252
pcap_netif_hw_init(void)253 void pcap_netif_hw_init(void)
254 {
255 rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO);
256
257 pcap_netif_device.dev_addr[0] = 0x00;
258 pcap_netif_device.dev_addr[1] = 0x60;
259 pcap_netif_device.dev_addr[2] = 0x37;
260 /* set mac address: (only for test) */
261 pcap_netif_device.dev_addr[3] = 0x12;
262 pcap_netif_device.dev_addr[4] = 0x34;
263 pcap_netif_device.dev_addr[5] = 0x56;
264
265 pcap_netif_device.parent.parent.init = pcap_netif_init;
266 pcap_netif_device.parent.parent.open = pcap_netif_open;
267 pcap_netif_device.parent.parent.close = pcap_netif_close;
268 pcap_netif_device.parent.parent.read = pcap_netif_read;
269 pcap_netif_device.parent.parent.write = pcap_netif_write;
270 pcap_netif_device.parent.parent.control = pcap_netif_control;
271 pcap_netif_device.parent.parent.user_data = RT_NULL;
272
273 pcap_netif_device.parent.eth_rx = pcap_netif_rx;
274 pcap_netif_device.parent.eth_tx = pcap_netif_tx;
275
276 eth_device_init(&(pcap_netif_device.parent), "e0");
277 }
278
279 #include <finsh.h>
list_pcap(void)280 void list_pcap(void)
281 {
282 int i=0;
283 pcap_if_t *alldevs;
284 pcap_if_t *d;
285 char errbuf[PCAP_ERRBUF_SIZE];
286
287 /* Retrieve the device list */
288 if(pcap_findalldevs(&alldevs, errbuf) == -1)
289 {
290 rt_kprintf("Error in pcap_findalldevs: %s\n", errbuf);
291 return -RT_ERROR;
292 }
293
294 /* Print the list */
295 for(d = alldevs; d; d = d->next)
296 {
297 rt_kprintf("%d. %s", ++i, d->name);
298 if (d->description)
299 rt_kprintf(" (%s)\n", d->description);
300 else
301 rt_kprintf(" (No description available)\n");
302 }
303 if(i == 0)
304 {
305 rt_kprintf("\nNo interfaces found! Make sure WinPcap is installed.\n");
306 return -RT_ERROR;
307 }
308
309 pcap_freealldevs(alldevs);
310
311 return ;
312 }
313 FINSH_FUNCTION_EXPORT(list_pcap, show host netif adapter);
314