]> git.ipfire.org Git - thirdparty/ulogd2.git/commitdiff
Add IPv6 support, fix a few incorrect key assignments and make sure this doesn't
author/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org>
Tue, 6 Mar 2007 13:29:39 +0000 (13:29 +0000)
committer/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org>
Tue, 6 Mar 2007 13:29:39 +0000 (13:29 +0000)
repeat by using symbolic names to make sure the assignment matches the array
index.

filter/raw2packet/ulogd_raw2packet_BASE.c
include/ulogd/ipfix_protocol.h
include/ulogd/printpkt.h
input/packet/ulogd_inppkt_NFLOG.c
util/printpkt.c

index ca6767700c6532e5d005b0f2bb84d46dbd92d7d2..4420507b3e887e4a4a3fba9f9e75a83b2b0c1725 100644 (file)
 #include <stdlib.h>
 #include <sys/socket.h>
 #include <netinet/ip.h>
+#include <netinet/ip6.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
 #include <netinet/udp.h>
 #include <ulogd/ulogd.h>
 #include <ulogd/ipfix_protocol.h>
 
-
-/***********************************************************************
- *                     IP HEADER
- ***********************************************************************/
+enum output_keys {
+       KEY_IP_SADDR,
+       KEY_IP_DADDR,
+       KEY_IP_PROTOCOL,
+       KEY_IP_TOS,
+       KEY_IP_TTL,
+       KEY_IP_TOTLEN,
+       KEY_IP_IHL,
+       KEY_IP_CSUM,
+       KEY_IP_ID,
+       KEY_IP_FRAGOFF,
+       KEY_IP6_SADDR,
+       KEY_IP6_DADDR,
+       KEY_IP6_PAYLOAD_LEN,
+       KEY_IP6_PRIORITY,
+       KEY_IP6_FLOWLABEL,
+       KEY_IP6_HOPLIMIT,
+       KEY_IP6_NEXTHDR,
+       KEY_IP6_FRAG_OFF,
+       KEY_IP6_FRAG_ID,
+       KEY_TCP_SPORT,
+       KEY_TCP_DPORT,
+       KEY_TCP_SEQ,
+       KEY_TCP_ACKSEQ,
+       KEY_TCP_WINDOW,
+       KEY_TCP_OFFSET,
+       KEY_TCP_RESERVED,
+       KEY_TCP_URG,
+       KEY_TCP_URGP,
+       KEY_TCP_ACK,
+       KEY_TCP_PSH,
+       KEY_TCP_RST,
+       KEY_TCP_SYN,
+       KEY_TCP_FIN,
+       KEY_TCP_RES1,
+       KEY_TCP_RES2,
+       KEY_TCP_CSUM,
+       KEY_UDP_SPORT,
+       KEY_UDP_DPORT,
+       KEY_UDP_LEN,
+       KEY_UDP_CSUM,
+       KEY_ICMP_TYPE,
+       KEY_ICMP_CODE,
+       KEY_ICMP_ECHOID,
+       KEY_ICMP_ECHOSEQ,
+       KEY_ICMP_GATEWAY,
+       KEY_ICMP_FRAGMTU,
+       KEY_ICMP_CSUM,
+       KEY_ICMPV6_TYPE,
+       KEY_ICMPV6_CODE,
+       KEY_ICMPV6_ECHOID,
+       KEY_ICMPV6_ECHOSEQ,
+       KEY_ICMPV6_CSUM,
+       KEY_AHESP_SPI,
+};
 
 static struct ulogd_key iphdr_rets[] = {
-       { 
+       [KEY_IP_SADDR] = 
                .type = ULOGD_RET_IPADDR,
                .flags = ULOGD_RETF_NONE, 
                .name = "ip.saddr", 
@@ -56,7 +109,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_sourceIPv4Address,
                },
        },
-       {
+       [KEY_IP_DADDR] = {
                .type = ULOGD_RET_IPADDR,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.daddr", 
@@ -65,7 +118,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_destinationIPv4Address,
                },
        },
-       {
+       [KEY_IP_PROTOCOL] = {
                .type = ULOGD_RET_UINT8,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.protocol", 
@@ -74,7 +127,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_protocolIdentifier,
                },
        },
-       {
+       [KEY_IP_TOS] = {
                .type = ULOGD_RET_UINT8,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.tos", 
@@ -83,7 +136,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_classOfServiceIPv4,
                },
        },
-       {
+       [KEY_IP_TTL] = {
                .type = ULOGD_RET_UINT8,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.ttl", 
@@ -92,7 +145,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_ipTimeToLive,
                },
        },
-       {
+       [KEY_IP_TOTLEN] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.totlen", 
@@ -101,7 +154,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_totalLengthIPv4,
                },
        },
-       {
+       [KEY_IP_IHL] = {
                .type = ULOGD_RET_UINT8,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.ihl", 
@@ -110,12 +163,12 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_internetHeaderLengthIPv4,
                },
        },
-       {
+       [KEY_IP_CSUM] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.csum", 
        },
-       {
+       [KEY_IP_ID] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.id", 
@@ -124,7 +177,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_identificationIPv4,
                },
        },
-       {
+       [KEY_IP_FRAGOFF] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "ip.fragoff", 
@@ -133,10 +186,72 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_fragmentOffsetIPv4,
                },
        },
-
-       /* 10 */
-
-       {
+       [KEY_IP6_SADDR] = {
+               .type = ULOGD_RET_RAW,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.saddr",
+               .ipfix = {
+                       .vendor = IPFIX_VENDOR_IETF,
+                       .field_id = IPFIX_sourceIPv6Address,
+               },
+       },
+       [KEY_IP6_DADDR] = {
+               .type = ULOGD_RET_RAW,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.daddr",
+               .ipfix = {
+                       .vendor = IPFIX_VENDOR_IETF,
+                       .field_id = IPFIX_destinationIPv6Address,
+               },
+       },
+       [KEY_IP6_PAYLOAD_LEN] = {
+               .type = ULOGD_RET_UINT16,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.payload_len",
+               .ipfix = {
+                       .vendor = IPFIX_VENDOR_IETF,
+                       .field_id = IPFIX_payloadLengthIPv6,
+               },
+       },
+       [KEY_IP6_PRIORITY] = {
+               .type = ULOGD_RET_UINT8,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.priority",
+       },
+       [KEY_IP6_FLOWLABEL] = {
+               .type = ULOGD_RET_UINT32,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.flowlabel",
+               .ipfix = {
+                       .vendor = IPFIX_VENDOR_IETF,
+                       .field_id = IPFIX_flowLabelIPv6,
+               },
+       },
+       [KEY_IP6_HOPLIMIT] = {
+               .type = ULOGD_RET_UINT8,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.hoplimit",
+       },
+       [KEY_IP6_NEXTHDR] = {
+               .type = ULOGD_RET_UINT8,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.nexthdr",
+               .ipfix = {
+                       .vendor = IPFIX_VENDOR_IETF,
+                       .field_id = IPFIX_nextHeaderIPv6,
+               },
+       },
+       [KEY_IP6_FRAG_OFF] = {
+               .type = ULOGD_RET_UINT16,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.fragoff",
+       },
+       [KEY_IP6_FRAG_ID] = {
+               .type = ULOGD_RET_UINT32,
+               .flags = ULOGD_RETF_NONE,
+               .name = "ip6.fragid",
+       },
+       [KEY_TCP_SPORT] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.sport", 
@@ -145,7 +260,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_tcpSourcePort,
                },
        },
-       {
+       [KEY_TCP_DPORT] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.dport", 
@@ -154,7 +269,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_tcpDestinationPort,
                },
        },
-       {
+       [KEY_TCP_SEQ] = {
                .type = ULOGD_RET_UINT32,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.seq", 
@@ -163,7 +278,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_tcpSequenceNumber,
                },
        },
-       {
+       [KEY_TCP_ACKSEQ] = {
                .type = ULOGD_RET_UINT32,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.ackseq", 
@@ -172,17 +287,17 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_tcpAcknowledgementNumber,
                },
        },
-       {
+       [KEY_TCP_OFFSET] = {
                .type = ULOGD_RET_UINT8,
                .flags = ULOGD_RETF_NONE, 
                .name = "tcp.offset",
        },
-       {
+       [KEY_TCP_RESERVED] = {
                .type = ULOGD_RET_UINT8,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.reserved",
        }, 
-       {
+       [KEY_TCP_WINDOW] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.window",
@@ -191,12 +306,12 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_tcpWindowSize,
                },
        },
-       {
+       [KEY_TCP_URG] = {
                .type = ULOGD_RET_BOOL, 
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.urg", 
        },
-       {
+       [KEY_TCP_URGP] = {
                .type = ULOGD_RET_UINT16, 
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.urgp",
@@ -205,50 +320,47 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_tcpUrgentPointer,
                },
        },
-       {
+       [KEY_TCP_ACK] = {
                .type = ULOGD_RET_BOOL, 
                .flags = ULOGD_RETF_NONE, 
                .name = "tcp.ack", 
        },
-       {
+       [KEY_TCP_PSH] = {
                .type = ULOGD_RET_BOOL,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.psh",
        },
-       {
+       [KEY_TCP_RST] = {
                .type = ULOGD_RET_BOOL,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.rst",
        },
-       {
+       [KEY_TCP_SYN] = {
                .type = ULOGD_RET_BOOL,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.syn",
        },
-       {
+       [KEY_TCP_FIN] = {
                .type = ULOGD_RET_BOOL,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.fin",
        },
-       {
+       [KEY_TCP_RES1] = {
                .type = ULOGD_RET_BOOL,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.res1",
        },
-       {
+       [KEY_TCP_RES2] = {
                .type = ULOGD_RET_BOOL,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.res2",
        },
-       {
+       [KEY_TCP_CSUM] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "tcp.csum",
        },
-
-       /* 27 */
-
-       {
+       [KEY_UDP_SPORT] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "udp.sport", 
@@ -257,7 +369,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_udpSourcePort,
                },
        },
-       {
+       [KEY_UDP_DPORT] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "udp.dport", 
@@ -266,21 +378,17 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_udpDestinationPort,
                },
        },
-       {
+       [KEY_UDP_LEN] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "udp.len", 
        },
-       {
+       [KEY_UDP_CSUM] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "udp.csum",
        },
-
-       /* 31 */
-
-
-       {
+       [KEY_ICMP_TYPE] = {
                .type = ULOGD_RET_UINT8,
                .flags = ULOGD_RETF_NONE,
                .name = "icmp.type", 
@@ -289,7 +397,7 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_icmpTypeIPv4,
                },
        },
-       {
+       [KEY_ICMP_CODE] = {
                .type = ULOGD_RET_UINT8,
                .flags = ULOGD_RETF_NONE,
                .name = "icmp.code", 
@@ -298,93 +406,121 @@ static struct ulogd_key iphdr_rets[] = {
                        .field_id = IPFIX_icmpCodeIPv4,
                },
        },
-       {
+       [KEY_ICMP_ECHOID] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "icmp.echoid", 
        },
-       {
+       [KEY_ICMP_ECHOSEQ] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "icmp.echoseq",
        },
-       {
+       [KEY_ICMP_GATEWAY] = {
                .type = ULOGD_RET_IPADDR,
                .flags = ULOGD_RETF_NONE,
                .name = "icmp.gateway", 
        },
-       {
+       [KEY_ICMP_FRAGMTU] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "icmp.fragmtu", 
        },
-       {
+       [KEY_ICMP_CSUM] = {
                .type = ULOGD_RET_UINT16,
                .flags = ULOGD_RETF_NONE,
                .name = "icmp.csum",
        },
-       {
+       [KEY_ICMPV6_TYPE] = {
+               .type = ULOGD_RET_UINT8,
+               .flags = ULOGD_RETF_NONE,
+               .name = "icmpv6.type", 
+               .ipfix = {
+                       .vendor = IPFIX_VENDOR_IETF,
+                       .field_id = IPFIX_icmpTypeIPv6,
+               },
+       },
+       [KEY_ICMPV6_CODE] = {
+               .type = ULOGD_RET_UINT8,
+               .flags = ULOGD_RETF_NONE,
+               .name = "icmpv6.code", 
+               .ipfix = {
+                       .vendor = IPFIX_VENDOR_IETF,
+                       .field_id = IPFIX_icmpCodeIPv6,
+               },
+       },
+       [KEY_ICMPV6_ECHOID] = {
+               .type = ULOGD_RET_UINT16,
+               .flags = ULOGD_RETF_NONE,
+               .name = "icmpv6.echoid", 
+       },
+       [KEY_ICMPV6_ECHOSEQ] = {
+               .type = ULOGD_RET_UINT16,
+               .flags = ULOGD_RETF_NONE,
+               .name = "icmpv6.echoseq",
+       },
+       [KEY_ICMPV6_CSUM] = {
+               .type = ULOGD_RET_UINT16,
+               .flags = ULOGD_RETF_NONE,
+               .name = "icmpv6.csum",
+       },
+       [KEY_AHESP_SPI] = {
                .type = ULOGD_RET_UINT32,
                .flags = ULOGD_RETF_NONE,
                .name = "ahesp.spi",
        },
 
-       /* 39 */
-
 };
 
 /***********************************************************************
  *                     TCP HEADER
  ***********************************************************************/
 
-static int _interp_tcp(struct ulogd_pluginstance *pi)
+static int _interp_tcp(struct ulogd_pluginstance *pi, struct tcphdr *tcph,
+                      u_int32_t len)
 {
-       struct ulogd_key *ret = &pi->output.keys[10];
-       struct iphdr *iph = (struct iphdr *)
-                               pi->input.keys[0].u.source->u.value.ptr;
-       void *protoh = (u_int32_t *)iph + iph->ihl;
-       struct tcphdr *tcph = (struct tcphdr *) protoh;
+       struct ulogd_key *ret = pi->output.keys;
 
-       if (iph->protocol != IPPROTO_TCP)
+       if (len < sizeof(struct tcphdr))
                return 0;
        
-       ret[0].u.value.ui16 = ntohs(tcph->source);
-       ret[0].flags |= ULOGD_RETF_VALID;
-       ret[1].u.value.ui16 = ntohs(tcph->dest);
-       ret[1].flags |= ULOGD_RETF_VALID;
-       ret[2].u.value.ui32 = ntohl(tcph->seq);
-       ret[2].flags |= ULOGD_RETF_VALID;
-       ret[3].u.value.ui32 = ntohl(tcph->ack_seq);
-       ret[3].flags |= ULOGD_RETF_VALID;
-       ret[4].u.value.ui8 = ntohs(tcph->doff);
-       ret[4].flags |= ULOGD_RETF_VALID;
-       ret[5].u.value.ui8 = ntohs(tcph->res1);
-       ret[5].flags |= ULOGD_RETF_VALID;
-       ret[6].u.value.ui16 = ntohs(tcph->window);
-       ret[6].flags |= ULOGD_RETF_VALID;
-
-       ret[7].u.value.b = tcph->urg;
-       ret[7].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_SPORT].u.value.ui16 = ntohs(tcph->source);
+       ret[KEY_TCP_SPORT].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_DPORT].u.value.ui16 = ntohs(tcph->dest);
+       ret[KEY_TCP_DPORT].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_SEQ].u.value.ui32 = ntohl(tcph->seq);
+       ret[KEY_TCP_SEQ].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_ACKSEQ].u.value.ui32 = ntohl(tcph->ack_seq);
+       ret[KEY_TCP_ACKSEQ].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_OFFSET].u.value.ui8 = ntohs(tcph->doff);
+       ret[KEY_TCP_OFFSET].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_RESERVED].u.value.ui8 = ntohs(tcph->res1);
+       ret[KEY_TCP_RESERVED].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_WINDOW].u.value.ui16 = ntohs(tcph->window);
+       ret[KEY_TCP_WINDOW].flags |= ULOGD_RETF_VALID;
+
+       ret[KEY_TCP_URG].u.value.b = tcph->urg;
+       ret[KEY_TCP_URG].flags |= ULOGD_RETF_VALID;
        if (tcph->urg) {
-               ret[8].u.value.ui16 = ntohs(tcph->urg_ptr);
-               ret[8].flags |= ULOGD_RETF_VALID;
+               ret[KEY_TCP_URGP].u.value.ui16 = ntohs(tcph->urg_ptr);
+               ret[KEY_TCP_URGP].flags |= ULOGD_RETF_VALID;
        }
-       ret[9].u.value.b = tcph->ack;
-       ret[9].flags |= ULOGD_RETF_VALID;
-       ret[10].u.value.b = tcph->psh;
-       ret[10].flags |= ULOGD_RETF_VALID;
-       ret[11].u.value.b = tcph->rst;
-       ret[11].flags |= ULOGD_RETF_VALID;
-       ret[12].u.value.b = tcph->syn;
-       ret[12].flags |= ULOGD_RETF_VALID;
-       ret[13].u.value.b = tcph->fin;
-       ret[13].flags |= ULOGD_RETF_VALID;
-       ret[14].u.value.b = tcph->res1;
-       ret[14].flags |= ULOGD_RETF_VALID;
-       ret[15].u.value.b = tcph->res2;
-       ret[15].flags |= ULOGD_RETF_VALID;
-       ret[16].u.value.ui16 = ntohs(tcph->check);
-       ret[16].u.value.ui16 = ULOGD_RETF_VALID;
+       ret[KEY_TCP_ACK].u.value.b = tcph->ack;
+       ret[KEY_TCP_ACK].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_PSH].u.value.b = tcph->psh;
+       ret[KEY_TCP_PSH].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_RST].u.value.b = tcph->rst;
+       ret[KEY_TCP_RST].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_SYN].u.value.b = tcph->syn;
+       ret[KEY_TCP_SYN].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_FIN].u.value.b = tcph->fin;
+       ret[KEY_TCP_FIN].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_RES1].u.value.b = tcph->res1;
+       ret[KEY_TCP_RES1].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_RES2].u.value.b = tcph->res2;
+       ret[KEY_TCP_RES2].flags |= ULOGD_RETF_VALID;
+       ret[KEY_TCP_CSUM].u.value.ui16 = ntohs(tcph->check);
+       ret[KEY_TCP_CSUM].u.value.ui16 = ULOGD_RETF_VALID;
        
        return 0;
 }
@@ -393,26 +529,23 @@ static int _interp_tcp(struct ulogd_pluginstance *pi)
  *                     UDP HEADER
  ***********************************************************************/
 
-static int _interp_udp(struct ulogd_pluginstance *pi)
+static int _interp_udp(struct ulogd_pluginstance *pi, struct udphdr *udph,
+                      u_int32_t len)
                
 {
-       struct ulogd_key *ret = &pi->output.keys[27];
-       struct iphdr *iph = (struct iphdr *) 
-                               pi->input.keys[0].u.source->u.value.ptr;
-       void *protoh = (u_int32_t *)iph + iph->ihl;
-       struct udphdr *udph = protoh;
+       struct ulogd_key *ret = pi->output.keys;
 
-       if (iph->protocol != IPPROTO_UDP)
+       if (len < sizeof(struct udphdr))
                return 0;
 
-       ret[0].u.value.ui16 = ntohs(udph->source);
-       ret[0].flags |= ULOGD_RETF_VALID;
-       ret[1].u.value.ui16 = ntohs(udph->dest);
-       ret[1].flags |= ULOGD_RETF_VALID;
-       ret[2].u.value.ui16 = ntohs(udph->len);
-       ret[2].flags |= ULOGD_RETF_VALID;
-       ret[3].u.value.ui16 = ntohs(udph->check);
-       ret[3].flags |= ULOGD_RETF_VALID;
+       ret[KEY_UDP_SPORT].u.value.ui16 = ntohs(udph->source);
+       ret[KEY_UDP_SPORT].flags |= ULOGD_RETF_VALID;
+       ret[KEY_UDP_DPORT].u.value.ui16 = ntohs(udph->dest);
+       ret[KEY_UDP_DPORT].flags |= ULOGD_RETF_VALID;
+       ret[KEY_UDP_LEN].u.value.ui16 = ntohs(udph->len);
+       ret[KEY_UDP_LEN].flags |= ULOGD_RETF_VALID;
+       ret[KEY_UDP_CSUM].u.value.ui16 = ntohs(udph->check);
+       ret[KEY_UDP_CSUM].flags |= ULOGD_RETF_VALID;
        
        return 0;
 }
@@ -421,116 +554,296 @@ static int _interp_udp(struct ulogd_pluginstance *pi)
  *                     ICMP HEADER
  ***********************************************************************/
 
-static int _interp_icmp(struct ulogd_pluginstance *pi)
+static int _interp_icmp(struct ulogd_pluginstance *pi, struct icmphdr *icmph,
+                       u_int32_t len)
 {
-       struct ulogd_key *ret = &pi->output.keys[31];
-       struct iphdr *iph = (struct iphdr *) 
-                               pi->input.keys[0].u.source->u.value.ptr;
-       void *protoh = (u_int32_t *)iph + iph->ihl;
-       struct icmphdr *icmph = protoh;
+       struct ulogd_key *ret = pi->output.keys;
 
-       if (iph->protocol != IPPROTO_ICMP)
+       if (len < sizeof(struct icmphdr))
                return 0;
-       
-       ret[0].u.value.ui8 = icmph->type;
-       ret[0].flags |= ULOGD_RETF_VALID;
-       ret[1].u.value.ui8 = icmph->code;
-       ret[1].flags |= ULOGD_RETF_VALID;
+
+       ret[KEY_ICMP_TYPE].u.value.ui8 = icmph->type;
+       ret[KEY_ICMP_TYPE].flags |= ULOGD_RETF_VALID;
+       ret[KEY_ICMP_CODE].u.value.ui8 = icmph->code;
+       ret[KEY_ICMP_CODE].flags |= ULOGD_RETF_VALID;
 
        switch (icmph->type) {
-               case ICMP_ECHO:
-               case ICMP_ECHOREPLY:
-                       ret[2].u.value.ui16 = ntohs(icmph->un.echo.id);
-                       ret[2].flags |= ULOGD_RETF_VALID;
-                       ret[3].u.value.ui16 = ntohs(icmph->un.echo.sequence);
-                       ret[3].flags |= ULOGD_RETF_VALID;
-                       break;
-               case ICMP_REDIRECT:
-               case ICMP_PARAMETERPROB:
-                       ret[4].u.value.ui32 = ntohl(icmph->un.gateway);
-                       ret[4].flags |= ULOGD_RETF_VALID;
-                       break;
-               case ICMP_DEST_UNREACH:
-                       if (icmph->code == ICMP_FRAG_NEEDED) {
-                               ret[5].u.value.ui16 = ntohs(icmph->un.frag.mtu);
-                               ret[5].flags |= ULOGD_RETF_VALID;
-                       }
-                       break;
+       case ICMP_ECHO:
+       case ICMP_ECHOREPLY:
+               ret[KEY_ICMP_ECHOID].u.value.ui16 = ntohs(icmph->un.echo.id);
+               ret[KEY_ICMP_ECHOID].flags |= ULOGD_RETF_VALID;
+               ret[KEY_ICMP_ECHOSEQ].u.value.ui16 = ntohs(icmph->un.echo.sequence);
+               ret[KEY_ICMP_ECHOSEQ].flags |= ULOGD_RETF_VALID;
+               break;
+       case ICMP_REDIRECT:
+       case ICMP_PARAMETERPROB:
+               ret[KEY_ICMP_GATEWAY].u.value.ui32 = ntohl(icmph->un.gateway);
+               ret[KEY_ICMP_GATEWAY].flags |= ULOGD_RETF_VALID;
+               break;
+       case ICMP_DEST_UNREACH:
+               if (icmph->code == ICMP_FRAG_NEEDED) {
+                       ret[KEY_ICMP_FRAGMTU].u.value.ui16 = ntohs(icmph->un.frag.mtu);
+                       ret[KEY_ICMP_FRAGMTU].flags |= ULOGD_RETF_VALID;
+               }
+               break;
        }
-       ret[6].u.value.ui16 = icmph->checksum;
-       ret[6].flags |= ULOGD_RETF_VALID;
+       ret[KEY_ICMP_CSUM].u.value.ui16 = icmph->checksum;
+       ret[KEY_ICMP_CSUM].flags |= ULOGD_RETF_VALID;
 
        return 0;
 }
 
 /***********************************************************************
- *                     IPSEC HEADER 
+ *                     ICMPv6 HEADER
  ***********************************************************************/
 
-static int _interp_ahesp(struct ulogd_pluginstance *pi)
+static int _interp_icmpv6(struct ulogd_pluginstance *pi, struct icmp6_hdr *icmph,
+                         u_int32_t len)
 {
-       struct ulogd_key *ret = &pi->output.keys[38];
-       struct iphdr *iph = (struct iphdr *) 
-                               pi->input.keys[0].u.source->u.value.ptr;
-       void *protoh = (u_int32_t *)iph + iph->ihl;
+       struct ulogd_key *ret = pi->output.keys;
+
+       if (len < sizeof(struct icmp6_hdr))
+               return 0;
 
+       ret[KEY_ICMPV6_TYPE].u.value.ui8 = icmph->icmp6_type;
+       ret[KEY_ICMPV6_TYPE].flags |= ULOGD_RETF_VALID;
+       ret[KEY_ICMPV6_CODE].u.value.ui8 = icmph->icmp6_code;
+       ret[KEY_ICMPV6_CODE].flags |= ULOGD_RETF_VALID;
+
+       switch (icmph->icmp6_type) {
+       case ICMP6_ECHO_REQUEST:
+       case ICMP6_ECHO_REPLY:
+               ret[KEY_ICMPV6_ECHOID].u.value.ui16 = ntohs(icmph->icmp6_id);
+               ret[KEY_ICMPV6_ECHOID].flags |= ULOGD_RETF_VALID;
+               ret[KEY_ICMPV6_ECHOSEQ].u.value.ui16 = ntohs(icmph->icmp6_seq);
+               ret[KEY_ICMPV6_ECHOSEQ].flags |= ULOGD_RETF_VALID;
+               break;
+       }
+       ret[KEY_ICMPV6_CSUM].u.value.ui16 = icmph->icmp6_cksum;
+       ret[KEY_ICMPV6_CSUM].flags |= ULOGD_RETF_VALID;
+
+       return 0;
+}
+
+
+/***********************************************************************
+ *                     IPSEC HEADER 
+ ***********************************************************************/
+static int _interp_ahesp(struct ulogd_pluginstance *pi, void *protoh,
+                        u_int32_t len)
+{
 #if 0
+       struct ulogd_key *ret = pi->output.keys;
        struct esphdr *esph = protoh;
 
-       if (iph->protocol != IPPROTO_ESP)
-               return NULL;
+       if (len < sizeof(struct esphdr))
+               return 0;
 
-       ret[0].u.value.ui32 = ntohl(esph->spi);
-       ret[0].flags |= ULOGD_RETF_VALID;
+       ret[KEY_AHESP_SPI].u.value.ui32 = ntohl(esph->spi);
+       ret[KEY_AHESP_SPI].flags |= ULOGD_RETF_VALID;
 #endif
 
        return 0;
 }
 
-static int _interp_iphdr(struct ulogd_pluginstance *pi)
+/***********************************************************************
+ *                     IP HEADER
+ ***********************************************************************/
+
+static int _interp_iphdr(struct ulogd_pluginstance *pi, u_int32_t len)
 {
        struct ulogd_key *ret = pi->output.keys;
-       struct iphdr *iph = (struct iphdr *) 
-                               pi->input.keys[0].u.source->u.value.ptr;
-
-       ret[0].u.value.ui32 = ntohl(iph->saddr);
-       ret[0].flags |= ULOGD_RETF_VALID;
-       ret[1].u.value.ui32 = ntohl(iph->daddr);
-       ret[1].flags |= ULOGD_RETF_VALID;
-       ret[2].u.value.ui8 = iph->protocol;
-       ret[2].flags |= ULOGD_RETF_VALID;
-       ret[3].u.value.ui8 = iph->tos;
-       ret[3].flags |= ULOGD_RETF_VALID;
-       ret[4].u.value.ui8 = iph->ttl;
-       ret[4].flags |= ULOGD_RETF_VALID;
-       ret[5].u.value.ui16 = ntohs(iph->tot_len);
-       ret[5].flags |= ULOGD_RETF_VALID;
-       ret[6].u.value.ui8 = iph->ihl;
-       ret[6].flags |= ULOGD_RETF_VALID;
-       ret[7].u.value.ui16 = ntohs(iph->check);
-       ret[7].flags |= ULOGD_RETF_VALID;
-       ret[8].u.value.ui16 = ntohs(iph->id);
-       ret[8].flags |= ULOGD_RETF_VALID;
-       ret[9].u.value.ui16 = ntohs(iph->frag_off);
-       ret[9].flags |= ULOGD_RETF_VALID;
+       struct iphdr *iph = pi->input.keys[0].u.source->u.value.ptr;
+       void *nexthdr = (u_int32_t *)iph + iph->ihl;
+
+       if (len < sizeof(struct iphdr) || len <= iph->ihl * 4)
+               return 0;
+       len -= iph->ihl * 4;
+
+       ret[KEY_IP_SADDR].u.value.ui32 = iph->saddr;
+       ret[KEY_IP_SADDR].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_DADDR].u.value.ui32 = iph->daddr;
+       ret[KEY_IP_DADDR].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_PROTOCOL].u.value.ui8 = iph->protocol;
+       ret[KEY_IP_PROTOCOL].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_TOS].u.value.ui8 = iph->tos;
+       ret[KEY_IP_TOS].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_TTL].u.value.ui8 = iph->ttl;
+       ret[KEY_IP_TTL].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_TOTLEN].u.value.ui16 = ntohs(iph->tot_len);
+       ret[KEY_IP_TOTLEN].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_IHL].u.value.ui8 = iph->ihl;
+       ret[KEY_IP_IHL].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_CSUM].u.value.ui16 = ntohs(iph->check);
+       ret[KEY_IP_CSUM].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_ID].u.value.ui16 = ntohs(iph->id);
+       ret[KEY_IP_ID].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP_FRAGOFF].u.value.ui16 = ntohs(iph->frag_off);
+       ret[KEY_IP_FRAGOFF].flags |= ULOGD_RETF_VALID;
 
        switch (iph->protocol) {
-               case IPPROTO_TCP:
-                       _interp_tcp(pi);
-                       break;
-               case IPPROTO_UDP:
-                       _interp_udp(pi);
+       case IPPROTO_TCP:
+               _interp_tcp(pi, nexthdr, len);
+               break;
+       case IPPROTO_UDP:
+               _interp_udp(pi, nexthdr, len);
+               break;
+       case IPPROTO_ICMP:
+               _interp_icmp(pi, nexthdr, len);
+               break;
+       case IPPROTO_AH:
+       case IPPROTO_ESP:
+               _interp_ahesp(pi, nexthdr, len);
+               break;
+       }
+
+       return 0;
+}
+
+/***********************************************************************
+ *                     IPv6 HEADER
+ ***********************************************************************/
+
+static int ip6_ext_hdr(u_int8_t nexthdr)
+{
+       switch (nexthdr) {
+       case IPPROTO_HOPOPTS:
+       case IPPROTO_ROUTING:
+       case IPPROTO_FRAGMENT:
+       case IPPROTO_ESP:
+       case IPPROTO_AH:
+       case IPPROTO_DSTOPTS:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int _interp_ipv6hdr(struct ulogd_pluginstance *pi, u_int32_t len)
+{
+       struct ulogd_key *ret = pi->output.keys;
+       struct ip6_hdr *ipv6h = pi->input.keys[0].u.source->u.value.ptr;
+       unsigned int ptr, hdrlen = 0;
+       u_int8_t curhdr;
+       int fragment = 0;
+
+       if (len < sizeof(struct ip6_hdr))
+               return 0;
+
+       ret[KEY_IP6_SADDR].u.value.ptr = &ipv6h->ip6_src;
+       ret[KEY_IP6_SADDR].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP6_DADDR].u.value.ptr = &ipv6h->ip6_dst;
+       ret[KEY_IP6_DADDR].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP6_PAYLOAD_LEN].u.value.ui16 = ntohs(ipv6h->ip6_plen);
+       ret[KEY_IP6_PAYLOAD_LEN].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP6_PRIORITY].u.value.ui8 = ntohl(ipv6h->ip6_flow & 0x0ff00000) >> 20;
+       ret[KEY_IP6_PRIORITY].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP6_FLOWLABEL].u.value.ui32 = ntohl(ipv6h->ip6_flow & 0x000fffff);
+       ret[KEY_IP6_FLOWLABEL].flags |= ULOGD_RETF_VALID;
+       ret[KEY_IP6_HOPLIMIT].u.value.ui8 = ipv6h->ip6_hlim;
+       ret[KEY_IP6_HOPLIMIT].flags |= ULOGD_RETF_VALID;
+
+       curhdr = ipv6h->ip6_nxt;
+       ptr = sizeof(struct ip6_hdr);
+       len -= sizeof(struct ip6_hdr);
+
+       while (curhdr != IPPROTO_NONE && ip6_ext_hdr(curhdr)) {
+               struct ip6_ext *ext = (void *)ipv6h + ptr;
+
+               if (len < sizeof(struct ip6_ext))
+                       return 0;
+
+               switch (curhdr) {
+               case IPPROTO_FRAGMENT: {
+                       struct ip6_frag *fh = (struct ip6_frag *)ext;
+
+                       hdrlen = sizeof(struct ip6_frag);
+                       if (len < hdrlen)
+                               return 0;
+                       len -= hdrlen;
+
+                       ret[KEY_IP6_FRAG_OFF].u.value.ui16 = ntohs(fh->ip6f_offlg & IP6F_OFF_MASK);
+                       ret[KEY_IP6_FRAG_OFF].flags |= ULOGD_RETF_VALID;
+                       ret[KEY_IP6_FRAG_ID].u.value.ui32 = ntohl(fh->ip6f_ident);
+                       ret[KEY_IP6_FRAG_ID].flags |= ULOGD_RETF_VALID;
+
+                       if (ntohs(fh->ip6f_offlg & IP6F_OFF_MASK))
+                               fragment = 1;
                        break;
-               case IPPROTO_ICMP:
-                       _interp_icmp(pi);
+               }
+               case IPPROTO_DSTOPTS:
+               case IPPROTO_ROUTING:
+               case IPPROTO_HOPOPTS:
+                       if (fragment)
+                               goto out;
+
+                       hdrlen = (ext->ip6e_len + 1) << 3;
+                       if (len < hdrlen)
+                               return 0;
+                       len -= hdrlen;
                        break;
                case IPPROTO_AH:
-               case IPPROTO_ESP:
-                       _interp_ahesp(pi);
+                       if (fragment)
+                               goto out;
+
+                       hdrlen = (ext->ip6e_len + 2) << 2;
+                       if (len < hdrlen)
+                               return 0;
+                       len -= hdrlen;
+
+                       _interp_ahesp(pi, (void *)ext, len);
                        break;
+               case IPPROTO_ESP:
+                       if (fragment)
+                               goto out;
+
+                       hdrlen = (ext->ip6e_len + 2) << 2;
+                       if (len < hdrlen)
+                               return 0;
+                       len -= hdrlen;
+
+                       _interp_ahesp(pi, (void *)ext, len);
+                       goto out;
+               default:
+                       return 0;
+               }
+
+               curhdr = ext->ip6e_nxt;
+               ptr += hdrlen;
+       }
+
+       if (fragment)
+               goto out;
+
+       switch (curhdr) {
+       case IPPROTO_TCP:
+               _interp_tcp(pi, (void *)ipv6h + ptr, len);
+               break;
+       case IPPROTO_UDP:
+               _interp_udp(pi, (void *)ipv6h + ptr, len);
+               break;
+       case IPPROTO_ICMPV6:
+               _interp_icmpv6(pi, (void *)ipv6h + ptr, len);
+               break;
        }
 
+out:
+       ret[KEY_IP6_NEXTHDR].u.value.ui8 = curhdr;
+       ret[KEY_IP6_NEXTHDR].flags |= ULOGD_RETF_VALID;
+       return 0;
+}
 
+static int _interp_pkt(struct ulogd_pluginstance *pi)
+{
+       u_int32_t len = pi->input.keys[1].u.source->u.value.ui32;
+       u_int8_t family = pi->input.keys[2].u.source->u.value.ui8;
+
+       switch (family) {
+       case AF_INET:
+               return _interp_iphdr(pi, len);
+       case AF_INET6:
+               return _interp_ipv6hdr(pi, len);
+       }
        return 0;
 }
 
@@ -540,9 +853,21 @@ static struct ulogd_key base_inp[] = {
                .name = "raw.pkt", 
                .ipfix = { 
                        .vendor = IPFIX_VENDOR_NETFILTER, 
-                       .field_id = 
+                       .field_id = IPFIX_NF_rawpacket,
                },
        },
+       {
+               .type = ULOGD_RET_UINT32,
+               .name = "raw.pktlen", 
+               .ipfix = {
+                       .vendor = IPFIX_VENDOR_NETFILTER, 
+                       .field_id = IPFIX_NF_rawpacket_length,
+               },
+       },
+       {
+               .type = ULOGD_RET_UINT8,
+               .name = "oob.family",
+       }
 };
 
 static struct ulogd_plugin base_plugin = {
@@ -557,7 +882,7 @@ static struct ulogd_plugin base_plugin = {
                .num_keys = ARRAY_SIZE(iphdr_rets),
                .type = ULOGD_DTYPE_PACKET,
                },
-       .interp = &_interp_iphdr,
+       .interp = &_interp_pkt,
        .version = ULOGD_VERSION,
 };
 
index 2bf1c3e7d816e27521f3e14a64f30b0ad7beb82f..5d7e46aab5d3199f4fb6532a4d5654d5b013016b 100644 (file)
@@ -64,7 +64,7 @@ enum {
        IPFIX_postPacketDeltaCount      = 24,
        IPFIX_minimumPacketLength       = 25,
        IPFIX_maximumPacketLength       = 26,
-       IPFIX_sooureIPv6Address         = 27,
+       IPFIX_sourceIPv6Address         = 27,
        IPFIX_destinationIPv6Address    = 28,
        IPFIX_sourceIPv6Mask            = 29,
        IPFIX_destinationIPv6Mask       = 30,
index bdaeaa4e3c1fe8f0e8a278bda5c999ea60d6da62..3db2862436bd2f2582045d772e7a90ad425c6925 100644 (file)
@@ -1,8 +1,62 @@
 #ifndef _PRINTPKT_H
 #define _PRINTPKT_H
 
-#define INTR_IDS       35
-extern struct ulogd_key printpkt_keys[INTR_IDS];
+enum pkt_keys {
+       KEY_OOB_FAMILY,
+       KEY_OOB_TIME_SEC,
+       KEY_OOB_PREFIX,
+       KEY_OOB_IN,
+       KEY_OOB_OUT,
+       KEY_RAW_MAC,
+       KEY_RAW_MACLEN,
+       KEY_IP_SADDR,
+       KEY_IP_DADDR,
+       KEY_IP_TOTLEN,
+       KEY_IP_TOS,
+       KEY_IP_TTL,
+       KEY_IP_ID,
+       KEY_IP_FRAGOFF,
+       KEY_IP_PROTOCOL,
+       KEY_IP6_SADDR,
+       KEY_IP6_DADDR,
+       KEY_IP6_PAYLOAD_LEN,
+       KEY_IP6_PRIORITY,
+       KEY_IP6_HOPLIMIT,
+       KEY_IP6_FLOWLABEL,
+       KEY_IP6_NEXTHDR,
+       KEY_IP6_FRAG_OFF,
+       KEY_IP6_FRAG_ID,
+       KEY_TCP_SPORT,
+       KEY_TCP_DPORT,
+       KEY_TCP_SEQ,
+       KEY_TCP_ACKSEQ,
+       KEY_TCP_WINDOW,
+       KEY_TCP_SYN,
+       KEY_TCP_ACK,
+       KEY_TCP_PSH,
+       KEY_TCP_RST,
+       KEY_TCP_FIN,
+       KEY_TCP_URG,
+       KEY_TCP_URGP,
+       KEY_UDP_SPORT,
+       KEY_UDP_DPORT,
+       KEY_UDP_LEN,
+       KEY_ICMP_TYPE,
+       KEY_ICMP_CODE,
+       KEY_ICMP_ECHOID,
+       KEY_ICMP_ECHOSEQ,
+       KEY_ICMP_GATEWAY,
+       KEY_ICMP_FRAGMTU,
+       KEY_ICMPV6_TYPE,
+       KEY_ICMPV6_CODE,
+       KEY_ICMPV6_ECHOID,
+       KEY_ICMPV6_ECHOSEQ,
+       KEY_AHESP_SPI,
+       __PRINTPKT_KEYS
+};
+#define PRINTPKT_KEYS (__PRINTPKT_KEYS)
+
+extern struct ulogd_key printpkt_keys[PRINTPKT_KEYS];
 
 int printpkt_print(struct ulogd_key *res, char *buf);
 
index f30925911c72af8c117b02260a37d4b12a2d9243..81f973056fa37d9702c1998cde5e97d99cd2212e 100644 (file)
@@ -212,6 +212,16 @@ static struct ulogd_key output_keys[] = {
                        .field_id = IPFIX_NF_seq_global,
                },
        },
+       {
+               .type = ULOGD_RET_UINT8,
+               .flags = ULOGD_RETF_NONE,
+               .name = "oob.family",
+       },
+       {
+               .type = ULOGD_RET_UINT16,
+               .flags = ULOGD_RETF_NONE,
+               .name = "oob.protocol",
+       },
 };
 
 static inline int 
@@ -229,16 +239,19 @@ interp_packet(struct ulogd_pluginstance *upi, struct nflog_data *ldata)
        u_int32_t indev = nflog_get_indev(ldata);
        u_int32_t outdev = nflog_get_outdev(ldata);
        u_int32_t seq;
-       
+
+       ret[14].u.value.ui8 = af_ce(upi->config_kset).u.value;
 
        if (ph) {
                /* FIXME */
                ret[10].u.value.ui8 = ph->hook;
                ret[10].flags |= ULOGD_RETF_VALID;
+               ret[15].u.value.ui16 = ntohs(ph->hw_protocol);
+               ret[15].flags |= ULOGD_RETF_VALID;
        }
 
        if (hw) {
-               ret[0].u.value.ptr = &hw->hw_addr;
+               ret[0].u.value.ptr = hw->hw_addr;
                ret[0].flags |= ULOGD_RETF_VALID;
                ret[11].u.value.ui16 = ntohs(hw->hw_addrlen);
                ret[11].flags |= ULOGD_RETF_VALID;
@@ -286,14 +299,13 @@ interp_packet(struct ulogd_pluginstance *upi, struct nflog_data *ldata)
        }
 
        if (nflog_get_seq(ldata, &seq)) {
-               ret[10].u.value.ui32 = seq;
-               ret[10].flags |= ULOGD_RETF_VALID;
+               ret[12].u.value.ui32 = seq;
+               ret[12].flags |= ULOGD_RETF_VALID;
        }
        if (nflog_get_seq_global(ldata, &seq)) {
-               ret[11].u.value.ui32 = seq;
-               ret[11].flags |= ULOGD_RETF_VALID;
+               ret[13].u.value.ui32 = seq;
+               ret[13].flags |= ULOGD_RETF_VALID;
        }
-       
        ulogd_propagate_results(upi);
        return 0;
 }
index ec6cd02f5dba901929b801a2c93f519b0507580b..7719cae14426dfe27e44915b3a94e6c4875c3aa6 100644 (file)
 #include <arpa/inet.h>
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
 #include <ulogd/ulogd.h>
 #include <ulogd/conffile.h>
 #include <ulogd/printpkt.h>
 
-#define NIPQUAD(addr) \
-       ((unsigned char *)&addr)[0], \
-       ((unsigned char *)&addr)[1], \
-        ((unsigned char *)&addr)[2], \
-        ((unsigned char *)&addr)[3]
-
-struct ulogd_key printpkt_keys[INTR_IDS] = {
-       { .name = "oob.time.sec", },
-       { .name = "oob.prefix", },
-       { .name = "oob.in", },
-       { .name = "oob.out", },
-       { .name = "raw.mac", },
-       { .name = "ip.saddr", },
-       { .name = "ip.daddr", },
-       { .name = "ip.totlen", },
-       { .name = "ip.tos", },
-       { .name = "ip.ttl", },
-       { .name = "ip.id", },
-       { .name = "ip.fragoff", },
-       { .name = "ip.protocol", },
-       { .name = "tcp.sport", },
-       { .name = "tcp.dport", },
-       { .name = "tcp.seq", },
-       { .name = "tcp.ackseq", },
-       { .name = "tcp.window", },
-       { .name = "tcp.urg", },
-       { .name = "tcp.ack", },
-       { .name = "tcp.psh", },
-       { .name = "tcp.rst", },
-       { .name = "tcp.syn", },
-       { .name = "tcp.fin", },
-       { .name = "tcp.urgp", },
-       { .name = "udp.sport", },
-       { .name = "udp.dport", },
-       { .name = "udp.len", },
-       { .name = "icmp.type", },
-       { .name = "icmp.code", },
-       { .name = "icmp.echoid", },
-       { .name = "icmp.echoseq", },
-       { .name = "icmp.gateway", },
-       { .name = "icmp.fragmtu", },
-       { .name = "ahesp.spi", },
+struct ulogd_key printpkt_keys[] = {
+       [KEY_OOB_FAMILY]        = { .name = "oob.family", },
+       [KEY_OOB_TIME_SEC]      = { .name = "oob.time.sec", },
+       [KEY_OOB_PREFIX]        = { .name = "oob.prefix", },
+       [KEY_OOB_IN]            = { .name = "oob.in", },
+       [KEY_OOB_OUT]           = { .name = "oob.out", },
+       [KEY_RAW_MAC]           = { .name = "raw.mac", },
+       [KEY_RAW_MACLEN]        = { .name = "raw.mac_len", },
+       [KEY_IP_SADDR]          = { .name = "ip.saddr", },
+       [KEY_IP_DADDR]          = { .name = "ip.daddr", },
+       [KEY_IP_TOTLEN]         = { .name = "ip.totlen", },
+       [KEY_IP_TOS]            = { .name = "ip.tos", },
+       [KEY_IP_TTL]            = { .name = "ip.ttl", },
+       [KEY_IP_ID]             = { .name = "ip.id", },
+       [KEY_IP_FRAGOFF]        = { .name = "ip.fragoff", },
+       [KEY_IP_PROTOCOL]       = { .name = "ip.protocol", },
+       [KEY_IP6_SADDR]         = { .name = "ip6.saddr", },
+       [KEY_IP6_DADDR]         = { .name = "ip6.daddr", },
+       [KEY_IP6_PAYLOAD_LEN]   = { .name = "ip6.payload_len" },
+       [KEY_IP6_PRIORITY]      = { .name = "ip6.priority" },
+       [KEY_IP6_HOPLIMIT]      = { .name = "ip6.hoplimit" },
+       [KEY_IP6_FLOWLABEL]     = { .name = "ip6.flowlabel" },
+       [KEY_IP6_NEXTHDR]       = { .name = "ip6.nexthdr" },
+       [KEY_IP6_FRAG_OFF]      = { .name = "ip6.fragoff" },
+       [KEY_IP6_FRAG_ID]       = { .name = "ip6.fragid" },
+       [KEY_TCP_SPORT]         = { .name = "tcp.sport", },
+       [KEY_TCP_DPORT]         = { .name = "tcp.dport", },
+       [KEY_TCP_SEQ]           = { .name = "tcp.seq", },
+       [KEY_TCP_ACKSEQ]        = { .name = "tcp.ackseq", },
+       [KEY_TCP_WINDOW]        = { .name = "tcp.window", },
+       [KEY_TCP_SYN]           = { .name = "tcp.syn", },
+       [KEY_TCP_ACK]           = { .name = "tcp.ack", },
+       [KEY_TCP_URG]           = { .name = "tcp.urg", },
+       [KEY_TCP_PSH]           = { .name = "tcp.psh", },
+       [KEY_TCP_RST]           = { .name = "tcp.rst", },
+       [KEY_TCP_FIN]           = { .name = "tcp.fin", },
+       [KEY_TCP_URG]           = { .name = "tcp.urg", },
+       [KEY_TCP_URGP]          = { .name = "tcp.urgp", },
+       [KEY_UDP_SPORT]         = { .name = "udp.sport", },
+       [KEY_UDP_DPORT]         = { .name = "udp.dport", },
+       [KEY_UDP_LEN]           = { .name = "udp.len", },
+       [KEY_ICMP_TYPE]         = { .name = "icmp.type", },
+       [KEY_ICMP_CODE]         = { .name = "icmp.code", },
+       [KEY_ICMP_ECHOID]       = { .name = "icmp.echoid", },
+       [KEY_ICMP_ECHOSEQ]      = { .name = "icmp.echoseq", },
+       [KEY_ICMP_GATEWAY]      = { .name = "icmp.gateway", },
+       [KEY_ICMP_FRAGMTU]      = { .name = "icmp.fragmtu", },
+       [KEY_ICMPV6_TYPE]       = { .name = "icmpv6.type", },
+       [KEY_ICMPV6_CODE]       = { .name = "icmpv6.code", },
+       [KEY_ICMPV6_ECHOID]     = { .name = "icmpv6.echoid", },
+       [KEY_ICMPV6_ECHOSEQ]    = { .name = "icmpv6.echoseq", },
+       [KEY_AHESP_SPI]         = { .name = "ahesp.spi", },
 };
 
 #define GET_VALUE(res, x)      (res[x].u.source->u.value)
 #define GET_FLAGS(res, x)      (res[x].u.source->flags)
 #define pp_is_valid(res, x)    (GET_FLAGS(res, x) & ULOGD_RETF_VALID)
 
-int printpkt_print(struct ulogd_key *res, char *buf)
+static int printpkt_proto(struct ulogd_key *res, char *buf, int protocol)
 {
        char *buf_cur = buf;
 
-       if (pp_is_valid(res, 1))
-               buf_cur += sprintf(buf_cur, "%s ", (char *) GET_VALUE(res, 1).ptr);
-
-       if (pp_is_valid(res, 2) && pp_is_valid(res, 3)) {
-               buf_cur += sprintf(buf_cur, "IN=%s OUT=%s ", 
-                                  (char *) GET_VALUE(res, 2).ptr, 
-                                  (char *) GET_VALUE(res, 3).ptr);
-       }
-
-       /* FIXME: configurable */
-       if (pp_is_valid(res, 4))
-               buf_cur += sprintf(buf_cur, "MAC=%s ",
-                                  (char *) GET_VALUE(res, 4).ptr);
-       else
-               buf_cur += sprintf(buf_cur, "MAC= ");
-       
-       if (pp_is_valid(res, 5))
-               buf_cur += sprintf(buf_cur, "SRC=%s ", inet_ntoa(
-                               (struct in_addr) {htonl(GET_VALUE(res, 5).ui32)}));
-
-       if (pp_is_valid(res, 6))
-               buf_cur += sprintf(buf_cur, "DST=%s ", inet_ntoa(
-                               (struct in_addr) {htonl(GET_VALUE(res, 6).ui32)}));
-
-       /* FIXME: add pp_is_valid calls to remainder of file */
-       buf_cur += sprintf(buf_cur,"LEN=%u TOS=%02X PREC=0x%02X TTL=%u ID=%u ", 
-                       GET_VALUE(res, 7).ui16, GET_VALUE(res, 8).ui8 & IPTOS_TOS_MASK, 
-                       GET_VALUE(res, 8).ui8 & IPTOS_PREC_MASK, GET_VALUE(res, 9).ui8,
-                       GET_VALUE(res, 10).ui16);
-
-       if (GET_VALUE(res, 10).ui16 & IP_RF) 
-               buf_cur += sprintf(buf_cur, "CE ");
-
-       if (GET_VALUE(res, 11).ui16 & IP_DF)
-               buf_cur += sprintf(buf_cur, "DF ");
-
-       if (GET_VALUE(res, 11).ui16 & IP_MF)
-               buf_cur += sprintf(buf_cur, "MF ");
-
-       if (GET_VALUE(res, 11).ui16 & IP_OFFMASK)
-               buf_cur += sprintf(buf_cur, "FRAG:%u ", 
-                               GET_VALUE(res, 11).ui16 & IP_OFFMASK);
+       switch (protocol) {
+       case IPPROTO_TCP:
+               buf_cur += sprintf(buf_cur, "PROTO=KEY_TCP ");
 
-       switch (GET_VALUE(res, 12).ui8) {
+               if (!pp_is_valid(res, KEY_TCP_SPORT)) {
+                       buf_cur += sprintf(buf_cur, "INCOMPLETE");
+                       break;
+               }
 
-       case IPPROTO_TCP:
-               buf_cur += sprintf(buf_cur, "PROTO=TCP ");
                buf_cur += sprintf(buf_cur, "SPT=%u DPT=%u ",
-                               GET_VALUE(res, 13).ui16, GET_VALUE(res, 14).ui16);
+                                  GET_VALUE(res, KEY_TCP_SPORT).ui16,
+                                  GET_VALUE(res, KEY_TCP_DPORT).ui16);
                /* FIXME: config */
                buf_cur += sprintf(buf_cur, "SEQ=%u ACK=%u ", 
-                               GET_VALUE(res, 15).ui32, GET_VALUE(res, 16).ui32);
+                                  GET_VALUE(res, KEY_TCP_SEQ).ui32,
+                                  GET_VALUE(res, KEY_TCP_ACKSEQ).ui32);
 
-               buf_cur += sprintf(buf_cur, "WINDOW=%u ", GET_VALUE(res, 17).ui16);
+               buf_cur += sprintf(buf_cur, "WINDOW=%u ",
+                                  GET_VALUE(res, KEY_TCP_WINDOW).ui16);
 
 //             buf_cur += sprintf(buf_cur, "RES=0x%02x ", 
                
-               if (GET_VALUE(res, 18).b)
+               if (GET_VALUE(res, KEY_TCP_URG).b)
                        buf_cur += sprintf(buf_cur, "URG ");
 
-               if (GET_VALUE(res, 19).b)
+               if (GET_VALUE(res, KEY_TCP_ACK).b)
                        buf_cur += sprintf(buf_cur, "ACK ");
 
-               if (GET_VALUE(res, 20).b)
+               if (GET_VALUE(res, KEY_TCP_PSH).b)
                        buf_cur += sprintf(buf_cur, "PSH ");
 
-               if (GET_VALUE(res, 21).b)
+               if (GET_VALUE(res, KEY_TCP_RST).b)
                        buf_cur += sprintf(buf_cur, "RST ");
 
-               if (GET_VALUE(res, 22).b)
+               if (GET_VALUE(res, KEY_TCP_SYN).b)
                        buf_cur += sprintf(buf_cur, "SYN ");
 
-               if (GET_VALUE(res, 23).b)
+               if (GET_VALUE(res, KEY_TCP_FIN).b)
                        buf_cur += sprintf(buf_cur, "FIN ");
 
-               buf_cur += sprintf(buf_cur, "URGP=%u ", GET_VALUE(res, 24).ui16);
+               buf_cur += sprintf(buf_cur, "URGP=%u ",
+                                  GET_VALUE(res, KEY_TCP_URGP).ui16);
 
                break;
+
        case IPPROTO_UDP:
+               buf_cur += sprintf(buf_cur, "PROTO=KEY_UDP ");
 
-               buf_cur += sprintf(buf_cur, "PROTO=UDP ");
+               if (!pp_is_valid(res, KEY_UDP_SPORT)) {
+                       buf_cur += sprintf(buf_cur, "INCOMPLETE");
+                       break;
+               }
 
                buf_cur += sprintf(buf_cur, "SPT=%u DPT=%u LEN=%u ", 
-                               GET_VALUE(res, 25).ui16, GET_VALUE(res, 26).ui16, 
-                               GET_VALUE(res, 27).ui16);
+                                  GET_VALUE(res, KEY_UDP_SPORT).ui16,
+                                  GET_VALUE(res, KEY_UDP_DPORT).ui16, 
+                                  GET_VALUE(res, KEY_UDP_LEN).ui16);
+               break;
+       case IPPROTO_ESP:
+       case IPPROTO_AH:
+               buf_cur += sprintf(buf_cur, "PROTO=%s ",
+                                  GET_VALUE(res, KEY_IP_PROTOCOL).ui8 == IPPROTO_ESP ? "ESP" : "AH");
+
+               if (!pp_is_valid(res, KEY_AHESP_SPI)) {
+                       buf_cur += sprintf(buf_cur, "INCOMPLETE");
                        break;
-       case IPPROTO_ICMP:
+               }
+
+               buf_cur += sprintf(buf_cur, "SPI=0x%x ",
+                                  GET_VALUE(res, KEY_AHESP_SPI).ui32);
+               break;
+       }
+
+       return buf_cur - buf;
+}
+
+static int printpkt_ipv4(struct ulogd_key *res, char *buf)
+{
+       char *buf_cur = buf;
+       char tmp[INET_ADDRSTRLEN];
+
+       if (pp_is_valid(res, KEY_IP_SADDR))
+               buf_cur += sprintf(buf_cur, "SRC=%s ",
+                                  inet_ntop(AF_INET,
+                                            &GET_VALUE(res, KEY_IP_SADDR).ui32,
+                                            tmp, sizeof(tmp)));
 
+       if (pp_is_valid(res, KEY_IP_DADDR))
+               buf_cur += sprintf(buf_cur, "DST=%s ",
+                                  inet_ntop(AF_INET,
+                                            &GET_VALUE(res, KEY_IP_DADDR).ui32,
+                                            tmp, sizeof(tmp)));
+
+       /* FIXME: add pp_is_valid calls to remainder of file */
+       buf_cur += sprintf(buf_cur,"LEN=%u TOS=%02X PREC=0x%02X TTL=%u ID=%u ", 
+                          GET_VALUE(res, KEY_IP_TOTLEN).ui16,
+                          GET_VALUE(res, KEY_IP_TOS).ui8 & IPTOS_TOS_MASK, 
+                          GET_VALUE(res, KEY_IP_TOS).ui8 & IPTOS_PREC_MASK,
+                          GET_VALUE(res, KEY_IP_TTL).ui8,
+                          GET_VALUE(res, KEY_IP_ID).ui16);
+
+       if (GET_VALUE(res, KEY_IP_FRAGOFF).ui16 & IP_RF) 
+               buf_cur += sprintf(buf_cur, "CE ");
+
+       if (GET_VALUE(res, KEY_IP_FRAGOFF).ui16 & IP_DF)
+               buf_cur += sprintf(buf_cur, "DF ");
+
+       if (GET_VALUE(res, KEY_IP_FRAGOFF).ui16 & IP_MF)
+               buf_cur += sprintf(buf_cur, "MF ");
+
+       if (GET_VALUE(res, KEY_IP_FRAGOFF).ui16 & IP_OFFMASK)
+               buf_cur += sprintf(buf_cur, "FRAG:%u ", 
+                                  GET_VALUE(res, KEY_IP_FRAGOFF).ui16 & IP_OFFMASK);
+
+       switch (GET_VALUE(res, KEY_IP_PROTOCOL).ui8) {
+       case IPPROTO_TCP:
+       case IPPROTO_UDP:
+       case IPPROTO_ESP:
+       case IPPROTO_AH:
+               buf_cur += printpkt_proto(res, buf_cur,
+                                         GET_VALUE(res, KEY_IP_PROTOCOL).ui8);
+               break;
+
+       case IPPROTO_ICMP:
                buf_cur += sprintf(buf_cur, "PROTO=ICMP ");
 
+               if (!pp_is_valid(res, KEY_ICMP_TYPE)) {
+                       buf_cur += sprintf(buf_cur, "INCOMPLETE");
+                       break;
+               }
+
                buf_cur += sprintf(buf_cur, "TYPE=%u CODE=%u ",
-                               GET_VALUE(res, 28).ui8, GET_VALUE(res, 29).ui8);
+                                  GET_VALUE(res, KEY_ICMP_TYPE).ui8,
+                                  GET_VALUE(res, KEY_ICMP_CODE).ui8);
 
-               switch (GET_VALUE(res, 28).ui8) {
+               switch (GET_VALUE(res, KEY_ICMP_TYPE).ui8) {
                case ICMP_ECHO:
                case ICMP_ECHOREPLY:
                        buf_cur += sprintf(buf_cur, "ID=%u SEQ=%u ", 
-                                          GET_VALUE(res, 30).ui16,
-                                          GET_VALUE(res, 31).ui16);
+                                          GET_VALUE(res, KEY_ICMP_ECHOID).ui16,
+                                          GET_VALUE(res, KEY_ICMP_ECHOSEQ).ui16);
                        break;
                case ICMP_PARAMETERPROB:
                        buf_cur += sprintf(buf_cur, "PARAMETER=%u ",
-                                          GET_VALUE(res, 32).ui32 >> 24);
+                                          GET_VALUE(res, KEY_ICMP_GATEWAY).ui32 >> 24);
                        break;
                case ICMP_REDIRECT:
-                       buf_cur += sprintf(buf_cur, "GATEWAY=%s ", inet_ntoa((struct in_addr) {htonl(GET_VALUE(res, 32).ui32)}));
+                       buf_cur += sprintf(buf_cur, "GATEWAY=%s ",
+                                          inet_ntop(AF_INET,
+                                                    &GET_VALUE(res, KEY_ICMP_GATEWAY).ui32,
+                                                    tmp, sizeof(tmp)));
                        break;
                case ICMP_DEST_UNREACH:
-                       if (GET_VALUE(res, 29).ui8 == ICMP_FRAG_NEEDED)
+                       if (GET_VALUE(res, KEY_ICMP_CODE).ui8 == ICMP_FRAG_NEEDED)
                                buf_cur += sprintf(buf_cur, "MTU=%u ", 
-                                                  GET_VALUE(res, 33).ui16);
+                                                  GET_VALUE(res, KEY_ICMP_FRAGMTU).ui16);
                        break;
                }
                break;
+       default:
+               buf_cur += sprintf(buf_cur, "PROTO=%u ",
+                                  GET_VALUE(res, KEY_IP_PROTOCOL).ui8);
+       }
+
+       return buf_cur - buf;
+}
+
+static int printpkt_ipv6(struct ulogd_key *res, char *buf)
+{
+       char *buf_cur = buf;
+       char tmp[INET6_ADDRSTRLEN];
+
+       if (pp_is_valid(res, KEY_IP6_SADDR))
+               buf_cur += sprintf(buf_cur, "SRC=%s ",
+                                  inet_ntop(AF_INET6,
+                                            GET_VALUE(res, KEY_IP6_SADDR).ptr,
+                                            tmp, sizeof(tmp)));
+
+       if (pp_is_valid(res, KEY_IP6_DADDR))
+               buf_cur += sprintf(buf_cur, "DST=%s ",
+                                  inet_ntop(AF_INET6,
+                                            GET_VALUE(res, KEY_IP6_DADDR).ptr,
+                                            tmp, sizeof(tmp)));
+
+       if (pp_is_valid(res, KEY_IP6_PAYLOAD_LEN))
+               buf_cur += sprintf(buf_cur, "LEN=%Zu ",
+                                  GET_VALUE(res, KEY_IP6_PAYLOAD_LEN).ui16 +
+                                  sizeof(struct ip6_hdr));
+
+       if (pp_is_valid(res, KEY_IP6_PRIORITY))
+               buf_cur += sprintf(buf_cur, "TC=%u ",
+                                  GET_VALUE(res, KEY_IP6_PRIORITY).ui8);
+
+       if (pp_is_valid(res, KEY_IP6_HOPLIMIT))
+               buf_cur += sprintf(buf_cur, "HOPLIMIT=%u ",
+                                  GET_VALUE(res, KEY_IP6_HOPLIMIT).ui8);
+       
+       if (pp_is_valid(res, KEY_IP6_FLOWLABEL))
+               buf_cur += sprintf(buf_cur, "FLOWLBL=%u ",
+                                  GET_VALUE(res, KEY_IP6_FLOWLABEL).ui32);
+
+       if (pp_is_valid(res, KEY_IP6_FRAG_OFF) && pp_is_valid(res, KEY_IP6_FRAG_ID))
+               buf_cur += sprintf(buf_cur, "FRAG: %u ID: %08x ",
+                                  GET_VALUE(res, KEY_IP6_FRAG_OFF).ui16,
+                                  GET_VALUE(res, KEY_IP6_FRAG_ID).ui32);
+
+       switch (GET_VALUE(res, KEY_IP6_NEXTHDR).ui8) {
+       case IPPROTO_TCP:
+       case IPPROTO_UDP:
        case IPPROTO_ESP:
        case IPPROTO_AH:
-               buf_cur += sprintf(buf_cur, "PROTO=%s ", GET_VALUE(res, 12).ui8 == IPPROTO_ESP ? "ESP" : "AH");
-               /* FIXME: "INCOMPLETE [%u bytes]" in case of short pkt */
-               if (pp_is_valid(res, 34)) {
-                       buf_cur += sprintf(buf_cur, "SPI=0x%x ", GET_VALUE(res, 34).ui32);
+               buf_cur += printpkt_proto(res, buf_cur,
+                                         GET_VALUE(res, KEY_IP6_NEXTHDR).ui8);
+               break;
+       case IPPROTO_ICMPV6:
+               buf_cur += sprintf(buf_cur, "PROTO=ICMPv6 ");
+
+               if (!pp_is_valid(res, KEY_ICMPV6_TYPE)) {
+                       buf_cur += sprintf(buf_cur, "INCOMPLETE");
+                       break;
+               }
+
+               if (!(pp_is_valid(res, KEY_ICMPV6_TYPE) &&
+                     pp_is_valid(res, KEY_ICMPV6_CODE))) {
+                       buf_cur += sprintf(buf_cur, "TRUNCATED");
+                       break;
+               }
+
+               buf_cur += sprintf(buf_cur, "TYPE=%u CODE=%u ",
+                                  GET_VALUE(res, KEY_ICMPV6_TYPE).ui8,
+                                  GET_VALUE(res, KEY_ICMPV6_CODE).ui8);
+
+               switch (GET_VALUE(res, KEY_ICMPV6_TYPE).ui8) {
+               case ICMP6_ECHO_REQUEST:
+               case ICMP6_ECHO_REPLY:
+                       buf_cur += sprintf(buf_cur, "ID=%u SEQ=%u ", 
+                                          GET_VALUE(res, KEY_ICMPV6_ECHOID).ui16,
+                                          GET_VALUE(res, KEY_ICMPV6_ECHOSEQ).ui16);
+                       break;
                }
                break;
-       default:
+       }
+
+       return buf_cur - buf;
+}
 
-               buf_cur += sprintf(buf_cur, "PROTO=%u ", GET_VALUE(res, 12).ui8);
+int printpkt_print(struct ulogd_key *res, char *buf)
+{
+       char *buf_cur = buf;
+
+       if (pp_is_valid(res, KEY_OOB_PREFIX))
+               buf_cur += sprintf(buf_cur, "%s ",
+                                  (char *) GET_VALUE(res, KEY_OOB_PREFIX).ptr);
+
+       if (pp_is_valid(res, KEY_OOB_IN) && pp_is_valid(res, KEY_OOB_OUT))
+               buf_cur += sprintf(buf_cur, "IN=%s OUT=%s ", 
+                                  (char *) GET_VALUE(res, KEY_OOB_IN).ptr, 
+                                  (char *) GET_VALUE(res, KEY_OOB_OUT).ptr);
+
+       /* FIXME: configurable */
+       if (pp_is_valid(res, KEY_RAW_MAC)) {
+               unsigned char *mac = (unsigned char *) GET_VALUE(res, KEY_RAW_MAC).ptr;
+               int i, len = GET_VALUE(res, KEY_RAW_MACLEN).ui16 * 2;
+
+               buf_cur += sprintf(buf_cur, "MAC=");
+               for (i = 0; i < len; i++)
+                       buf_cur += sprintf(buf_cur, "%02x%c", mac[i],
+                                          i == len - 1 ? ' ' : ':');
+       } else
+               buf_cur += sprintf(buf_cur, "MAC= ");
+
+       switch (GET_VALUE(res, KEY_OOB_FAMILY).ui8) {
+       case AF_INET:
+               buf_cur += printpkt_ipv4(res, buf_cur);
+               break;
+       case AF_INET6:
+               buf_cur += printpkt_ipv6(res, buf_cur);
+               break;
        }
+
        strcat(buf_cur, "\n");
 
        return 0;