~ubuntu-branches/ubuntu/saucy/suricata/saucy-updates

1.1.18 by Pierre Chifflier
Import upstream version 1.4
1
/* Copyright (C) 2011,2012 Open Information Security Foundation
1.1.10 by Pierre Chifflier
Import upstream version 1.1
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
1.1.18 by Pierre Chifflier
Import upstream version 1.4
19
 *  \defgroup afppacket AF_PACKET running mode
20
 *
21
 *  @{
22
 */
23
24
/**
1.1.10 by Pierre Chifflier
Import upstream version 1.1
25
 * \file
26
 *
27
 * \author Eric Leblond <eric@regit.org>
28
 *
29
 * AF_PACKET socket acquisition support
30
 *
31
 * \todo watch other interface event to detect suppression of the monitored
32
 *       interface
33
 */
34
35
#include "suricata-common.h"
36
#include "config.h"
37
#include "suricata.h"
38
#include "decode.h"
39
#include "packet-queue.h"
40
#include "threads.h"
41
#include "threadvars.h"
42
#include "tm-queuehandlers.h"
43
#include "tm-modules.h"
44
#include "tm-threads.h"
45
#include "tm-threads-common.h"
46
#include "conf.h"
47
#include "util-debug.h"
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
48
#include "util-device.h"
1.1.10 by Pierre Chifflier
Import upstream version 1.1
49
#include "util-error.h"
50
#include "util-privs.h"
51
#include "util-optimize.h"
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
52
#include "util-checksum.h"
1.1.18 by Pierre Chifflier
Import upstream version 1.4
53
#include "util-ioctl.h"
1.1.10 by Pierre Chifflier
Import upstream version 1.1
54
#include "tmqh-packetpool.h"
55
#include "source-af-packet.h"
1.1.13 by Pierre Chifflier
Import upstream version 1.3
56
#include "runmodes.h"
1.1.10 by Pierre Chifflier
Import upstream version 1.1
57
58
#ifdef HAVE_AF_PACKET
1.1.18 by Pierre Chifflier
Import upstream version 1.4
59
60
#if HAVE_SYS_IOCTL_H
1.1.10 by Pierre Chifflier
Import upstream version 1.1
61
#include <sys/ioctl.h>
1.1.18 by Pierre Chifflier
Import upstream version 1.4
62
#endif
63
64
#if HAVE_LINUX_IF_ETHER_H
1.1.10 by Pierre Chifflier
Import upstream version 1.1
65
#include <linux/if_ether.h>
1.1.18 by Pierre Chifflier
Import upstream version 1.4
66
#endif
67
68
#if HAVE_LINUX_IF_PACKET_H
1.1.10 by Pierre Chifflier
Import upstream version 1.1
69
#include <linux/if_packet.h>
1.1.18 by Pierre Chifflier
Import upstream version 1.4
70
#endif
71
72
#if HAVE_LINUX_IF_ARP_H
1.1.10 by Pierre Chifflier
Import upstream version 1.1
73
#include <linux/if_arp.h>
1.1.18 by Pierre Chifflier
Import upstream version 1.4
74
#endif
1.1.13 by Pierre Chifflier
Import upstream version 1.3
75
1.1.18 by Pierre Chifflier
Import upstream version 1.4
76
#if HAVE_LINUX_FILTER_H
1.1.13 by Pierre Chifflier
Import upstream version 1.3
77
#include <linux/filter.h>
1.1.10 by Pierre Chifflier
Import upstream version 1.1
78
#endif
79
1.1.18 by Pierre Chifflier
Import upstream version 1.4
80
#if HAVE_SYS_MMAN_H
1.1.13 by Pierre Chifflier
Import upstream version 1.3
81
#include <sys/mman.h>
1.1.18 by Pierre Chifflier
Import upstream version 1.4
82
#endif
83
84
#endif /* HAVE_AF_PACKET */
1.1.13 by Pierre Chifflier
Import upstream version 1.3
85
1.1.10 by Pierre Chifflier
Import upstream version 1.1
86
extern uint8_t suricata_ctl_flags;
87
extern int max_pending_packets;
88
89
#ifndef HAVE_AF_PACKET
90
91
TmEcode NoAFPSupportExit(ThreadVars *, void *, void **);
92
93
void TmModuleReceiveAFPRegister (void) {
94
    tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
95
    tmm_modules[TMM_RECEIVEAFP].ThreadInit = NoAFPSupportExit;
96
    tmm_modules[TMM_RECEIVEAFP].Func = NULL;
97
    tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = NULL;
98
    tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
99
    tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
100
    tmm_modules[TMM_RECEIVEAFP].cap_flags = 0;
101
    tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
102
}
103
104
/**
105
 * \brief Registration Function for DecodeAFP.
106
 * \todo Unit tests are needed for this module.
107
 */
108
void TmModuleDecodeAFPRegister (void) {
109
    tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
110
    tmm_modules[TMM_DECODEAFP].ThreadInit = NoAFPSupportExit;
111
    tmm_modules[TMM_DECODEAFP].Func = NULL;
112
    tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
113
    tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
114
    tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
115
    tmm_modules[TMM_DECODEAFP].cap_flags = 0;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
116
    tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
117
}
118
119
/**
120
 * \brief this function prints an error message and exits.
121
 */
122
TmEcode NoAFPSupportExit(ThreadVars *tv, void *initdata, void **data)
123
{
124
    SCLogError(SC_ERR_NO_AF_PACKET,"Error creating thread %s: you do not have "
125
               "support for AF_PACKET enabled, on Linux host please recompile "
126
               "with --enable-af-packet", tv->name);
127
    exit(EXIT_FAILURE);
128
}
129
130
#else /* We have AF_PACKET support */
131
132
#define AFP_IFACE_NAME_LENGTH 48
133
134
#define AFP_STATE_DOWN 0
135
#define AFP_STATE_UP 1
136
137
#define AFP_RECONNECT_TIMEOUT 500000
1.1.18 by Pierre Chifflier
Import upstream version 1.4
138
#define AFP_DOWN_COUNTER_INTERVAL 40
1.1.10 by Pierre Chifflier
Import upstream version 1.1
139
140
#define POLL_TIMEOUT 100
141
1.1.18 by Pierre Chifflier
Import upstream version 1.4
142
#ifndef TP_STATUS_USER_BUSY
143
/* for new use latest bit available in tp_status */
144
#define TP_STATUS_USER_BUSY (1 << 31)
145
#endif
146
1.1.13 by Pierre Chifflier
Import upstream version 1.3
147
/** protect pfring_set_bpf_filter, as it is not thread safe */
148
static SCMutex afpacket_bpf_set_filter_lock = PTHREAD_MUTEX_INITIALIZER;
149
1.1.10 by Pierre Chifflier
Import upstream version 1.1
150
enum {
151
    AFP_READ_OK,
152
    AFP_READ_FAILURE,
153
    AFP_FAILURE,
1.1.18 by Pierre Chifflier
Import upstream version 1.4
154
    AFP_KERNEL_DROP,
1.1.10 by Pierre Chifflier
Import upstream version 1.1
155
};
156
1.1.13 by Pierre Chifflier
Import upstream version 1.3
157
union thdr {
158
    struct tpacket2_hdr *h2;
159
    void *raw;
160
};
161
1.1.10 by Pierre Chifflier
Import upstream version 1.1
162
/**
163
 * \brief Structure to hold thread specific variables.
164
 */
165
typedef struct AFPThreadVars_
166
{
167
    /* thread specific socket */
168
    int socket;
169
    /* handle state */
170
    unsigned char afp_state;
171
172
    /* data link type for the thread */
173
    int datalink;
174
    int cooked;
175
176
    /* counters */
177
    uint32_t pkts;
178
    uint64_t bytes;
179
    uint32_t errs;
180
181
    ThreadVars *tv;
182
    TmSlot *slot;
183
184
    uint8_t *data; /** Per function and thread data */
185
    int datalen; /** Length of per function and thread data */
186
187
    char iface[AFP_IFACE_NAME_LENGTH];
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
188
    LiveDevice *livedev;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
189
    int down_count;
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
190
1.1.13 by Pierre Chifflier
Import upstream version 1.3
191
    /* Filter */
192
    char *bpf_filter;
193
1.1.10 by Pierre Chifflier
Import upstream version 1.1
194
    /* socket buffer size */
195
    int buffer_size;
196
    int promisc;
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
197
    ChecksumValidationMode checksum_mode;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
198
1.1.18 by Pierre Chifflier
Import upstream version 1.4
199
    /* IPS stuff */
200
    char out_iface[AFP_IFACE_NAME_LENGTH];
201
    AFPPeer *mpeer;
202
1.1.13 by Pierre Chifflier
Import upstream version 1.3
203
    int flags;
204
    uint16_t capture_kernel_packets;
205
    uint16_t capture_kernel_drops;
206
1.1.10 by Pierre Chifflier
Import upstream version 1.1
207
    int cluster_id;
208
    int cluster_type;
209
210
    int threads;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
211
    int copy_mode;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
212
1.1.13 by Pierre Chifflier
Import upstream version 1.3
213
    struct tpacket_req req;
214
    unsigned int tp_hdrlen;
215
    unsigned int ring_buflen;
216
    char *ring_buf;
217
    char *frame_buf;
218
    unsigned int frame_offset;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
219
    int ring_size;
220
1.1.10 by Pierre Chifflier
Import upstream version 1.1
221
} AFPThreadVars;
222
223
TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
224
TmEcode ReceiveAFPThreadInit(ThreadVars *, void *, void **);
225
void ReceiveAFPThreadExitStats(ThreadVars *, void *);
226
TmEcode ReceiveAFPThreadDeinit(ThreadVars *, void *);
227
TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot);
228
229
TmEcode DecodeAFPThreadInit(ThreadVars *, void *, void **);
230
TmEcode DecodeAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
231
1.1.13 by Pierre Chifflier
Import upstream version 1.3
232
TmEcode AFPSetBPFFilter(AFPThreadVars *ptv);
1.1.18 by Pierre Chifflier
Import upstream version 1.4
233
static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose);
234
static int AFPGetDevFlags(int fd, const char *ifname);
235
static int AFPDerefSocket(AFPPeer* peer);
236
static int AFPRefSocket(AFPPeer* peer);
1.1.13 by Pierre Chifflier
Import upstream version 1.3
237
1.1.10 by Pierre Chifflier
Import upstream version 1.1
238
/**
239
 * \brief Registration Function for RecieveAFP.
240
 * \todo Unit tests are needed for this module.
241
 */
242
void TmModuleReceiveAFPRegister (void) {
243
    tmm_modules[TMM_RECEIVEAFP].name = "ReceiveAFP";
244
    tmm_modules[TMM_RECEIVEAFP].ThreadInit = ReceiveAFPThreadInit;
245
    tmm_modules[TMM_RECEIVEAFP].Func = NULL;
246
    tmm_modules[TMM_RECEIVEAFP].PktAcqLoop = ReceiveAFPLoop;
247
    tmm_modules[TMM_RECEIVEAFP].ThreadExitPrintStats = ReceiveAFPThreadExitStats;
248
    tmm_modules[TMM_RECEIVEAFP].ThreadDeinit = NULL;
249
    tmm_modules[TMM_RECEIVEAFP].RegisterTests = NULL;
250
    tmm_modules[TMM_RECEIVEAFP].cap_flags = SC_CAP_NET_RAW;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
251
    tmm_modules[TMM_RECEIVEAFP].flags = TM_FLAG_RECEIVE_TM;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
252
}
253
1.1.18 by Pierre Chifflier
Import upstream version 1.4
254
255
/**
256
 *  \defgroup afppeers AFP peers list
257
 *
258
 * AF_PACKET has an IPS mode were interface are peered: packet from
259
 * on interface are sent the peered interface and the other way. The ::AFPPeer
260
 * list is maitaining the list of peers. Each ::AFPPeer is storing the needed
261
 * information to be able to send packet on the interface.
262
 * A element of the list must not be destroyed during the run of Suricata as it
263
 * is used by ::Packet and other threads.
264
 *
265
 *  @{
266
 */
267
268
typedef struct AFPPeersList_ {
269
    TAILQ_HEAD(, AFPPeer_) peers; /**< Head of list of fragments. */
270
    int cnt;
271
    int peered;
272
    int turn; /**< Next value for initialisation order */
273
    SC_ATOMIC_DECLARE(int, reached); /**< Counter used to synchronize start */
274
} AFPPeersList;
275
276
/**
277
 * \brief Update the peer.
278
 *
279
 * Update the AFPPeer of a thread ie set new state, socket number
280
 * or iface index.
281
 *
282
 */
283
void AFPPeerUpdate(AFPThreadVars *ptv)
284
{
285
    if (ptv->mpeer == NULL) {
286
        return;
287
    }
288
    (void)SC_ATOMIC_SET(ptv->mpeer->if_idx, AFPGetIfnumByDev(ptv->socket, ptv->iface, 0));
289
    (void)SC_ATOMIC_SET(ptv->mpeer->socket, ptv->socket);
290
    (void)SC_ATOMIC_SET(ptv->mpeer->state, ptv->afp_state);
291
}
292
293
/**
294
 * \brief Clean and free ressource used by an ::AFPPeer
295
 */
296
void AFPPeerClean(AFPPeer *peer)
297
{
298
    if (peer->flags & AFP_SOCK_PROTECT)
299
        SCMutexDestroy(&peer->sock_protect);
300
    SC_ATOMIC_DESTROY(peer->socket);
301
    SC_ATOMIC_DESTROY(peer->if_idx);
302
    SC_ATOMIC_DESTROY(peer->state);
303
    SCFree(peer);
304
}
305
306
AFPPeersList peerslist;
307
308
309
/**
310
 * \brief Init the global list of ::AFPPeer
311
 */
312
TmEcode AFPPeersListInit()
313
{
314
    SCEnter();
315
    TAILQ_INIT(&peerslist.peers);
316
    peerslist.peered = 0;
317
    peerslist.cnt = 0;
318
    peerslist.turn = 0;
319
    SC_ATOMIC_INIT(peerslist.reached);
320
    (void) SC_ATOMIC_SET(peerslist.reached, 0);
321
    SCReturnInt(TM_ECODE_OK);
322
}
323
324
/**
325
 * \brief Check that all ::AFPPeer got a peer
326
 *
327
 * \retval TM_ECODE_FAILED if some threads are not peered or TM_ECODE_OK else.
328
 */
329
TmEcode AFPPeersListCheck()
330
{
331
#define AFP_PEERS_MAX_TRY 4
332
#define AFP_PEERS_WAIT 20000
333
    int try = 0;
334
    SCEnter();
335
    while (try < AFP_PEERS_MAX_TRY) {
336
        if (peerslist.cnt != peerslist.peered) {
337
            usleep(AFP_PEERS_WAIT);
338
        } else {
339
            SCReturnInt(TM_ECODE_OK);
340
        }
341
        try++;
342
    }
343
    SCLogError(SC_ERR_AFP_CREATE, "Threads number not equals");
344
    SCReturnInt(TM_ECODE_FAILED);
345
}
346
347
/**
348
 * \brief Declare a new AFP thread to AFP peers list.
349
 */
350
TmEcode AFPPeersListAdd(AFPThreadVars *ptv)
351
{
352
    SCEnter();
353
    AFPPeer *peer = SCMalloc(sizeof(AFPPeer));
354
    AFPPeer *pitem;
355
    int mtu, out_mtu;
356
357
    if (unlikely(peer == NULL)) {
358
        SCReturnInt(TM_ECODE_FAILED);
359
    }
360
    memset(peer, 0, sizeof(AFPPeer));
361
    SC_ATOMIC_INIT(peer->socket);
362
    SC_ATOMIC_INIT(peer->sock_usage);
363
    SC_ATOMIC_INIT(peer->if_idx);
364
    SC_ATOMIC_INIT(peer->state);
365
    peer->flags = ptv->flags;
366
    peer->turn = peerslist.turn++;
367
368
    if (peer->flags & AFP_SOCK_PROTECT) {
369
        SCMutexInit(&peer->sock_protect, NULL);
370
    }
371
372
    (void)SC_ATOMIC_SET(peer->sock_usage, 0);
373
    (void)SC_ATOMIC_SET(peer->state, AFP_STATE_DOWN);
374
    strlcpy(peer->iface, ptv->iface, AFP_IFACE_NAME_LENGTH);
375
    ptv->mpeer = peer;
376
    /* add element to iface list */
377
    TAILQ_INSERT_TAIL(&peerslist.peers, peer, next);
378
379
    if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
380
        peerslist.cnt++;
381
382
        /* Iter to find a peer */
383
        TAILQ_FOREACH(pitem, &peerslist.peers, next) {
384
            if (pitem->peer)
385
                continue;
386
            if (strcmp(pitem->iface, ptv->out_iface))
387
                continue;
388
            peer->peer = pitem;
389
            pitem->peer = peer;
390
            mtu = GetIfaceMTU(ptv->iface);
391
            out_mtu = GetIfaceMTU(ptv->out_iface);
392
            if (mtu != out_mtu) {
393
                SCLogError(SC_ERR_AFP_CREATE,
394
                        "MTU on %s (%d) and %s (%d) are not equal, "
395
                        "transmission of packets bigger than %d will fail.",
396
                        ptv->iface, mtu,
397
                        ptv->out_iface, out_mtu,
398
                        (out_mtu > mtu) ? mtu : out_mtu);
399
            }
400
            peerslist.peered += 2;
401
            break;
402
        }
403
    }
404
405
    AFPPeerUpdate(ptv);
406
407
    SCReturnInt(TM_ECODE_OK);
408
}
409
410
int AFPPeersListWaitTurn(AFPPeer *peer)
411
{
412
    /* If turn is zero, we already have started threads once */
413
    if (peerslist.turn == 0)
414
        return 0;
415
416
    if (peer->turn == SC_ATOMIC_GET(peerslist.reached))
417
        return 0;
418
    return 1;
419
}
420
421
void AFPPeersListReachedInc()
422
{
423
    if (peerslist.turn == 0)
424
        return;
425
426
    if (SC_ATOMIC_ADD(peerslist.reached, 1) == peerslist.turn) {
427
        SCLogInfo("All AFP capture threads are running.");
428
        (void)SC_ATOMIC_SET(peerslist.reached, 0);
429
        /* Set turn to 0 to skip syncrhonization when ReceiveAFPLoop is
430
         * restarted.
431
         */
432
        peerslist.turn = 0;
433
    }
434
}
435
436
/**
437
 * \brief Clean the global peers list.
438
 */
439
void AFPPeersListClean()
440
{
441
    AFPPeer *pitem;
442
443
    while ((pitem = TAILQ_FIRST(&peerslist.peers))) {
444
        TAILQ_REMOVE(&peerslist.peers, pitem, next);
445
        AFPPeerClean(pitem);
446
    }
447
}
448
449
/**
450
 * @}
451
 */
452
1.1.10 by Pierre Chifflier
Import upstream version 1.1
453
/**
454
 * \brief Registration Function for DecodeAFP.
455
 * \todo Unit tests are needed for this module.
456
 */
457
void TmModuleDecodeAFPRegister (void) {
458
    tmm_modules[TMM_DECODEAFP].name = "DecodeAFP";
459
    tmm_modules[TMM_DECODEAFP].ThreadInit = DecodeAFPThreadInit;
460
    tmm_modules[TMM_DECODEAFP].Func = DecodeAFP;
461
    tmm_modules[TMM_DECODEAFP].ThreadExitPrintStats = NULL;
462
    tmm_modules[TMM_DECODEAFP].ThreadDeinit = NULL;
463
    tmm_modules[TMM_DECODEAFP].RegisterTests = NULL;
464
    tmm_modules[TMM_DECODEAFP].cap_flags = 0;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
465
    tmm_modules[TMM_DECODEAFP].flags = TM_FLAG_DECODE_TM;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
466
}
467
1.1.18 by Pierre Chifflier
Import upstream version 1.4
468
1.1.10 by Pierre Chifflier
Import upstream version 1.1
469
static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose);
470
1.1.18 by Pierre Chifflier
Import upstream version 1.4
471
static inline void AFPDumpCounters(AFPThreadVars *ptv)
1.1.13 by Pierre Chifflier
Import upstream version 1.3
472
{
473
#ifdef PACKET_STATISTICS
1.1.18 by Pierre Chifflier
Import upstream version 1.4
474
    struct tpacket_stats kstats;
475
    socklen_t len = sizeof (struct tpacket_stats);
476
    if (getsockopt(ptv->socket, SOL_PACKET, PACKET_STATISTICS,
477
                &kstats, &len) > -1) {
478
        SCLogDebug("(%s) Kernel: Packets %" PRIu32 ", dropped %" PRIu32 "",
479
                ptv->tv->name,
480
                kstats.tp_packets, kstats.tp_drops);
481
        SCPerfCounterAddUI64(ptv->capture_kernel_packets, ptv->tv->sc_perf_pca, kstats.tp_packets);
482
        SCPerfCounterAddUI64(ptv->capture_kernel_drops, ptv->tv->sc_perf_pca, kstats.tp_drops);
483
        (void) SC_ATOMIC_ADD(ptv->livedev->drop, kstats.tp_drops);
484
    }
1.1.13 by Pierre Chifflier
Import upstream version 1.3
485
#endif
486
}
1.1.10 by Pierre Chifflier
Import upstream version 1.1
487
488
/**
489
 * \brief AF packet read function.
490
 *
491
 * This function fills
492
 * From here the packets are picked up by the DecodeAFP thread.
493
 *
494
 * \param user pointer to AFPThreadVars
495
 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
496
 */
497
int AFPRead(AFPThreadVars *ptv)
498
{
499
    Packet *p = NULL;
500
    /* XXX should try to use read that get directly to packet */
501
    int offset = 0;
502
    int caplen;
503
    struct sockaddr_ll from;
504
    struct iovec iov;
505
    struct msghdr msg;
506
    struct cmsghdr *cmsg;
507
    union {
508
        struct cmsghdr cmsg;
509
        char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
510
    } cmsg_buf;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
511
    unsigned char aux_checksum = 0;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
512
513
    msg.msg_name = &from;
514
    msg.msg_namelen = sizeof(from);
515
    msg.msg_iov = &iov;
516
    msg.msg_iovlen = 1;
517
    msg.msg_control = &cmsg_buf;
518
    msg.msg_controllen = sizeof(cmsg_buf);
519
    msg.msg_flags = 0;
520
521
    if (ptv->cooked)
522
        offset = SLL_HEADER_LEN;
523
    else
524
        offset = 0;
525
    iov.iov_len = ptv->datalen - offset;
526
    iov.iov_base = ptv->data + offset;
527
528
    caplen = recvmsg(ptv->socket, &msg, MSG_TRUNC);
529
530
    if (caplen < 0) {
531
        SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
532
                errno);
533
        SCReturnInt(AFP_READ_FAILURE);
534
    }
535
536
    p = PacketGetFromQueueOrAlloc();
537
    if (p == NULL) {
538
        SCReturnInt(AFP_FAILURE);
539
    }
1.1.18 by Pierre Chifflier
Import upstream version 1.4
540
    PKT_SET_SRC(p, PKT_SRC_WIRE);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
541
542
    /* get timestamp of packet via ioctl */
543
    if (ioctl(ptv->socket, SIOCGSTAMP, &p->ts) == -1) {
544
        SCLogWarning(SC_ERR_AFP_READ, "recvmsg failed with error code %" PRId32,
545
                errno);
546
        TmqhOutputPacketpool(ptv->tv, p);
547
        SCReturnInt(AFP_READ_FAILURE);
548
    }
549
550
    ptv->pkts++;
551
    ptv->bytes += caplen + offset;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
552
    (void) SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
553
    p->livedev = ptv->livedev;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
554
555
    /* add forged header */
556
    if (ptv->cooked) {
557
        SllHdr * hdrp = (SllHdr *)ptv->data;
558
        /* XXX this is minimalist, but this seems enough */
559
        hdrp->sll_protocol = from.sll_protocol;
560
    }
561
562
    p->datalink = ptv->datalink;
563
    SET_PKT_LEN(p, caplen + offset);
564
    if (PacketCopyData(p, ptv->data, GET_PKT_LEN(p)) == -1) {
565
        TmqhOutputPacketpool(ptv->tv, p);
566
        SCReturnInt(AFP_FAILURE);
567
    }
568
    SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
569
               GET_PKT_LEN(p), p, GET_PKT_DATA(p));
570
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
571
    /* We only check for checksum disable */
572
    if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
573
        p->flags |= PKT_IGNORE_CHECKSUM;
574
    } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
575
        if (ptv->livedev->ignore_checksum) {
576
            p->flags |= PKT_IGNORE_CHECKSUM;
577
        } else if (ChecksumAutoModeCheck(ptv->pkts,
578
                                          SC_ATOMIC_GET(ptv->livedev->pkts),
579
                                          SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
580
            ptv->livedev->ignore_checksum = 1;
581
            p->flags |= PKT_IGNORE_CHECKSUM;
582
        }
583
    } else {
1.1.13 by Pierre Chifflier
Import upstream version 1.3
584
        aux_checksum = 1;
585
    }
586
587
    /* List is NULL if we don't have activated auxiliary data */
588
    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
589
        struct tpacket_auxdata *aux;
590
591
        if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
592
                cmsg->cmsg_level != SOL_PACKET ||
593
                cmsg->cmsg_type != PACKET_AUXDATA)
594
            continue;
595
596
        aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
597
598
        if (aux_checksum && (aux->tp_status & TP_STATUS_CSUMNOTREADY)) {
599
            p->flags |= PKT_IGNORE_CHECKSUM;
600
        }
601
        break;
602
    }
603
604
    if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
605
        TmqhOutputPacketpool(ptv->tv, p);
606
        SCReturnInt(AFP_FAILURE);
607
    }
608
    SCReturnInt(AFP_READ_OK);
609
}
610
1.1.18 by Pierre Chifflier
Import upstream version 1.4
611
TmEcode AFPWritePacket(Packet *p)
612
{
613
    struct sockaddr_ll socket_address;
614
    int socket;
615
616
    if (p->afp_v.copy_mode == AFP_COPY_MODE_IPS) {
617
        if (p->action & ACTION_DROP) {
618
            return TM_ECODE_OK;
619
        }
620
    }
621
622
    if (SC_ATOMIC_GET(p->afp_v.peer->state) == AFP_STATE_DOWN)
623
        return TM_ECODE_OK;
624
625
    if (p->ethh == NULL) {
626
        SCLogWarning(SC_ERR_INVALID_VALUE, "Should have an Ethernet header");
627
        return TM_ECODE_FAILED;
628
    }
629
    /* Index of the network device */
630
    socket_address.sll_ifindex = SC_ATOMIC_GET(p->afp_v.peer->if_idx);
631
    /* Address length*/
632
    socket_address.sll_halen = ETH_ALEN;
633
    /* Destination MAC */
634
    memcpy(socket_address.sll_addr, p->ethh, 6);
635
636
    /* Send packet, locking the socket if necessary */
637
    if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
638
        SCMutexLock(&p->afp_v.peer->sock_protect);
639
    socket = SC_ATOMIC_GET(p->afp_v.peer->socket);
640
    if (sendto(socket, GET_PKT_DATA(p), GET_PKT_LEN(p), 0,
641
               (struct sockaddr*) &socket_address,
642
               sizeof(struct sockaddr_ll)) < 0) {
643
        SCLogWarning(SC_ERR_SOCKET, "Sending packet failed on socket %d: %s",
644
                  socket,
645
                  strerror(errno));
646
        if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
647
            SCMutexUnlock(&p->afp_v.peer->sock_protect);
648
        return TM_ECODE_FAILED;
649
    }
650
    if (p->afp_v.peer->flags & AFP_SOCK_PROTECT)
651
        SCMutexUnlock(&p->afp_v.peer->sock_protect);
652
653
    return TM_ECODE_OK;
654
}
655
656
TmEcode AFPReleaseDataFromRing(ThreadVars *t, Packet *p)
657
{
658
    int ret = TM_ECODE_OK;
659
    /* Need to be in copy mode and need to detect early release
660
       where Ethernet header could not be set (and pseudo packet) */
661
    if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
662
        ret = AFPWritePacket(p);
663
    }
664
665
    if (AFPDerefSocket(p->afp_v.mpeer) == 0)
666
        goto cleanup;
667
668
    if (p->afp_v.relptr) {
669
        union thdr h;
670
        h.raw = p->afp_v.relptr;
671
        h.h2->tp_status = TP_STATUS_KERNEL;
672
    }
673
674
cleanup:
675
    AFPV_CLEANUP(&p->afp_v);
676
    return ret;
677
}
678
1.1.13 by Pierre Chifflier
Import upstream version 1.3
679
/**
680
 * \brief AF packet read function for ring
681
 *
682
 * This function fills
683
 * From here the packets are picked up by the DecodeAFP thread.
684
 *
685
 * \param user pointer to AFPThreadVars
686
 * \retval TM_ECODE_FAILED on failure and TM_ECODE_OK on success
687
 */
688
int AFPReadFromRing(AFPThreadVars *ptv)
689
{
690
    Packet *p = NULL;
691
    union thdr h;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
692
    struct sockaddr_ll *from;
693
    uint8_t emergency_flush = 0;
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
694
    int read_pkts = 0;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
695
    int loop_start = -1;
696
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
697
698
    /* Loop till we have packets available */
699
    while (1) {
1.1.18 by Pierre Chifflier
Import upstream version 1.4
700
        if (unlikely(suricata_ctl_flags != 0)) {
701
            break;
702
        }
703
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
704
        /* Read packet from ring */
705
        h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
706
        if (h.raw == NULL) {
707
            SCReturnInt(AFP_FAILURE);
708
        }
1.1.18 by Pierre Chifflier
Import upstream version 1.4
709
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
710
        if (h.h2->tp_status == TP_STATUS_KERNEL) {
711
            if (read_pkts == 0) {
1.1.18 by Pierre Chifflier
Import upstream version 1.4
712
                if (loop_start == -1) {
713
                    loop_start = ptv->frame_offset;
714
                } else if (unlikely(loop_start == (int)ptv->frame_offset)) {
715
                    SCReturnInt(AFP_READ_OK);
716
                }
717
                if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
718
                    ptv->frame_offset = 0;
719
                }
720
                continue;
721
            }
722
            if ((emergency_flush) && (ptv->flags & AFP_EMERGENCY_MODE)) {
723
                SCReturnInt(AFP_KERNEL_DROP);
724
            } else {
725
                SCReturnInt(AFP_READ_OK);
726
            }
727
        }
728
729
        read_pkts++;
730
        loop_start = -1;
731
732
        /* Our packet is still used by suricata, we exit read loop to
733
         * gain some time */
734
        if (h.h2->tp_status & TP_STATUS_USER_BUSY) {
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
735
            SCReturnInt(AFP_READ_OK);
736
        }
737
1.1.18 by Pierre Chifflier
Import upstream version 1.4
738
        if ((ptv->flags & AFP_EMERGENCY_MODE) && (emergency_flush == 1)) {
739
            h.h2->tp_status = TP_STATUS_KERNEL;
740
            goto next_frame;
741
        }
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
742
743
        p = PacketGetFromQueueOrAlloc();
744
        if (p == NULL) {
745
            SCReturnInt(AFP_FAILURE);
746
        }
1.1.18 by Pierre Chifflier
Import upstream version 1.4
747
        PKT_SET_SRC(p, PKT_SRC_WIRE);
748
749
        /* Suricata will treat packet so telling it is busy, this
750
         * status will be reset to 0 (ie TP_STATUS_KERNEL) in the release
751
         * function. */
752
        h.h2->tp_status |= TP_STATUS_USER_BUSY;
753
754
        from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
755
756
        ptv->pkts++;
757
        ptv->bytes += h.h2->tp_len;
758
        (void) SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
759
        p->livedev = ptv->livedev;
760
761
        /* add forged header */
762
        if (ptv->cooked) {
763
            SllHdr * hdrp = (SllHdr *)ptv->data;
764
            /* XXX this is minimalist, but this seems enough */
765
            hdrp->sll_protocol = from->sll_protocol;
766
        }
767
768
        p->datalink = ptv->datalink;
769
        if (h.h2->tp_len > h.h2->tp_snaplen) {
770
            SCLogDebug("Packet length (%d) > snaplen (%d), truncating",
771
                    h.h2->tp_len, h.h2->tp_snaplen);
772
        }
773
        if (ptv->flags & AFP_ZERO_COPY) {
774
            if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
775
                TmqhOutputPacketpool(ptv->tv, p);
776
                SCReturnInt(AFP_FAILURE);
1.1.18 by Pierre Chifflier
Import upstream version 1.4
777
            } else {
778
                p->afp_v.relptr = h.raw;
779
                p->ReleaseData = AFPReleaseDataFromRing;
780
                p->afp_v.mpeer = ptv->mpeer;
781
                AFPRefSocket(ptv->mpeer);
782
783
                p->afp_v.copy_mode = ptv->copy_mode;
784
                if (p->afp_v.copy_mode != AFP_COPY_MODE_NONE) {
785
                    p->afp_v.peer = ptv->mpeer->peer;
786
                } else {
787
                    p->afp_v.peer = NULL;
788
                }
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
789
            }
790
        } else {
791
            if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
792
                TmqhOutputPacketpool(ptv->tv, p);
793
                SCReturnInt(AFP_FAILURE);
794
            }
795
        }
796
        /* Timestamp */
797
        p->ts.tv_sec = h.h2->tp_sec;
798
        p->ts.tv_usec = h.h2->tp_nsec/1000;
799
        SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
800
                GET_PKT_LEN(p), p, GET_PKT_DATA(p));
801
802
        /* We only check for checksum disable */
803
        if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
804
            p->flags |= PKT_IGNORE_CHECKSUM;
805
        } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
806
            if (ptv->livedev->ignore_checksum) {
807
                p->flags |= PKT_IGNORE_CHECKSUM;
808
            } else if (ChecksumAutoModeCheck(ptv->pkts,
809
                        SC_ATOMIC_GET(ptv->livedev->pkts),
810
                        SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
811
                ptv->livedev->ignore_checksum = 1;
812
                p->flags |= PKT_IGNORE_CHECKSUM;
813
            }
814
        } else {
815
            if (h.h2->tp_status & TP_STATUS_CSUMNOTREADY) {
816
                p->flags |= PKT_IGNORE_CHECKSUM;
817
            }
818
        }
1.1.18 by Pierre Chifflier
Import upstream version 1.4
819
        if (h.h2->tp_status & TP_STATUS_LOSING) {
820
            emergency_flush = 1;
821
            AFPDumpCounters(ptv);
822
        }
823
824
        /* release frame if not in zero copy mode */
825
        if (!(ptv->flags &  AFP_ZERO_COPY)) {
826
            h.h2->tp_status = TP_STATUS_KERNEL;
827
        }
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
828
829
        if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
830
            h.h2->tp_status = TP_STATUS_KERNEL;
831
            if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
832
                ptv->frame_offset = 0;
833
            }
834
            TmqhOutputPacketpool(ptv->tv, p);
835
            SCReturnInt(AFP_FAILURE);
836
        }
837
1.1.18 by Pierre Chifflier
Import upstream version 1.4
838
next_frame:
1.1.13 by Pierre Chifflier
Import upstream version 1.3
839
        if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
840
            ptv->frame_offset = 0;
1.1.19 by Pierre Chifflier
Import upstream version 1.4.1
841
            /* Get out of loop to be sure we will reach maintenance tasks */
842
            SCReturnInt(AFP_READ_OK);
1.1.13 by Pierre Chifflier
Import upstream version 1.3
843
        }
844
    }
845
1.1.10 by Pierre Chifflier
Import upstream version 1.1
846
    SCReturnInt(AFP_READ_OK);
847
}
848
1.1.18 by Pierre Chifflier
Import upstream version 1.4
849
/**
850
 * \brief Reference socket
851
 *
852
 * \retval O in case of failure, 1 in case of success
853
 */
854
static int AFPRefSocket(AFPPeer* peer)
855
{
856
    if (unlikely(peer == NULL))
857
        return 0;
858
859
    (void)SC_ATOMIC_ADD(peer->sock_usage, 1);
860
    return 1;
861
}
862
863
864
/**
865
 * \brief Dereference socket
866
 *
867
 * \retval 1 if socket is still alive, 0 if not
868
 */
869
static int AFPDerefSocket(AFPPeer* peer)
870
{
871
    if (SC_ATOMIC_SUB(peer->sock_usage, 1) == 0) {
872
        if (SC_ATOMIC_GET(peer->state) == AFP_STATE_DOWN) {
873
            SCLogInfo("Cleaning socket connected to '%s'", peer->iface);
874
            close(SC_ATOMIC_GET(peer->socket));
875
            return 0;
876
        }
877
    }
878
    return 1;
879
}
880
881
void AFPSwitchState(AFPThreadVars *ptv, int state)
882
{
883
    ptv->afp_state = state;
884
    ptv->down_count = 0;
885
886
    AFPPeerUpdate(ptv);
887
888
    /* Do cleaning if switching to down state */
889
    if (state == AFP_STATE_DOWN) {
890
        if (ptv->frame_buf) {
891
            /* only used in reading phase, we can free it */
892
            SCFree(ptv->frame_buf);
893
            ptv->frame_buf = NULL;
894
        }
895
        if (ptv->socket != -1) {
896
            /* we need to wait for all packets to return data */
897
            if (SC_ATOMIC_SUB(ptv->mpeer->sock_usage, 1) == 0) {
898
                SCLogInfo("Cleaning socket connected to '%s'", ptv->iface);
899
                close(ptv->socket);
900
                ptv->socket = -1;
901
            }
902
        }
903
    }
904
    if (state == AFP_STATE_UP) {
905
         (void)SC_ATOMIC_SET(ptv->mpeer->sock_usage, 1);
906
    }
907
}
908
909
/**
910
 * \brief Try to reopen socket
911
 *
912
 * \retval 0 in case of success, negative if error occurs or a condition
913
 * is not met.
914
 */
1.1.10 by Pierre Chifflier
Import upstream version 1.1
915
static int AFPTryReopen(AFPThreadVars *ptv)
916
{
917
    int afp_activate_r;
918
1.1.18 by Pierre Chifflier
Import upstream version 1.4
919
    ptv->down_count++;
920
921
922
    /* Don't reconnect till we have packet that did not release data */
923
    if (SC_ATOMIC_GET(ptv->mpeer->sock_usage) != 0) {
924
        return -1;
925
    }
1.1.10 by Pierre Chifflier
Import upstream version 1.1
926
927
    afp_activate_r = AFPCreateSocket(ptv, ptv->iface, 0);
928
    if (afp_activate_r != 0) {
1.1.18 by Pierre Chifflier
Import upstream version 1.4
929
        if (ptv->down_count % AFP_DOWN_COUNTER_INTERVAL == 0) {
930
            SCLogWarning(SC_ERR_AFP_CREATE, "Can not open iface '%s'",
931
                         ptv->iface);
932
        }
1.1.10 by Pierre Chifflier
Import upstream version 1.1
933
        return afp_activate_r;
934
    }
935
1.1.18 by Pierre Chifflier
Import upstream version 1.4
936
    SCLogInfo("Interface '%s' is back", ptv->iface);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
937
    return 0;
938
}
939
940
/**
941
 *  \brief Main AF_PACKET reading Loop function
942
 */
943
TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
944
{
1.1.18 by Pierre Chifflier
Import upstream version 1.4
945
    SCEnter();
946
1.1.10 by Pierre Chifflier
Import upstream version 1.1
947
    uint16_t packet_q_len = 0;
948
    AFPThreadVars *ptv = (AFPThreadVars *)data;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
949
    struct pollfd fds;
950
    int r;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
951
    TmSlot *s = (TmSlot *)slot;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
952
    time_t last_dump = 0;
953
    struct timeval current_time;
954
1.1.10 by Pierre Chifflier
Import upstream version 1.1
955
    ptv->slot = s->slot_next;
956
1.1.18 by Pierre Chifflier
Import upstream version 1.4
957
    if (ptv->afp_state == AFP_STATE_DOWN) {
958
        /* Wait for our turn, threads before us must have opened the socket */
959
        while (AFPPeersListWaitTurn(ptv->mpeer)) {
960
            usleep(1000);
961
        }
962
        r = AFPCreateSocket(ptv, ptv->iface, 1);
963
        if (r < 0) {
964
            SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket");
965
        }
966
        AFPPeersListReachedInc();
967
    }
968
    if (ptv->afp_state == AFP_STATE_UP) {
969
        SCLogInfo("Thread %s using socket %d", tv->name, ptv->socket);
970
    }
1.1.10 by Pierre Chifflier
Import upstream version 1.1
971
972
    fds.fd = ptv->socket;
973
    fds.events = POLLIN;
974
975
    while (1) {
976
        /* Start by checking the state of our interface */
977
        if (unlikely(ptv->afp_state == AFP_STATE_DOWN)) {
978
            int dbreak = 0;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
979
1.1.10 by Pierre Chifflier
Import upstream version 1.1
980
            do {
981
                usleep(AFP_RECONNECT_TIMEOUT);
982
                if (suricata_ctl_flags != 0) {
983
                    dbreak = 1;
984
                    break;
985
                }
986
                r = AFPTryReopen(ptv);
1.1.14 by Pierre Chifflier
Import upstream version 1.3.2
987
                fds.fd = ptv->socket;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
988
            } while (r < 0);
989
            if (dbreak == 1)
990
                break;
991
        }
992
993
        /* make sure we have at least one packet in the packet pool, to prevent
994
         * us from alloc'ing packets at line rate */
995
        do {
996
            packet_q_len = PacketPoolSize();
997
            if (unlikely(packet_q_len == 0)) {
998
                PacketPoolWait();
999
            }
1000
        } while (packet_q_len == 0);
1001
1002
        r = poll(&fds, 1, POLL_TIMEOUT);
1003
1004
        if (suricata_ctl_flags != 0) {
1005
            break;
1006
        }
1007
1008
        if (r > 0 &&
1009
                (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1010
            if (fds.revents & (POLLHUP | POLLRDHUP)) {
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1011
                AFPSwitchState(ptv, AFP_STATE_DOWN);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1012
                continue;
1013
            } else if (fds.revents & POLLERR) {
1014
                char c;
1015
                /* Do a recv to get errno */
1016
                if (recv(ptv->socket, &c, sizeof c, MSG_PEEK) != -1)
1017
                    continue; /* what, no error? */
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1018
                SCLogError(SC_ERR_AFP_READ,
1019
                           "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1020
                           ptv->iface, errno, strerror(errno));
1021
                AFPSwitchState(ptv, AFP_STATE_DOWN);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1022
                continue;
1023
            } else if (fds.revents & POLLNVAL) {
1024
                SCLogError(SC_ERR_AFP_READ, "Invalid polling request");
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1025
                AFPSwitchState(ptv, AFP_STATE_DOWN);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1026
                continue;
1027
            }
1028
        } else if (r > 0) {
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1029
            if (ptv->flags & AFP_RING_MODE) {
1030
                r = AFPReadFromRing(ptv);
1031
            } else {
1032
                /* AFPRead will call TmThreadsSlotProcessPkt on read packets */
1033
                r = AFPRead(ptv);
1034
            }
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1035
            switch (r) {
1036
                case AFP_READ_FAILURE:
1037
                    /* AFPRead in error: best to reset the socket */
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1038
                    SCLogError(SC_ERR_AFP_READ,
1039
                           "AFPRead error reading data from iface '%s': (%d" PRIu32 ") %s",
1040
                           ptv->iface, errno, strerror(errno));
1041
                    AFPSwitchState(ptv, AFP_STATE_DOWN);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1042
                    continue;
1043
                case AFP_FAILURE:
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1044
                    AFPSwitchState(ptv, AFP_STATE_DOWN);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1045
                    SCReturnInt(TM_ECODE_FAILED);
1046
                    break;
1047
                case AFP_READ_OK:
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1048
                    /* Trigger one dump of stats every second */
1049
                    TimeGet(&current_time);
1050
                    if (current_time.tv_sec != last_dump) {
1051
                        AFPDumpCounters(ptv);
1052
                        last_dump = current_time.tv_sec;
1053
                    }
1054
                    break;
1055
                case AFP_KERNEL_DROP:
1056
                    AFPDumpCounters(ptv);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1057
                    break;
1058
            }
1059
        } else if ((r < 0) && (errno != EINTR)) {
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1060
            SCLogError(SC_ERR_AFP_READ, "Error reading data from iface '%s': (%d" PRIu32 ") %s",
1061
                       ptv->iface,
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1062
                       errno, strerror(errno));
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1063
            AFPSwitchState(ptv, AFP_STATE_DOWN);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1064
            continue;
1065
        }
1066
        SCPerfSyncCountersIfSignalled(tv, 0);
1067
    }
1068
1069
    SCReturnInt(TM_ECODE_OK);
1070
}
1071
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1072
static int AFPGetDevFlags(int fd, const char *ifname)
1073
{
1074
    struct ifreq ifr;
1075
1076
    memset(&ifr, 0, sizeof(ifr));
1077
    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1078
1079
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
1080
        SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1081
                   ifname, strerror(errno));
1082
        return -1;
1083
    }
1084
1085
    return ifr.ifr_flags;
1086
}
1087
1088
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1089
static int AFPGetIfnumByDev(int fd, const char *ifname, int verbose)
1090
{
1091
    struct ifreq ifr;
1092
1093
    memset(&ifr, 0, sizeof(ifr));
1094
    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1095
1096
    if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
1097
           if (verbose)
1098
               SCLogError(SC_ERR_AFP_CREATE, "Unable to find iface %s: %s",
1099
                          ifname, strerror(errno));
1100
        return -1;
1101
    }
1102
1103
    return ifr.ifr_ifindex;
1104
}
1105
1106
static int AFPGetDevLinktype(int fd, const char *ifname)
1107
{
1108
    struct ifreq ifr;
1109
1110
    memset(&ifr, 0, sizeof(ifr));
1111
    strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1112
1113
    if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
1114
        SCLogError(SC_ERR_AFP_CREATE, "Unable to find type for iface \"%s\": %s",
1115
                   ifname, strerror(errno));
1116
        return -1;
1117
    }
1118
1119
    switch (ifr.ifr_hwaddr.sa_family) {
1120
        case ARPHRD_LOOPBACK:
1121
            return LINKTYPE_ETHERNET;
1122
        case ARPHRD_PPP:
1123
            return LINKTYPE_RAW;
1124
        default:
1125
            return ifr.ifr_hwaddr.sa_family;
1126
    }
1127
}
1128
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1129
static int AFPComputeRingParams(AFPThreadVars *ptv, int order)
1130
{
1131
    /* Compute structure:
1132
       Target is to store all pending packets
1133
       with a size equal to MTU + auxdata
1134
       And we keep a decent number of block
1135
1136
       To do so:
1137
       Compute frame_size (aligned to be able to fit in block
1138
       Check which block size we need. Blocksize is a 2^n * pagesize
1139
       We then need to get order, big enough to have
1140
       frame_size < block size
1141
       Find number of frame per block (divide)
1142
       Fill in packet_req
1143
1144
       Compute frame size:
1145
       described in packet_mmap.txt
1146
       dependant on snaplen (need to use a variable ?)
1147
snaplen: MTU ?
1148
tp_hdrlen determine_version in daq_afpacket
1149
in V1:  sizeof(struct tpacket_hdr);
1150
in V2: val in getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len)
1151
frame size: TPACKET_ALIGN(snaplen + TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1152
1153
     */
1154
    int tp_hdrlen = sizeof(struct tpacket_hdr);
1155
    int snaplen = default_packet_size;
1156
1157
    ptv->req.tp_frame_size = TPACKET_ALIGN(snaplen +TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1158
    ptv->req.tp_block_size = getpagesize() << order;
1159
    int frames_per_block = ptv->req.tp_block_size / ptv->req.tp_frame_size;
1160
    if (frames_per_block == 0) {
1161
        SCLogInfo("frame size to big");
1162
        return -1;
1163
    }
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1164
    ptv->req.tp_frame_nr = ptv->ring_size;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1165
    ptv->req.tp_block_nr = ptv->req.tp_frame_nr / frames_per_block + 1;
1166
    /* exact division */
1167
    ptv->req.tp_frame_nr = ptv->req.tp_block_nr * frames_per_block;
1168
    SCLogInfo("AF_PACKET RX Ring params: block_size=%d block_nr=%d frame_size=%d frame_nr=%d",
1169
              ptv->req.tp_block_size, ptv->req.tp_block_nr,
1170
              ptv->req.tp_frame_size, ptv->req.tp_frame_nr);
1171
    return 1;
1172
}
1173
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1174
static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
1175
{
1176
    int r;
1177
    struct packet_mreq sock_params;
1178
    struct sockaddr_ll bind_address;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1179
    int order;
1180
    unsigned int i;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1181
    int if_idx;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1182
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1183
    /* open socket */
1184
    ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1185
    if (ptv->socket == -1) {
1186
        SCLogError(SC_ERR_AFP_CREATE, "Couldn't create a AF_PACKET socket, error %s", strerror(errno));
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1187
        goto error;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1188
    }
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1189
    if_idx = AFPGetIfnumByDev(ptv->socket, devname, verbose);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1190
    /* bind socket */
1191
    memset(&bind_address, 0, sizeof(bind_address));
1192
    bind_address.sll_family = AF_PACKET;
1193
    bind_address.sll_protocol = htons(ETH_P_ALL);
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1194
    bind_address.sll_ifindex = if_idx;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1195
    if (bind_address.sll_ifindex == -1) {
1196
        if (verbose)
1197
            SCLogError(SC_ERR_AFP_CREATE, "Couldn't find iface %s", devname);
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1198
        goto socket_err;
1199
    }
1200
1201
1202
1203
    if (ptv->promisc != 0) {
1204
        /* Force promiscuous mode */
1205
        memset(&sock_params, 0, sizeof(sock_params));
1206
        sock_params.mr_type = PACKET_MR_PROMISC;
1207
        sock_params.mr_ifindex = bind_address.sll_ifindex;
1208
        r = setsockopt(ptv->socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(void *)&sock_params, sizeof(sock_params));
1209
        if (r < 0) {
1210
            SCLogError(SC_ERR_AFP_CREATE,
1211
                    "Couldn't switch iface %s to promiscuous, error %s",
1212
                    devname, strerror(errno));
1213
            goto frame_err;
1214
        }
1215
    }
1216
1217
    if (ptv->checksum_mode == CHECKSUM_VALIDATION_KERNEL) {
1218
        int val = 1;
1219
        if (setsockopt(ptv->socket, SOL_PACKET, PACKET_AUXDATA, &val,
1220
                    sizeof(val)) == -1 && errno != ENOPROTOOPT) {
1221
            SCLogWarning(SC_ERR_NO_AF_PACKET,
1222
                         "'kernel' checksum mode not supported, failling back to full mode.");
1223
            ptv->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
1224
        }
1225
    }
1226
1227
    /* set socket recv buffer size */
1228
    if (ptv->buffer_size != 0) {
1229
        /*
1230
         * Set the socket buffer size to the specified value.
1231
         */
1232
        SCLogInfo("Setting AF_PACKET socket buffer to %d", ptv->buffer_size);
1233
        if (setsockopt(ptv->socket, SOL_SOCKET, SO_RCVBUF,
1234
                       &ptv->buffer_size,
1235
                       sizeof(ptv->buffer_size)) == -1) {
1236
            SCLogError(SC_ERR_AFP_CREATE,
1237
                    "Couldn't set buffer size to %d on iface %s, error %s",
1238
                    ptv->buffer_size, devname, strerror(errno));
1239
            goto frame_err;
1240
        }
1241
    }
1242
1243
    r = bind(ptv->socket, (struct sockaddr *)&bind_address, sizeof(bind_address));
1244
    if (r < 0) {
1245
        if (verbose) {
1246
            if (errno == ENETDOWN) {
1247
                SCLogError(SC_ERR_AFP_CREATE,
1248
                        "Couldn't bind AF_PACKET socket, iface %s is down",
1249
                        devname);
1250
            } else {
1251
                SCLogError(SC_ERR_AFP_CREATE,
1252
                        "Couldn't bind AF_PACKET socket to iface %s, error %s",
1253
                        devname, strerror(errno));
1254
            }
1255
        }
1256
        goto frame_err;
1257
    }
1258
1259
    int if_flags = AFPGetDevFlags(ptv->socket, ptv->iface);
1260
    if (if_flags == -1) {
1261
        if (verbose) {
1262
            SCLogError(SC_ERR_AFP_READ,
1263
                    "Can not acces to interface '%s'",
1264
                    ptv->iface);
1265
        }
1266
        goto frame_err;
1267
    }
1268
    if ((if_flags & IFF_UP) == 0) {
1269
        if (verbose) {
1270
            SCLogError(SC_ERR_AFP_READ,
1271
                    "Interface '%s' is down",
1272
                    ptv->iface);
1273
        }
1274
        goto frame_err;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1275
    }
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1276
1277
    if (ptv->flags & AFP_RING_MODE) {
1278
        int val = TPACKET_V2;
1279
        unsigned int len = sizeof(val);
1280
        if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
1281
            if (errno == ENOPROTOOPT) {
1282
                SCLogError(SC_ERR_AFP_CREATE,
1283
                           "Too old kernel giving up (need 2.6.27 at least)");
1284
            }
1285
            SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len");
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1286
            goto socket_err;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1287
        }
1288
        ptv->tp_hdrlen = val;
1289
1290
        val = TPACKET_V2;
1291
        if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val,
1292
                    sizeof(val)) < 0) {
1293
            SCLogError(SC_ERR_AFP_CREATE,
1294
                       "Can't activate TPACKET_V2 on packet socket: %s",
1295
                       strerror(errno));
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1296
            goto socket_err;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1297
        }
1298
1299
        /* Allocate RX ring */
1300
#define DEFAULT_ORDER 3
1301
        for (order = DEFAULT_ORDER; order >= 0; order--) {
1302
            if (AFPComputeRingParams(ptv, order) != 1) {
1303
                SCLogInfo("Ring parameter are incorrect. Please correct the devel");
1304
            }
1305
1306
            r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, (void *) &ptv->req, sizeof(ptv->req));
1307
            if (r < 0) {
1308
                if (errno == ENOMEM) {
1309
                    SCLogInfo("Memory issue with ring parameters. Retrying.");
1310
                    continue;
1311
                }
1312
                SCLogError(SC_ERR_MEM_ALLOC,
1313
                        "Unable to allocate RX Ring for iface %s: (%d) %s",
1314
                        devname,
1315
                        errno,
1316
                        strerror(errno));
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1317
                goto socket_err;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1318
            } else {
1319
                break;
1320
            }
1321
        }
1322
1323
        if (order < 0) {
1324
            SCLogError(SC_ERR_MEM_ALLOC,
1325
                    "Unable to allocate RX Ring for iface %s (order 0 failed)",
1326
                    devname);
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1327
            goto socket_err;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1328
        }
1329
1330
        /* Allocate the Ring */
1331
        ptv->ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
1332
        ptv->ring_buf = mmap(0, ptv->ring_buflen, PROT_READ|PROT_WRITE,
1333
                MAP_SHARED, ptv->socket, 0);
1334
        if (ptv->ring_buf == MAP_FAILED) {
1335
            SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap");
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1336
            goto socket_err;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1337
        }
1338
        /* allocate a ring for each frame header pointer*/
1339
        ptv->frame_buf = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *));
1340
        if (ptv->frame_buf == NULL) {
1341
            SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf");
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1342
            goto mmap_err;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1343
        }
1344
        memset(ptv->frame_buf, 0, ptv->req.tp_frame_nr * sizeof (union thdr *));
1345
        /* fill the header ring with proper frame ptr*/
1346
        ptv->frame_offset = 0;
1347
        for (i = 0; i < ptv->req.tp_block_nr; ++i) {
1348
            void *base = &ptv->ring_buf[i * ptv->req.tp_block_size];
1349
            unsigned int j;
1350
            for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
1351
                (((union thdr **)ptv->frame_buf)[ptv->frame_offset]) = base;
1352
                base += ptv->req.tp_frame_size;
1353
            }
1354
        }
1355
        ptv->frame_offset = 0;
1356
    }
1357
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1358
    SCLogInfo("Using interface '%s' via socket %d", (char *)devname, ptv->socket);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1359
1360
#ifdef HAVE_PACKET_FANOUT
1361
    /* add binded socket to fanout group */
1362
    if (ptv->threads > 1) {
1363
        uint32_t option = 0;
1364
        uint16_t mode = ptv->cluster_type;
1365
        uint16_t id = ptv->cluster_id;
1366
        option = (mode << 16) | (id & 0xffff);
1367
        r = setsockopt(ptv->socket, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
1368
        if (r < 0) {
1369
            SCLogError(SC_ERR_AFP_CREATE,
1370
                       "Coudn't set fanout mode, error %s",
1371
                       strerror(errno));
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1372
            goto frame_err;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1373
        }
1374
    }
1375
#endif
1376
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1377
    ptv->datalink = AFPGetDevLinktype(ptv->socket, ptv->iface);
1378
    switch (ptv->datalink) {
1379
        case ARPHRD_PPP:
1380
        case ARPHRD_ATM:
1381
            ptv->cooked = 1;
1382
    }
1383
1384
    TmEcode rc;
1385
    rc = AFPSetBPFFilter(ptv);
1386
    if (rc == TM_ECODE_FAILED) {
1387
        SCLogError(SC_ERR_AFP_CREATE, "Set AF_PACKET bpf filter \"%s\" failed.", ptv->bpf_filter);
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1388
        goto frame_err;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1389
    }
1390
1391
    /* Init is ok */
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1392
    AFPSwitchState(ptv, AFP_STATE_UP);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1393
    return 0;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1394
1395
frame_err:
1396
    if (ptv->frame_buf)
1397
        SCFree(ptv->frame_buf);
1398
mmap_err:
1399
    /* Packet mmap does the cleaning when socket is closed */
1400
socket_err:
1401
    close(ptv->socket);
1402
    ptv->socket = -1;
1403
error:
1404
    return -1;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1405
}
1406
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1407
TmEcode AFPSetBPFFilter(AFPThreadVars *ptv)
1408
{
1409
    struct bpf_program filter;
1410
    struct sock_fprog  fcode;
1411
    int rc;
1412
1413
    if (!ptv->bpf_filter)
1414
        return TM_ECODE_OK;
1415
1416
    SCMutexLock(&afpacket_bpf_set_filter_lock);
1417
1418
    SCLogInfo("Using BPF '%s' on iface '%s'",
1419
              ptv->bpf_filter,
1420
              ptv->iface);
1421
    if (pcap_compile_nopcap(default_packet_size,  /* snaplen_arg */
1422
                ptv->datalink,    /* linktype_arg */
1423
                &filter,       /* program */
1424
                ptv->bpf_filter, /* const char *buf */
1425
                0,             /* optimize */
1426
                0              /* mask */
1427
                ) == -1) {
1428
        SCLogError(SC_ERR_AFP_CREATE, "Filter compilation failed.");
1429
        SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1430
        return TM_ECODE_FAILED;
1431
    }
1432
    SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1433
1434
    if (filter.bf_insns == NULL) {
1435
        SCLogError(SC_ERR_AFP_CREATE, "Filter badly setup.");
1436
        return TM_ECODE_FAILED;
1437
    }
1438
1439
    fcode.len    = filter.bf_len;
1440
    fcode.filter = (struct sock_filter*)filter.bf_insns;
1441
1442
    rc = setsockopt(ptv->socket, SOL_SOCKET, SO_ATTACH_FILTER, &fcode, sizeof(fcode));
1443
1444
    if(rc == -1) {
1445
        SCLogError(SC_ERR_AFP_CREATE, "Failed to attach filter: %s", strerror(errno));
1446
        return TM_ECODE_FAILED;
1447
    }
1448
1449
    SCMutexUnlock(&afpacket_bpf_set_filter_lock);
1450
    return TM_ECODE_OK;
1451
}
1452
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1453
1454
/**
1455
 * \brief Init function for ReceiveAFP.
1456
 *
1457
 * \param tv pointer to ThreadVars
1458
 * \param initdata pointer to the interface passed from the user
1459
 * \param data pointer gets populated with AFPThreadVars
1460
 *
1461
 * \todo Create a general AFP setup function.
1462
 */
1463
TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
1464
    SCEnter();
1465
    AFPIfaceConfig *afpconfig = initdata;
1466
1467
    if (initdata == NULL) {
1468
        SCLogError(SC_ERR_INVALID_ARGUMENT, "initdata == NULL");
1469
        SCReturnInt(TM_ECODE_FAILED);
1470
    }
1471
1472
    AFPThreadVars *ptv = SCMalloc(sizeof(AFPThreadVars));
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1473
    if (unlikely(ptv == NULL)) {
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1474
        afpconfig->DerefFunc(afpconfig);
1475
        SCReturnInt(TM_ECODE_FAILED);
1476
    }
1477
    memset(ptv, 0, sizeof(AFPThreadVars));
1478
1479
    ptv->tv = tv;
1480
    ptv->cooked = 0;
1481
1482
    strlcpy(ptv->iface, afpconfig->iface, AFP_IFACE_NAME_LENGTH);
1483
    ptv->iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
1484
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
1485
    ptv->livedev = LiveGetDevice(ptv->iface);
1486
    if (ptv->livedev == NULL) {
1487
        SCLogError(SC_ERR_INVALID_VALUE, "Unable to find Live device");
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1488
        SCFree(ptv);
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
1489
        SCReturnInt(TM_ECODE_FAILED);
1490
    }
1491
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1492
    ptv->buffer_size = afpconfig->buffer_size;
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1493
    ptv->ring_size = afpconfig->ring_size;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1494
1495
    ptv->promisc = afpconfig->promisc;
1.1.12 by Pierre Chifflier
Import upstream version 1.2.1
1496
    ptv->checksum_mode = afpconfig->checksum_mode;
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1497
    ptv->bpf_filter = NULL;
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1498
1499
    ptv->threads = 1;
1500
#ifdef HAVE_PACKET_FANOUT
1501
    ptv->cluster_type = PACKET_FANOUT_LB;
1502
    ptv->cluster_id = 1;
1503
    /* We only set cluster info if the number of reader threads is greater than 1 */
1504
    if (afpconfig->threads > 1) {
1505
            ptv->cluster_id = afpconfig->cluster_id;
1506
            ptv->cluster_type = afpconfig->cluster_type;
1507
            ptv->threads = afpconfig->threads;
1508
    }
1509
#endif
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1510
    ptv->flags = afpconfig->flags;
1511
1512
    if (afpconfig->bpf_filter) {
1513
        ptv->bpf_filter = afpconfig->bpf_filter;
1514
    }
1515
1516
#ifdef PACKET_STATISTICS
1517
    ptv->capture_kernel_packets = SCPerfTVRegisterCounter("capture.kernel_packets",
1518
            ptv->tv,
1519
            SC_PERF_TYPE_UINT64,
1520
            "NULL");
1521
    ptv->capture_kernel_drops = SCPerfTVRegisterCounter("capture.kernel_drops",
1522
            ptv->tv,
1523
            SC_PERF_TYPE_UINT64,
1524
            "NULL");
1525
#endif
1526
1527
    char *active_runmode = RunmodeGetActive();
1528
1529
    if (active_runmode && !strcmp("workers", active_runmode)) {
1530
        ptv->flags |= AFP_ZERO_COPY;
1531
        SCLogInfo("Enabling zero copy mode");
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1532
    } else {
1533
        /* If we are using copy mode we need a lock */
1534
        ptv->flags |= AFP_SOCK_PROTECT;
1535
    }
1536
1537
    /* If we are in RING mode, then we can use ZERO copy
1538
     * by using the data release mechanism */
1539
    if (ptv->flags & AFP_RING_MODE) {
1540
        ptv->flags |= AFP_ZERO_COPY;
1541
        SCLogInfo("Enabling zero copy mode by using data release call");
1542
    }
1543
1544
    ptv->copy_mode = afpconfig->copy_mode;
1545
    if (ptv->copy_mode != AFP_COPY_MODE_NONE) {
1546
        strlcpy(ptv->out_iface, afpconfig->out_iface, AFP_IFACE_NAME_LENGTH);
1547
        ptv->out_iface[AFP_IFACE_NAME_LENGTH - 1]= '\0';
1.1.20 by Pierre Chifflier
Import upstream version 1.4.2
1548
        /* Warn about BPF filter consequence */
1549
        if (ptv->bpf_filter) {
1550
            SCLogWarning(SC_WARN_UNCOMMON, "Enabling a BPF filter in IPS mode result"
1551
                      " in dropping all non matching packets.");
1552
        }
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1553
    }
1554
1.1.20 by Pierre Chifflier
Import upstream version 1.4.2
1555
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1556
    if (AFPPeersListAdd(ptv) == TM_ECODE_FAILED) {
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1557
        SCFree(ptv);
1558
        afpconfig->DerefFunc(afpconfig);
1559
        SCReturnInt(TM_ECODE_FAILED);
1560
    }
1561
1562
#define T_DATA_SIZE 70000
1563
    ptv->data = SCMalloc(T_DATA_SIZE);
1564
    if (ptv->data == NULL) {
1565
        afpconfig->DerefFunc(afpconfig);
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1566
        SCFree(ptv);
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1567
        SCReturnInt(TM_ECODE_FAILED);
1568
    }
1569
    ptv->datalen = T_DATA_SIZE;
1570
#undef T_DATA_SIZE
1571
1572
    *data = (void *)ptv;
1573
1574
    afpconfig->DerefFunc(afpconfig);
1575
    SCReturnInt(TM_ECODE_OK);
1576
}
1577
1578
/**
1579
 * \brief This function prints stats to the screen at exit.
1580
 * \param tv pointer to ThreadVars
1581
 * \param data pointer that gets cast into AFPThreadVars for ptv
1582
 */
1583
void ReceiveAFPThreadExitStats(ThreadVars *tv, void *data) {
1584
    SCEnter();
1585
    AFPThreadVars *ptv = (AFPThreadVars *)data;
1586
1587
#ifdef PACKET_STATISTICS
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1588
    AFPDumpCounters(ptv);
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1589
    SCLogInfo("(%s) Kernel: Packets %" PRIu64 ", dropped %" PRIu64 "",
1590
            tv->name,
1591
            (uint64_t) SCPerfGetLocalCounterValue(ptv->capture_kernel_packets, tv->sc_perf_pca),
1592
            (uint64_t) SCPerfGetLocalCounterValue(ptv->capture_kernel_drops, tv->sc_perf_pca));
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1593
#endif
1594
1595
    SCLogInfo("(%s) Packets %" PRIu32 ", bytes %" PRIu64 "", tv->name, ptv->pkts, ptv->bytes);
1596
}
1597
1598
/**
1599
 * \brief DeInit function closes af packet socket at exit.
1600
 * \param tv pointer to ThreadVars
1601
 * \param data pointer that gets cast into AFPThreadVars for ptv
1602
 */
1603
TmEcode ReceiveAFPThreadDeinit(ThreadVars *tv, void *data) {
1604
    AFPThreadVars *ptv = (AFPThreadVars *)data;
1605
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1606
    AFPSwitchState(ptv, AFP_STATE_DOWN);
1607
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1608
    if (ptv->data != NULL) {
1609
        SCFree(ptv->data);
1610
        ptv->data = NULL;
1611
    }
1612
    ptv->datalen = 0;
1613
1.1.13 by Pierre Chifflier
Import upstream version 1.3
1614
    ptv->bpf_filter = NULL;
1615
1.1.10 by Pierre Chifflier
Import upstream version 1.1
1616
    SCReturnInt(TM_ECODE_OK);
1617
}
1618
1619
/**
1620
 * \brief This function passes off to link type decoders.
1621
 *
1622
 * DecodeAFP reads packets from the PacketQueue and passes
1623
 * them off to the proper link type decoder.
1624
 *
1625
 * \param t pointer to ThreadVars
1626
 * \param p pointer to the current packet
1627
 * \param data pointer that gets cast into AFPThreadVars for ptv
1628
 * \param pq pointer to the current PacketQueue
1629
 */
1630
TmEcode DecodeAFP(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq)
1631
{
1632
    SCEnter();
1633
    DecodeThreadVars *dtv = (DecodeThreadVars *)data;
1634
1635
    /* update counters */
1636
    SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca);
1637
    SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca);
1638
1639
    SCPerfCounterAddUI64(dtv->counter_bytes, tv->sc_perf_pca, GET_PKT_LEN(p));
1640
#if 0
1641
    SCPerfCounterAddDouble(dtv->counter_bytes_per_sec, tv->sc_perf_pca, GET_PKT_LEN(p));
1642
    SCPerfCounterAddDouble(dtv->counter_mbit_per_sec, tv->sc_perf_pca,
1643
                           (GET_PKT_LEN(p) * 8)/1000000.0);
1644
#endif
1645
1646
    SCPerfCounterAddUI64(dtv->counter_avg_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
1647
    SCPerfCounterSetUI64(dtv->counter_max_pkt_size, tv->sc_perf_pca, GET_PKT_LEN(p));
1648
1649
    /* call the decoder */
1650
    switch(p->datalink) {
1651
        case LINKTYPE_LINUX_SLL:
1652
            DecodeSll(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1653
            break;
1654
        case LINKTYPE_ETHERNET:
1655
            DecodeEthernet(tv, dtv, p,GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1656
            break;
1657
        case LINKTYPE_PPP:
1658
            DecodePPP(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1659
            break;
1660
        case LINKTYPE_RAW:
1661
            DecodeRaw(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq);
1662
            break;
1663
        default:
1664
            SCLogError(SC_ERR_DATALINK_UNIMPLEMENTED, "Error: datalink type %" PRId32 " not yet supported in module DecodeAFP", p->datalink);
1665
            break;
1666
    }
1667
1668
    SCReturnInt(TM_ECODE_OK);
1669
}
1670
1671
TmEcode DecodeAFPThreadInit(ThreadVars *tv, void *initdata, void **data)
1672
{
1673
    SCEnter();
1674
    DecodeThreadVars *dtv = NULL;
1675
1676
    dtv = DecodeThreadVarsAlloc();
1677
1678
    if (dtv == NULL)
1679
        SCReturnInt(TM_ECODE_FAILED);
1680
1681
    DecodeRegisterPerfCounters(dtv, tv);
1682
1683
    *data = (void *)dtv;
1684
1685
    SCReturnInt(TM_ECODE_OK);
1686
}
1687
1688
#endif /* HAVE_AF_PACKET */
1689
/* eof */
1.1.18 by Pierre Chifflier
Import upstream version 1.4
1690
/**
1691
 * @}
1692
 */