1 /*
2 * Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 */
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <sys/ioctl.h>
41 #include <sys/tree.h>
42 #include <sys/queue.h>
43 #ifdef HAVE_SYS_TIME_H
44 #include <sys/time.h>
45 #endif
46
47 #include <err.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <syslog.h>
53 #include <unistd.h>
54
55 #include <event.h>
56 #include <pcap.h>
57 #include <dnet.h>
58
59 #include "tagging.h"
60
61 struct evbuffer *_buf;
62
63 void
tagging_init()64 tagging_init()
65 {
66 _buf = evbuffer_new();
67 }
68
69 /*
70 * We encode integer's by nibbles; the first nibble contains the number
71 * of significant nibbles - 1; this allows us to encode up to 64-bit
72 * integers. This function is byte-order independent.
73 */
74
75 void
encode__int(struct evbuffer * evbuf,uint32_t number)76 encode__int(struct evbuffer *evbuf, uint32_t number)
77 {
78 int off = 1, nibbles = 0;
79 uint8_t data[5];
80
81 memset(data, 0, sizeof(data));
82 while (number) {
83 if (off & 0x1)
84 data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f);
85 else
86 data[off/2] = (data[off/2] & 0x0f) |
87 ((number & 0x0f) << 4);
88 number >>= 4;
89 off++;
90 }
91
92 if (off > 2)
93 nibbles = off - 2;
94
95 /* Off - 1 is the number of encoded nibbles */
96 data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);
97
98 evbuffer_add(evbuf, data, (off + 1) / 2);
99 }
100
101 /*
102 * Marshal a data type, the general format is as follows:
103 *
104 * tag number: one byte; length: var bytes; payload: var bytes
105 */
106
107 void
tag_marshal(struct evbuffer * evbuf,uint8_t tag,void * data,uint16_t len)108 tag_marshal(struct evbuffer *evbuf, uint8_t tag, void *data, uint16_t len)
109 {
110 evbuffer_add(evbuf, &tag, sizeof(tag));
111 encode__int(evbuf, len);
112 evbuffer_add(evbuf, data, len);
113 }
114
115 /* Marshaling for integers */
116 void
tag_marshal_int(struct evbuffer * evbuf,uint8_t tag,uint32_t integer)117 tag_marshal_int(struct evbuffer *evbuf, uint8_t tag, uint32_t integer)
118 {
119 evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
120 encode__int(_buf, integer);
121
122 evbuffer_add(evbuf, &tag, sizeof(tag));
123 encode__int(evbuf, EVBUFFER_LENGTH(_buf));
124 evbuffer_add_buffer(evbuf, _buf);
125 }
126
127 void
tag_marshal_string(struct evbuffer * buf,uint8_t tag,char * string)128 tag_marshal_string(struct evbuffer *buf, uint8_t tag, char *string)
129 {
130 tag_marshal(buf, tag, string, strlen(string));
131 }
132
133 void
tag_marshal_timeval(struct evbuffer * evbuf,uint8_t tag,struct timeval * tv)134 tag_marshal_timeval(struct evbuffer *evbuf, uint8_t tag, struct timeval *tv)
135 {
136 evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
137
138 encode__int(_buf, tv->tv_sec);
139 encode__int(_buf, tv->tv_usec);
140
141 tag_marshal(evbuf, tag, EVBUFFER_DATA(_buf),
142 EVBUFFER_LENGTH(_buf));
143 }
144
145 void
tag_marshal_record(struct evbuffer * evbuf,uint8_t tag,struct record * record)146 tag_marshal_record(struct evbuffer *evbuf, uint8_t tag, struct record *record)
147 {
148 struct evbuffer *tmp = evbuffer_new();
149
150 record_marshal(tmp, record);
151 tag_marshal(evbuf, tag, EVBUFFER_DATA(tmp), EVBUFFER_LENGTH(tmp));
152 evbuffer_free(tmp);
153 }
154
155 /*
156 * Functions for un/marshaling dnet's struct addr; we create a tagged
157 * stream to save space. Otherwise, we would have pay the overhead of
158 * IPv6 address sizes for every kind of address.
159 */
160
161 #define MARSHAL(tag, what) do { \
162 tag_marshal(evbuf, tag, &(what), sizeof(what)); \
163 } while (0)
164
165 void
addr_marshal(struct evbuffer * evbuf,struct addr * addr)166 addr_marshal(struct evbuffer *evbuf, struct addr *addr)
167 {
168 tag_marshal_int(evbuf, ADDR_TYPE, addr->addr_type);
169 tag_marshal_int(evbuf, ADDR_BITS, addr->addr_bits);
170
171 switch (addr->addr_type) {
172 case ADDR_TYPE_ETH:
173 MARSHAL(ADDR_ADDR, addr->addr_eth);
174 break;
175 case ADDR_TYPE_IP:
176 MARSHAL(ADDR_ADDR, addr->addr_ip);
177 break;
178 case ADDR_TYPE_IP6:
179 MARSHAL(ADDR_ADDR, addr->addr_ip6);
180 break;
181 }
182 }
183
184 /*
185 * Functions to un/marshal records.
186 */
187
188 void
record_marshal(struct evbuffer * evbuf,struct record * record)189 record_marshal(struct evbuffer *evbuf, struct record *record)
190 {
191 struct evbuffer *addr = evbuffer_new();
192 struct hash *hash;
193
194 if (timerisset(&record->tv_start))
195 tag_marshal_timeval(evbuf, REC_TV_START, &record->tv_start);
196 if (timerisset(&record->tv_end))
197 tag_marshal_timeval(evbuf, REC_TV_END, &record->tv_end);
198
199 /* Encode an address */
200 evbuffer_drain(addr, EVBUFFER_LENGTH(addr));
201 addr_marshal(addr, &record->src);
202 tag_marshal(evbuf, REC_SRC, EVBUFFER_DATA(addr), EVBUFFER_LENGTH(addr));
203
204 evbuffer_drain(addr, EVBUFFER_LENGTH(addr));
205 addr_marshal(addr, &record->dst);
206 tag_marshal(evbuf, REC_DST, EVBUFFER_DATA(addr), EVBUFFER_LENGTH(addr));
207
208 tag_marshal_int(evbuf, REC_SRC_PORT, record->src_port);
209 tag_marshal_int(evbuf, REC_DST_PORT, record->dst_port);
210 tag_marshal_int(evbuf, REC_PROTO, record->proto);
211 tag_marshal_int(evbuf, REC_STATE, record->state);
212
213 if (record->os_fp != NULL)
214 tag_marshal_string(evbuf, REC_OS_FP, record->os_fp);
215
216 TAILQ_FOREACH(hash, &record->hashes, next)
217 tag_marshal(evbuf, REC_HASH, hash->digest, sizeof(hash->digest));
218
219 if (record->bytes)
220 tag_marshal_int(evbuf, REC_BYTES, record->bytes);
221 if (record->flags)
222 tag_marshal_int(evbuf, REC_FLAGS, record->flags);
223
224 evbuffer_free(addr);
225 }
226