screen: Add helpers to easy use color by name
[netsniff-ng.git] / trafgen_proto.c
blob214547e90e07474cded3acda02695d063a5f6b58
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Subject to the GPL, version 2.
4 */
6 #include <stddef.h>
7 #include <string.h>
8 #include <netinet/in.h>
9 #include <linux/if_ether.h>
11 #include "dev.h"
12 #include "xmalloc.h"
13 #include "trafgen_conf.h"
14 #include "trafgen_l2.h"
15 #include "trafgen_l3.h"
16 #include "trafgen_l4.h"
17 #include "trafgen_proto.h"
19 #define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
20 ((f)->mask ? (f)->mask : (0xffffffff)))
22 #define field_unmask_and_unshift(f, v) (((v) & \
23 ((f)->mask ? (f)->mask : (0xffffffff))) >> (f)->shift)
25 static struct proto_ctx ctx;
27 #define PROTO_MAX_LAYERS 16
29 static struct proto_hdr *headers[PROTO_MAX_LAYERS];
30 static size_t headers_count;
32 static struct proto_hdr *registered;
34 static inline struct proto_hdr *proto_current_header(void)
36 if (headers_count > 0)
37 return headers[headers_count - 1];
39 panic("No header was added\n");
42 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
44 struct proto_hdr *lower = NULL;
45 size_t i;
47 if (headers_count == 0)
48 return NULL;
50 for (i = 1, lower = headers[0]; i < headers_count; i++) {
51 if (headers[i] == hdr)
52 return headers[i - 1];
55 return lower;
58 uint8_t *proto_header_ptr(struct proto_hdr *hdr)
60 return &current_packet()->payload[hdr->pkt_offset];
63 static struct proto_hdr *proto_header_by_id(enum proto_id id)
65 struct proto_hdr *p = registered;
67 for (; p; p = p->next)
68 if (p->id == id)
69 return p;
71 panic("Can't lookup proto by id %u\n", id);
74 void proto_header_register(struct proto_hdr *hdr)
76 hdr->next = registered;
77 registered = hdr;
79 hdr->fields = NULL;
80 hdr->fields_count = 0;
83 static void proto_fields_realloc(struct proto_hdr *hdr, size_t count)
85 hdr->fields = xrealloc(hdr->fields, count * sizeof(*hdr->fields));
86 hdr->fields_count = count;
89 void proto_header_fields_add(struct proto_hdr *hdr,
90 const struct proto_field *fields, size_t count)
92 struct packet *pkt = current_packet();
93 struct proto_field *f;
94 int i;
96 if (!hdr->fields)
97 hdr->pkt_offset = pkt->len;
99 proto_fields_realloc(hdr, hdr->fields_count + count);
101 for (i = 0; count >= 1; count--, i++) {
102 f = &hdr->fields[hdr->fields_count - count];
104 f->id = fields[i].id;
105 f->len = fields[i].len;
106 f->is_set = false;
107 f->shift = fields[i].shift;
108 f->mask = fields[i].mask;
109 f->pkt_offset = hdr->pkt_offset + fields[i].offset;
111 if (f->pkt_offset + f->len > pkt->len)
112 set_fill(0, (f->pkt_offset + f->len) - pkt->len);
116 static struct proto_field *proto_field_by_id(struct proto_hdr *hdr, uint32_t fid)
118 int i;
120 for (i = 0; i < hdr->fields_count; i++)
121 if (hdr->fields[i].id == fid)
122 return &hdr->fields[i];
124 panic("Failed lookup field id %u for proto id %u\n", fid, hdr->id);
127 bool proto_field_is_set(struct proto_hdr *hdr, uint32_t fid)
129 struct proto_field *field = proto_field_by_id(hdr, fid);
131 return field ? field->is_set : false;
134 struct proto_hdr *proto_header_init(enum proto_id pid)
136 struct proto_hdr *hdr = proto_header_by_id(pid);
137 struct proto_hdr *new_hdr;
139 if (headers_count >= PROTO_MAX_LAYERS)
140 panic("Too many proto headers\n");
142 new_hdr = xmalloc(sizeof(*new_hdr));
143 memcpy(new_hdr, hdr, sizeof(*new_hdr));
145 if (new_hdr->header_init)
146 new_hdr->header_init(new_hdr);
148 headers[headers_count++] = new_hdr;
149 return new_hdr;
152 void proto_header_finish(struct proto_hdr *hdr)
154 if (hdr && hdr->header_finish)
155 hdr->header_finish(hdr);
158 struct proto_hdr *proto_lower_default_add(struct proto_hdr *hdr,
159 enum proto_id pid)
161 struct proto_hdr *current;
163 if (headers_count > 0) {
164 current = proto_current_header();
166 if (current->layer >= proto_header_by_id(pid)->layer)
167 goto set_proto;
168 if (current->id == pid)
169 goto set_proto;
172 current = proto_header_init(pid);
174 set_proto:
175 if (current->set_next_proto)
176 current->set_next_proto(current, hdr->id);
178 return current;
181 static void __proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
182 uint8_t *bytes, bool is_default, bool is_be)
184 struct proto_field *field;
185 uint8_t *payload, *p8;
186 uint16_t *p16;
187 uint32_t *p32;
188 uint32_t v32;
189 uint16_t v16;
190 uint8_t v8;
192 field = proto_field_by_id(hdr, fid);
194 if (is_default && field->is_set)
195 return;
197 payload = &current_packet()->payload[field->pkt_offset];
199 if (field->len == 1) {
200 p8 = payload;
201 *p8 = field->mask ? *p8 & ~field->mask : *p8;
203 v8 = field_shift_and_mask(field, *bytes);
204 v8 = field->mask ? (v8 | *p8) : v8;
206 bytes = &v8;
207 } else if (field->len == 2) {
208 p16 = (uint16_t *)payload;
209 *p16 = be16_to_cpu(*p16);
210 *p16 = cpu_to_be16(field->mask ? *p16 & ~field->mask : *p16);
212 v16 = field_shift_and_mask(field, *(uint16_t *)bytes);
213 v16 = is_be ? cpu_to_be16(v16) : v16;
214 v16 = field->mask ? (v16 | *p16) : v16;
216 bytes = (uint8_t *)&v16;
217 } else if (field->len == 4) {
218 p32 = (uint32_t *)payload;
219 *p32 = be32_to_cpu(*p32);
220 *p32 = cpu_to_be32(field->mask ? *p32 & ~field->mask : *p32);
222 v32 = field_shift_and_mask(field, *(uint32_t *)bytes);
223 v32 = is_be ? cpu_to_be32(v32) : v32;
224 v32 = field->mask ? (v32 | *p32) : v32;
226 bytes = (uint8_t *)&v32;
229 memcpy(payload, bytes, field->len);
231 if (!is_default)
232 field->is_set = true;
235 void proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid, uint8_t *bytes)
237 __proto_field_set_bytes(hdr, fid, bytes, false, false);
240 static uint8_t *__proto_field_get_bytes(struct proto_field *field)
242 struct packet *pkt = current_packet();
244 return &pkt->payload[field->pkt_offset];
247 void proto_field_set_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
249 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
252 uint8_t proto_field_get_u8(struct proto_hdr *hdr, uint32_t fid)
254 struct proto_field *field = proto_field_by_id(hdr, fid);
255 uint8_t val = *__proto_field_get_bytes(field);
257 return field_unmask_and_unshift(field, val);
260 void proto_field_set_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
262 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
265 uint16_t proto_field_get_u16(struct proto_hdr *hdr, uint32_t fid)
267 struct proto_field *field = proto_field_by_id(hdr, fid);
268 uint16_t val = *(uint16_t *)__proto_field_get_bytes(field);
270 return field_unmask_and_unshift(field, be16_to_cpu(val));
273 void proto_field_set_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
275 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
278 uint32_t proto_field_get_u32(struct proto_hdr *hdr, uint32_t fid)
280 struct proto_field *field = proto_field_by_id(hdr, fid);
281 uint32_t val = *(uint32_t *)__proto_field_get_bytes(field);
283 return field_unmask_and_unshift(field, be32_to_cpu(val));
286 void proto_field_set_default_bytes(struct proto_hdr *hdr, uint32_t fid, uint8_t *bytes)
288 __proto_field_set_bytes(hdr, fid, bytes, true, false);
291 void proto_field_set_default_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
293 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
296 void proto_field_set_default_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
298 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
301 void proto_field_set_default_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
303 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
306 void proto_field_set_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
308 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, false, true);
311 void proto_field_set_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
313 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, false, true);
316 void proto_field_set_default_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
318 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, true);
321 void proto_field_set_default_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
323 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, true);
326 static void __proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid,
327 bool is_default)
329 uint8_t mac[ETH_ALEN];
330 int ret;
332 if (proto_field_is_set(hdr, fid))
333 return;
335 if (!hdr->ctx->dev)
336 panic("Device is not specified\n");
338 ret = device_hw_address(hdr->ctx->dev, mac, sizeof(mac));
339 if (ret < 0)
340 panic("Could not get device hw address\n");
342 __proto_field_set_bytes(hdr, fid, mac, is_default, false);
345 void proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
347 __proto_field_set_dev_mac(hdr, fid, false);
350 void proto_field_set_default_dev_mac(struct proto_hdr *hdr, uint32_t fid)
352 __proto_field_set_dev_mac(hdr, fid, true);
355 static void __proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid,
356 bool is_default)
358 struct sockaddr_storage ss = { };
359 struct sockaddr_in *ss4;
360 uint32_t ip_addr;
361 int ret;
363 if (proto_field_is_set(hdr, fid))
364 return;
366 ret = device_address(hdr->ctx->dev, AF_INET, &ss);
367 if (ret < 0)
368 panic("Could not get device IPv4 address\n");
370 ss4 = (struct sockaddr_in *) &ss;
371 ip_addr = ss4->sin_addr.s_addr;
373 __proto_field_set_bytes(hdr, fid, (uint8_t *)&ip_addr, is_default, false);
376 void proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
378 __proto_field_set_dev_ipv4(hdr, fid, false);
381 void proto_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
383 __proto_field_set_dev_ipv4(hdr, fid, true);
386 void protos_init(const char *dev)
388 struct proto_hdr *p;
390 ctx.dev = dev;
392 protos_l2_init();
393 protos_l3_init();
394 protos_l4_init();
396 for (p = registered; p; p = p->next)
397 p->ctx = &ctx;
400 void proto_packet_finish(void)
402 ssize_t i;
404 /* Go down from upper layers to do last calculations (checksum) */
405 for (i = headers_count - 1; i >= 0; i--) {
406 struct proto_hdr *p = headers[i];
408 if (p->packet_finish)
409 p->packet_finish(p);
412 for (i = 0; i < headers_count; i++) {
413 struct proto_hdr *p = headers[i];
415 if (p->fields) {
416 xfree(p->fields);
417 p->fields_count = 0;
420 xfree(headers[i]);
423 headers_count = 0;