trafgen: Fix output pcap file name length trimming
[netsniff-ng.git] / trafgen_proto.c
blobc2cbffb47f851fe49c4aa273b99dfa914b4bf8d7
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 struct dev_io *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 if (dev_io_is_netdev(ctx.dev)) {
512 ret = device_hw_address(dev_io_name_get(ctx.dev), mac, sizeof(mac));
513 if (ret < 0)
514 panic("Could not get device hw address\n");
516 __proto_field_set_bytes(field, mac, 6, is_default, false);
520 void proto_hdr_field_set_dev_mac(struct proto_hdr *hdr, uint32_t fid)
522 __proto_hdr_field_set_dev_mac(hdr, fid, false);
525 void proto_hdr_field_set_default_dev_mac(struct proto_hdr *hdr, uint32_t fid)
527 __proto_hdr_field_set_dev_mac(hdr, fid, true);
530 static void __proto_hdr_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid,
531 bool is_default)
533 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
534 struct sockaddr_storage ss = { };
535 struct sockaddr_in *ss4;
536 int ret;
538 if (proto_hdr_field_is_set(hdr, fid))
539 return;
541 if (dev_io_is_netdev(ctx.dev)) {
542 ret = device_address(dev_io_name_get(ctx.dev), AF_INET, &ss);
543 if (ret < 0) {
544 fprintf(stderr, "Warning: Could not get device IPv4 address for %s\n",
545 dev_io_name_get(ctx.dev));
546 return;
549 ss4 = (struct sockaddr_in *) &ss;
550 __proto_field_set_bytes(field, (uint8_t *)&ss4->sin_addr.s_addr, 4, is_default, false);
554 void proto_hdr_field_set_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
556 __proto_hdr_field_set_dev_ipv4(hdr, fid, false);
559 void proto_hdr_field_set_default_dev_ipv4(struct proto_hdr *hdr, uint32_t fid)
561 __proto_hdr_field_set_dev_ipv4(hdr, fid, true);
564 static void __proto_hdr_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid,
565 bool is_default)
567 struct proto_field *field = proto_hdr_field_by_id(hdr, fid);
568 struct sockaddr_storage ss = { };
569 struct sockaddr_in6 *ss6;
570 int ret;
572 if (proto_hdr_field_is_set(hdr, fid))
573 return;
575 if (dev_io_is_netdev(ctx.dev)) {
576 ret = device_address(dev_io_name_get(ctx.dev), AF_INET6, &ss);
577 if (ret < 0) {
578 fprintf(stderr, "Warning: Could not get device IPv6 address for %s\n",
579 dev_io_name_get(ctx.dev));
580 return;
583 ss6 = (struct sockaddr_in6 *) &ss;
584 __proto_field_set_bytes(field, (uint8_t *)&ss6->sin6_addr.s6_addr, 16, is_default, false);
588 void proto_hdr_field_set_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
590 __proto_hdr_field_set_dev_ipv6(hdr, fid, false);
593 void proto_hdr_field_set_default_dev_ipv6(struct proto_hdr *hdr, uint32_t fid)
595 __proto_hdr_field_set_dev_ipv6(hdr, fid, true);
598 void proto_hdr_field_set_string(struct proto_hdr *hdr, uint32_t fid, const char *str)
600 proto_hdr_field_set_bytes(hdr, fid, (uint8_t *)str, strlen(str) + 1);
603 void proto_hdr_field_set_default_string(struct proto_hdr *hdr, uint32_t fid, const char *str)
605 proto_hdr_field_set_default_bytes(hdr, fid, (uint8_t *)str, strlen(str) + 1);
608 void proto_field_set_u8(struct proto_field *field, uint8_t val)
610 __proto_field_set_bytes(field, &val, 1, false, false);
613 uint8_t proto_field_get_u8(struct proto_field *field)
615 uint8_t val = *__proto_field_get_bytes(field);
617 return field_unmask_and_unshift(field, val);
620 void proto_field_set_u16(struct proto_field *field, uint16_t val)
622 __proto_field_set_bytes(field, (uint8_t *)&val, 2, false, false);
625 uint16_t proto_field_get_u16(struct proto_field *field)
627 uint16_t val = *(uint16_t *)__proto_field_get_bytes(field);
629 return field_unmask_and_unshift(field, be16_to_cpu(val));
632 void proto_field_set_u32(struct proto_field *field, uint32_t val)
634 __proto_field_set_bytes(field, (uint8_t *)&val, 4, false, false);
637 uint32_t proto_field_get_u32(struct proto_field *field)
639 uint32_t val = *(uint32_t *)__proto_field_get_bytes(field);
641 return field_unmask_and_unshift(field, be32_to_cpu(val));
644 void proto_field_set_be16(struct proto_field *field, uint16_t val)
646 __proto_field_set_bytes(field, (uint8_t *)&val, 2, false, true);
649 void proto_field_set_be32(struct proto_field *field, uint32_t val)
651 __proto_field_set_bytes(field, (uint8_t *)&val, 4, false, true);
654 void proto_field_set_bytes(struct proto_field *field, const uint8_t *bytes, size_t len)
656 __proto_field_set_bytes(field, bytes, len, false, false);
659 void proto_field_set_string(struct proto_field *field, const char *str)
661 proto_field_set_bytes(field, (uint8_t *)str, strlen(str) + 1);
664 void proto_field_set_default_string(struct proto_field *field, const char *str)
666 __proto_field_set_bytes(field, (uint8_t *)str, strlen(str) + 1, true, false);
669 void protos_init(struct dev_io *dev)
671 ctx.dev = dev;
673 protos_l2_init();
674 protos_l3_init();
675 protos_l4_init();
676 protos_l7_init();
679 void proto_packet_update(uint32_t idx)
681 struct packet *pkt = packet_get(idx);
682 ssize_t i;
684 for (i = pkt->headers_count - 1; i >= 0; i--) {
685 struct proto_hdr *hdr = pkt->headers[i];
687 if (hdr->ops->packet_update)
688 hdr->ops->packet_update(hdr);
692 void proto_packet_finish(void)
694 struct proto_hdr **headers = current_packet()->headers;
695 size_t headers_count = current_packet()->headers_count;
696 ssize_t i;
698 /* Go down from upper layers to do last calculations (checksum) */
699 for (i = headers_count - 1; i >= 0; i--) {
700 struct proto_hdr *hdr = headers[i];
701 const struct proto_ops *ops = hdr->ops;
703 if (ops && ops->packet_finish)
704 ops->packet_finish(hdr);
708 static inline uint32_t field_inc(struct proto_field *field)
710 uint32_t min = field->func.min;
711 uint32_t max = field->func.max;
712 uint32_t val = field->func.val;
713 uint32_t inc = field->func.inc;
714 uint32_t next;
716 next = (val + inc) % (max + 1);
717 field->func.val = max(next, min);
719 return val;
722 static void field_inc_func(struct proto_field *field)
724 if (field->len == 1) {
725 proto_field_set_u8(field, field_inc(field));
726 } else if (field->len == 2) {
727 proto_field_set_be16(field, field_inc(field));
728 } else if (field->len == 4) {
729 proto_field_set_be32(field, field_inc(field));
730 } else if (field->len > 4) {
731 uint8_t *bytes = __proto_field_get_bytes(field);
733 bytes += field->len - 4;
735 *(uint32_t *)bytes = bswap_32(field_inc(field));
739 static inline uint32_t field_rand(struct proto_field *field)
741 return field->func.min + (rand() % ((field->func.max - field->func.min) + 1));
744 static void field_rnd_func(struct proto_field *field)
746 if (field->len == 1) {
747 proto_field_set_u8(field, (uint8_t) field_rand(field));
748 } else if (field->len == 2) {
749 proto_field_set_be16(field, (uint16_t) field_rand(field));
750 } else if (field->len == 4) {
751 proto_field_set_be32(field, (uint32_t) field_rand(field));
752 } else if (field->len > 4) {
753 uint8_t *bytes = __proto_field_get_bytes(field);
754 uint32_t i;
756 for (i = 0; i < field->len; i++)
757 bytes[i] = (uint8_t) field_rand(field);
761 void proto_field_func_add(struct proto_field *field,
762 struct proto_field_func *func)
764 bug_on(!func);
766 field->func.update_field = func->update_field;
767 field->func.type = func->type;
768 field->func.max = func->max ?: UINT32_MAX - 1;
769 field->func.min = func->min;
770 field->func.inc = func->inc;
772 if (func->type & PROTO_FIELD_FUNC_INC) {
773 if (func->type & PROTO_FIELD_FUNC_MIN)
774 field->func.val = func->min;
775 else if (field->len == 1)
776 field->func.val = proto_field_get_u8(field);
777 else if (field->len == 2)
778 field->func.val = proto_field_get_u16(field);
779 else if (field->len == 4)
780 field->func.val = proto_field_get_u32(field);
781 else if (field->len > 4) {
782 uint8_t *bytes = __proto_field_get_bytes(field);
784 bytes += field->len - 4;
785 field->func.val = bswap_32(*(uint32_t *)bytes);
788 field->func.update_field = field_inc_func;
789 } else if (func->type & PROTO_FIELD_FUNC_RND) {
790 field->func.update_field = field_rnd_func;
794 void proto_field_dyn_apply(struct proto_field *field)
796 if (field->func.update_field)
797 field->func.update_field(field);
799 if (field->hdr->ops->field_changed)
800 field->hdr->ops->field_changed(field);
803 struct dev_io *proto_dev_get(void)
805 return ctx.dev;