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