631abf1a4763cf56b1296680b1ad2d85311d4cdb
[mmondor.git] / mmsoftware / tap-bridge / modules / tap-logger.c
1 /* $Id: tap-logger.c,v 1.4 2007/12/23 16:52:17 mmondor Exp $ */
2
3 /*
4 * Copyright (C) 2007, Matthew Mondor
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Matthew Mondor.
18 * 4. The name of Matthew Mondor may not be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission.
21 * 5. Redistribution of source code may not be released under the terms of
22 * any GNU Public License derivate.
23 *
24 * THIS SOFTWARE IS PROVIDED BY MATTHEW MONDOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL MATTHEW MONDOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <stdarg.h>
39 #include <stdint.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43
44 #include <tap-bridge.h>
45 #include <tap-headers.h>
46
47
48 static bool mod_init(tap_t *, tap_t *);
49 static bool mod_recv_int(tap_t *, fnode_t *);
50 static bool mod_recv_ext(tap_t *, fnode_t *);
51 static void mod_exit(void);
52
53 static void logprintf(const char *, ...);
54 static void frame_log(frame_t *, const char *);
55
56
57 module_t module = {
58 mod_init,
59 mod_recv_int,
60 mod_recv_ext,
61 NULL,
62 mod_exit
63 };
64
65
66 static tap_t *tap_int, *tap_ext;
67 static int logfd = -1;
68
69
70 static bool
71 mod_init(tap_t *tap_i, tap_t *tap_e)
72 {
73 void **udata;
74
75 tap_int = tap_i;
76 tap_ext = tap_e;
77
78 if ((udata = key_lookup("tap_logger_file")) == NULL) {
79 if ((udata = key_create("tap_logger_file")) == NULL)
80 return false;
81 if ((logfd = open("/tmp/tap-filter.log",
82 O_CREAT | O_WRONLY | O_APPEND)) == -1) {
83 key_destroy("tap_logger_file");
84 warning(errno, "fopen(/tmp/tap-filter.log)");
85 return false;
86 }
87 if ((*udata = malloc(sizeof(int))) == NULL) {
88 key_destroy("tap_logger_file");
89 warning(errno, "malloc(int)");
90 return false;
91 }
92
93 *((int *)*udata) = logfd;
94 } else
95 logfd = *((int *)*udata);
96
97 return true;
98 }
99
100 static bool
101 mod_recv_int(tap_t *tap, fnode_t *n)
102 {
103
104 frame_log(n->frame, "<");
105 fnode_destroy(n);
106 return true;
107 }
108
109 static bool
110 mod_recv_ext(tap_t *tap, fnode_t *n)
111 {
112
113 frame_log(n->frame, ">");
114 fnode_destroy(n);
115 return true;
116 }
117
118 static void
119 mod_exit(void)
120 {
121
122 /* NOOP */
123 }
124
125
126 /*
127 * We want line buffering, and can't use stdio as it won't restart write(2) on
128 * EINTR events.
129 */
130 static void
131 logprintf(const char *fmt, ...)
132 {
133 char buf[1024];
134 va_list lst;
135 int len;
136
137 va_start(lst, fmt);
138 len = vsnprintf(buf, sizeof(buf) - 1, fmt, lst);
139 va_end(lst);
140
141 while (write(logfd, buf, len) == -1 && errno == EINTR) ;
142 }
143
144 static void
145 frame_log(frame_t *f, const char *d)
146 {
147 char origin[32], destination[32];
148 struct hdr_tap *hdrtap = (struct hdr_tap *)f->data;
149 void *ahdrtap = &hdrtap[1];
150
151 if (f->size < sizeof(struct hdr_tap)) {
152 logprintf("%s Short ethernet frame: size=%u\n", d, f->size);
153 return;
154 }
155
156 (void) macaddr_string(origin, 31, &f->origin);
157 (void) macaddr_string(destination, 31, &f->destination);
158 logprintf("%s src=%s, dst=%s etype=%04x size=%u\n",
159 d, origin, destination, f->type, f->size);
160
161 /*
162 * Orignally used switch/case but if proves to be cleaner because of
163 * required variables, while requireing less indentation levels.
164 */
165 if (f->type == HDR_TAP_ETYPE_ARP) {
166 struct hdr_arp *hdrarp;
167
168 if (f->size < sizeof(struct hdr_tap) +
169 sizeof(struct hdr_arp)) {
170 logprintf(" Short ARP header\n");
171 return;
172 }
173 hdrarp = ahdrtap;
174 /* XXX */
175
176 return;
177 }
178
179 if (f->type == HDR_TAP_ETYPE_IP) {
180 struct hdr_ip *hdrip;
181 uint16_t t;
182 int flags, off;
183 /*void *ahdrip;*/
184
185 if (f->size < sizeof(struct hdr_tap) + sizeof(struct hdr_ip)) {
186 logprintf(" Short IP header\n");
187 return;
188 }
189 hdrip = ahdrtap;
190 t = BYTEORDER_HOST16(hdrip->flags_off);
191 flags = HDR_IP_FLAGS_GET(t);
192 off = HDR_IP_OFF_GET(t);
193 logprintf(" IP: flags=%02x off=%04x\n", flags, off);
194 /* XXX */
195
196 return;
197 }
198
199 logprintf(" Unsupported ethertype (0x%04x)\n", f->type);
200 }