]>
Commit | Line | Data |
---|---|---|
5e5034b0 DL |
1 | /* |
2 | * MLD protocol definitions | |
3 | * Copyright (C) 2022 David Lamparter for NetDEF, Inc. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the Free | |
7 | * Software Foundation; either version 2 of the License, or (at your option) | |
8 | * any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
13 | * more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along | |
16 | * with this program; see the file COPYING; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | */ | |
19 | ||
20 | #ifndef _PIM6_MLD_PROTOCOL_H | |
21 | #define _PIM6_MLD_PROTOCOL_H | |
22 | ||
23 | #include <stdalign.h> | |
24 | #include <stdint.h> | |
25 | ||
26 | /* There is a struct icmp6_hdr provided by OS, but it includes 4 bytes of data. | |
27 | * Not helpful for us if we want to put the MLD struct after it. | |
28 | */ | |
29 | ||
30 | struct icmp6_plain_hdr { | |
31 | uint8_t icmp6_type; | |
32 | uint8_t icmp6_code; | |
33 | uint16_t icmp6_cksum; | |
34 | }; | |
35 | static_assert(sizeof(struct icmp6_plain_hdr) == 4, "struct mismatch"); | |
36 | static_assert(alignof(struct icmp6_plain_hdr) <= 4, "struct mismatch"); | |
37 | ||
38 | /* for MLDv1 query, report and leave all use the same packet format */ | |
39 | struct mld_v1_pkt { | |
40 | uint16_t max_resp_code; | |
41 | uint16_t rsvd0; | |
42 | struct in6_addr grp; | |
43 | }; | |
44 | static_assert(sizeof(struct mld_v1_pkt) == 20, "struct mismatch"); | |
45 | static_assert(alignof(struct mld_v1_pkt) <= 4, "struct mismatch"); | |
46 | ||
47 | ||
48 | struct mld_v2_query_hdr { | |
49 | uint16_t max_resp_code; | |
50 | uint16_t rsvd0; | |
51 | struct in6_addr grp; | |
52 | uint8_t flags; | |
53 | uint8_t qqic; | |
54 | uint16_t n_src; | |
55 | struct in6_addr srcs[0]; | |
56 | }; | |
57 | static_assert(sizeof(struct mld_v2_query_hdr) == 24, "struct mismatch"); | |
58 | static_assert(alignof(struct mld_v2_query_hdr) <= 4, "struct mismatch"); | |
59 | ||
60 | ||
61 | struct mld_v2_report_hdr { | |
62 | uint16_t rsvd; | |
63 | uint16_t n_records; | |
64 | }; | |
65 | static_assert(sizeof(struct mld_v2_report_hdr) == 4, "struct mismatch"); | |
66 | static_assert(alignof(struct mld_v2_report_hdr) <= 4, "struct mismatch"); | |
67 | ||
68 | ||
69 | struct mld_v2_rec_hdr { | |
70 | uint8_t type; | |
71 | uint8_t aux_len; | |
72 | uint16_t n_src; | |
73 | struct in6_addr grp; | |
74 | struct in6_addr srcs[0]; | |
75 | }; | |
76 | static_assert(sizeof(struct mld_v2_rec_hdr) == 20, "struct mismatch"); | |
77 | static_assert(alignof(struct mld_v2_rec_hdr) <= 4, "struct mismatch"); | |
78 | ||
79 | /* clang-format off */ | |
80 | enum icmp6_mld_type { | |
81 | ICMP6_MLD_QUERY = 130, | |
82 | ICMP6_MLD_V1_REPORT = 131, | |
83 | ICMP6_MLD_V1_DONE = 132, | |
84 | ICMP6_MLD_V2_REPORT = 143, | |
85 | }; | |
86 | ||
87 | enum mld_v2_rec_type { | |
88 | MLD_RECTYPE_IS_INCLUDE = 1, | |
89 | MLD_RECTYPE_IS_EXCLUDE = 2, | |
90 | MLD_RECTYPE_CHANGE_TO_INCLUDE = 3, | |
91 | MLD_RECTYPE_CHANGE_TO_EXCLUDE = 4, | |
92 | MLD_RECTYPE_ALLOW_NEW_SOURCES = 5, | |
93 | MLD_RECTYPE_BLOCK_OLD_SOURCES = 6, | |
94 | }; | |
95 | /* clang-format on */ | |
96 | ||
97 | /* helper functions */ | |
98 | ||
99 | static inline unsigned int mld_max_resp_decode(uint16_t wire) | |
100 | { | |
101 | uint16_t code = ntohs(wire); | |
102 | uint8_t exp; | |
103 | ||
104 | if (code < 0x8000) | |
105 | return code; | |
106 | exp = (code >> 12) & 0x7; | |
107 | return ((code & 0xfff) | 0x1000) << (exp + 3); | |
108 | } | |
109 | ||
110 | static inline uint16_t mld_max_resp_encode(uint32_t value) | |
111 | { | |
112 | uint16_t code; | |
113 | uint8_t exp; | |
114 | ||
115 | if (value < 0x8000) | |
116 | code = value; | |
117 | else { | |
118 | exp = 16 - __builtin_clz(value); | |
119 | code = (value >> (exp + 3)) & 0xfff; | |
120 | code |= 0x8000 | (exp << 12); | |
121 | } | |
122 | return htons(code); | |
123 | } | |
124 | ||
125 | #endif /* _PIM6_MLD_PROTOCOL_H */ |