[Oisf-devel] [PATCH] pcap: do not leave if interface goes down
Eric Leblond
eric at regit.org
Thu Mar 24 12:45:40 UTC 2011
Hi again,
Victor Julien <victor at inliniac.net> a écrit :
>On 03/24/2011 01:16 PM, Eric Leblond wrote:
>>
>>
>> Hi,
>>
>> Victor Julien <victor at inliniac.net> a écrit :
>>
>>> Good idea to address this Eric. I'm not completely convinced about
>the
>>> approach yet though. My concern is that while the pcap interface is
>>> down
>>> we send an empty packet through the engine, which I don't like.
>Maybe
>>> we
>>> should make the thread modules capable of returning an error
>condition
>>> without the thread restart mechanism kicking in... thoughts?
>>
>> I clearly agree with the point on the empty packet. That's not sexy
>at all.
>>
>> We could introduce a Continue/finish return that could be use to
>indicate that the thread module should stop the treatment.
>
>What about a simple loop in the ReceivePcap function that just loops
>the
>TryReopen function until it succeeds or we interrupt it?
Easy to implement. I like it.
I was thinking we could not stay for long in this function.
I send you a patch which implement this ASAP.
BR,
>
>Cheers,
>Victor
>
>> BR,
>>
>>>
>>> Cheers,
>>> Victor
>>>
>>> On 03/21/2011 09:56 PM, Eric Leblond wrote:
>>>> This patch changes suricata behaviour to support interface like
>>>> ppp. Prior to this patch, a suricata listening to an interface
>>>> was leaving when the interface goes down. This patch modifies
>>>> the behaviour to automatically reconnect. Suricata retries to
>>>> open the interface every 0,5s until it succeeds.
>>>> ---
>>>> src/source-pcap.c | 113
>>> +++++++++++++++++++++++++++++++++++++++++++++++++++--
>>>> 1 files changed, 109 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/src/source-pcap.c b/src/source-pcap.c
>>>> index 26cabd8..a78f9f9 100644
>>>> --- a/src/source-pcap.c
>>>> +++ b/src/source-pcap.c
>>>> @@ -63,6 +63,12 @@ static TAILQ_HEAD(, PcapDevice_) pcap_devices =
>>>>
>>>> /** max packets < 65536 */
>>>> #define PCAP_FILE_MAX_PKTS 256
>>>> +#define PCAP_IFACE_NAME_LENGTH 48
>>>> +
>>>> +#define PCAP_STATE_DOWN 0
>>>> +#define PCAP_STATE_UP 1
>>>> +
>>>> +#define PCAP_RECONNECT_TIMEOUT 500000
>>>>
>>>> /**
>>>> * \brief Structure to hold thread specific variables.
>>>> @@ -71,7 +77,11 @@ typedef struct PcapThreadVars_
>>>> {
>>>> /* thread specific handle */
>>>> pcap_t *pcap_handle;
>>>> -
>>>> + /* handle state */
>>>> + unsigned char pcap_state;
>>>> +#if LIBPCAP_VERSION_MAJOR == 0
>>>> + char iface[PCAP_IFACE_NAME_LENGTH];
>>>> +#endif
>>>> /* thread specific bpf */
>>>> struct bpf_program filter;
>>>>
>>>> @@ -173,6 +183,77 @@ void PcapCallback(char *user, struct
>pcap_pkthdr
>>> *h, u_char *pkt) {
>>>> ptv->array_idx++;
>>>> }
>>>>
>>>> +#if LIBPCAP_VERSION_MAJOR == 1
>>>> +static int PcapTryReopen(PcapThreadVars *ptv)
>>>> +{
>>>> + int pcap_activate_r;
>>>> + char *tmpbpfstring;
>>>> +
>>>> + ptv->pcap_state = PCAP_STATE_DOWN;
>>>> + pcap_activate_r = pcap_activate(ptv->pcap_handle);
>>>> + if (pcap_activate_r != 0) {
>>>> + return -1;
>>>> + }
>>>> + /* set bpf filter if we have one */
>>>> + if (ConfGet("bpf-filter", &tmpbpfstring) != 1) {
>>>> + SCLogDebug("could not get bpf or none specified");
>>>> + } else {
>>>> + SCLogInfo("using bpf-filter \"%s\"", tmpbpfstring);
>>>> +
>>>> +
>>> if(pcap_compile(ptv->pcap_handle,&ptv->filter,tmpbpfstring,1,0) < 0)
>{
>>>> + SCLogError(SC_ERR_BPF,"bpf compilation error
>>> %s",pcap_geterr(ptv->pcap_handle));
>>>> + return -1;
>>>> + }
>>>> +
>>>> + if(pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) {
>>>> + SCLogError(SC_ERR_BPF,"could not set bpf filter
>>> %s",pcap_geterr(ptv->pcap_handle));
>>>> + return -1;
>>>> + }
>>>> + }
>>>> +
>>>> + SCLogInfo("Recovering interface listening");
>>>> + ptv->pcap_state = PCAP_STATE_UP;
>>>> + return 0;
>>>> +}
>>>> +#else /* implied LIBPCAP_VERSION_MAJOR == 0 */
>>>> +static int PcapTryReopen(PcapThreadVars *ptv)
>>>> +{
>>>> + char errbuf[PCAP_ERRBUF_SIZE] = "";
>>>> +
>>>> + ptv->pcap_state = PCAP_STATE_DOWN;
>>>> + pcap_close(ptv->pcap_handle);
>>>> +
>>>> + ptv->pcap_handle = pcap_open_live((char *)ptv->iface,
>>> LIBPCAP_SNAPLEN,
>>>> + LIBPCAP_PROMISC, LIBPCAP_COPYWAIT, errbuf);
>>>> + if (ptv->pcap_handle == NULL) {
>>>> + SCLogError(SC_ERR_PCAP_OPEN_LIVE, "Problem creating pcap
>>> handler for live mode, error %s", errbuf);
>>>> + return -1;
>>>> + }
>>>> +
>>>> + /* set bpf filter if we have one */
>>>> + if (ConfGet("bpf-filter", &tmpbpfstring) != 1) {
>>>> + SCLogDebug("could not get bpf or none specified");
>>>> + } else {
>>>> + SCLogInfo("using bpf-filter \"%s\"", tmpbpfstring);
>>>> +
>>>> +
>>> if(pcap_compile(ptv->pcap_handle,&ptv->filter,tmpbpfstring,1,0) < 0)
>{
>>>> + SCLogError(SC_ERR_BPF,"bpf compilation error
>>> %s",pcap_geterr(ptv->pcap_handle));
>>>> + return -1;
>>>> + }
>>>> +
>>>> + if(pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) {
>>>> + SCLogError(SC_ERR_BPF,"could not set bpf filter
>>> %s",pcap_geterr(ptv->pcap_handle));
>>>> + return -1;
>>>> + }
>>>> + }
>>>> +
>>>> + SCLogInfo("Recovering interface listening");
>>>> + ptv->pcap_state = PCAP_STATE_UP;
>>>> + return 0;
>>>> +}
>>>> +
>>>> +#endif
>>>> +
>>>> /**
>>>> * \brief Recieves packets from an interface via libpcap.
>>>> *
>>>> @@ -190,6 +271,14 @@ TmEcode ReceivePcap(ThreadVars *tv, Packet *p,
>>> void *data, PacketQueue *pq, Pack
>>>>
>>>> PcapThreadVars *ptv = (PcapThreadVars *)data;
>>>>
>>>> + /* test pcap handle */
>>>> + if (ptv->pcap_state == PCAP_STATE_DOWN) {
>>>> + int r = PcapTryReopen(ptv);
>>>> + if (r < 0) {
>>>> + usleep(PCAP_RECONNECT_TIMEOUT);
>>>> + }
>>>> + SCReturnInt(TM_ECODE_OK);
>>>> + }
>>>> /* make sure we have at least one packet in the packet pool,
>to
>>> prevent
>>>> * us from alloc'ing packets at line rate */
>>>> while (packet_q_len == 0) {
>>>> @@ -229,8 +318,9 @@ TmEcode ReceivePcap(ThreadVars *tv, Packet *p,
>>> void *data, PacketQueue *pq, Pack
>>>> SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 "
>>> %s",
>>>> r, pcap_geterr(ptv->pcap_handle));
>>>>
>>>> - EngineStop();
>>>> - SCReturnInt(TM_ECODE_FAILED);
>>>> + /* try to reopen */
>>>> + PcapTryReopen(ptv);
>>>> + SCReturnInt(TM_ECODE_OK);
>>>> }
>>>>
>>>> if (suricata_ctl_flags != 0) {
>>>> @@ -278,7 +368,6 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv,
>>> void *initdata, void **data) {
>>>> ptv->tv = tv;
>>>>
>>>> SCLogInfo("using interface %s", (char *)initdata);
>>>> -
>>>> /* XXX create a general pcap setup function */
>>>> char errbuf[PCAP_ERRBUF_SIZE];
>>>> ptv->pcap_handle = pcap_create((char *)initdata, errbuf);
>>>> @@ -339,6 +428,9 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv,
>>> void *initdata, void **data) {
>>>> SCLogError(SC_ERR_PCAP_ACTIVATE_HANDLE, "Couldn't activate
>>> the pcap handler, error %s", pcap_geterr(ptv->pcap_handle));
>>>> SCFree(ptv);
>>>> SCReturnInt(TM_ECODE_FAILED);
>>>> + ptv->pcap_state = PCAP_STATE_DOWN;
>>>> + } else {
>>>> + ptv->pcap_state = PCAP_STATE_UP;
>>>> }
>>>>
>>>> /* set bpf filter if we have one */
>>>> @@ -389,12 +481,18 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv,
>>> void *initdata, void **data) {
>>>> ptv->tv = tv;
>>>>
>>>> SCLogInfo("using interface %s", (char *)initdata);
>>>> + if(strlen(initdata)>PCAP_IFACE_NAME_LENGTH) {
>>>> + SCFree(ptv);
>>>> + SCReturnInt(TM_ECODE_FAILED);
>>>> + }
>>>> + strncpy(ptv->iface, PCAP_IFACE_NAME_LENGTH, initdata);
>>>>
>>>> char errbuf[PCAP_ERRBUF_SIZE] = "";
>>>> ptv->pcap_handle = pcap_open_live((char *)initdata,
>>> LIBPCAP_SNAPLEN,
>>>> LIBPCAP_PROMISC,
>>> LIBPCAP_COPYWAIT, errbuf);
>>>> if (ptv->pcap_handle == NULL) {
>>>> SCLogError(SC_ERR_PCAP_OPEN_LIVE, "Problem creating pcap
>>> handler for live mode, error %s", errbuf);
>>>> + SCFree(ptv);
>>>> SCReturnInt(TM_ECODE_FAILED);
>>>> }
>>>>
>>>> @@ -406,11 +504,13 @@ TmEcode ReceivePcapThreadInit(ThreadVars *tv,
>>> void *initdata, void **data) {
>>>>
>>>>
>>> if(pcap_compile(ptv->pcap_handle,&ptv->filter,tmpbpfstring,1,0) < 0)
>{
>>>> SCLogError(SC_ERR_BPF,"bpf compilation error
>>> %s",pcap_geterr(ptv->pcap_handle));
>>>> + SCFree(ptv);
>>>> return TM_ECODE_FAILED;
>>>> }
>>>>
>>>> if(pcap_setfilter(ptv->pcap_handle,&ptv->filter) < 0) {
>>>> SCLogError(SC_ERR_BPF,"could not set bpf filter
>>> %s",pcap_geterr(ptv->pcap_handle));
>>>> + SCFree(ptv);
>>>> return TM_ECODE_FAILED;
>>>> }
>>>> }
>>>> @@ -481,6 +581,11 @@ TmEcode DecodePcap(ThreadVars *tv, Packet *p,
>>> void *data, PacketQueue *pq, Packe
>>>> SCEnter();
>>>> DecodeThreadVars *dtv = (DecodeThreadVars *)data;
>>>>
>>>> + /* packet is not a real one */
>>>> + if (p->datalink == 0) {
>>>> + SCReturnInt(TM_ECODE_OK);
>>>> + }
>>>> +
>>>> /* update counters */
>>>> SCPerfCounterIncr(dtv->counter_pkts, tv->sc_perf_pca);
>>>> SCPerfCounterIncr(dtv->counter_pkts_per_sec, tv->sc_perf_pca);
>>>
>>>
>>> --
>>> ---------------------------------------------
>>> Victor Julien
>>> http://www.inliniac.net/
>>> PGP: http://www.inliniac.net/victorjulien.asc
>>> ---------------------------------------------
>>
>
>
>--
>---------------------------------------------
>Victor Julien
>http://www.inliniac.net/
>PGP: http://www.inliniac.net/victorjulien.asc
>---------------------------------------------
--
Envoyé de mon téléphone Android avec K-9 Mail. Excusez la brièveté.
More information about the Oisf-devel
mailing list