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