2 * netsniff-ng - the packet sniffing beast
3 * Subject to the GPL, version 2.
8 #include <netinet/in.h>
9 #include <linux/if_ether.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)
29 static struct ctx ctx
;
31 static const struct proto_ops
*registered_ops
[__PROTO_MAX
];
33 struct packet
*proto_hdr_packet(struct proto_hdr
*hdr
)
35 return packet_get(hdr
->pkt_id
);
38 struct proto_hdr
*packet_last_header(struct packet
*pkt
)
40 struct proto_hdr
**headers
= &pkt
->headers
[0];
42 if (pkt
->headers_count
== 0)
45 return headers
[pkt
->headers_count
- 1];
48 struct proto_hdr
*proto_lower_header(struct proto_hdr
*hdr
)
50 struct packet
*pkt
= packet_get(hdr
->pkt_id
);
51 struct proto_hdr
**headers
= &pkt
->headers
[0];
56 return headers
[hdr
->index
- 1];
59 struct proto_hdr
*proto_upper_header(struct proto_hdr
*hdr
)
61 struct packet
*pkt
= packet_get(hdr
->pkt_id
);
62 struct proto_hdr
**headers
= &pkt
->headers
[0];
63 size_t headers_count
= pkt
->headers_count
;
65 if (hdr
->index
== headers_count
- 1)
68 return headers
[hdr
->index
+ 1];
71 uint8_t *proto_header_ptr(struct proto_hdr
*hdr
)
73 return &packet_get(hdr
->pkt_id
)->payload
[hdr
->pkt_offset
];
76 static const struct proto_ops
*proto_ops_by_id(enum proto_id id
)
78 const struct proto_ops
*ops
= registered_ops
[id
];
80 bug_on(ops
->id
!= id
);
84 void proto_ops_register(const struct proto_ops
*ops
)
86 bug_on(ops
->id
>= __PROTO_MAX
);
87 registered_ops
[ops
->id
] = ops
;
90 static void proto_fields_realloc(struct proto_hdr
*hdr
, size_t count
)
92 hdr
->fields
= xrealloc(hdr
->fields
, count
* sizeof(*hdr
->fields
));
93 hdr
->fields_count
= count
;
96 void proto_header_fields_add(struct proto_hdr
*hdr
,
97 const struct proto_field
*fields
, size_t count
)
99 struct packet
*pkt
= packet_get(hdr
->pkt_id
);
100 struct proto_field
*f
;
103 if (pkt
->headers_count
> 0) {
104 struct proto_hdr
*last
= packet_last_header(pkt
);
107 hdr
->pkt_offset
= last
->pkt_offset
+ last
->len
;
110 proto_fields_realloc(hdr
, hdr
->fields_count
+ count
);
112 for (i
= 0; count
>= 1; count
--, i
++) {
115 f
= &hdr
->fields
[hdr
->fields_count
- count
];
117 f
->id
= fields
[i
].id
;
118 f
->len
= fields
[i
].len
;
120 f
->shift
= fields
[i
].shift
;
121 f
->mask
= fields
[i
].mask
;
122 f
->pkt_offset
= hdr
->pkt_offset
+ fields
[i
].offset
;
128 fill_len
= (f
->pkt_offset
+ f
->len
) - (hdr
->pkt_offset
+ hdr
->len
);
130 if (!pkt
->is_created
)
131 set_fill(0, (f
->pkt_offset
+ f
->len
) - pkt
->len
);
138 struct proto_field
*proto_hdr_field_by_id(struct proto_hdr
*hdr
, uint32_t fid
)
140 /* Assume the fields are stored in the same order as the respective
141 * enum, so the index can be used for faster lookup here.
143 bug_on(hdr
->fields
[fid
].id
!= fid
);
145 return &hdr
->fields
[fid
];
148 bool proto_hdr_field_is_set(struct proto_hdr
*hdr
, uint32_t fid
)
150 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
152 return field
? field
->is_set
: false;
155 struct proto_hdr
*proto_packet_apply(enum proto_id pid
, struct packet
*pkt
)
157 struct proto_hdr
**headers
= &pkt
->headers
[0];
158 const struct proto_ops
*ops
= proto_ops_by_id(pid
);
159 struct proto_hdr
*hdr
;
161 bug_on(pkt
->headers_count
>= PROTO_MAX_LAYERS
);
163 hdr
= xzmalloc(sizeof(*hdr
));
165 hdr
->pkt_id
= pkt
->id
;
167 if (ops
&& ops
->header_init
)
168 ops
->header_init(hdr
);
170 /* This is very important to have it after header_init as
171 * pkt->headers_count might be changed by adding default lower headers */
172 hdr
->index
= pkt
->headers_count
;
174 headers
[pkt
->headers_count
++] = hdr
;
178 struct proto_hdr
*proto_header_push(enum proto_id pid
)
180 return proto_packet_apply(pid
, current_packet());
183 void proto_header_finish(struct proto_hdr
*hdr
)
185 if (hdr
&& hdr
->ops
&& hdr
->ops
->header_finish
)
186 hdr
->ops
->header_finish(hdr
);
189 enum proto_id
proto_hdr_get_next_proto(struct proto_hdr
*hdr
)
191 if (hdr
->ops
&& hdr
->ops
->get_next_proto
)
192 return hdr
->ops
->get_next_proto(hdr
);
197 struct proto_hdr
*proto_hdr_push_sub_header(struct proto_hdr
*hdr
, int id
)
199 struct proto_hdr
*sub_hdr
;
201 sub_hdr
= xzmalloc(sizeof(struct proto_hdr
));
202 sub_hdr
->index
= hdr
->sub_headers_count
;
203 sub_hdr
->parent
= hdr
;
206 hdr
->sub_headers_count
++;
207 hdr
->sub_headers
= xrealloc(hdr
->sub_headers
,
208 hdr
->sub_headers_count
* sizeof(struct proto_hdr
*));
210 hdr
->sub_headers
[hdr
->sub_headers_count
- 1] = sub_hdr
;
212 if (hdr
->ops
->push_sub_header
)
213 hdr
->ops
->push_sub_header(hdr
, sub_hdr
);
215 if (sub_hdr
->ops
->header_init
)
216 sub_hdr
->ops
->header_init(sub_hdr
);
221 static void __proto_hdr_set_offset(struct proto_hdr
*hdr
, uint16_t pkt_offset
)
225 hdr
->pkt_offset
= pkt_offset
;
227 for (i
= 0; i
< hdr
->fields_count
; i
++) {
228 struct proto_field
*f
= &hdr
->fields
[i
];
230 f
->pkt_offset
= pkt_offset
+ f
->offset
;
234 void proto_hdr_move_sub_header(struct proto_hdr
*hdr
, struct proto_hdr
*from
,
235 struct proto_hdr
*to
)
237 struct proto_hdr
*src_hdr
, *dst_hdr
, *tmp
;
238 uint8_t *src_ptr
, *dst_ptr
;
239 uint16_t to_pkt_offset
;
247 if (hdr
->sub_headers_count
< 2)
249 if (from
->index
== to
->index
)
252 buf
= xmemdupz(proto_header_ptr(from
), from
->len
);
254 to_pkt_offset
= to
->pkt_offset
;
255 to_index
= to
->index
;
257 if (from
->index
< to
->index
) {
258 src_hdr
= hdr
->sub_headers
[from
->index
+ 1];
261 src_ptr
= proto_header_ptr(src_hdr
);
262 dst_ptr
= proto_header_ptr(from
);
263 len
= (to
->pkt_offset
+ to
->len
) - src_hdr
->pkt_offset
;
265 pkt_offset
= from
->pkt_offset
;
269 dst_hdr
= hdr
->sub_headers
[from
->index
- 1];
271 src_ptr
= proto_header_ptr(src_hdr
);
272 dst_ptr
= src_ptr
+ from
->len
;
273 len
= from
->pkt_offset
- to
->pkt_offset
;
275 pkt_offset
= to
->pkt_offset
+ from
->len
;
279 hdr
->sub_headers
[from
->index
] = to
;
280 hdr
->sub_headers
[to
->index
] = from
;
282 for (i
= src_hdr
->index
; i
<= dst_hdr
->index
; i
++) {
283 tmp
= hdr
->sub_headers
[i
];
285 __proto_hdr_set_offset(tmp
, pkt_offset
);
286 pkt_offset
+= tmp
->len
;
289 for (i
= src_hdr
->index
; i
<= dst_hdr
->index
; i
++)
290 hdr
->sub_headers
[i
]->index
= i
+ idx_shift
;
292 memmove(dst_ptr
, src_ptr
, len
);
294 from
->pkt_offset
= to_pkt_offset
;
295 from
->index
= to_index
;
297 memcpy(proto_header_ptr(from
), buf
, from
->len
);
302 struct proto_hdr
*proto_lower_default_add(struct proto_hdr
*upper
,
305 struct packet
*pkt
= proto_hdr_packet(upper
);
306 size_t headers_count
= pkt
->headers_count
;
307 struct proto_hdr
*current
;
308 const struct proto_ops
*ops
;
310 if (headers_count
> 0) {
311 current
= pkt
->headers
[headers_count
- 1];
314 if (ops
->layer
>= proto_ops_by_id(pid
)->layer
)
320 current
= proto_header_push(pid
);
324 if (ops
&& ops
->set_next_proto
)
325 ops
->set_next_proto(current
, upper
->ops
->id
);
330 static void __proto_field_relocate(struct proto_field
*field
)
332 struct proto_hdr
*hdr
= field
->hdr
;
333 struct packet
*pkt
= packet_get(hdr
->pkt_id
);
337 /* If this is a last field then just calculate 'pkt_offset' */
338 if (field
->id
== hdr
->fields_count
- 1) {
339 field
->pkt_offset
= hdr
->pkt_offset
+ hdr
->len
- field
->len
;
343 /* Use 'pkt_offset' from the 1st real (len > 0) field after the
345 for (i
= field
->id
+ 1; i
< hdr
->fields_count
; i
++) {
346 if (hdr
->fields
[i
].len
== 0)
349 field
->pkt_offset
= hdr
->fields
[i
].pkt_offset
;
353 /* Move payload of overlapped fields (each after the 'target' field) */
354 from
= &pkt
->payload
[field
->pkt_offset
];
355 to
= &pkt
->payload
[field
->pkt_offset
+ field
->len
];
356 memcpy(to
, from
, hdr
->len
- field
->len
);
358 /* Recalculate 'pkt_offset' of the rest fields */
359 for (; i
< hdr
->fields_count
; i
++) {
360 struct proto_field
*tmp
= &hdr
->fields
[i
];
365 tmp
->pkt_offset
+= field
->len
;
369 static void __proto_field_set_bytes(struct proto_field
*field
,
370 const uint8_t *bytes
, size_t len
,
371 bool is_default
, bool is_be
)
373 uint8_t *payload
, *p8
;
380 if (is_default
&& field
->is_set
)
383 if (field
->len
== 0) {
384 field
->hdr
->len
+= len
;
388 __proto_field_relocate(field
);
391 payload
= &packet_get(field
->hdr
->pkt_id
)->payload
[field
->pkt_offset
];
393 if (field
->len
== 1) {
395 *p8
= field
->mask
? *p8
& ~field
->mask
: *p8
;
397 v8
= field_shift_and_mask(field
, *bytes
);
398 v8
= field
->mask
? (v8
| *p8
) : v8
;
401 } else if (field
->len
== 2) {
402 p16
= (uint16_t *)payload
;
403 *p16
= be16_to_cpu(*p16
);
404 *p16
= cpu_to_be16(field
->mask
? *p16
& ~field
->mask
: *p16
);
406 v16
= field_shift_and_mask(field
, *(const uint16_t *)bytes
);
407 v16
= is_be
? cpu_to_be16(v16
) : v16
;
408 v16
= field
->mask
? (v16
| *p16
) : v16
;
410 bytes
= (uint8_t *)&v16
;
411 } else if (field
->len
== 4) {
412 p32
= (uint32_t *)payload
;
413 *p32
= be32_to_cpu(*p32
);
414 *p32
= cpu_to_be32(field
->mask
? *p32
& ~field
->mask
: *p32
);
416 v32
= field_shift_and_mask(field
, *(const uint32_t *)bytes
);
417 v32
= is_be
? cpu_to_be32(v32
) : v32
;
418 v32
= field
->mask
? (v32
| *p32
) : v32
;
420 bytes
= (uint8_t *)&v32
;
423 memcpy(payload
, bytes
, field
->len
);
426 field
->is_set
= true;
429 void proto_hdr_field_set_bytes(struct proto_hdr
*hdr
, uint32_t fid
,
430 const uint8_t *bytes
, size_t len
)
432 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
434 __proto_field_set_bytes(field
, bytes
, len
, false, false);
437 static uint8_t *__proto_field_get_bytes(struct proto_field
*field
)
439 return &packet_get(field
->hdr
->pkt_id
)->payload
[field
->pkt_offset
];
442 uint8_t *proto_hdr_field_get_bytes(struct proto_hdr
*hdr
, uint32_t fid
)
444 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
446 return __proto_field_get_bytes(field
);
449 void proto_hdr_field_set_u8(struct proto_hdr
*hdr
, uint32_t fid
, uint8_t val
)
451 proto_hdr_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, 1);
454 uint8_t proto_hdr_field_get_u8(struct proto_hdr
*hdr
, uint32_t fid
)
456 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
457 uint8_t val
= *__proto_field_get_bytes(field
);
459 return field_unmask_and_unshift(field
, val
);
462 void proto_hdr_field_set_u16(struct proto_hdr
*hdr
, uint32_t fid
, uint16_t val
)
464 proto_hdr_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, 2);
467 uint16_t proto_hdr_field_get_u16(struct proto_hdr
*hdr
, uint32_t fid
)
469 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
470 uint16_t val
= *(uint16_t *)__proto_field_get_bytes(field
);
472 return field_unmask_and_unshift(field
, be16_to_cpu(val
));
475 void proto_hdr_field_set_u32(struct proto_hdr
*hdr
, uint32_t fid
, uint32_t val
)
477 proto_hdr_field_set_bytes(hdr
, fid
, (uint8_t *)&val
, 4);
480 uint32_t proto_hdr_field_get_u32(struct proto_hdr
*hdr
, uint32_t fid
)
482 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
483 uint32_t val
= *(uint32_t *)__proto_field_get_bytes(field
);
485 return field_unmask_and_unshift(field
, be32_to_cpu(val
));
488 uint32_t proto_hdr_field_get_be32(struct proto_hdr
*hdr
, uint32_t fid
)
490 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
491 uint32_t val
= *(uint32_t *)__proto_field_get_bytes(field
);
493 return field_unmask_and_unshift(field
, val
);
496 void proto_hdr_field_set_default_bytes(struct proto_hdr
*hdr
, uint32_t fid
,
497 const uint8_t *bytes
, size_t len
)
499 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
501 __proto_field_set_bytes(field
, bytes
, len
, true, false);
504 void proto_hdr_field_set_default_u8(struct proto_hdr
*hdr
, uint32_t fid
, uint8_t val
)
506 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
508 __proto_field_set_bytes(field
, (uint8_t *)&val
, 1, true, false);
511 void proto_hdr_field_set_default_u16(struct proto_hdr
*hdr
, uint32_t fid
, uint16_t val
)
513 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
515 __proto_field_set_bytes(field
, (uint8_t *)&val
, 2, true, false);
518 void proto_hdr_field_set_default_u32(struct proto_hdr
*hdr
, uint32_t fid
, uint32_t val
)
520 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
522 __proto_field_set_bytes(field
, (uint8_t *)&val
, 4, true, false);
525 void proto_hdr_field_set_be16(struct proto_hdr
*hdr
, uint32_t fid
, uint16_t val
)
527 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
529 __proto_field_set_bytes(field
, (uint8_t *)&val
, 2, false, true);
532 void proto_hdr_field_set_be32(struct proto_hdr
*hdr
, uint32_t fid
, uint32_t val
)
534 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
536 __proto_field_set_bytes(field
, (uint8_t *)&val
, 4, false, true);
539 void proto_hdr_field_set_default_be16(struct proto_hdr
*hdr
, uint32_t fid
, uint16_t val
)
541 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
543 __proto_field_set_bytes(field
, (uint8_t *)&val
, 2, true, true);
546 void proto_hdr_field_set_default_be32(struct proto_hdr
*hdr
, uint32_t fid
, uint32_t val
)
548 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
550 __proto_field_set_bytes(field
, (uint8_t *)&val
, 4, true, true);
553 static void __proto_hdr_field_set_dev_mac(struct proto_hdr
*hdr
, uint32_t fid
,
556 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
557 uint8_t mac
[ETH_ALEN
];
560 if (proto_hdr_field_is_set(hdr
, fid
))
563 if (dev_io_is_netdev(ctx
.dev
)) {
564 ret
= device_hw_address(dev_io_name_get(ctx
.dev
), mac
, sizeof(mac
));
566 panic("Could not get device hw address\n");
568 __proto_field_set_bytes(field
, mac
, 6, is_default
, false);
572 void proto_hdr_field_set_dev_mac(struct proto_hdr
*hdr
, uint32_t fid
)
574 __proto_hdr_field_set_dev_mac(hdr
, fid
, false);
577 void proto_hdr_field_set_default_dev_mac(struct proto_hdr
*hdr
, uint32_t fid
)
579 __proto_hdr_field_set_dev_mac(hdr
, fid
, true);
582 static void __proto_hdr_field_set_dev_ipv4(struct proto_hdr
*hdr
, uint32_t fid
,
585 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
586 struct sockaddr_storage ss
= { };
587 struct sockaddr_in
*ss4
;
590 if (proto_hdr_field_is_set(hdr
, fid
))
593 if (dev_io_is_netdev(ctx
.dev
)) {
594 ret
= device_address(dev_io_name_get(ctx
.dev
), AF_INET
, &ss
);
596 fprintf(stderr
, "Warning: Could not get device IPv4 address for %s\n",
597 dev_io_name_get(ctx
.dev
));
601 ss4
= (struct sockaddr_in
*) &ss
;
602 __proto_field_set_bytes(field
, (uint8_t *)&ss4
->sin_addr
.s_addr
, 4, is_default
, false);
606 void proto_hdr_field_set_dev_ipv4(struct proto_hdr
*hdr
, uint32_t fid
)
608 __proto_hdr_field_set_dev_ipv4(hdr
, fid
, false);
611 void proto_hdr_field_set_default_dev_ipv4(struct proto_hdr
*hdr
, uint32_t fid
)
613 __proto_hdr_field_set_dev_ipv4(hdr
, fid
, true);
616 static void __proto_hdr_field_set_dev_ipv6(struct proto_hdr
*hdr
, uint32_t fid
,
619 struct proto_field
*field
= proto_hdr_field_by_id(hdr
, fid
);
620 struct sockaddr_storage ss
= { };
621 struct sockaddr_in6
*ss6
;
624 if (proto_hdr_field_is_set(hdr
, fid
))
627 if (dev_io_is_netdev(ctx
.dev
)) {
628 ret
= device_address(dev_io_name_get(ctx
.dev
), AF_INET6
, &ss
);
630 fprintf(stderr
, "Warning: Could not get device IPv6 address for %s\n",
631 dev_io_name_get(ctx
.dev
));
635 ss6
= (struct sockaddr_in6
*) &ss
;
636 __proto_field_set_bytes(field
, (uint8_t *)&ss6
->sin6_addr
.s6_addr
, 16, is_default
, false);
640 void proto_hdr_field_set_dev_ipv6(struct proto_hdr
*hdr
, uint32_t fid
)
642 __proto_hdr_field_set_dev_ipv6(hdr
, fid
, false);
645 void proto_hdr_field_set_default_dev_ipv6(struct proto_hdr
*hdr
, uint32_t fid
)
647 __proto_hdr_field_set_dev_ipv6(hdr
, fid
, true);
650 void proto_hdr_field_set_string(struct proto_hdr
*hdr
, uint32_t fid
, const char *str
)
652 proto_hdr_field_set_bytes(hdr
, fid
, (uint8_t *)str
, strlen(str
) + 1);
655 void proto_hdr_field_set_default_string(struct proto_hdr
*hdr
, uint32_t fid
, const char *str
)
657 proto_hdr_field_set_default_bytes(hdr
, fid
, (uint8_t *)str
, strlen(str
) + 1);
660 void proto_field_set_u8(struct proto_field
*field
, uint8_t val
)
662 __proto_field_set_bytes(field
, &val
, 1, false, false);
665 uint8_t proto_field_get_u8(struct proto_field
*field
)
667 uint8_t val
= *__proto_field_get_bytes(field
);
669 return field_unmask_and_unshift(field
, val
);
672 void proto_field_set_u16(struct proto_field
*field
, uint16_t val
)
674 __proto_field_set_bytes(field
, (uint8_t *)&val
, 2, false, false);
677 uint16_t proto_field_get_u16(struct proto_field
*field
)
679 uint16_t val
= *(uint16_t *)__proto_field_get_bytes(field
);
681 return field_unmask_and_unshift(field
, be16_to_cpu(val
));
684 void proto_field_set_u32(struct proto_field
*field
, uint32_t val
)
686 __proto_field_set_bytes(field
, (uint8_t *)&val
, 4, false, false);
689 uint32_t proto_field_get_u32(struct proto_field
*field
)
691 uint32_t val
= *(uint32_t *)__proto_field_get_bytes(field
);
693 return field_unmask_and_unshift(field
, be32_to_cpu(val
));
696 uint32_t proto_field_get_be32(struct proto_field
*field
)
698 uint32_t val
= *(uint32_t *)__proto_field_get_bytes(field
);
700 return field_unmask_and_unshift(field
, val
);
703 void proto_field_set_be16(struct proto_field
*field
, uint16_t val
)
705 __proto_field_set_bytes(field
, (uint8_t *)&val
, 2, false, true);
708 void proto_field_set_be32(struct proto_field
*field
, uint32_t val
)
710 __proto_field_set_bytes(field
, (uint8_t *)&val
, 4, false, true);
713 void proto_field_set_bytes(struct proto_field
*field
, const uint8_t *bytes
, size_t len
)
715 __proto_field_set_bytes(field
, bytes
, len
, false, false);
718 void proto_field_set_string(struct proto_field
*field
, const char *str
)
720 proto_field_set_bytes(field
, (uint8_t *)str
, strlen(str
) + 1);
723 void proto_field_set_default_string(struct proto_field
*field
, const char *str
)
725 __proto_field_set_bytes(field
, (uint8_t *)str
, strlen(str
) + 1, true, false);
728 void protos_init(struct dev_io
*dev
)
738 void proto_packet_update(uint32_t idx
)
740 struct packet
*pkt
= packet_get(idx
);
743 for (i
= pkt
->headers_count
- 1; i
>= 0; i
--) {
744 struct proto_hdr
*hdr
= pkt
->headers
[i
];
746 if (hdr
->ops
->packet_update
)
747 hdr
->ops
->packet_update(hdr
);
751 void proto_packet_finish(void)
753 struct proto_hdr
**headers
= current_packet()->headers
;
754 size_t headers_count
= current_packet()->headers_count
;
757 /* Go down from upper layers to do last calculations (checksum) */
758 for (i
= headers_count
- 1; i
>= 0; i
--) {
759 struct proto_hdr
*hdr
= headers
[i
];
760 const struct proto_ops
*ops
= hdr
->ops
;
762 if (ops
&& ops
->packet_finish
)
763 ops
->packet_finish(hdr
);
766 current_packet()->is_created
= true;
769 static inline uint32_t field_inc(struct proto_field
*field
)
771 uint32_t min
= field
->func
.min
;
772 uint32_t max
= field
->func
.max
;
773 uint32_t val
= field
->func
.val
;
774 uint32_t inc
= field
->func
.inc
;
777 next
= (val
+ inc
) % (max
+ 1);
778 field
->func
.val
= max(next
, min
);
783 static void field_inc_func(struct proto_field
*field
)
785 if (field
->len
== 1) {
786 proto_field_set_u8(field
, field_inc(field
));
787 } else if (field
->len
== 2) {
788 proto_field_set_be16(field
, field_inc(field
));
789 } else if (field
->len
== 4) {
790 proto_field_set_be32(field
, field_inc(field
));
791 } else if (field
->len
> 4) {
792 uint8_t *bytes
= __proto_field_get_bytes(field
);
794 bytes
+= field
->len
- 4;
796 *(uint32_t *)bytes
= bswap_32(field_inc(field
));
800 static inline uint32_t field_rand(struct proto_field
*field
)
802 return field
->func
.min
+ (rand() % ((field
->func
.max
- field
->func
.min
) + 1));
805 static void field_rnd_func(struct proto_field
*field
)
807 if (field
->len
== 1) {
808 proto_field_set_u8(field
, (uint8_t) field_rand(field
));
809 } else if (field
->len
== 2) {
810 proto_field_set_be16(field
, (uint16_t) field_rand(field
));
811 } else if (field
->len
== 4) {
812 proto_field_set_be32(field
, (uint32_t) field_rand(field
));
813 } else if (field
->len
> 4) {
814 uint8_t *bytes
= __proto_field_get_bytes(field
);
817 for (i
= 0; i
< field
->len
; i
++)
818 bytes
[i
] = (uint8_t) field_rand(field
);
822 void proto_field_func_add(struct proto_field
*field
,
823 struct proto_field_func
*func
)
827 field
->func
.update_field
= func
->update_field
;
828 field
->func
.type
= func
->type
;
829 field
->func
.max
= func
->max
?: UINT32_MAX
- 1;
830 field
->func
.min
= func
->min
;
831 field
->func
.inc
= func
->inc
;
833 if (func
->type
& PROTO_FIELD_FUNC_INC
) {
834 if (func
->type
& PROTO_FIELD_FUNC_MIN
)
835 field
->func
.val
= func
->min
;
836 else if (field
->len
== 1)
837 field
->func
.val
= proto_field_get_u8(field
);
838 else if (field
->len
== 2)
839 field
->func
.val
= proto_field_get_u16(field
);
840 else if (field
->len
== 4)
841 field
->func
.val
= proto_field_get_u32(field
);
842 else if (field
->len
> 4) {
843 uint8_t *bytes
= __proto_field_get_bytes(field
);
845 bytes
+= field
->len
- 4;
846 field
->func
.val
= bswap_32(*(uint32_t *)bytes
);
849 field
->func
.update_field
= field_inc_func
;
850 } else if (func
->type
& PROTO_FIELD_FUNC_RND
) {
851 field
->func
.update_field
= field_rnd_func
;
855 void proto_field_dyn_apply(struct proto_field
*field
)
857 if (field
->func
.update_field
)
858 field
->func
.update_field(field
);
860 if (field
->hdr
->ops
->field_changed
)
861 field
->hdr
->ops
->field_changed(field
);
864 struct dev_io
*proto_dev_get(void)