trafgen: proto: Improve to find lower header by index
[netsniff-ng.git] / trafgen_proto.c
blobb0a198f3511e14837245f66cb2101946d0e44c0a
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 struct ctx {
26 const char *dev;
28 static struct ctx ctx;
30 static const struct proto_ops *registered_ops[__PROTO_MAX];
32 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
34 struct packet *pkt = packet_get(hdr->pkt_id);
35 struct proto_hdr **headers = &pkt->headers[0];
37 if (hdr->index == 0)
38 return NULL;
40 return headers[hdr->index - 1];
43 uint8_t *proto_header_ptr(struct proto_hdr *hdr)
45 return &packet_get(hdr->pkt_id)->payload[hdr->pkt_offset];
48 static const struct proto_ops *proto_ops_by_id(enum proto_id id)
50 const struct proto_ops *ops = registered_ops[id];
52 bug_on(ops->id != id);
53 return ops;
56 void proto_ops_register(const struct proto_ops *ops)
58 bug_on(ops->id >= __PROTO_MAX);
59 registered_ops[ops->id] = ops;
62 static void proto_fields_realloc(struct proto_hdr *hdr, size_t count)
64 hdr->fields = xrealloc(hdr->fields, count * sizeof(*hdr->fields));
65 hdr->fields_count = count;
68 void proto_header_fields_add(struct proto_hdr *hdr,
69 const struct proto_field *fields, size_t count)
71 struct packet *pkt = packet_get(hdr->pkt_id);
72 struct proto_field *f;
73 int i;
75 if (!hdr->fields)
76 hdr->pkt_offset = pkt->len;
78 proto_fields_realloc(hdr, hdr->fields_count + count);
80 for (i = 0; count >= 1; count--, i++) {
81 f = &hdr->fields[hdr->fields_count - count];
83 f->id = fields[i].id;
84 f->len = fields[i].len;
85 f->is_set = false;
86 f->shift = fields[i].shift;
87 f->mask = fields[i].mask;
88 f->pkt_offset = hdr->pkt_offset + fields[i].offset;
89 f->hdr = hdr;
91 if (f->pkt_offset + f->len > pkt->len) {
92 hdr->len += f->len;
93 set_fill(0, (f->pkt_offset + f->len) - pkt->len);
98 static struct proto_field *proto_field_by_id(struct proto_hdr *hdr, uint32_t fid)
100 /* Assume the fields are stored in the same order as the respective
101 * enum, so the index can be used for faster lookup here.
103 bug_on(hdr->fields[fid].id != fid);
105 return &hdr->fields[fid];
108 bool proto_field_is_set(struct proto_hdr *hdr, uint32_t fid)
110 struct proto_field *field = proto_field_by_id(hdr, fid);
112 return field ? field->is_set : false;
115 struct proto_hdr *proto_header_push(enum proto_id pid)
117 struct packet *pkt = current_packet();
118 struct proto_hdr **headers = &pkt->headers[0];
119 const struct proto_ops *ops = proto_ops_by_id(pid);
120 struct proto_hdr *hdr;
122 bug_on(pkt->headers_count >= PROTO_MAX_LAYERS);
124 hdr = xzmalloc(sizeof(*hdr));
125 hdr->ops = ops;
126 hdr->pkt_id = current_packet_id();
128 if (ops && ops->header_init)
129 ops->header_init(hdr);
131 /* This is very important to have it after header_init as
132 * pkt->headers_count might be changed by adding default lower headers */
133 hdr->index = pkt->headers_count;
135 headers[pkt->headers_count++] = hdr;
136 return hdr;
139 void proto_header_finish(struct proto_hdr *hdr)
141 if (hdr && hdr->ops && hdr->ops->header_finish)
142 hdr->ops->header_finish(hdr);
145 struct proto_hdr *proto_lower_default_add(struct proto_hdr *upper,
146 enum proto_id pid)
148 struct proto_hdr *current;
149 size_t headers_count = current_packet()->headers_count;
150 const struct proto_ops *ops;
152 if (headers_count > 0) {
153 current = current_packet()->headers[headers_count - 1];
154 ops = current->ops;
156 if (ops->layer >= proto_ops_by_id(pid)->layer)
157 goto set_proto;
158 if (ops->id == pid)
159 goto set_proto;
162 current = proto_header_push(pid);
163 ops = current->ops;
165 set_proto:
166 if (ops && ops->set_next_proto)
167 ops->set_next_proto(current, upper->ops->id);
169 return current;
172 static void __proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
173 const uint8_t *bytes, bool is_default,
174 bool is_be)
176 struct proto_field *field;
177 uint8_t *payload, *p8;
178 uint16_t *p16;
179 uint32_t *p32;
180 uint32_t v32;
181 uint16_t v16;
182 uint8_t v8;
184 field = proto_field_by_id(hdr, fid);
186 if (is_default && field->is_set)
187 return;
189 payload = &packet_get(hdr->pkt_id)->payload[field->pkt_offset];
191 if (field->len == 1) {
192 p8 = payload;
193 *p8 = field->mask ? *p8 & ~field->mask : *p8;
195 v8 = field_shift_and_mask(field, *bytes);
196 v8 = field->mask ? (v8 | *p8) : v8;
198 bytes = &v8;
199 } else if (field->len == 2) {
200 p16 = (uint16_t *)payload;
201 *p16 = be16_to_cpu(*p16);
202 *p16 = cpu_to_be16(field->mask ? *p16 & ~field->mask : *p16);
204 v16 = field_shift_and_mask(field, *(uint16_t *)bytes);
205 v16 = is_be ? cpu_to_be16(v16) : v16;
206 v16 = field->mask ? (v16 | *p16) : v16;
208 bytes = (uint8_t *)&v16;
209 } else if (field->len == 4) {
210 p32 = (uint32_t *)payload;
211 *p32 = be32_to_cpu(*p32);
212 *p32 = cpu_to_be32(field->mask ? *p32 & ~field->mask : *p32);
214 v32 = field_shift_and_mask(field, *(uint32_t *)bytes);
215 v32 = is_be ? cpu_to_be32(v32) : v32;
216 v32 = field->mask ? (v32 | *p32) : v32;
218 bytes = (uint8_t *)&v32;
221 memcpy(payload, bytes, field->len);
223 if (!is_default)
224 field->is_set = true;
227 void proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
228 const uint8_t *bytes)
230 __proto_field_set_bytes(hdr, fid, bytes, false, false);
233 static uint8_t *__proto_field_get_bytes(struct proto_field *field)
235 return &packet_get(field->hdr->pkt_id)->payload[field->pkt_offset];
238 void proto_field_set_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
240 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
243 uint8_t proto_field_get_u8(struct proto_hdr *hdr, uint32_t fid)
245 struct proto_field *field = proto_field_by_id(hdr, fid);
246 uint8_t val = *__proto_field_get_bytes(field);
248 return field_unmask_and_unshift(field, val);
251 void proto_field_set_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
253 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
256 uint16_t proto_field_get_u16(struct proto_hdr *hdr, uint32_t fid)
258 struct proto_field *field = proto_field_by_id(hdr, fid);
259 uint16_t val = *(uint16_t *)__proto_field_get_bytes(field);
261 return field_unmask_and_unshift(field, be16_to_cpu(val));
264 void proto_field_set_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
266 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
269 uint32_t proto_field_get_u32(struct proto_hdr *hdr, uint32_t fid)
271 struct proto_field *field = proto_field_by_id(hdr, fid);
272 uint32_t val = *(uint32_t *)__proto_field_get_bytes(field);
274 return field_unmask_and_unshift(field, be32_to_cpu(val));
277 void proto_field_set_default_bytes(struct proto_hdr *hdr, uint32_t fid,
278 const uint8_t *bytes)
280 __proto_field_set_bytes(hdr, fid, bytes, true, false);
283 void proto_field_set_default_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
285 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
288 void proto_field_set_default_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
290 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
293 void proto_field_set_default_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
295 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
298 void proto_field_set_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
300 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, false, true);
303 void proto_field_set_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
305 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, false, true);
308 void proto_field_set_default_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
310 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, true);
313 void proto_field_set_default_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
315 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, true);
318 static void __proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid,
319 bool is_default)
321 uint8_t mac[ETH_ALEN];
322 int ret;
324 if (proto_field_is_set(hdr, fid))
325 return;
327 ret = device_hw_address(ctx.dev, mac, sizeof(mac));
328 if (ret < 0)
329 panic("Could not get device hw address\n");
331 __proto_field_set_bytes(hdr, fid, mac, is_default, false);
334 void proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
336 __proto_field_set_dev_mac(hdr, fid, false);
339 void proto_field_set_default_dev_mac(struct proto_hdr *hdr, uint32_t fid)
341 __proto_field_set_dev_mac(hdr, fid, true);
344 static void __proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid,
345 bool is_default)
347 struct sockaddr_storage ss = { };
348 struct sockaddr_in *ss4;
349 int ret;
351 if (proto_field_is_set(hdr, fid))
352 return;
354 ret = device_address(ctx.dev, AF_INET, &ss);
355 if (ret < 0)
356 panic("Could not get device IPv4 address\n");
358 ss4 = (struct sockaddr_in *) &ss;
359 __proto_field_set_bytes(hdr, fid, (uint8_t *)&ss4->sin_addr.s_addr, is_default, false);
362 void proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
364 __proto_field_set_dev_ipv4(hdr, fid, false);
367 void proto_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
369 __proto_field_set_dev_ipv4(hdr, fid, true);
372 static void __proto_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid,
373 bool is_default)
375 struct sockaddr_storage ss = { };
376 struct sockaddr_in6 *ss6;
377 int ret;
379 if (proto_field_is_set(hdr, fid))
380 return;
382 ret = device_address(ctx.dev, AF_INET6, &ss);
383 if (ret < 0)
384 panic("Could not get device IPv6 address\n");
386 ss6 = (struct sockaddr_in6 *) &ss;
387 __proto_field_set_bytes(hdr, fid, (uint8_t *)&ss6->sin6_addr.s6_addr, is_default, false);
390 void proto_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
392 __proto_field_set_dev_ipv6(hdr, fid, false);
395 void proto_field_set_default_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
397 __proto_field_set_dev_ipv6(hdr, fid, true);
400 void protos_init(const char *dev)
402 ctx.dev = dev;
404 protos_l2_init();
405 protos_l3_init();
406 protos_l4_init();
409 void proto_packet_update(uint32_t idx)
411 struct packet *pkt = packet_get(idx);
412 ssize_t i;
414 for (i = pkt->headers_count - 1; i >= 0; i--) {
415 struct proto_hdr *hdr = pkt->headers[i];
417 if (hdr->ops->packet_update)
418 hdr->ops->packet_update(hdr);
422 void proto_packet_finish(void)
424 struct proto_hdr **headers = current_packet()->headers;
425 size_t headers_count = current_packet()->headers_count;
426 ssize_t i;
428 /* Go down from upper layers to do last calculations (checksum) */
429 for (i = headers_count - 1; i >= 0; i--) {
430 struct proto_hdr *hdr = headers[i];
431 const struct proto_ops *ops = hdr->ops;
433 if (ops && ops->packet_finish)
434 ops->packet_finish(hdr);
438 static inline uint32_t field_inc(struct proto_field *field)
440 uint32_t min = field->func.min;
441 uint32_t max = field->func.max;
442 uint32_t val = field->func.val;
443 uint32_t inc = field->func.inc;
444 uint32_t next;
446 next = (val + inc) % (max + 1);
447 field->func.val = max(next, min);
449 return val;
452 static void field_inc_func(struct proto_field *field)
454 if (field->len == 1) {
455 proto_field_set_u8(field->hdr, field->id, field_inc(field));
456 } else if (field->len == 2) {
457 proto_field_set_be16(field->hdr, field->id, field_inc(field));
458 } else if (field->len == 4) {
459 proto_field_set_be32(field->hdr, field->id, field_inc(field));
460 } else if (field->len > 4) {
461 uint8_t *bytes = __proto_field_get_bytes(field);
463 bytes += field->len - 4;
465 *(uint32_t *)bytes = bswap_32(field_inc(field));
469 static inline uint32_t field_rand(struct proto_field *field)
471 return field->func.min + (rand() % ((field->func.max - field->func.min) + 1));
474 static void field_rnd_func(struct proto_field *field)
476 if (field->len == 1) {
477 proto_field_set_u8(field->hdr, field->id,
478 (uint8_t) field_rand(field));
479 } else if (field->len == 2) {
480 proto_field_set_be16(field->hdr, field->id,
481 (uint16_t) field_rand(field));
482 } else if (field->len == 4) {
483 proto_field_set_be32(field->hdr, field->id,
484 (uint32_t) field_rand(field));
485 } else if (field->len > 4) {
486 uint8_t *bytes = __proto_field_get_bytes(field);
487 uint32_t i;
489 for (i = 0; i < field->len; i++)
490 bytes[i] = (uint8_t) field_rand(field);
494 void proto_field_func_add(struct proto_hdr *hdr, uint32_t fid,
495 struct proto_field_func *func)
497 struct proto_field *field = proto_field_by_id(hdr, fid);
499 bug_on(!func);
501 field->func.update_field = func->update_field;
502 field->func.type = func->type;
503 field->func.max = func->max ?: UINT32_MAX - 1;
504 field->func.min = func->min;
505 field->func.inc = func->inc;
507 if (func->type & PROTO_FIELD_FUNC_INC) {
508 if (func->type & PROTO_FIELD_FUNC_MIN)
509 field->func.val = func->min;
510 else if (field->len == 1)
511 field->func.val = proto_field_get_u8(hdr, fid);
512 else if (field->len == 2)
513 field->func.val = proto_field_get_u16(hdr, fid);
514 else if (field->len == 4)
515 field->func.val = proto_field_get_u32(hdr, fid);
516 else if (field->len > 4) {
517 uint8_t *bytes = __proto_field_get_bytes(field);
519 bytes += field->len - 4;
520 field->func.val = bswap_32(*(uint32_t *)bytes);
523 field->func.update_field = field_inc_func;
524 } else if (func->type & PROTO_FIELD_FUNC_RND) {
525 field->func.update_field = field_rnd_func;
529 void proto_field_dyn_apply(struct proto_field *field)
531 if (field->func.update_field)
532 field->func.update_field(field);
534 if (field->hdr->ops->field_changed)
535 field->hdr->ops->field_changed(field);