fix mac address are truncated problem when compiling ulogd with -D_FORTIFY_SOURCE...
[distributedratelimiting.git] / extensions / ulogd_BASE.c
1 /* ulogd_MAC.c, Version $Revision: 5239 $
2  *
3  * ulogd interpreter plugin for 
4  *      o MAC addresses
5  *      o NFMARK field
6  *      o TIME
7  *      o Interface names
8  *      o IP header
9  *      o TCP header
10  *      o UDP header
11  *      o ICMP header
12  *      o AH/ESP header
13  *      o GRE header
14  *
15  * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
16  *
17  *  This program is free software; you can redistribute it and/or modify
18  *  it under the terms of the GNU General Public License version 2 
19  *  as published by the Free Software Foundation
20  *
21  *  This program is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *  GNU General Public License for more details.
25  *
26  *  You should have received a copy of the GNU General Public License
27  *  along with this program; if not, write to the Free Software
28  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29  
30  * $Id: ulogd_BASE.c 5239 2005-02-12 21:22:56Z laforge $
31  *
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <sys/socket.h>
37 #include <netinet/ip.h>
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
40 #include <netinet/ip_icmp.h>
41 #include <netinet/udp.h>
42 #include <ulogd/ulogd.h>
43 #include <ulogd/gre.h>
44
45 /***********************************************************************
46  *                      Raw header
47  ***********************************************************************/
48 static ulog_iret_t raw_rets[] = {
49         { .type = ULOGD_RET_STRING, 
50           .flags = ULOGD_RETF_FREE, 
51           .key = "raw.mac",
52         },
53         { .type = ULOGD_RET_RAW,
54           .flags = ULOGD_RETF_NONE,
55           .key = "raw.pkt",
56         },
57         { .type = ULOGD_RET_UINT32, 
58           .flags = ULOGD_RETF_NONE, 
59           .key = "raw.pktlen",
60         },
61 };
62
63 static ulog_iret_t *_interp_raw(ulog_interpreter_t *ip, 
64                                 ulog_packet_msg_t *pkt)
65 {
66         unsigned char *p;
67         int i;
68         char *buf = NULL;
69         ulog_iret_t *ret = ip->result;
70
71         if (pkt->mac_len) {
72                 buf = (char *) malloc(3 * pkt->mac_len + 1);
73                 if (!buf) {
74                         ulogd_log(ULOGD_ERROR, "OOM!!!\n");
75                         return NULL;
76                 }
77                 *buf = '\0';
78
79                 p = pkt->mac;
80                 for (i = 0; i < pkt->mac_len; i++, p++)
81                         sprintf(buf + (i*3), "%02x%c", *p, i==pkt->mac_len-1 ? ' ':':');
82                 ret[0].value.ptr = buf;
83                 ret[0].flags |= ULOGD_RETF_VALID;
84         }
85
86         /* include pointer to raw ipv4 packet */
87         ret[1].value.ptr = pkt->payload;
88         ret[1].flags |= ULOGD_RETF_VALID;
89         ret[2].value.ui32 = pkt->data_len;
90         ret[2].flags |= ULOGD_RETF_VALID;
91
92         return ret;
93 }
94
95 /***********************************************************************
96  *                      OUT OF BAND
97  ***********************************************************************/
98
99 static ulog_iret_t oob_rets[] = {
100         { .type = ULOGD_RET_STRING, 
101           .flags = ULOGD_RETF_NONE, 
102           .key = "oob.prefix",
103         },
104         { .type = ULOGD_RET_UINT32, 
105           .flags = ULOGD_RETF_NONE, 
106           .key = "oob.time.sec", 
107         },
108         { .type = ULOGD_RET_UINT32, 
109           .flags = ULOGD_RETF_NONE, 
110           .key = "oob.time.usec", 
111         },
112         { .type = ULOGD_RET_UINT32, 
113           .flags = ULOGD_RETF_NONE, 
114           .key = "oob.mark", 
115         },
116         { .type = ULOGD_RET_STRING, 
117           .flags = ULOGD_RETF_NONE, 
118           .key = "oob.in", 
119         }, 
120         { .type = ULOGD_RET_STRING, 
121           .flags = ULOGD_RETF_NONE, 
122           .key = "oob.out", 
123         },
124 };
125
126 static ulog_iret_t *_interp_oob(struct ulog_interpreter *ip, 
127                                 ulog_packet_msg_t *pkt)
128 {
129         ulog_iret_t *ret = ip->result;
130
131         ret[0].value.ptr = pkt->prefix;
132         ret[0].flags |= ULOGD_RETF_VALID;
133
134         /* god knows why timestamp_usec contains crap if timestamp_sec == 0
135          * if (pkt->timestamp_sec || pkt->timestamp_usec) { */
136         if (pkt->timestamp_sec) {
137                 ret[1].value.ui32 = pkt->timestamp_sec;
138                 ret[1].flags |= ULOGD_RETF_VALID;
139                 ret[2].value.ui32 = pkt->timestamp_usec;
140                 ret[2].flags |= ULOGD_RETF_VALID;
141         } else {
142                 ret[1].flags &= ~ULOGD_RETF_VALID;
143                 ret[2].flags &= ~ULOGD_RETF_VALID;
144         }
145
146         ret[3].value.ui32 = pkt->mark;
147         ret[3].flags |= ULOGD_RETF_VALID;
148         ret[4].value.ptr = pkt->indev_name;
149         ret[4].flags |= ULOGD_RETF_VALID;
150         ret[5].value.ptr = pkt->outdev_name;
151         ret[5].flags |= ULOGD_RETF_VALID;
152         
153         return ret;
154 }
155
156 /***********************************************************************
157  *                      IP HEADER
158  ***********************************************************************/
159
160 static ulog_iret_t iphdr_rets[] = {
161         { .type = ULOGD_RET_IPADDR, 
162           .flags = ULOGD_RETF_NONE, 
163           .key = "ip.saddr", 
164         },
165         { .type = ULOGD_RET_IPADDR, 
166           .flags = ULOGD_RETF_NONE, 
167           .key = "ip.daddr", 
168         },
169         { .type = ULOGD_RET_UINT8, 
170           .flags = ULOGD_RETF_NONE, 
171           .key = "ip.protocol", 
172         },
173         { .type = ULOGD_RET_UINT8, 
174           .flags = ULOGD_RETF_NONE, 
175           .key = "ip.tos", 
176         },
177         { .type = ULOGD_RET_UINT8, 
178           .flags = ULOGD_RETF_NONE, 
179           .key = "ip.ttl", 
180         },
181         { .type = ULOGD_RET_UINT16, 
182           .flags = ULOGD_RETF_NONE, 
183           .key = "ip.totlen", 
184         },
185         { .type = ULOGD_RET_UINT8, 
186           .flags = ULOGD_RETF_NONE, 
187           .key = "ip.ihl", 
188         },
189         { .type = ULOGD_RET_UINT16, 
190           .flags = ULOGD_RETF_NONE, 
191           .key = "ip.csum", 
192         },
193         { .type = ULOGD_RET_UINT16, 
194           .flags = ULOGD_RETF_NONE, 
195           .key = "ip.id", 
196         },
197         { .type = ULOGD_RET_UINT16, 
198           .flags = ULOGD_RETF_NONE, 
199           .key = "ip.fragoff", 
200         },
201 };
202
203 static ulog_iret_t *_interp_iphdr(struct ulog_interpreter *ip, 
204                                 ulog_packet_msg_t *pkt)
205 {
206         ulog_iret_t *ret = ip->result;
207         struct iphdr *iph = (struct iphdr *) pkt->payload;
208
209         ret[0].value.ui32 = ntohl(iph->saddr);
210         ret[0].flags |= ULOGD_RETF_VALID;
211         ret[1].value.ui32 = ntohl(iph->daddr);
212         ret[1].flags |= ULOGD_RETF_VALID;
213         ret[2].value.ui8 = iph->protocol;
214         ret[2].flags |= ULOGD_RETF_VALID;
215         ret[3].value.ui8 = iph->tos;
216         ret[3].flags |= ULOGD_RETF_VALID;
217         ret[4].value.ui8 = iph->ttl;
218         ret[4].flags |= ULOGD_RETF_VALID;
219         ret[5].value.ui16 = ntohs(iph->tot_len);
220         ret[5].flags |= ULOGD_RETF_VALID;
221         ret[6].value.ui8 = iph->ihl;
222         ret[6].flags |= ULOGD_RETF_VALID;
223         ret[7].value.ui16 = ntohs(iph->check);
224         ret[7].flags |= ULOGD_RETF_VALID;
225         ret[8].value.ui16 = ntohs(iph->id);
226         ret[8].flags |= ULOGD_RETF_VALID;
227         ret[9].value.ui16 = ntohs(iph->frag_off);
228         ret[9].flags |= ULOGD_RETF_VALID;
229
230         return ret;
231 }
232
233 /***********************************************************************
234  *                      TCP HEADER
235  ***********************************************************************/
236 static ulog_iret_t tcphdr_rets[] = {
237         { .type = ULOGD_RET_UINT16, 
238           .flags = ULOGD_RETF_NONE, 
239           .key = "tcp.sport", 
240         },
241         { .type = ULOGD_RET_UINT16, 
242           .flags = ULOGD_RETF_NONE, 
243           .key = "tcp.dport", 
244         },
245         { .type = ULOGD_RET_UINT32, 
246           .flags = ULOGD_RETF_NONE, 
247           .key = "tcp.seq",
248         },
249         { .type = ULOGD_RET_UINT32, 
250           .flags = ULOGD_RETF_NONE, 
251           .key = "tcp.ackseq", 
252         }, 
253         { .type = ULOGD_RET_UINT8, 
254           .flags = ULOGD_RETF_NONE, 
255           .key = "tcp.offset",
256         }, 
257         { .type = ULOGD_RET_UINT8, 
258           .flags = ULOGD_RETF_NONE, 
259           .key = "tcp.reserved",
260         },
261         { .type = ULOGD_RET_UINT16, 
262           .flags = ULOGD_RETF_NONE, 
263           .key = "tcp.window",
264         },
265         { .type = ULOGD_RET_BOOL, 
266           .flags = ULOGD_RETF_NONE, 
267           .key = "tcp.urg", 
268         },
269         { .type = ULOGD_RET_UINT16, 
270           .flags = ULOGD_RETF_NONE, 
271           .key = "tcp.urgp",
272         }, 
273         { .type = ULOGD_RET_BOOL, 
274           .flags = ULOGD_RETF_NONE, 
275           .key = "tcp.ack", 
276         },
277         { .type = ULOGD_RET_BOOL, 
278           .flags = ULOGD_RETF_NONE,
279           .key = "tcp.psh", 
280         },
281         { .type = ULOGD_RET_BOOL, 
282           .flags = ULOGD_RETF_NONE, 
283           .key = "tcp.rst", 
284         },
285         { .type = ULOGD_RET_BOOL, 
286           .flags = ULOGD_RETF_NONE, 
287           .key = "tcp.syn", 
288         }, 
289         { .type = ULOGD_RET_BOOL, 
290           .flags = ULOGD_RETF_NONE, 
291           .key = "tcp.fin", 
292         },
293         { .type = ULOGD_RET_BOOL, 
294           .flags = ULOGD_RETF_NONE, 
295           .key = "tcp.res1",
296         },
297         { .type = ULOGD_RET_BOOL, 
298           .flags = ULOGD_RETF_NONE, 
299           .key = "tcp.res2",
300         },
301         { .type = ULOGD_RET_UINT16, 
302           .flags = ULOGD_RETF_NONE, 
303           .key = "tcp.csum",
304         },
305 };
306
307 static ulog_iret_t *_interp_tcphdr(struct ulog_interpreter *ip, 
308                                 ulog_packet_msg_t *pkt)
309 {
310         struct iphdr *iph = (struct iphdr *) pkt->payload;
311         void *protoh = (u_int32_t *)iph + iph->ihl;
312         struct tcphdr *tcph = (struct tcphdr *) protoh;
313         ulog_iret_t *ret = ip->result;
314
315         if (iph->protocol != IPPROTO_TCP)
316                 return NULL;
317         
318         ret[0].value.ui16 = ntohs(tcph->source);
319         ret[0].flags |= ULOGD_RETF_VALID;
320         ret[1].value.ui16 = ntohs(tcph->dest);
321         ret[1].flags |= ULOGD_RETF_VALID;
322         ret[2].value.ui32 = ntohl(tcph->seq);
323         ret[2].flags |= ULOGD_RETF_VALID;
324         ret[3].value.ui32 = ntohl(tcph->ack_seq);
325         ret[3].flags |= ULOGD_RETF_VALID;
326         ret[4].value.ui8 = ntohs(tcph->doff);
327         ret[4].flags |= ULOGD_RETF_VALID;
328         ret[5].value.ui8 = ntohs(tcph->res1);
329         ret[5].flags |= ULOGD_RETF_VALID;
330         ret[6].value.ui16 = ntohs(tcph->window);
331         ret[6].flags |= ULOGD_RETF_VALID;
332
333         ret[7].value.b = tcph->urg;
334         ret[7].flags |= ULOGD_RETF_VALID;
335         if (tcph->urg) {
336                 ret[8].value.ui16 = ntohs(tcph->urg_ptr);
337                 ret[8].flags |= ULOGD_RETF_VALID;
338         }
339         ret[9].value.b = tcph->ack;
340         ret[9].flags |= ULOGD_RETF_VALID;
341         ret[10].value.b = tcph->psh;
342         ret[10].flags |= ULOGD_RETF_VALID;
343         ret[11].value.b = tcph->rst;
344         ret[11].flags |= ULOGD_RETF_VALID;
345         ret[12].value.b = tcph->syn;
346         ret[12].flags |= ULOGD_RETF_VALID;
347         ret[13].value.b = tcph->fin;
348         ret[13].flags |= ULOGD_RETF_VALID;
349         ret[14].value.b = tcph->res1;
350         ret[14].flags |= ULOGD_RETF_VALID;
351         ret[15].value.b = tcph->res2;
352         ret[15].flags |= ULOGD_RETF_VALID;
353         ret[16].value.ui16 = ntohs(tcph->check);
354         ret[16].value.ui16 = ULOGD_RETF_VALID;
355         
356         return ret;
357 }
358
359 /***********************************************************************
360  *                      UDP HEADER
361  ***********************************************************************/
362 static ulog_iret_t udphdr_rets[] = {
363         { .type = ULOGD_RET_UINT16, 
364           .flags = ULOGD_RETF_NONE, 
365           .key = "udp.sport", 
366         },
367         { .type = ULOGD_RET_UINT16, 
368           .flags = ULOGD_RETF_NONE, 
369           .key = "udp.dport", 
370         }, 
371         { .type = ULOGD_RET_UINT16, 
372           .flags = ULOGD_RETF_NONE, 
373           .key = "udp.len", 
374         },
375         { .type = ULOGD_RET_UINT16, 
376           .flags = ULOGD_RETF_NONE, 
377           .key = "udp.csum",
378         },
379 };
380
381 static ulog_iret_t *_interp_udp(struct ulog_interpreter *ip, 
382                                 ulog_packet_msg_t *pkt)
383 {
384         struct iphdr *iph = (struct iphdr *) pkt->payload;
385         void *protoh = (u_int32_t *)iph + iph->ihl;
386         struct udphdr *udph = protoh;
387         ulog_iret_t *ret = ip->result;
388
389         if (iph->protocol != IPPROTO_UDP)
390                 return NULL;
391
392         ret[0].value.ui16 = ntohs(udph->source);
393         ret[0].flags |= ULOGD_RETF_VALID;
394         ret[1].value.ui16 = ntohs(udph->dest);
395         ret[1].flags |= ULOGD_RETF_VALID;
396         ret[2].value.ui16 = ntohs(udph->len);
397         ret[2].flags |= ULOGD_RETF_VALID;
398         ret[3].value.ui16 = ntohs(udph->check);
399         ret[3].flags |= ULOGD_RETF_VALID;
400         
401         return ret;
402 }
403
404 /***********************************************************************
405  *                      ICMP HEADER
406  ***********************************************************************/
407
408 static ulog_iret_t icmphdr_rets[] = {
409         { .type = ULOGD_RET_UINT8, 
410           .flags = ULOGD_RETF_NONE, 
411           .key = "icmp.type", 
412         }, 
413         { .type = ULOGD_RET_UINT8, 
414           .flags = ULOGD_RETF_NONE, 
415           .key = "icmp.code", 
416         },
417         { .type = ULOGD_RET_UINT16, 
418           .flags = ULOGD_RETF_NONE, 
419           .key = "icmp.echoid", 
420         }, 
421         { .type = ULOGD_RET_UINT16, 
422           .flags = ULOGD_RETF_NONE, 
423           .key = "icmp.echoseq", 
424         },
425         { .type = ULOGD_RET_IPADDR, 
426           .flags = ULOGD_RETF_NONE, 
427           .key = "icmp.gateway", 
428         },
429         { .type = ULOGD_RET_UINT16, 
430           .flags = ULOGD_RETF_NONE, 
431           .key = "icmp.fragmtu", 
432         }, 
433         { .type = ULOGD_RET_UINT16, 
434           .flags = ULOGD_RETF_NONE, 
435           .key = "icmp.csum",
436         },
437 };
438
439 static ulog_iret_t *_interp_icmp(struct ulog_interpreter *ip, 
440                                 ulog_packet_msg_t *pkt)
441 {
442         struct iphdr *iph = (struct iphdr *) pkt->payload;
443         void *protoh = (u_int32_t *)iph + iph->ihl;
444         struct icmphdr *icmph = protoh;
445         ulog_iret_t *ret = ip->result;
446
447         if (iph->protocol != IPPROTO_ICMP)
448                 return NULL;
449         
450         ret[0].value.ui8 = icmph->type;
451         ret[0].flags |= ULOGD_RETF_VALID;
452         ret[1].value.ui8 = icmph->code;
453         ret[1].flags |= ULOGD_RETF_VALID;
454
455         switch(icmph->type) {
456                 case ICMP_ECHO:
457                 case ICMP_ECHOREPLY:
458                         ret[2].value.ui16 = ntohs(icmph->un.echo.id);
459                         ret[2].flags |= ULOGD_RETF_VALID;
460                         ret[3].value.ui16 = ntohs(icmph->un.echo.sequence);
461                         ret[3].flags |= ULOGD_RETF_VALID;
462                         break;
463                 case ICMP_REDIRECT:
464                 case ICMP_PARAMETERPROB:
465                         ret[4].value.ui32 = ntohl(icmph->un.gateway);
466                         ret[4].flags |= ULOGD_RETF_VALID;
467                         break;
468                 case ICMP_DEST_UNREACH:
469                         if (icmph->code == ICMP_FRAG_NEEDED) {
470                                 ret[5].value.ui16 = ntohs(icmph->un.frag.mtu);
471                                 ret[5].flags |= ULOGD_RETF_VALID;
472                         }
473                         break;
474         }
475         ret[6].value.ui16 = icmph->checksum;
476         ret[6].flags |= ULOGD_RETF_VALID;
477
478         return ret;
479 }
480
481 /***********************************************************************
482  *                      IPSEC HEADER 
483  ***********************************************************************/
484
485 static ulog_iret_t ahesphdr_rets[] = {
486         { .type = ULOGD_RET_UINT32, 
487           .flags = ULOGD_RETF_NONE, 
488           .key = "ahesp.spi", 
489         },
490 };
491
492 static ulog_iret_t *_interp_ahesp(struct ulog_interpreter *ip, 
493                                 ulog_packet_msg_t *pkt)
494 {
495
496         ulog_iret_t *ret = ip->result;
497 #if 0
498         struct iphdr *iph = (struct iphdr *) pkt->payload;
499         void *protoh = (u_int32_t *) (iph + iph->ihl);
500         struct esphdr *esph = protoh;
501
502         if (iph->protocol != IPPROTO_ESP)
503                 return NULL;
504
505         ret[0].value.ui32 = ntohl(esph->spi);
506         ret[0].flags |= ULOGD_RETF_VALID;
507 #endif
508
509         return ret;
510 }
511
512 /***********************************************************************
513  *                      GRE/PPTP HEADER
514  ***********************************************************************/
515
516 static ulog_iret_t gre_rets[] = {
517         { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.csum",
518                 { b: 0 } },
519         { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.route", 
520                 { b: 0 } },
521         { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.key", 
522                 { b: 0 } },
523         { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.seq", 
524                 { b: 0 } },
525         { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.ssr", 
526                 { b: 0 } },
527         { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.recur", 
528                 { b: 0 } },
529         { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.ack", 
530                 { b: 0 } },
531         { NULL, NULL, 0, ULOGD_RET_UINT8, ULOGD_RETF_NONE, "gre.version",
532                 { ui8 :0 } },
533         { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "gre.protocol",
534                 { ui16: 0 } },
535         { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "gre.csum",
536                 { ui16: 0 } },
537         { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "gre.key",
538                 { ui32: 0 } },
539         { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "gre.seq",
540                 { ui32: 0 } },
541         { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "pptp.pktlen", 
542                 { ui16: 0 } },
543         { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "pptp.callid", 
544                 { ui16: 0 } },
545         { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "pptp.seq", 
546                 { ui32: 0 } },
547         { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "pptp.ack", 
548                 { ui32: 0 } },
549 };
550
551 static ulog_iret_t *_interp_gre(struct ulog_interpreter *ip, 
552                                 ulog_packet_msg_t *pkt)
553 {
554         struct iphdr *iph = (struct iphdr *) pkt->payload;
555         void *protoh = (u_int32_t *)iph + iph->ihl;
556         struct grehdr *greh = protoh;
557         struct pptphdr *pptph = protoh;
558         ulog_iret_t *ret = ip->result;
559
560         if (iph->protocol != IPPROTO_GRE)
561                 return NULL;
562
563         ret[0].value.b = (greh->flags_ver & GRE_FLAG_CKSUM) ? 1 : 0;
564         ret[0].flags |= ULOGD_RETF_VALID;
565         ret[1].value.b = (greh->flags_ver & GRE_FLAG_ROUTE) ? 1 : 0;
566         ret[1].flags |= ULOGD_RETF_VALID;
567         ret[2].value.b = (greh->flags_ver & GRE_FLAG_KEY) ? 1 : 0;
568         ret[2].flags |= ULOGD_RETF_VALID;
569         ret[3].value.b = (greh->flags_ver & GRE_FLAG_SEQ) ? 1 : 0;
570         ret[3].flags |= ULOGD_RETF_VALID;
571         ret[4].value.b = (greh->flags_ver & GRE_FLAG_SSR) ? 1 : 0;
572         ret[4].flags |= ULOGD_RETF_VALID;
573         ret[5].value.b = (greh->flags_ver & GRE_FLAG_RECUR) ? 1 : 0;
574         ret[5].flags |= ULOGD_RETF_VALID;
575         ret[6].value.b = (greh->flags_ver & GRE_FLAG_ACK) ? 1 : 0;
576         ret[6].flags |= ULOGD_RETF_VALID;
577         ret[7].value.ui8 = (greh->flags_ver & GRE_FLAG_VER);
578         ret[7].flags |= ULOGD_RETF_VALID;
579         ret[8].value.ui16 = ntohs(greh->protocol);
580         ret[8].flags |= ULOGD_RETF_VALID;
581
582         ret[9].flags &= ~ULOGD_RETF_VALID;
583         ret[10].flags &= ~ULOGD_RETF_VALID;
584         ret[11].flags &= ~ULOGD_RETF_VALID;
585         ret[12].flags &= ~ULOGD_RETF_VALID;
586         ret[13].flags &= ~ULOGD_RETF_VALID;
587         ret[14].flags &= ~ULOGD_RETF_VALID;
588         ret[15].flags &= ~ULOGD_RETF_VALID;
589
590         if ((greh->flags_ver & GRE_FLAG_VER) == GRE_VER_GRE) {
591                 if (greh->flags_ver & GRE_FLAG_CKSUM) {
592                         ret[9].value.ui16 = ntohs(greh->cksum);
593                         ret[9].flags |= ULOGD_RETF_VALID;
594                 }
595                 if (greh->flags_ver & GRE_FLAG_KEY) {
596                         ret[10].value.ui32 = ntohl(greh->key);
597                         ret[10].flags |= ULOGD_RETF_VALID;
598                 }
599                 if (greh->flags_ver & GRE_FLAG_SEQ) {
600                         ret[11].value.ui32 = ntohl(greh->seq);
601                         ret[11].flags |= ULOGD_RETF_VALID;
602                 }
603         } else if ((greh->flags_ver & GRE_FLAG_VER) == GRE_VER_PPTP) {
604                 ret[12].value.ui16 = ntohs(pptph->payload_len);
605                 ret[12].flags |= ULOGD_RETF_VALID;
606                 ret[13].value.ui16 = ntohs(pptph->call_id);
607                 ret[13].flags |= ULOGD_RETF_VALID;
608                 if (greh->flags_ver & GRE_FLAG_SEQ) {
609                         ret[14].value.ui32 = ntohl(pptph->seq);
610                         ret[14].flags |= ULOGD_RETF_VALID;
611                 }
612                 if (greh->flags_ver & GRE_FLAG_ACK) {
613                         ret[15].value.ui32 = ntohl(pptph->ack);
614                         ret[15].flags |= ULOGD_RETF_VALID;
615                 }
616         }
617         
618         return ret;
619 }
620
621
622 static ulog_interpreter_t base_ip[] = {
623         { .name = "raw", 
624           .interp = &_interp_raw, 
625           .key_num = 3, 
626           .result = raw_rets },
627         { .name = "oob", 
628           .interp = &_interp_oob, 
629           .key_num = 6, 
630           .result = oob_rets },
631         { .name  = "ip", 
632           .interp = &_interp_iphdr, 
633           .key_num = 10, 
634           .result = iphdr_rets },
635         { .name = "tcp", 
636           .interp = &_interp_tcphdr, 
637           .key_num = 17, 
638           .result = tcphdr_rets },
639         { .name = "icmp", 
640           .interp = &_interp_icmp, 
641           .key_num = 7, 
642           .result = icmphdr_rets },
643         { .name = "udp", 
644           .interp = &_interp_udp, 
645           .key_num = 4, 
646           .result = udphdr_rets },
647         { .name = "ahesp", 
648           .interp = &_interp_ahesp, 
649           .key_num = 1, 
650           .result = ahesphdr_rets },
651         { NULL, "gre", 0, &_interp_gre, 16, gre_rets },
652         { NULL, "", 0, NULL, 0, NULL }, 
653 };
654
655 void _base_reg_ip(void)
656 {
657         ulog_interpreter_t *ip = base_ip;
658         ulog_interpreter_t *p;
659
660         for (p = ip; p->interp; p++) {
661                 register_interpreter(p);
662         }
663 }
664
665 void _init(void)
666 {
667         _base_reg_ip();
668 }