-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpcap.c
127 lines (117 loc) · 2.66 KB
/
pcap.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "subr.h"
#include "global.h"
#include <pcap/pcap.h>
static void
pcap_init_if(struct thread *t)
{
int i, rc, fd, *dlt_buf, snaplen;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *pcap;
snaplen = 1500;
pcap = pcap_create(t->t_ifname, errbuf);
if (pcap == NULL) {
panic(0, "pcap_create('%s') failed (%s)", t->t_ifname, errbuf);
}
rc = pcap_set_immediate_mode(pcap, 1);
if (rc < 0) {
panic(0, "pcap_set_immediate_mode('%s', 1) failed (%s)",
t->t_ifname, pcap_geterr(pcap));
}
rc = pcap_set_promisc(pcap, 1);
if (rc < 0) {
panic(0, "pcap_set_promisc('%s', 1) failed (%s)",
t->t_ifname, pcap_geterr(pcap));
}
rc = pcap_set_snaplen(pcap, snaplen);
if (rc < 0) {
panic(0, "pcap_set_snaplen('%s', %d) failed (%s)",
t->t_ifname, snaplen, pcap_geterr(pcap));
}
rc = pcap_activate(pcap);
if (rc != 0) {
panic(0, "pcap_activate('%s') failed (%s)",
t->t_ifname, pcap_geterr(pcap));
}
rc = pcap_list_datalinks(pcap, &dlt_buf);
if (rc < 0) {
panic(0, "pcap_list_datatlinks('%s') failed (%s)",
t->t_ifname, pcap_geterr(pcap));
}
for (i = 0; i < rc; ++i) {
if (dlt_buf[i] == DLT_EN10MB) {
break;
}
}
if (i == rc) {
panic(0, "%s doesn't support DLT_EN10MB datalink type", t->t_ifname);
}
pcap_free_datalinks(dlt_buf);
pcap_setdirection(pcap, PCAP_D_IN);
rc = pcap_setnonblock(pcap, 1, errbuf);
if (rc < 0) {
panic(0, "pcap_setnonblock('%s') failed (%s)", t->t_ifname, errbuf);
}
fd = pcap_get_selectable_fd(pcap);
if (fd < 0) {
panic(0, "pcap_get_selectable_fd('%s') failed (%s)",
t->t_ifname, pcap_geterr(pcap));
}
t->t_pcap = pcap;
multiplexer_add(t, fd);
}
void
pcap_init_threads(struct thread *threads, int n_threads)
{
int i;
for (i = 0; i < n_threads; ++i) {
pcap_init_if(threads + i);
}
}
bool
pcap_is_tx_throttled(void)
{
return multiplexer_get_events(0) & POLLOUT;
}
void
pcap_init_tx_packet(struct packet *pkt)
{
pkt->pkt.buf = pkt->pkt_body;
pkt->pkt.len = 0;
}
bool
pcap_tx_packet(struct packet *pkt)
{
assert(pkt->pkt.len);
if (pcap_inject(current->t_pcap, pkt->pkt.buf, pkt->pkt.len) <= 0) {
add_pending_packet(pkt);
multiplexer_pollout(0);
return false;
} else {
return true;
}
}
int
pcap_rx(int queue_id)
{
int n, rc;
const u_char *pkt_dat;
struct pcap_pkthdr *pkt_hdr;
n = 0;
for (;;) {
rc = pcap_next_ex(current->t_pcap, &pkt_hdr, &pkt_dat);
if (rc == 1) {
io_process((void *)pkt_dat, pkt_hdr->caplen);
n++;
} else {
break;
}
}
return n;
}
struct transport_ops pcap_io_ops = {
.tr_io_init_op = pcap_init_threads,
.tr_io_is_tx_throttled_op = pcap_is_tx_throttled,
.tr_io_init_tx_packet_op = pcap_init_tx_packet,
.tr_io_tx_packet_op = pcap_tx_packet,
.tr_io_rx_op = pcap_rx,
};