trafgen: proto: Reference to packet from struct proto_hdr
[netsniff-ng.git] / trafgen_proto.c
blobe5b1ad355dbbc1d36e87ad23fcb54df5e3587439
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 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
36 struct proto_hdr *lower = NULL;
37 size_t i;
39 if (headers_count == 0)
40 return NULL;
42 for (i = 1, lower = headers[0]; i < headers_count; i++) {
43 if (headers[i] == hdr)
44 return headers[i - 1];
47 return lower;
50 uint8_t *proto_header_ptr(struct proto_hdr *hdr)
52 return &packet_get(hdr->pkt_id)->payload[hdr->pkt_offset];
55 static struct proto_hdr *proto_header_by_id(enum proto_id id)
57 struct proto_hdr *p = registered;
59 for (; p; p = p->next)
60 if (p->id == id)
61 return p;
63 panic("Can't lookup proto by id %u\n", id);
66 void proto_header_register(struct proto_hdr *hdr)
68 hdr->next = registered;
69 registered = hdr;
71 hdr->fields = NULL;
72 hdr->fields_count = 0;
75 static void proto_fields_realloc(struct proto_hdr *hdr, size_t count)
77 hdr->fields = xrealloc(hdr->fields, count * sizeof(*hdr->fields));
78 hdr->fields_count = count;
81 void proto_header_fields_add(struct proto_hdr *hdr,
82 const struct proto_field *fields, size_t count)
84 struct packet *pkt = packet_get(hdr->pkt_id);
85 struct proto_field *f;
86 int i;
88 if (!hdr->fields)
89 hdr->pkt_offset = pkt->len;
91 proto_fields_realloc(hdr, hdr->fields_count + count);
93 for (i = 0; count >= 1; count--, i++) {
94 f = &hdr->fields[hdr->fields_count - count];
96 f->id = fields[i].id;
97 f->len = fields[i].len;
98 f->is_set = false;
99 f->shift = fields[i].shift;
100 f->mask = fields[i].mask;
101 f->pkt_offset = hdr->pkt_offset + fields[i].offset;
102 f->hdr = hdr;
104 if (f->pkt_offset + f->len > pkt->len) {
105 hdr->len += f->len;
106 set_fill(0, (f->pkt_offset + f->len) - pkt->len);
111 static struct proto_field *proto_field_by_id(struct proto_hdr *hdr, uint32_t fid)
113 int i;
115 for (i = 0; i < hdr->fields_count; i++)
116 if (hdr->fields[i].id == fid)
117 return &hdr->fields[i];
119 panic("Failed lookup field id %u for proto id %u\n", fid, hdr->id);
122 bool proto_field_is_set(struct proto_hdr *hdr, uint32_t fid)
124 struct proto_field *field = proto_field_by_id(hdr, fid);
126 return field ? field->is_set : false;
129 struct proto_hdr *proto_header_init(enum proto_id pid)
131 struct proto_hdr *hdr = proto_header_by_id(pid);
132 struct proto_hdr *new_hdr;
134 bug_on(headers_count >= PROTO_MAX_LAYERS);
136 new_hdr = xmalloc(sizeof(*new_hdr));
137 memcpy(new_hdr, hdr, sizeof(*new_hdr));
139 new_hdr->pkt_id = current_packet_id();
141 if (new_hdr->header_init)
142 new_hdr->header_init(new_hdr);
144 headers[headers_count++] = new_hdr;
145 return new_hdr;
148 void proto_header_finish(struct proto_hdr *hdr)
150 if (hdr && hdr->header_finish)
151 hdr->header_finish(hdr);
154 struct proto_hdr *proto_lower_default_add(struct proto_hdr *hdr,
155 enum proto_id pid)
157 struct proto_hdr *current;
159 if (headers_count > 0) {
160 current = headers[headers_count - 1];
162 if (current->layer >= proto_header_by_id(pid)->layer)
163 goto set_proto;
164 if (current->id == pid)
165 goto set_proto;
168 current = proto_header_init(pid);
170 set_proto:
171 if (current->set_next_proto)
172 current->set_next_proto(current, hdr->id);
174 return current;
177 static void __proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
178 uint8_t *bytes, bool is_default, bool is_be)
180 struct proto_field *field;
181 uint8_t *payload, *p8;
182 uint16_t *p16;
183 uint32_t *p32;
184 uint32_t v32;
185 uint16_t v16;
186 uint8_t v8;
188 field = proto_field_by_id(hdr, fid);
190 if (is_default && field->is_set)
191 return;
193 payload = &packet_get(hdr->pkt_id)->payload[field->pkt_offset];
195 if (field->len == 1) {
196 p8 = payload;
197 *p8 = field->mask ? *p8 & ~field->mask : *p8;
199 v8 = field_shift_and_mask(field, *bytes);
200 v8 = field->mask ? (v8 | *p8) : v8;
202 bytes = &v8;
203 } else if (field->len == 2) {
204 p16 = (uint16_t *)payload;
205 *p16 = be16_to_cpu(*p16);
206 *p16 = cpu_to_be16(field->mask ? *p16 & ~field->mask : *p16);
208 v16 = field_shift_and_mask(field, *(uint16_t *)bytes);
209 v16 = is_be ? cpu_to_be16(v16) : v16;
210 v16 = field->mask ? (v16 | *p16) : v16;
212 bytes = (uint8_t *)&v16;
213 } else if (field->len == 4) {
214 p32 = (uint32_t *)payload;
215 *p32 = be32_to_cpu(*p32);
216 *p32 = cpu_to_be32(field->mask ? *p32 & ~field->mask : *p32);
218 v32 = field_shift_and_mask(field, *(uint32_t *)bytes);
219 v32 = is_be ? cpu_to_be32(v32) : v32;
220 v32 = field->mask ? (v32 | *p32) : v32;
222 bytes = (uint8_t *)&v32;
225 memcpy(payload, bytes, field->len);
227 if (!is_default)
228 field->is_set = true;
231 void proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid, uint8_t *bytes)
233 __proto_field_set_bytes(hdr, fid, bytes, false, false);
236 static uint8_t *__proto_field_get_bytes(struct proto_field *field)
238 return &packet_get(field->hdr->pkt_id)->payload[field->pkt_offset];
241 void proto_field_set_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
243 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
246 uint8_t proto_field_get_u8(struct proto_hdr *hdr, uint32_t fid)
248 struct proto_field *field = proto_field_by_id(hdr, fid);
249 uint8_t val = *__proto_field_get_bytes(field);
251 return field_unmask_and_unshift(field, val);
254 void proto_field_set_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
256 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
259 uint16_t proto_field_get_u16(struct proto_hdr *hdr, uint32_t fid)
261 struct proto_field *field = proto_field_by_id(hdr, fid);
262 uint16_t val = *(uint16_t *)__proto_field_get_bytes(field);
264 return field_unmask_and_unshift(field, be16_to_cpu(val));
267 void proto_field_set_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
269 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
272 uint32_t proto_field_get_u32(struct proto_hdr *hdr, uint32_t fid)
274 struct proto_field *field = proto_field_by_id(hdr, fid);
275 uint32_t val = *(uint32_t *)__proto_field_get_bytes(field);
277 return field_unmask_and_unshift(field, be32_to_cpu(val));
280 void proto_field_set_default_bytes(struct proto_hdr *hdr, uint32_t fid, uint8_t *bytes)
282 __proto_field_set_bytes(hdr, fid, bytes, true, false);
285 void proto_field_set_default_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
287 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
290 void proto_field_set_default_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
292 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
295 void proto_field_set_default_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
297 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
300 void proto_field_set_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
302 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, false, true);
305 void proto_field_set_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
307 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, false, true);
310 void proto_field_set_default_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
312 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, true);
315 void proto_field_set_default_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
317 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, true);
320 static void __proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid,
321 bool is_default)
323 uint8_t mac[ETH_ALEN];
324 int ret;
326 if (proto_field_is_set(hdr, fid))
327 return;
329 if (!hdr->ctx->dev)
330 panic("Device is not specified\n");
332 ret = device_hw_address(hdr->ctx->dev, mac, sizeof(mac));
333 if (ret < 0)
334 panic("Could not get device hw address\n");
336 __proto_field_set_bytes(hdr, fid, mac, is_default, false);
339 void proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
341 __proto_field_set_dev_mac(hdr, fid, false);
344 void proto_field_set_default_dev_mac(struct proto_hdr *hdr, uint32_t fid)
346 __proto_field_set_dev_mac(hdr, fid, true);
349 static void __proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid,
350 bool is_default)
352 struct sockaddr_storage ss = { };
353 struct sockaddr_in *ss4;
354 int ret;
356 if (proto_field_is_set(hdr, fid))
357 return;
359 ret = device_address(hdr->ctx->dev, AF_INET, &ss);
360 if (ret < 0)
361 panic("Could not get device IPv4 address\n");
363 ss4 = (struct sockaddr_in *) &ss;
364 __proto_field_set_bytes(hdr, fid, (uint8_t *)&ss4->sin_addr.s_addr, is_default, false);
367 void proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
369 __proto_field_set_dev_ipv4(hdr, fid, false);
372 void proto_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
374 __proto_field_set_dev_ipv4(hdr, fid, true);
377 static void __proto_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid,
378 bool is_default)
380 struct sockaddr_storage ss = { };
381 struct sockaddr_in6 *ss6;
382 int ret;
384 if (proto_field_is_set(hdr, fid))
385 return;
387 ret = device_address(hdr->ctx->dev, AF_INET6, &ss);
388 if (ret < 0)
389 panic("Could not get device IPv6 address\n");
391 ss6 = (struct sockaddr_in6 *) &ss;
392 __proto_field_set_bytes(hdr, fid, (uint8_t *)&ss6->sin6_addr.s6_addr, is_default, false);
395 void proto_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
397 __proto_field_set_dev_ipv6(hdr, fid, false);
400 void proto_field_set_default_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
402 __proto_field_set_dev_ipv6(hdr, fid, true);
405 void protos_init(const char *dev)
407 struct proto_hdr *p;
409 ctx.dev = dev;
411 protos_l2_init();
412 protos_l3_init();
413 protos_l4_init();
415 for (p = registered; p; p = p->next)
416 p->ctx = &ctx;
419 void proto_packet_finish(void)
421 ssize_t i;
423 /* Go down from upper layers to do last calculations (checksum) */
424 for (i = headers_count - 1; i >= 0; i--) {
425 struct proto_hdr *p = headers[i];
427 if (p->packet_finish)
428 p->packet_finish(p);
431 for (i = 0; i < headers_count; i++) {
432 struct proto_hdr *p = headers[i];
434 if (p->fields) {
435 xfree(p->fields);
436 p->fields_count = 0;
439 xfree(headers[i]);
442 headers_count = 0;