trafgen: proto: Add functon to fill field with device ipv4 address
[netsniff-ng.git] / trafgen_proto.c
blob2c090b2ee0d3700c66d326f13b40069d412c8786
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_proto.h"
17 #define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
18 ((f)->mask ? (f)->mask : (0xffffffff)))
20 #define field_unmask_and_unshift(f, v) (((v) & \
21 ((f)->mask ? (f)->mask : (0xffffffff))) >> (f)->shift)
23 static struct proto_ctx ctx;
25 #define PROTO_MAX_LAYERS 16
27 static struct proto_hdr *headers[PROTO_MAX_LAYERS];
28 static size_t headers_count;
30 static struct proto_hdr *registered;
32 struct proto_hdr *proto_current_header(void)
34 if (headers_count > 0)
35 return headers[headers_count - 1];
37 panic("No header was added\n");
40 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
42 struct proto_hdr *lower = NULL;
43 size_t i;
45 if (headers_count == 0)
46 return NULL;
48 for (i = 1, lower = headers[0]; i < headers_count; i++) {
49 if (headers[i] == hdr)
50 return headers[i - 1];
53 return lower;
56 uint8_t *proto_header_ptr(struct proto_hdr *hdr)
58 return &current_packet()->payload[hdr->pkt_offset];
61 static struct proto_hdr *proto_header_by_id(enum proto_id id)
63 struct proto_hdr *p = registered;
65 for (; p; p = p->next)
66 if (p->id == id)
67 return p;
69 panic("Can't lookup proto by id %u\n", id);
72 void proto_header_register(struct proto_hdr *hdr)
74 hdr->next = registered;
75 registered = hdr;
77 hdr->fields = NULL;
78 hdr->fields_count = 0;
81 static void proto_fields_realloc(struct proto_hdr *hdr, size_t count)
83 hdr->fields = xrealloc(hdr->fields, count * sizeof(*hdr->fields));
84 hdr->fields_count = count;
87 void proto_header_fields_add(struct proto_hdr *hdr, struct proto_field *fields,
88 size_t count)
90 struct packet *pkt = current_packet();
91 struct proto_field *f;
92 int i;
94 if (!hdr->fields)
95 hdr->pkt_offset = pkt->len;
97 proto_fields_realloc(hdr, hdr->fields_count + count);
99 for (i = 0; count >= 1; count--, i++) {
100 f = &hdr->fields[hdr->fields_count - count];
102 f->id = fields[i].id;
103 f->len = fields[i].len;
104 f->is_set = false;
105 f->shift = fields[i].shift;
106 f->mask = fields[i].mask;
107 f->pkt_offset = hdr->pkt_offset + fields[i].offset;
109 if (f->pkt_offset + f->len > pkt->len)
110 set_fill(0, (f->pkt_offset + f->len) - pkt->len);
114 static struct proto_field *proto_field_by_id(struct proto_hdr *hdr, uint32_t fid)
116 int i;
118 for (i = 0; i < hdr->fields_count; i++)
119 if (hdr->fields[i].id == fid)
120 return &hdr->fields[i];
122 panic("Failed lookup field id %u for proto id %u\n", fid, hdr->id);
125 bool proto_field_is_set(struct proto_hdr *hdr, uint32_t fid)
127 struct proto_field *field = proto_field_by_id(hdr, fid);
129 return field ? field->is_set : false;
132 void proto_header_init(enum proto_id pid)
134 struct proto_hdr *hdr = proto_header_by_id(pid);
135 struct proto_hdr *new_hdr;
137 if (headers_count >= PROTO_MAX_LAYERS)
138 panic("Too many proto headers\n");
140 new_hdr = xmalloc(sizeof(*new_hdr));
141 memcpy(new_hdr, hdr, sizeof(*new_hdr));
143 if (new_hdr->header_init)
144 new_hdr->header_init(new_hdr);
146 headers[headers_count++] = new_hdr;
149 void proto_header_finish(struct proto_hdr *hdr)
151 if (hdr && hdr->header_finish)
152 hdr->header_finish(hdr);
155 void proto_lower_default_add(enum proto_id pid)
157 if (headers_count > 0) {
158 if (proto_current_header()->layer >= proto_header_by_id(pid)->layer)
159 return;
160 if (proto_current_header()->id == pid)
161 return;
164 proto_header_init(pid);
167 static void __proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
168 uint8_t *bytes, bool is_default, bool is_be)
170 struct proto_field *field;
171 uint8_t *payload;
172 uint32_t v32;
173 uint16_t v16;
174 uint8_t v8;
176 field = proto_field_by_id(hdr, fid);
178 if (is_default && field->is_set)
179 return;
181 payload = &current_packet()->payload[field->pkt_offset];
183 if (field->len == 1) {
184 v8 = field_shift_and_mask(field, *bytes);
185 v8 = field->mask ? (v8 | *payload) : v8;
186 bytes = &v8;
187 } else if (field->len == 2) {
188 v16 = field_shift_and_mask(field, *(uint16_t *)bytes);
189 v16 = is_be ? cpu_to_be16(v16) : v16;
190 v16 = field->mask ? (v16 | *(uint16_t *)payload) : v16;
191 bytes = (uint8_t *)&v16;
192 } else if (field->len == 4) {
193 v32 = field_shift_and_mask(field, *(uint32_t *)bytes);
194 v32 = is_be ? cpu_to_be32(v32) : v32;
195 v32 = field->mask ? (v32 | *(uint32_t *)payload) : v32;
196 bytes = (uint8_t *)&v32;
199 memcpy(payload, bytes, field->len);
201 if (!is_default)
202 field->is_set = true;
205 void proto_field_set_bytes(struct proto_hdr *hdr, uint32_t fid, uint8_t *bytes)
207 __proto_field_set_bytes(hdr, fid, bytes, false, false);
210 static uint8_t *__proto_field_get_bytes(struct proto_field *field)
212 struct packet *pkt = current_packet();
214 return &pkt->payload[field->pkt_offset];
217 void proto_field_set_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
219 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
222 uint8_t proto_field_get_u8(struct proto_hdr *hdr, uint32_t fid)
224 struct proto_field *field = proto_field_by_id(hdr, fid);
225 uint8_t val = *__proto_field_get_bytes(field);
227 return field_unmask_and_unshift(field, val);
230 void proto_field_set_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
232 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
235 uint16_t proto_field_get_u16(struct proto_hdr *hdr, uint32_t fid)
237 struct proto_field *field = proto_field_by_id(hdr, fid);
238 uint16_t val = *(uint16_t *)__proto_field_get_bytes(field);
240 return field_unmask_and_unshift(field, be16_to_cpu(val));
243 void proto_field_set_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
245 proto_field_set_bytes(hdr, fid, (uint8_t *)&val);
248 uint32_t proto_field_get_u32(struct proto_hdr *hdr, uint32_t fid)
250 struct proto_field *field = proto_field_by_id(hdr, fid);
251 uint32_t val = *(uint32_t *)__proto_field_get_bytes(field);
253 return field_unmask_and_unshift(field, be32_to_cpu(val));
256 void proto_field_set_default_bytes(struct proto_hdr *hdr, uint32_t fid, uint8_t *bytes)
258 __proto_field_set_bytes(hdr, fid, bytes, true, false);
261 void proto_field_set_default_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
263 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
266 void proto_field_set_default_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
268 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
271 void proto_field_set_default_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
273 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, false);
276 void proto_field_set_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
278 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, false, true);
281 void proto_field_set_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
283 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, false, true);
286 void proto_field_set_default_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
288 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, true);
291 void proto_field_set_default_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
293 __proto_field_set_bytes(hdr, fid, (uint8_t *)&val, true, true);
296 static void __proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid,
297 bool is_default)
299 uint8_t mac[ETH_ALEN];
300 int ret;
302 if (proto_field_is_set(hdr, fid))
303 return;
305 if (!hdr->ctx->dev)
306 panic("Device is not specified\n");
308 ret = device_hw_address(hdr->ctx->dev, mac, sizeof(mac));
309 if (ret < 0)
310 panic("Could not get device hw address\n");
312 __proto_field_set_bytes(hdr, fid, mac, is_default, false);
315 void proto_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
317 __proto_field_set_dev_mac(hdr, fid, false);
320 void proto_field_set_default_dev_mac(struct proto_hdr *hdr, uint32_t fid)
322 __proto_field_set_dev_mac(hdr, fid, true);
325 static void __proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid,
326 bool is_default)
328 struct sockaddr_storage ss = { };
329 struct sockaddr_in *ss4;
330 uint32_t ip_addr;
331 int ret;
333 if (proto_field_is_set(hdr, fid))
334 return;
336 ret = device_address(hdr->ctx->dev, AF_INET, &ss);
337 if (ret < 0)
338 panic("Could not get device IPv4 address\n");
340 ss4 = (struct sockaddr_in *) &ss;
341 ip_addr = ss4->sin_addr.s_addr;
343 __proto_field_set_bytes(hdr, fid, (uint8_t *)&ip_addr, is_default, false);
346 void proto_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
348 __proto_field_set_dev_ipv4(hdr, fid, false);
351 void proto_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
353 __proto_field_set_dev_ipv4(hdr, fid, true);
356 void protos_init(const char *dev)
358 struct proto_hdr *p;
360 ctx.dev = dev;
362 protos_l2_init();
364 for (p = registered; p; p = p->next)
365 p->ctx = &ctx;
368 void proto_packet_finish(void)
370 ssize_t i;
372 /* Go down from upper layers to do last calculations (checksum) */
373 for (i = headers_count - 1; i >= 0; i--) {
374 struct proto_hdr *p = headers[i];
376 if (p->packet_finish)
377 p->packet_finish(p);
380 for (i = 0; i < headers_count; i++) {
381 struct proto_hdr *p = headers[i];
383 if (p->fields) {
384 xfree(p->fields);
385 p->fields_count = 0;
388 xfree(headers[i]);
391 headers_count = 0;