[Snort-devel] snort with openbsd pflog on linux box

Ronaldo Maia romaia at ...2474...
Thu Jul 26 10:39:23 EDT 2007


Hello there!

Sometime ago, we were using a openbsd box with snort to parse
openbsd's pflogs and that was working fine, but recently we move to a
linux box, and snort was not able to parse that correctly anymore.

Investigating the source, I found quite a few issues:

- openbsd pfloghdr changed, and snort PflogHdr is no longer up-to-date
with that. [http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/if_pflog.h]

- given this change, snort should be able to parse pflogs with
different headers. just like tcpdump can.

- openbsd and linux sa_family_t types are different:
  linux: typedef unsigned short  sa_family_t;
  openbsd: typedef u_int8_t sa_family_t;

So, a snort compiled on linux wouldn't parse pflogs correctly.

- on this two systems, AF_INET6 differ too:
  linux:  #define AF_INET6    10
  openbsd:  #define AF_INET6        24

Again, we have a problem.

So, based on tcpdump code, I came up with a patch (attached), that
fixes all this problems.

I hope I did the right thing, and would like to see some thoughts on it.

-- 
Ronaldo Maia
-------------- next part --------------
Index: src/decode.c
===================================================================
RCS file: /cvsroot/snort/src/decode.c,v
retrieving revision 1.139
diff -u -p -r1.139 decode.c
--- src/decode.c	6 Jul 2007 15:57:47 -0000	1.139
+++ src/decode.c	26 Jul 2007 14:09:47 -0000
@@ -1252,6 +1252,9 @@ void DecodeOldPflog(Packet * p, struct p
     return;
 }
 
+#define OPENBSD_AF_INET     2
+#define OPENBSD_AF_INET6    24
+
 /*
  * Function: DecodePflog(Packet *, struct pcap_pkthdr *, u_int8_t *)
  *
@@ -1268,6 +1271,7 @@ void DecodePflog(Packet * p, struct pcap
 {
     u_int32_t pkt_len;      /* suprisingly, the length of the packet */
     u_int32_t cap_len;      /* caplen value */
+    u_int hdrlen;
     PROFILE_VARS;
 
     PREPROC_PROFILE_START(decodePerfStats);
@@ -1289,7 +1293,7 @@ void DecodePflog(Packet * p, struct pcap
                 (unsigned long)cap_len, (unsigned long)pkt_len););
 
     /* do a little validation */
-    if(p->pkth->caplen < PFLOG_HDRLEN)
+    if(p->pkth->caplen < MIN_PFLOG_HDRLEN)
     {
         if(pv.verbose_flag)
         {
@@ -1302,22 +1306,30 @@ void DecodePflog(Packet * p, struct pcap
 
     /* lay the pf header structure over the packet data */
     p->pfh = (PflogHdr *) pkt;
+    /* depending on OpenBSD version, pflog header may have different sizes. */
+    hdrlen = BPF_WORDALIGN(p->pfh->length);
 
     /*  get the network type - should only be AF_INET or AF_INET6 */
     /* p->pfh->af is sa_family_t which is a u_int8_t */
     switch(p->pfh->af)
     {
         case AF_INET:   /* IPv4 */
+#if OPENBSD_AF_INET != AF_INET
+        case OPENBSD_AF_INET:       /* XXX: read pcap files */
+#endif
             DEBUG_WRAP(DebugMessage(DEBUG_DECODE, "IP datagram size calculated to be %lu "
                         "bytes\n", (unsigned long)(cap_len - PFLOG_HDRLEN)););
 
-            DecodeIP(p->pkt + PFLOG_HDRLEN, cap_len - PFLOG_HDRLEN, p);
+            DecodeIP(p->pkt + hdrlen, cap_len - hdrlen, p);
             PREPROC_PROFILE_END(decodePerfStats);
             return;
 
 #ifdef AF_INET6
         case AF_INET6:  /* IPv6 */
-            DecodeIPV6(p->pkt + PFLOG_HDRLEN, (cap_len - PFLOG_HDRLEN), p);
+#if OPENBSD_AF_INET6 != AF_INET6
+        case OPENBSD_AF_INET6:      /* XXX: read pcap files */
+#endif
+            DecodeIPV6(p->pkt + hdrlen, (cap_len - hdrlen), p);
             PREPROC_PROFILE_END(decodePerfStats);
             return;
 #endif
Index: src/decode.h
===================================================================
RCS file: /cvsroot/snort/src/decode.h,v
retrieving revision 1.104
diff -u -p -r1.104 decode.h
--- src/decode.h	6 Jul 2007 15:57:47 -0000	1.104
+++ src/decode.h	26 Jul 2007 14:09:48 -0000
@@ -735,23 +735,33 @@ typedef struct _OldPflog_hdr
 /* OpenBSD pf firewall pflog0 header
  * (information from pf source in kernel)
  * the rule, reason, and action codes tell why the firewall dropped it -fleck
+ *
+ * Note that on OpenBSD, af type is sa_family_t. On linux, that's a unsigned short, but
+ * on OpenBSD, that's a u_int8_t, so we should explicitly use u_int8_t here.
  */
 
 typedef struct _Pflog_hdr
 {
-        int8_t          length;
-        sa_family_t     af;
+        u_int8_t        length;
+        u_int8_t        af;
         u_int8_t        action;
         u_int8_t        reason;
         char            ifname[IFNAMSIZ];
         char            ruleset[16];
         u_int32_t       rulenr;
         u_int32_t       subrulenr;
+        uid_t           uid;
+        pid_t           pid;
+        uid_t           rule_uid;
+        pid_t           rule_pid;
         u_int8_t        dir;
         u_int8_t        pad[3];
 } PflogHdr;
 
-#define PFLOG_HDRLEN    sizeof(struct _Pflog_hdr)
+#define PFLOG_HDRLEN        sizeof(struct _Pflog_hdr)
+#define MIN_PFLOG_HDRLEN    45
+
+
 
 /*
  * ssl_pkttype values.


More information about the Snort-devel mailing list