|
60 | 60 | #include "sunatmpos.h"
|
61 | 61 | #include "pflog.h"
|
62 | 62 | #include "ppp.h"
|
| 63 | +#include "batadv_packet.h" |
| 64 | +#include "batadv_legacy_packet.h" |
63 | 65 | #include "pcap/sll.h"
|
64 | 66 | #include "pcap/ipnet.h"
|
65 | 67 | #include "arcnet.h"
|
@@ -9436,6 +9438,168 @@ gen_geneve(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
|
9436 | 9438 | return b1;
|
9437 | 9439 | }
|
9438 | 9440 |
|
| 9441 | +static struct block * |
| 9442 | +gen_batadv_check_version(compiler_state_t *cstate, struct block *b0, bpf_u_int32 version) |
| 9443 | +{ |
| 9444 | + struct block *b1; |
| 9445 | + |
| 9446 | + if (version > UINT8_MAX) |
| 9447 | + bpf_error(cstate, |
| 9448 | + "batman-adv compatibility version number %u unsupported", |
| 9449 | + version); |
| 9450 | + |
| 9451 | + b1 = gen_cmp(cstate, OR_LINKPL, 1, BPF_B, version); |
| 9452 | + gen_and(b0, b1); |
| 9453 | + |
| 9454 | + return b1; |
| 9455 | +} |
| 9456 | + |
| 9457 | +static struct block * |
| 9458 | +gen_batadv_check_type(compiler_state_t *cstate, struct block *b0, |
| 9459 | + bpf_u_int32 version, bpf_u_int32 type) |
| 9460 | +{ |
| 9461 | + struct block *b1; |
| 9462 | + |
| 9463 | + switch (version) { |
| 9464 | + case 14: |
| 9465 | + case 15: |
| 9466 | + if (type > UINT8_MAX) |
| 9467 | + bpf_error(cstate, |
| 9468 | + "batman-adv packet type %u unsupported for compatibility version %u", |
| 9469 | + type, version); |
| 9470 | + |
| 9471 | + b1 = gen_cmp(cstate, OR_LINKPL, 0, BPF_B, type); |
| 9472 | + gen_and(b0, b1); |
| 9473 | + b0 = b1; |
| 9474 | + |
| 9475 | + break; |
| 9476 | + default: |
| 9477 | + bpf_error(cstate, |
| 9478 | + "batman-adv compatibility version number %u unsupported", |
| 9479 | + version); |
| 9480 | + } |
| 9481 | + |
| 9482 | + return b0; |
| 9483 | +} |
| 9484 | + |
| 9485 | + |
| 9486 | +static void gen_batadv_push_offset(compiler_state_t *cstate, u_int offset) |
| 9487 | +{ |
| 9488 | + PUSH_LINKHDR(cstate, DLT_EN10MB, cstate->off_linkpl.is_variable, |
| 9489 | + cstate->off_linkpl.constant_part + cstate->off_nl + offset, |
| 9490 | + cstate->off_linkpl.reg); |
| 9491 | + |
| 9492 | + cstate->off_linktype.constant_part += cstate->off_linkhdr.constant_part; |
| 9493 | + cstate->off_linkpl.constant_part += cstate->off_linkhdr.constant_part; |
| 9494 | + |
| 9495 | + cstate->off_nl = 0; |
| 9496 | + cstate->off_nl_nosnap = 0; /* no 802.2 LLC */ |
| 9497 | +} |
| 9498 | + |
| 9499 | +static void |
| 9500 | +gen_batadv_offsets_v14(compiler_state_t *cstate, bpf_u_int32 type) |
| 9501 | +{ |
| 9502 | + size_t offset; |
| 9503 | + |
| 9504 | + switch (type) { |
| 9505 | + case BATADV_LEGACY_UNICAST: /* 0x03 */ |
| 9506 | + offset = sizeof(struct batadv_legacy_unicast_packet); |
| 9507 | + break; |
| 9508 | + case BATADV_LEGACY_BCAST: /* 0x04 */ |
| 9509 | + offset = sizeof(struct batadv_legacy_bcast_packet); |
| 9510 | + break; |
| 9511 | + case BATADV_LEGACY_UNICAST_FRAG: /* 0x06 */ |
| 9512 | + offset = sizeof(struct batadv_legacy_unicast_frag_packet); |
| 9513 | + break; |
| 9514 | + case BATADV_LEGACY_UNICAST_4ADDR: /* 0x09 */ |
| 9515 | + offset = sizeof(struct batadv_legacy_unicast_4addr_packet); |
| 9516 | + break; |
| 9517 | + case BATADV_LEGACY_CODED: /* 0x0a */ |
| 9518 | + offset = sizeof(struct batadv_legacy_coded_packet); |
| 9519 | + break; |
| 9520 | + default: |
| 9521 | + offset = 0; |
| 9522 | + } |
| 9523 | + |
| 9524 | + if (offset) |
| 9525 | + gen_batadv_push_offset(cstate, (u_int)offset); |
| 9526 | +} |
| 9527 | + |
| 9528 | +static void |
| 9529 | +gen_batadv_offsets_v15(compiler_state_t *cstate, bpf_u_int32 type) |
| 9530 | +{ |
| 9531 | + size_t offset; |
| 9532 | + |
| 9533 | + switch (type) { |
| 9534 | + case BATADV_BCAST: /* 0x01 */ |
| 9535 | + offset = sizeof(struct batadv_bcast_packet); |
| 9536 | + break; |
| 9537 | + case BATADV_CODED: /* 0x02 */ |
| 9538 | + offset = sizeof(struct batadv_coded_packet); |
| 9539 | + break; |
| 9540 | + case BATADV_UNICAST: /* 0x40 */ |
| 9541 | + offset = sizeof(struct batadv_unicast_packet); |
| 9542 | + break; |
| 9543 | + case BATADV_UNICAST_FRAG: /* 0x41 */ |
| 9544 | + offset = sizeof(struct batadv_frag_packet); |
| 9545 | + break; |
| 9546 | + case BATADV_UNICAST_4ADDR: /* 0x42 */ |
| 9547 | + offset = sizeof(struct batadv_unicast_4addr_packet); |
| 9548 | + break; |
| 9549 | + case BATADV_UNICAST_TVLV: |
| 9550 | + /* unsupported for now, needs variable offset to |
| 9551 | + * take tvlv_len into account |
| 9552 | + */ |
| 9553 | + /* fall through */ |
| 9554 | + default: |
| 9555 | + offset = 0; |
| 9556 | + } |
| 9557 | + |
| 9558 | + if (offset) |
| 9559 | + gen_batadv_push_offset(cstate, (u_int)offset); |
| 9560 | +} |
| 9561 | + |
| 9562 | +static void |
| 9563 | +gen_batadv_offsets(compiler_state_t *cstate, bpf_u_int32 version, bpf_u_int32 type) |
| 9564 | +{ |
| 9565 | + switch (version) { |
| 9566 | + case 14: |
| 9567 | + gen_batadv_offsets_v14(cstate, type); |
| 9568 | + break; |
| 9569 | + case 15: |
| 9570 | + gen_batadv_offsets_v15(cstate, type); |
| 9571 | + break; |
| 9572 | + default: |
| 9573 | + break; |
| 9574 | + } |
| 9575 | +} |
| 9576 | + |
| 9577 | +struct block * |
| 9578 | +gen_batadv(compiler_state_t *cstate, bpf_u_int32 version, int has_version, |
| 9579 | + bpf_u_int32 type, int has_type) |
| 9580 | +{ |
| 9581 | + struct block *b0; |
| 9582 | + |
| 9583 | + /* |
| 9584 | + * Catch errors reported by us and routines below us, and return NULL |
| 9585 | + * on an error. |
| 9586 | + */ |
| 9587 | + if (setjmp(cstate->top_ctx)) |
| 9588 | + return (NULL); |
| 9589 | + |
| 9590 | + b0 = gen_linktype(cstate, ETHERTYPE_BATMAN); |
| 9591 | + |
| 9592 | + if (has_version) |
| 9593 | + b0 = gen_batadv_check_version(cstate, b0, version); |
| 9594 | + |
| 9595 | + if (has_type) { |
| 9596 | + b0 = gen_batadv_check_type(cstate, b0, version, type); |
| 9597 | + gen_batadv_offsets(cstate, version, type); |
| 9598 | + } |
| 9599 | + |
| 9600 | + return b0; |
| 9601 | +} |
| 9602 | + |
9439 | 9603 | /* Check that the encapsulated frame has a link layer header
|
9440 | 9604 | * for Ethernet filters. */
|
9441 | 9605 | static struct block *
|
|
0 commit comments