[Oisf-devel] [PATCH] pcap: do not leave if interface goes down
Eric Leblond
eric at regit.org
Thu Mar 24 12:16:38 UTC 2011
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.
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
>---------------------------------------------
--
Envoyé de mon téléphone Android avec K-9 Mail. Excusez la brièveté.
More information about the Oisf-devel
mailing list