trafgen: l7: Add DNS header generation API
[netsniff-ng.git] / trafgen_proto.c
blob0353d6b74e04c5dd01f8a5fe526bf4b42a84f4b5
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_l7.h"
18 #include "trafgen_proto.h"
20 #define field_shift_and_mask(f, v) (((v) << (f)->shift) & \
21 ((f)->mask ? (f)->mask : (0xffffffff)))
23 #define field_unmask_and_unshift(f, v) (((v) & \
24 ((f)->mask ? (f)->mask : (0xffffffff))) >> (f)->shift)
26 struct ctx {
27 const char *dev;
29 static struct ctx ctx;
31 static const struct proto_ops *registered_ops[__PROTO_MAX];
33 struct proto_hdr *proto_lower_header(struct proto_hdr *hdr)
35 struct packet *pkt = packet_get(hdr->pkt_id);
36 struct proto_hdr **headers = &pkt->headers[0];
38 if (hdr->index == 0)
39 return NULL;
41 return headers[hdr->index - 1];
44 struct proto_hdr *proto_upper_header(struct proto_hdr *hdr)
46 struct packet *pkt = packet_get(hdr->pkt_id);
47 struct proto_hdr **headers = &pkt->headers[0];
48 size_t headers_count = pkt->headers_count;
50 if (hdr->index == headers_count - 1)
51 return NULL;
53 return headers[hdr->index + 1];
56 uint8_t *proto_header_ptr(struct proto_hdr *hdr)
58 return &packet_get(hdr->pkt_id)->payload[hdr->pkt_offset];
61 static const struct proto_ops *proto_ops_by_id(enum proto_id id)
63 const struct proto_ops *ops = registered_ops[id];
65 bug_on(ops->id != id);
66 return ops;
69 void proto_ops_register(const struct proto_ops *ops)
71 bug_on(ops->id >= __PROTO_MAX);
72 registered_ops[ops->id] = ops;
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->len)
105 continue;
107 if (f->pkt_offset + f->len > pkt->len) {
108 hdr->len += f->len;
109 set_fill(0, (f->pkt_offset + f->len) - pkt->len);
114 struct proto_field *proto_hdr_field_by_id(struct proto_hdr *hdr, uint32_t fid)
116 /* Assume the fields are stored in the same order as the respective
117 * enum, so the index can be used for faster lookup here.
119 bug_on(hdr->fields[fid].id != fid);
121 return &hdr->fields[fid];
124 bool proto_hdr_field_is_set(struct proto_hdr *hdr, uint32_t fid)
126 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
128 return field ? field->is_set : false;
131 struct proto_hdr *proto_header_push(enum proto_id pid)
133 struct packet *pkt = current_packet();
134 struct proto_hdr **headers = &pkt->headers[0];
135 const struct proto_ops *ops = proto_ops_by_id(pid);
136 struct proto_hdr *hdr;
138 bug_on(pkt->headers_count >= PROTO_MAX_LAYERS);
140 hdr = xzmalloc(sizeof(*hdr));
141 hdr->ops = ops;
142 hdr->pkt_id = current_packet_id();
144 if (ops && ops->header_init)
145 ops->header_init(hdr);
147 /* This is very important to have it after header_init as
148 * pkt->headers_count might be changed by adding default lower headers */
149 hdr->index = pkt->headers_count;
151 headers[pkt->headers_count++] = hdr;
152 return hdr;
155 void proto_header_finish(struct proto_hdr *hdr)
157 if (hdr && hdr->ops && hdr->ops->header_finish)
158 hdr->ops->header_finish(hdr);
161 struct proto_hdr *proto_hdr_push_sub_header(struct proto_hdr *hdr, int id)
163 struct proto_hdr *sub_hdr;
165 sub_hdr = xzmalloc(sizeof(struct proto_hdr));
166 sub_hdr->index = hdr->sub_headers_count;
167 sub_hdr->parent = hdr;
168 sub_hdr->id = id;
170 hdr->sub_headers_count++;
171 hdr->sub_headers = xrealloc(hdr->sub_headers,
172 hdr->sub_headers_count * sizeof(struct proto_hdr *));
174 hdr->sub_headers[hdr->sub_headers_count - 1] = sub_hdr;
176 if (hdr->ops->push_sub_header)
177 hdr->ops->push_sub_header(hdr, sub_hdr);
179 if (sub_hdr->ops->header_init)
180 sub_hdr->ops->header_init(sub_hdr);
182 return sub_hdr;
185 static void __proto_hdr_set_offset(struct proto_hdr *hdr, uint16_t pkt_offset)
187 size_t i;
189 hdr->pkt_offset = pkt_offset;
191 for (i = 0; i < hdr->fields_count; i++) {
192 struct proto_field *f = &hdr->fields[i];
194 f->pkt_offset = pkt_offset + f->offset;
198 void proto_hdr_move_sub_header(struct proto_hdr *hdr, struct proto_hdr *from,
199 struct proto_hdr *to)
201 struct proto_hdr *src_hdr, *dst_hdr, *tmp;
202 uint8_t *src_ptr, *dst_ptr;
203 uint16_t to_pkt_offset;
204 uint16_t to_index;
205 uint16_t pkt_offset;
206 int idx_shift;
207 size_t len = 0;
208 uint8_t *buf;
209 int i;
211 if (hdr->sub_headers_count < 2)
212 return;
213 if (from->index == to->index)
214 return;
216 buf = xmemdupz(proto_header_ptr(from), from->len);
218 to_pkt_offset = to->pkt_offset;
219 to_index = to->index;
221 if (from->index < to->index) {
222 src_hdr = hdr->sub_headers[from->index + 1];
223 dst_hdr = to;
225 src_ptr = proto_header_ptr(src_hdr);
226 dst_ptr = proto_header_ptr(from);
227 len = (to->pkt_offset + to->len) - src_hdr->pkt_offset;
229 pkt_offset = from->pkt_offset;
230 idx_shift = 1;
231 } else {
232 src_hdr = to;
233 dst_hdr = hdr->sub_headers[from->index - 1];
235 src_ptr = proto_header_ptr(src_hdr);
236 dst_ptr = src_ptr + from->len;
237 len = from->pkt_offset - to->pkt_offset;
239 pkt_offset = to->pkt_offset + from->len;
240 idx_shift = -1;
243 hdr->sub_headers[from->index] = to;
244 hdr->sub_headers[to->index] = from;
246 for (i = src_hdr->index; i <= dst_hdr->index; i++) {
247 tmp = hdr->sub_headers[i];
249 __proto_hdr_set_offset(tmp, pkt_offset);
250 pkt_offset += tmp->len;
253 for (i = src_hdr->index; i <= dst_hdr->index; i++)
254 hdr->sub_headers[i]->index = i + idx_shift;
256 memmove(dst_ptr, src_ptr, len);
258 from->pkt_offset = to_pkt_offset;
259 from->index = to_index;
261 memcpy(proto_header_ptr(from), buf, from->len);
263 xfree(buf);
266 struct proto_hdr *proto_lower_default_add(struct proto_hdr *upper,
267 enum proto_id pid)
269 struct proto_hdr *current;
270 size_t headers_count = current_packet()->headers_count;
271 const struct proto_ops *ops;
273 if (headers_count > 0) {
274 current = current_packet()->headers[headers_count - 1];
275 ops = current->ops;
277 if (ops->layer >= proto_ops_by_id(pid)->layer)
278 goto set_proto;
279 if (ops->id == pid)
280 goto set_proto;
283 current = proto_header_push(pid);
284 ops = current->ops;
286 set_proto:
287 if (ops && ops->set_next_proto)
288 ops->set_next_proto(current, upper->ops->id);
290 return current;
293 static void __proto_field_relocate(struct proto_field *field)
295 struct proto_hdr *hdr = field->hdr;
296 struct packet *pkt = packet_get(hdr->pkt_id);
297 uint8_t *from, *to;
298 int i;
300 /* If this is a last field then just calculate 'pkt_offset' */
301 if (field->id == hdr->fields_count - 1) {
302 field->pkt_offset = hdr->pkt_offset + hdr->len - field->len;
303 return;
306 /* Use 'pkt_offset' from the 1st real (len > 0) field after the
307 * 'target' one */
308 for (i = field->id + 1; i < hdr->fields_count; i++) {
309 if (hdr->fields[i].len == 0)
310 continue;
312 field->pkt_offset = hdr->fields[i].pkt_offset;
313 break;
316 /* Move payload of overlapped fields (each after the 'target' field) */
317 from = &pkt->payload[field->pkt_offset];
318 to = &pkt->payload[field->pkt_offset + field->len];
319 memcpy(to, from, hdr->len - field->len);
321 /* Recalculate 'pkt_offset' of the rest fields */
322 for (; i < hdr->fields_count; i++) {
323 struct proto_field *tmp = &hdr->fields[i];
325 if (tmp->len == 0)
326 continue;
328 tmp->pkt_offset += field->len;
332 static void __proto_field_set_bytes(struct proto_field *field,
333 const uint8_t *bytes, size_t len,
334 bool is_default, bool is_be)
336 uint8_t *payload, *p8;
337 uint16_t *p16;
338 uint32_t *p32;
339 uint32_t v32;
340 uint16_t v16;
341 uint8_t v8;
343 if (is_default && field->is_set)
344 return;
346 if (field->len == 0) {
347 field->hdr->len += len;
348 field->len = len;
349 set_fill(0, len);
351 __proto_field_relocate(field);
354 payload = &packet_get(field->hdr->pkt_id)->payload[field->pkt_offset];
356 if (field->len == 1) {
357 p8 = payload;
358 *p8 = field->mask ? *p8 & ~field->mask : *p8;
360 v8 = field_shift_and_mask(field, *bytes);
361 v8 = field->mask ? (v8 | *p8) : v8;
363 bytes = &v8;
364 } else if (field->len == 2) {
365 p16 = (uint16_t *)payload;
366 *p16 = be16_to_cpu(*p16);
367 *p16 = cpu_to_be16(field->mask ? *p16 & ~field->mask : *p16);
369 v16 = field_shift_and_mask(field, *(const uint16_t *)bytes);
370 v16 = is_be ? cpu_to_be16(v16) : v16;
371 v16 = field->mask ? (v16 | *p16) : v16;
373 bytes = (uint8_t *)&v16;
374 } else if (field->len == 4) {
375 p32 = (uint32_t *)payload;
376 *p32 = be32_to_cpu(*p32);
377 *p32 = cpu_to_be32(field->mask ? *p32 & ~field->mask : *p32);
379 v32 = field_shift_and_mask(field, *(const uint32_t *)bytes);
380 v32 = is_be ? cpu_to_be32(v32) : v32;
381 v32 = field->mask ? (v32 | *p32) : v32;
383 bytes = (uint8_t *)&v32;
386 memcpy(payload, bytes, field->len);
388 if (!is_default)
389 field->is_set = true;
392 void proto_hdr_field_set_bytes(struct proto_hdr *hdr, uint32_t fid,
393 const uint8_t *bytes, size_t len)
395 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
397 __proto_field_set_bytes(field, bytes, len, false, false);
400 static uint8_t *__proto_field_get_bytes(struct proto_field *field)
402 return &packet_get(field->hdr->pkt_id)->payload[field->pkt_offset];
405 void proto_hdr_field_set_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
407 proto_hdr_field_set_bytes(hdr, fid, (uint8_t *)&val, 1);
410 uint8_t proto_hdr_field_get_u8(struct proto_hdr *hdr, uint32_t fid)
412 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
413 uint8_t val = *__proto_field_get_bytes(field);
415 return field_unmask_and_unshift(field, val);
418 void proto_hdr_field_set_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
420 proto_hdr_field_set_bytes(hdr, fid, (uint8_t *)&val, 2);
423 uint16_t proto_hdr_field_get_u16(struct proto_hdr *hdr, uint32_t fid)
425 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
426 uint16_t val = *(uint16_t *)__proto_field_get_bytes(field);
428 return field_unmask_and_unshift(field, be16_to_cpu(val));
431 void proto_hdr_field_set_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
433 proto_hdr_field_set_bytes(hdr, fid, (uint8_t *)&val, 4);
436 uint32_t proto_hdr_field_get_u32(struct proto_hdr *hdr, uint32_t fid)
438 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
439 uint32_t val = *(uint32_t *)__proto_field_get_bytes(field);
441 return field_unmask_and_unshift(field, be32_to_cpu(val));
444 void proto_hdr_field_set_default_bytes(struct proto_hdr *hdr, uint32_t fid,
445 const uint8_t *bytes, size_t len)
447 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
449 __proto_field_set_bytes(field, bytes, len, true, false);
452 void proto_hdr_field_set_default_u8(struct proto_hdr *hdr, uint32_t fid, uint8_t val)
454 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
456 __proto_field_set_bytes(field, (uint8_t *)&val, 1, true, false);
459 void proto_hdr_field_set_default_u16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
461 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
463 __proto_field_set_bytes(field, (uint8_t *)&val, 2, true, false);
466 void proto_hdr_field_set_default_u32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
468 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
470 __proto_field_set_bytes(field, (uint8_t *)&val, 4, true, false);
473 void proto_hdr_field_set_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
475 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
477 __proto_field_set_bytes(field, (uint8_t *)&val, 2, false, true);
480 void proto_hdr_field_set_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
482 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
484 __proto_field_set_bytes(field, (uint8_t *)&val, 4, false, true);
487 void proto_hdr_field_set_default_be16(struct proto_hdr *hdr, uint32_t fid, uint16_t val)
489 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
491 __proto_field_set_bytes(field, (uint8_t *)&val, 2, true, true);
494 void proto_hdr_field_set_default_be32(struct proto_hdr *hdr, uint32_t fid, uint32_t val)
496 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
498 __proto_field_set_bytes(field, (uint8_t *)&val, 4, true, true);
501 static void __proto_hdr_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid,
502 bool is_default)
504 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
505 uint8_t mac[ETH_ALEN];
506 int ret;
508 if (proto_hdr_field_is_set(hdr, fid))
509 return;
511 ret = device_hw_address(ctx.dev, mac, sizeof(mac));
512 if (ret < 0)
513 panic("Could not get device hw address\n");
515 __proto_field_set_bytes(field, mac, 6, is_default, false);
518 void proto_hdr_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
520 __proto_hdr_field_set_dev_mac(hdr, fid, false);
523 void proto_hdr_field_set_default_dev_mac(struct proto_hdr *hdr, uint32_t fid)
525 __proto_hdr_field_set_dev_mac(hdr, fid, true);
528 static void __proto_hdr_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid,
529 bool is_default)
531 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
532 struct sockaddr_storage ss = { };
533 struct sockaddr_in *ss4;
534 int ret;
536 if (proto_hdr_field_is_set(hdr, fid))
537 return;
539 ret = device_address(ctx.dev, AF_INET, &ss);
540 if (ret < 0) {
541 fprintf(stderr, "Warning: Could not get device IPv4 address for %s\n", ctx.dev);
542 return;
545 ss4 = (struct sockaddr_in *) &ss;
546 __proto_field_set_bytes(field, (uint8_t *)&ss4->sin_addr.s_addr, 4, is_default, false);
549 void proto_hdr_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
551 __proto_hdr_field_set_dev_ipv4(hdr, fid, false);
554 void proto_hdr_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
556 __proto_hdr_field_set_dev_ipv4(hdr, fid, true);
559 static void __proto_hdr_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid,
560 bool is_default)
562 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
563 struct sockaddr_storage ss = { };
564 struct sockaddr_in6 *ss6;
565 int ret;
567 if (proto_hdr_field_is_set(hdr, fid))
568 return;
570 ret = device_address(ctx.dev, AF_INET6, &ss);
571 if (ret < 0) {
572 fprintf(stderr, "Warning: Could not get device IPv6 address for %s\n", ctx.dev);
573 return;
576 ss6 = (struct sockaddr_in6 *) &ss;
577 __proto_field_set_bytes(field, (uint8_t *)&ss6->sin6_addr.s6_addr, 16, is_default, false);
580 void proto_hdr_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
582 __proto_hdr_field_set_dev_ipv6(hdr, fid, false);
585 void proto_hdr_field_set_default_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
587 __proto_hdr_field_set_dev_ipv6(hdr, fid, true);
590 void proto_hdr_field_set_string(struct proto_hdr *hdr, uint32_t fid, const char *str)
592 proto_hdr_field_set_bytes(hdr, fid, (uint8_t *)str, strlen(str) + 1);
595 void proto_hdr_field_set_default_string(struct proto_hdr *hdr, uint32_t fid, const char *str)
597 proto_hdr_field_set_default_bytes(hdr, fid, (uint8_t *)str, strlen(str) + 1);
600 void proto_field_set_u8(struct proto_field *field, uint8_t val)
602 __proto_field_set_bytes(field, &val, 1, false, false);
605 uint8_t proto_field_get_u8(struct proto_field *field)
607 uint8_t val = *__proto_field_get_bytes(field);
609 return field_unmask_and_unshift(field, val);
612 void proto_field_set_u16(struct proto_field *field, uint16_t val)
614 __proto_field_set_bytes(field, (uint8_t *)&val, 2, false, false);
617 uint16_t proto_field_get_u16(struct proto_field *field)
619 uint16_t val = *(uint16_t *)__proto_field_get_bytes(field);
621 return field_unmask_and_unshift(field, be16_to_cpu(val));
624 void proto_field_set_u32(struct proto_field *field, uint32_t val)
626 __proto_field_set_bytes(field, (uint8_t *)&val, 4, false, false);
629 uint32_t proto_field_get_u32(struct proto_field *field)
631 uint32_t val = *(uint32_t *)__proto_field_get_bytes(field);
633 return field_unmask_and_unshift(field, be32_to_cpu(val));
636 void proto_field_set_be16(struct proto_field *field, uint16_t val)
638 __proto_field_set_bytes(field, (uint8_t *)&val, 2, false, true);
641 void proto_field_set_be32(struct proto_field *field, uint32_t val)
643 __proto_field_set_bytes(field, (uint8_t *)&val, 4, false, true);
646 void proto_field_set_bytes(struct proto_field *field, const uint8_t *bytes, size_t len)
648 __proto_field_set_bytes(field, bytes, len, false, false);
651 void proto_field_set_string(struct proto_field *field, const char *str)
653 proto_field_set_bytes(field, (uint8_t *)str, strlen(str) + 1);
656 void proto_field_set_default_string(struct proto_field *field, const char *str)
658 __proto_field_set_bytes(field, (uint8_t *)str, strlen(str) + 1, true, false);
661 void protos_init(const char *dev)
663 ctx.dev = dev;
665 protos_l2_init();
666 protos_l3_init();
667 protos_l4_init();
668 protos_l7_init();
671 void proto_packet_update(uint32_t idx)
673 struct packet *pkt = packet_get(idx);
674 ssize_t i;
676 for (i = pkt->headers_count - 1; i >= 0; i--) {
677 struct proto_hdr *hdr = pkt->headers[i];
679 if (hdr->ops->packet_update)
680 hdr->ops->packet_update(hdr);
684 void proto_packet_finish(void)
686 struct proto_hdr **headers = current_packet()->headers;
687 size_t headers_count = current_packet()->headers_count;
688 ssize_t i;
690 /* Go down from upper layers to do last calculations (checksum) */
691 for (i = headers_count - 1; i >= 0; i--) {
692 struct proto_hdr *hdr = headers[i];
693 const struct proto_ops *ops = hdr->ops;
695 if (ops && ops->packet_finish)
696 ops->packet_finish(hdr);
700 static inline uint32_t field_inc(struct proto_field *field)
702 uint32_t min = field->func.min;
703 uint32_t max = field->func.max;
704 uint32_t val = field->func.val;
705 uint32_t inc = field->func.inc;
706 uint32_t next;
708 next = (val + inc) % (max + 1);
709 field->func.val = max(next, min);
711 return val;
714 static void field_inc_func(struct proto_field *field)
716 if (field->len == 1) {
717 proto_field_set_u8(field, field_inc(field));
718 } else if (field->len == 2) {
719 proto_field_set_be16(field, field_inc(field));
720 } else if (field->len == 4) {
721 proto_field_set_be32(field, field_inc(field));
722 } else if (field->len > 4) {
723 uint8_t *bytes = __proto_field_get_bytes(field);
725 bytes += field->len - 4;
727 *(uint32_t *)bytes = bswap_32(field_inc(field));
731 static inline uint32_t field_rand(struct proto_field *field)
733 return field->func.min + (rand() % ((field->func.max - field->func.min) + 1));
736 static void field_rnd_func(struct proto_field *field)
738 if (field->len == 1) {
739 proto_field_set_u8(field, (uint8_t) field_rand(field));
740 } else if (field->len == 2) {
741 proto_field_set_be16(field, (uint16_t) field_rand(field));
742 } else if (field->len == 4) {
743 proto_field_set_be32(field, (uint32_t) field_rand(field));
744 } else if (field->len > 4) {
745 uint8_t *bytes = __proto_field_get_bytes(field);
746 uint32_t i;
748 for (i = 0; i < field->len; i++)
749 bytes[i] = (uint8_t) field_rand(field);
753 void proto_field_func_add(struct proto_field *field,
754 struct proto_field_func *func)
756 bug_on(!func);
758 field->func.update_field = func->update_field;
759 field->func.type = func->type;
760 field->func.max = func->max ?: UINT32_MAX - 1;
761 field->func.min = func->min;
762 field->func.inc = func->inc;
764 if (func->type & PROTO_FIELD_FUNC_INC) {
765 if (func->type & PROTO_FIELD_FUNC_MIN)
766 field->func.val = func->min;
767 else if (field->len == 1)
768 field->func.val = proto_field_get_u8(field);
769 else if (field->len == 2)
770 field->func.val = proto_field_get_u16(field);
771 else if (field->len == 4)
772 field->func.val = proto_field_get_u32(field);
773 else if (field->len > 4) {
774 uint8_t *bytes = __proto_field_get_bytes(field);
776 bytes += field->len - 4;
777 field->func.val = bswap_32(*(uint32_t *)bytes);
780 field->func.update_field = field_inc_func;
781 } else if (func->type & PROTO_FIELD_FUNC_RND) {
782 field->func.update_field = field_rnd_func;
786 void proto_field_dyn_apply(struct proto_field *field)
788 if (field->func.update_field)
789 field->func.update_field(field);
791 if (field->hdr->ops->field_changed)
792 field->hdr->ops->field_changed(field);
795 const char *proto_dev_get(void)
797 return ctx.dev;