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)
68 char *buf, *oldbuf = NULL;
69 ulog_iret_t *ret = ip->result;
72 buf = (char *) malloc(3 * pkt->mac_len + 1);
74 ulogd_log(ULOGD_ERROR, "OOM!!!\n");
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;
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;
96 /***********************************************************************
98 ***********************************************************************/
100 static ulog_iret_t oob_rets[] = {
101 { .type = ULOGD_RET_STRING,
102 .flags = ULOGD_RETF_NONE,
105 { .type = ULOGD_RET_UINT32,
106 .flags = ULOGD_RETF_NONE,
107 .key = "oob.time.sec",
109 { .type = ULOGD_RET_UINT32,
110 .flags = ULOGD_RETF_NONE,
111 .key = "oob.time.usec",
113 { .type = ULOGD_RET_UINT32,
114 .flags = ULOGD_RETF_NONE,
117 { .type = ULOGD_RET_STRING,
118 .flags = ULOGD_RETF_NONE,
121 { .type = ULOGD_RET_STRING,
122 .flags = ULOGD_RETF_NONE,
127 static ulog_iret_t *_interp_oob(struct ulog_interpreter *ip,
128 ulog_packet_msg_t *pkt)
130 ulog_iret_t *ret = ip->result;
132 ret[0].value.ptr = pkt->prefix;
133 ret[0].flags |= ULOGD_RETF_VALID;
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;
143 ret[1].flags &= ~ULOGD_RETF_VALID;
144 ret[2].flags &= ~ULOGD_RETF_VALID;
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;
157 /***********************************************************************
159 ***********************************************************************/
161 static ulog_iret_t iphdr_rets[] = {
162 { .type = ULOGD_RET_IPADDR,
163 .flags = ULOGD_RETF_NONE,
166 { .type = ULOGD_RET_IPADDR,
167 .flags = ULOGD_RETF_NONE,
170 { .type = ULOGD_RET_UINT8,
171 .flags = ULOGD_RETF_NONE,
172 .key = "ip.protocol",
174 { .type = ULOGD_RET_UINT8,
175 .flags = ULOGD_RETF_NONE,
178 { .type = ULOGD_RET_UINT8,
179 .flags = ULOGD_RETF_NONE,
182 { .type = ULOGD_RET_UINT16,
183 .flags = ULOGD_RETF_NONE,
186 { .type = ULOGD_RET_UINT8,
187 .flags = ULOGD_RETF_NONE,
190 { .type = ULOGD_RET_UINT16,
191 .flags = ULOGD_RETF_NONE,
194 { .type = ULOGD_RET_UINT16,
195 .flags = ULOGD_RETF_NONE,
198 { .type = ULOGD_RET_UINT16,
199 .flags = ULOGD_RETF_NONE,
204 static ulog_iret_t *_interp_iphdr(struct ulog_interpreter *ip,
205 ulog_packet_msg_t *pkt)
207 ulog_iret_t *ret = ip->result;
208 struct iphdr *iph = (struct iphdr *) pkt->payload;
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;
234 /***********************************************************************
236 ***********************************************************************/
237 static ulog_iret_t tcphdr_rets[] = {
238 { .type = ULOGD_RET_UINT16,
239 .flags = ULOGD_RETF_NONE,
242 { .type = ULOGD_RET_UINT16,
243 .flags = ULOGD_RETF_NONE,
246 { .type = ULOGD_RET_UINT32,
247 .flags = ULOGD_RETF_NONE,
250 { .type = ULOGD_RET_UINT32,
251 .flags = ULOGD_RETF_NONE,
254 { .type = ULOGD_RET_UINT8,
255 .flags = ULOGD_RETF_NONE,
258 { .type = ULOGD_RET_UINT8,
259 .flags = ULOGD_RETF_NONE,
260 .key = "tcp.reserved",
262 { .type = ULOGD_RET_UINT16,
263 .flags = ULOGD_RETF_NONE,
266 { .type = ULOGD_RET_BOOL,
267 .flags = ULOGD_RETF_NONE,
270 { .type = ULOGD_RET_UINT16,
271 .flags = ULOGD_RETF_NONE,
274 { .type = ULOGD_RET_BOOL,
275 .flags = ULOGD_RETF_NONE,
278 { .type = ULOGD_RET_BOOL,
279 .flags = ULOGD_RETF_NONE,
282 { .type = ULOGD_RET_BOOL,
283 .flags = ULOGD_RETF_NONE,
286 { .type = ULOGD_RET_BOOL,
287 .flags = ULOGD_RETF_NONE,
290 { .type = ULOGD_RET_BOOL,
291 .flags = ULOGD_RETF_NONE,
294 { .type = ULOGD_RET_BOOL,
295 .flags = ULOGD_RETF_NONE,
298 { .type = ULOGD_RET_BOOL,
299 .flags = ULOGD_RETF_NONE,
302 { .type = ULOGD_RET_UINT16,
303 .flags = ULOGD_RETF_NONE,
308 static ulog_iret_t *_interp_tcphdr(struct ulog_interpreter *ip,
309 ulog_packet_msg_t *pkt)
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;
316 if (iph->protocol != IPPROTO_TCP)
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;
334 ret[7].value.b = tcph->urg;
335 ret[7].flags |= ULOGD_RETF_VALID;
337 ret[8].value.ui16 = ntohs(tcph->urg_ptr);
338 ret[8].flags |= ULOGD_RETF_VALID;
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;
360 /***********************************************************************
362 ***********************************************************************/
363 static ulog_iret_t udphdr_rets[] = {
364 { .type = ULOGD_RET_UINT16,
365 .flags = ULOGD_RETF_NONE,
368 { .type = ULOGD_RET_UINT16,
369 .flags = ULOGD_RETF_NONE,
372 { .type = ULOGD_RET_UINT16,
373 .flags = ULOGD_RETF_NONE,
376 { .type = ULOGD_RET_UINT16,
377 .flags = ULOGD_RETF_NONE,
382 static ulog_iret_t *_interp_udp(struct ulog_interpreter *ip,
383 ulog_packet_msg_t *pkt)
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;
390 if (iph->protocol != IPPROTO_UDP)
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;
405 /***********************************************************************
407 ***********************************************************************/
409 static ulog_iret_t icmphdr_rets[] = {
410 { .type = ULOGD_RET_UINT8,
411 .flags = ULOGD_RETF_NONE,
414 { .type = ULOGD_RET_UINT8,
415 .flags = ULOGD_RETF_NONE,
418 { .type = ULOGD_RET_UINT16,
419 .flags = ULOGD_RETF_NONE,
420 .key = "icmp.echoid",
422 { .type = ULOGD_RET_UINT16,
423 .flags = ULOGD_RETF_NONE,
424 .key = "icmp.echoseq",
426 { .type = ULOGD_RET_IPADDR,
427 .flags = ULOGD_RETF_NONE,
428 .key = "icmp.gateway",
430 { .type = ULOGD_RET_UINT16,
431 .flags = ULOGD_RETF_NONE,
432 .key = "icmp.fragmtu",
434 { .type = ULOGD_RET_UINT16,
435 .flags = ULOGD_RETF_NONE,
440 static ulog_iret_t *_interp_icmp(struct ulog_interpreter *ip,
441 ulog_packet_msg_t *pkt)
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;
448 if (iph->protocol != IPPROTO_ICMP)
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;
456 switch(icmph->type) {
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;
465 case ICMP_PARAMETERPROB:
466 ret[4].value.ui32 = ntohl(icmph->un.gateway);
467 ret[4].flags |= ULOGD_RETF_VALID;
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;
476 ret[6].value.ui16 = icmph->checksum;
477 ret[6].flags |= ULOGD_RETF_VALID;
482 /***********************************************************************
484 ***********************************************************************/
486 static ulog_iret_t ahesphdr_rets[] = {
487 { .type = ULOGD_RET_UINT32,
488 .flags = ULOGD_RETF_NONE,
493 static ulog_iret_t *_interp_ahesp(struct ulog_interpreter *ip,
494 ulog_packet_msg_t *pkt)
497 ulog_iret_t *ret = ip->result;
499 struct iphdr *iph = (struct iphdr *) pkt->payload;
500 void *protoh = (u_int32_t *) (iph + iph->ihl);
501 struct esphdr *esph = protoh;
503 if (iph->protocol != IPPROTO_ESP)
506 ret[0].value.ui32 = ntohl(esph->spi);
507 ret[0].flags |= ULOGD_RETF_VALID;
513 /***********************************************************************
515 ***********************************************************************/
517 static ulog_iret_t gre_rets[] = {
518 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.csum",
520 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.route",
522 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.key",
524 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.seq",
526 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.ssr",
528 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.recur",
530 { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "gre.flag.ack",
532 { NULL, NULL, 0, ULOGD_RET_UINT8, ULOGD_RETF_NONE, "gre.version",
534 { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "gre.protocol",
536 { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "gre.csum",
538 { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "gre.key",
540 { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "gre.seq",
542 { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "pptp.pktlen",
544 { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "pptp.callid",
546 { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "pptp.seq",
548 { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "pptp.ack",
552 static ulog_iret_t *_interp_gre(struct ulog_interpreter *ip,
553 ulog_packet_msg_t *pkt)
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;
561 if (iph->protocol != IPPROTO_GRE)
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;
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;
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;
596 if (greh->flags_ver & GRE_FLAG_KEY) {
597 ret[10].value.ui32 = ntohl(greh->key);
598 ret[10].flags |= ULOGD_RETF_VALID;
600 if (greh->flags_ver & GRE_FLAG_SEQ) {
601 ret[11].value.ui32 = ntohl(greh->seq);
602 ret[11].flags |= ULOGD_RETF_VALID;
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;
613 if (greh->flags_ver & GRE_FLAG_ACK) {
614 ret[15].value.ui32 = ntohl(pptph->ack);
615 ret[15].flags |= ULOGD_RETF_VALID;
623 static ulog_interpreter_t base_ip[] = {
625 .interp = &_interp_raw,
627 .result = raw_rets },
629 .interp = &_interp_oob,
631 .result = oob_rets },
633 .interp = &_interp_iphdr,
635 .result = iphdr_rets },
637 .interp = &_interp_tcphdr,
639 .result = tcphdr_rets },
641 .interp = &_interp_icmp,
643 .result = icmphdr_rets },
645 .interp = &_interp_udp,
647 .result = udphdr_rets },
649 .interp = &_interp_ahesp,
651 .result = ahesphdr_rets },
652 { NULL, "gre", 0, &_interp_gre, 16, gre_rets },
653 { NULL, "", 0, NULL, 0, NULL },
656 void _base_reg_ip(void)
658 ulog_interpreter_t *ip = base_ip;
659 ulog_interpreter_t *p;
661 for (p = ip; p->interp; p++) {
662 register_interpreter(p);