Line data Source code
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 108 : static inline unsigned int mld_max_resp_decode(uint16_t wire)
100 : {
101 108 : uint16_t code = ntohs(wire);
102 108 : uint8_t exp;
103 :
104 108 : if (code < 0x8000)
105 108 : return code;
106 0 : exp = (code >> 12) & 0x7;
107 0 : return ((code & 0xfff) | 0x1000) << (exp + 3);
108 : }
109 :
110 72 : static inline uint16_t mld_max_resp_encode(uint32_t value)
111 : {
112 72 : uint16_t code;
113 72 : uint8_t exp;
114 :
115 72 : if (value < 0x8000)
116 72 : code = value;
117 : else {
118 0 : exp = 16 - __builtin_clz(value);
119 0 : code = (value >> (exp + 3)) & 0xfff;
120 0 : code |= 0x8000 | (exp << 12);
121 : }
122 72 : return htons(code);
123 : }
124 :
125 : #endif /* _PIM6_MLD_PROTOCOL_H */
|