1/*********************************************************************
2   PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
3   See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
4
5   Authors: Daniele Lacamera
6 *********************************************************************/
7
8
9#include <pcap.h>
10#include "pico_device.h"
11#include "pico_dev_pcap.h"
12#include "pico_stack.h"
13
14#include <sys/poll.h>
15
16struct pico_device_pcap {
17    struct pico_device dev;
18    pcap_t *conn;
19};
20
21#define VDE_MTU 2048
22
23static int pico_pcap_send(struct pico_device *dev, void *buf, int len)
24{
25    struct pico_device_pcap *pcap = (struct pico_device_pcap *) dev;
26    /* dbg("[%s] send %d bytes.\n", dev->name, len); */
27    return pcap_inject(pcap->conn, buf, (uint32_t)len);
28}
29
30static void pico_dev_pcap_cb(u_char *u, const struct pcap_pkthdr *h, const u_char *data)
31{
32    struct pico_device *dev = (struct pico_device *)u;
33    const uint8_t *buf = (const uint8_t *)data;
34    pico_stack_recv(dev, buf, (uint32_t)h->len);
35}
36
37
38static int pico_pcap_poll(struct pico_device *dev, int loop_score)
39{
40    struct pico_device_pcap *pcap = (struct pico_device_pcap *) dev;
41    loop_score -= pcap_dispatch(pcap->conn, loop_score, pico_dev_pcap_cb, (u_char *) pcap);
42    return loop_score;
43}
44
45/* Public interface: create/destroy. */
46
47void pico_pcap_destroy(struct pico_device *dev)
48{
49    struct pico_device_pcap *pcap = (struct pico_device_pcap *) dev;
50    pcap_close(pcap->conn);
51}
52
53#define PICO_PCAP_MODE_LIVE 0
54#define PICO_PCAP_MODE_STORED 1
55
56static struct pico_device *pico_pcap_create(char *if_file_name, char *name, uint8_t *mac, int mode)
57{
58    struct pico_device_pcap *pcap = PICO_ZALLOC(sizeof(struct pico_device_pcap));
59    char errbuf[2000];
60    if (!pcap)
61        return NULL;
62
63    if( 0 != pico_device_init((struct pico_device *)pcap, name, mac)) {
64        dbg ("Pcap init failed.\n");
65        pico_pcap_destroy((struct pico_device *)pcap);
66        return NULL;
67    }
68
69    pcap->dev.overhead = 0;
70
71    if (mode == PICO_PCAP_MODE_LIVE)
72        pcap->conn = pcap_open_live(if_file_name, 2000, 100, 10, errbuf);
73    else
74        pcap->conn = pcap_open_offline(if_file_name, errbuf);
75
76    if (!pcap->conn) {
77        pico_pcap_destroy((struct pico_device *)pcap);
78        return NULL;
79    }
80
81    pcap->dev.send = pico_pcap_send;
82    pcap->dev.poll = pico_pcap_poll;
83    pcap->dev.destroy = pico_pcap_destroy;
84    dbg("Device %s created.\n", pcap->dev.name);
85    return (struct pico_device *)pcap;
86}
87
88struct pico_device *pico_pcap_create_fromfile(char *filename, char *name, uint8_t *mac)
89{
90    return pico_pcap_create(filename, name, mac, PICO_PCAP_MODE_STORED);
91}
92
93struct pico_device *pico_pcap_create_live(char *ifname, char *name, uint8_t *mac)
94{
95    return pico_pcap_create(ifname, name, mac, PICO_PCAP_MODE_LIVE);
96}
97