1 /* ulogd_MAC.c, Version $Revision: 5239 $
3 * ulogd interpreter plugin for
15 * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
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
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.
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
30 * $Id: ulogd_BASE.c 5239 2005-02-12 21:22:56Z laforge $
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>
45 /***********************************************************************
47 ***********************************************************************/
48 static ulog_iret_t raw_rets[] = {
49 { .type = ULOGD_RET_STRING,
50 .flags = ULOGD_RETF_FREE,
53 { .type = ULOGD_RET_RAW,
54 .flags = ULOGD_RETF_NONE,
57 { .type = ULOGD_RET_UINT32,
58 .flags = ULOGD_RETF_NONE,
63 static ulog_iret_t *_interp_raw(ulog_interpreter_t *ip,
64 ulog_packet_msg_t *pkt)
69 ulog_iret_t *ret = ip->result;
72 buf = (char *) malloc(3 * pkt->mac_len + 1);
74 ulogd_log(ULOGD_ERROR, "OOM!!!\n");
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;
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;
95 /***********************************************************************
97 ***********************************************************************/
99 static ulog_iret_t oob_rets[] = {
100 { .type = ULOGD_RET_STRING,
101 .flags = ULOGD_RETF_NONE,
104 { .type = ULOGD_RET_UINT32,
105 .flags = ULOGD_RETF_NONE,
106 .key = "oob.time.sec",
108 { .type = ULOGD_RET_UINT32,
109 .flags = ULOGD_RETF_NONE,
110 .key = "oob.time.usec",
112 { .type = ULOGD_RET_UINT32,
113 .flags = ULOGD_RETF_NONE,
116 { .type = ULOGD_RET_STRING,
117 .flags = ULOGD_RETF_NONE,
120 { .type = ULOGD_RET_STRING,
121 .flags = ULOGD_RETF_NONE,
126 static ulog_iret_t *_interp_oob(struct ulog_interpreter *ip,
127 ulog_packet_msg_t *pkt)
129 ulog_iret_t *ret = ip->result;
131 ret[0].value.ptr = pkt->prefix;
132 ret[0].flags |= ULOGD_RETF_VALID;
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;
142 ret[1].flags &= ~ULOGD_RETF_VALID;
143 ret[2].flags &= ~ULOGD_RETF_VALID;
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;
156 /***********************************************************************
158 ***********************************************************************/
160 static ulog_iret_t iphdr_rets[] = {
161 { .type = ULOGD_RET_IPADDR,
162 .flags = ULOGD_RETF_NONE,
165 { .type = ULOGD_RET_IPADDR,
166 .flags = ULOGD_RETF_NONE,
169 { .type = ULOGD_RET_UINT8,
170 .flags = ULOGD_RETF_NONE,
171 .key = "ip.protocol",
173 { .type = ULOGD_RET_UINT8,
174 .flags = ULOGD_RETF_NONE,
177 { .type = ULOGD_RET_UINT8,
178 .flags = ULOGD_RETF_NONE,
181 { .type = ULOGD_RET_UINT16,
182 .flags = ULOGD_RETF_NONE,
185 { .type = ULOGD_RET_UINT8,
186 .flags = ULOGD_RETF_NONE,
189 { .type = ULOGD_RET_UINT16,
190 .flags = ULOGD_RETF_NONE,
193 { .type = ULOGD_RET_UINT16,
194 .flags = ULOGD_RETF_NONE,
197 { .type = ULOGD_RET_UINT16,
198 .flags = ULOGD_RETF_NONE,
203 static ulog_iret_t *_interp_iphdr(struct ulog_interpreter *ip,
204 ulog_packet_msg_t *pkt)
206 ulog_iret_t *ret = ip->result;
207 struct iphdr *iph = (struct iphdr *) pkt->payload;
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;
233 /***********************************************************************
235 ***********************************************************************/
236 static ulog_iret_t tcphdr_rets[] = {
237 { .type = ULOGD_RET_UINT16,
238 .flags = ULOGD_RETF_NONE,
241 { .type = ULOGD_RET_UINT16,
242 .flags = ULOGD_RETF_NONE,
245 { .type = ULOGD_RET_UINT32,
246 .flags = ULOGD_RETF_NONE,
249 { .type = ULOGD_RET_UINT32,
250 .flags = ULOGD_RETF_NONE,
253 { .type = ULOGD_RET_UINT8,
254 .flags = ULOGD_RETF_NONE,
257 { .type = ULOGD_RET_UINT8,
258 .flags = ULOGD_RETF_NONE,
259 .key = "tcp.reserved",
261 { .type = ULOGD_RET_UINT16,
262 .flags = ULOGD_RETF_NONE,
265 { .type = ULOGD_RET_BOOL,
266 .flags = ULOGD_RETF_NONE,
269 { .type = ULOGD_RET_UINT16,
270 .flags = ULOGD_RETF_NONE,
273 { .type = ULOGD_RET_BOOL,
274 .flags = ULOGD_RETF_NONE,
277 { .type = ULOGD_RET_BOOL,
278 .flags = ULOGD_RETF_NONE,
281 { .type = ULOGD_RET_BOOL,
282 .flags = ULOGD_RETF_NONE,
285 { .type = ULOGD_RET_BOOL,
286 .flags = ULOGD_RETF_NONE,
289 { .type = ULOGD_RET_BOOL,
290 .flags = ULOGD_RETF_NONE,
293 { .type = ULOGD_RET_BOOL,
294 .flags = ULOGD_RETF_NONE,
297 { .type = ULOGD_RET_BOOL,
298 .flags = ULOGD_RETF_NONE,
301 { .type = ULOGD_RET_UINT16,
302 .flags = ULOGD_RETF_NONE,
307 static ulog_iret_t *_interp_tcphdr(struct ulog_interpreter *ip,
308 ulog_packet_msg_t *pkt)
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;
315 if (iph->protocol != IPPROTO_TCP)
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;
333 ret[7].value.b = tcph->urg;
334 ret[7].flags |= ULOGD_RETF_VALID;
336 ret[8].value.ui16 = ntohs(tcph->urg_ptr);
337 ret[8].flags |= ULOGD_RETF_VALID;
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;
359 /***********************************************************************
361 ***********************************************************************/
362 static ulog_iret_t udphdr_rets[] = {
363 { .type = ULOGD_RET_UINT16,
364 .flags = ULOGD_RETF_NONE,
367 { .type = ULOGD_RET_UINT16,
368 .flags = ULOGD_RETF_NONE,
371 { .type = ULOGD_RET_UINT16,
372 .flags = ULOGD_RETF_NONE,
375 { .type = ULOGD_RET_UINT16,
376 .flags = ULOGD_RETF_NONE,
381 static ulog_iret_t *_interp_udp(struct ulog_interpreter *ip,
382 ulog_packet_msg_t *pkt)
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;
389 if (iph->protocol != IPPROTO_UDP)
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;
404 /***********************************************************************
406 ***********************************************************************/
408 static ulog_iret_t icmphdr_rets[] = {
409 { .type = ULOGD_RET_UINT8,
410 .flags = ULOGD_RETF_NONE,
413 { .type = ULOGD_RET_UINT8,
414 .flags = ULOGD_RETF_NONE,
417 { .type = ULOGD_RET_UINT16,
418 .flags = ULOGD_RETF_NONE,
419 .key = "icmp.echoid",
421 { .type = ULOGD_RET_UINT16,
422 .flags = ULOGD_RETF_NONE,
423 .key = "icmp.echoseq",
425 { .type = ULOGD_RET_IPADDR,
426 .flags = ULOGD_RETF_NONE,
427 .key = "icmp.gateway",
429 { .type = ULOGD_RET_UINT16,
430 .flags = ULOGD_RETF_NONE,
431 .key = "icmp.fragmtu",
433 { .type = ULOGD_RET_UINT16,
434 .flags = ULOGD_RETF_NONE,
439 static ulog_iret_t *_interp_icmp(struct ulog_interpreter *ip,
440 ulog_packet_msg_t *pkt)
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;
447 if (iph->protocol != IPPROTO_ICMP)
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;
455 switch(icmph->type) {
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;
464 case ICMP_PARAMETERPROB:
465 ret[4].value.ui32 = ntohl(icmph->un.gateway);
466 ret[4].flags |= ULOGD_RETF_VALID;
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;
475 ret[6].value.ui16 = icmph->checksum;
476 ret[6].flags |= ULOGD_RETF_VALID;
481 /***********************************************************************
483 ***********************************************************************/
485 static ulog_iret_t ahesphdr_rets[] = {
486 { .type = ULOGD_RET_UINT32,
487 .flags = ULOGD_RETF_NONE,
492 static ulog_iret_t *_interp_ahesp(struct ulog_interpreter *ip,
493 ulog_packet_msg_t *pkt)
496 ulog_iret_t *ret = ip->result;
498 struct iphdr *iph = (struct iphdr *) pkt->payload;
499 void *protoh = (u_int32_t *) (iph + iph->ihl);
500 struct esphdr *esph = protoh;
502 if (iph->protocol != IPPROTO_ESP)
505 ret[0].value.ui32 = ntohl(esph->spi);
506 ret[0].flags |= ULOGD_RETF_VALID;
512 /***********************************************************************
514 ***********************************************************************/
516 static ulog_iret_t gre_rets[] = {
517 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.csum",
519 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.route",
521 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.key",
523 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.seq",
525 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.ssr",
527 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.recur",
529 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.ack",
531 { NULL, NULL, 0, ULOGD_RET_UINT8, ULOGD_RETF_NONE, "gre.version",
533 { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "gre.protocol",
535 { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "gre.csum",
537 { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "gre.key",
539 { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "gre.seq",
541 { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "pptp.pktlen",
543 { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "pptp.callid",
545 { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "pptp.seq",
547 { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "pptp.ack",
551 static ulog_iret_t *_interp_gre(struct ulog_interpreter *ip,
552 ulog_packet_msg_t *pkt)
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;
560 if (iph->protocol != IPPROTO_GRE)
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;
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;
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;
595 if (greh->flags_ver & GRE_FLAG_KEY) {
596 ret[10].value.ui32 = ntohl(greh->key);
597 ret[10].flags |= ULOGD_RETF_VALID;
599 if (greh->flags_ver & GRE_FLAG_SEQ) {
600 ret[11].value.ui32 = ntohl(greh->seq);
601 ret[11].flags |= ULOGD_RETF_VALID;
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;
612 if (greh->flags_ver & GRE_FLAG_ACK) {
613 ret[15].value.ui32 = ntohl(pptph->ack);
614 ret[15].flags |= ULOGD_RETF_VALID;
622 static ulog_interpreter_t base_ip[] = {
624 .interp = &_interp_raw,
626 .result = raw_rets },
628 .interp = &_interp_oob,
630 .result = oob_rets },
632 .interp = &_interp_iphdr,
634 .result = iphdr_rets },
636 .interp = &_interp_tcphdr,
638 .result = tcphdr_rets },
640 .interp = &_interp_icmp,
642 .result = icmphdr_rets },
644 .interp = &_interp_udp,
646 .result = udphdr_rets },
648 .interp = &_interp_ahesp,
650 .result = ahesphdr_rets },
651 { NULL, "gre", 0, &_interp_gre, 16, gre_rets },
652 { NULL, "", 0, NULL, 0, NULL },
655 void _base_reg_ip(void)
657 ulog_interpreter_t *ip = base_ip;
658 ulog_interpreter_t *p;
660 for (p = ip; p->interp; p++) {
661 register_interpreter(p);