]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
12e41d03 | 2 | /* |
896014f4 DL |
3 | * PIM for Quagga |
4 | * Copyright (C) 2008 Everton da Silva Marques | |
896014f4 | 5 | */ |
12e41d03 DL |
6 | |
7 | #ifndef PIM_MSG_H | |
8 | #define PIM_MSG_H | |
9 | ||
10 | #include <netinet/in.h> | |
d1fd950a MR |
11 | #if PIM_IPV == 6 |
12 | #include <netinet/ip6.h> | |
13 | #endif | |
12e41d03 | 14 | |
982bff89 | 15 | #include "pim_jp_agg.h" |
d57a8bbf | 16 | |
17 | #define PIM_HDR_LEN sizeof(struct pim_msg_header) | |
12e41d03 | 18 | /* |
d62a17ae | 19 | Number Description |
12e41d03 DL |
20 | ---------- ------------------ |
21 | 0 Reserved | |
22 | 1 IP (IP version 4) | |
23 | 2 IP6 (IP version 6) | |
24 | ||
25 | From: | |
26 | http://www.iana.org/assignments/address-family-numbers | |
27 | */ | |
34687162 | 28 | enum pim_msg_address_family { |
d62a17ae | 29 | PIM_MSG_ADDRESS_FAMILY_RESERVED, |
30 | PIM_MSG_ADDRESS_FAMILY_IPV4, | |
31 | PIM_MSG_ADDRESS_FAMILY_IPV6, | |
34687162 | 32 | }; |
12e41d03 | 33 | |
70ce34ae | 34 | /* |
be6a3245 | 35 | * pim_msg_hdr |
d57a8bbf | 36 | * ========================= |
37 | * PIM Header definition as per RFC 5059. N bit introduced to indicate | |
38 | * do-not-forward option in PIM Boot strap Message. | |
39 | * 0 1 2 3 | |
40 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
41 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
42 | * |PIM Ver| Type |N| Reserved | Checksum | | |
43 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
70ce34ae DS |
44 | */ |
45 | struct pim_msg_header { | |
be6a3245 | 46 | #if (BYTE_ORDER == LITTLE_ENDIAN) |
d62a17ae | 47 | uint8_t type : 4; |
48 | uint8_t ver : 4; | |
be6a3245 BA |
49 | uint8_t reserved : 7; |
50 | uint8_t Nbit : 1; /* No Fwd Bit */ | |
51 | #elif (BYTE_ORDER == BIG_ENDIAN) | |
52 | uint8_t ver : 4; | |
53 | uint8_t type : 4; | |
d57a8bbf | 54 | uint8_t Nbit : 1; /* No Fwd Bit */ |
55 | uint8_t reserved : 7; | |
be6a3245 BA |
56 | #else |
57 | #error"Please set byte order" | |
58 | #endif | |
d62a17ae | 59 | uint16_t checksum; |
60 | } __attribute__((packed)); | |
70ce34ae | 61 | |
74ac496f | 62 | struct pim_encoded_ipv4_unicast { |
d62a17ae | 63 | uint8_t family; |
64 | uint8_t reserved; | |
65 | struct in_addr addr; | |
66 | } __attribute__((packed)); | |
74ac496f | 67 | |
16763d77 DL |
68 | struct pim_encoded_ipv6_unicast { |
69 | uint8_t family; | |
70 | uint8_t reserved; | |
71 | struct in6_addr addr; | |
72 | } __attribute__((packed)); | |
73 | ||
71361a2c | 74 | /* |
75 | * Encoded Group format. RFC 4601 Sec 4.9.1 | |
76 | * 0 1 2 3 | |
77 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
78 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
79 | * | Addr Family | Encoding Type |B| Reserved |Z| Mask Len | | |
80 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
81 | * | Group multicast Address | |
82 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+... | |
83 | */ | |
74ac496f | 84 | struct pim_encoded_group_ipv4 { |
d62a17ae | 85 | uint8_t family; |
71361a2c | 86 | uint8_t ne; |
be6a3245 BA |
87 | #if (BYTE_ORDER == LITTLE_ENDIAN) |
88 | uint8_t sz : 1; /* scope zone bit */ | |
89 | uint8_t reserved : 6; /* Reserved */ | |
90 | uint8_t bidir : 1; /* Bidir bit */ | |
91 | #elif (BYTE_ORDER == BIG_ENDIAN) | |
d57a8bbf | 92 | uint8_t bidir : 1; /* Bidir bit */ |
93 | uint8_t reserved : 6; /* Reserved */ | |
94 | uint8_t sz : 1; /* scope zone bit */ | |
be6a3245 BA |
95 | #else |
96 | #error"Please set byte order" | |
97 | #endif | |
d62a17ae | 98 | uint8_t mask; |
99 | struct in_addr addr; | |
100 | } __attribute__((packed)); | |
74ac496f | 101 | |
16763d77 DL |
102 | struct pim_encoded_group_ipv6 { |
103 | uint8_t family; | |
104 | uint8_t ne; | |
105 | #if (BYTE_ORDER == LITTLE_ENDIAN) | |
106 | uint8_t sz : 1; /* scope zone bit */ | |
107 | uint8_t reserved : 6; /* Reserved */ | |
108 | uint8_t bidir : 1; /* Bidir bit */ | |
109 | #elif (BYTE_ORDER == BIG_ENDIAN) | |
110 | uint8_t bidir : 1; /* Bidir bit */ | |
111 | uint8_t reserved : 6; /* Reserved */ | |
112 | uint8_t sz : 1; /* scope zone bit */ | |
113 | #else | |
114 | #error "Please set byte order" | |
115 | #endif | |
116 | uint8_t mask; | |
117 | struct in6_addr addr; | |
118 | } __attribute__((packed)); | |
71361a2c | 119 | |
120 | /* | |
121 | * Encoded Source format. RFC 4601 Sec 4.9.1 | |
122 | * 0 1 2 3 | |
123 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
124 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
125 | * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len | | |
126 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
127 | * | Source Address | |
128 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-... | |
129 | */ | |
74ac496f | 130 | struct pim_encoded_source_ipv4 { |
d62a17ae | 131 | uint8_t family; |
71361a2c | 132 | uint8_t ne; |
d62a17ae | 133 | uint8_t bits; |
134 | uint8_t mask; | |
135 | struct in_addr addr; | |
136 | } __attribute__((packed)); | |
74ac496f | 137 | |
16763d77 DL |
138 | struct pim_encoded_source_ipv6 { |
139 | uint8_t family; | |
140 | uint8_t ne; | |
141 | uint8_t bits; | |
142 | uint8_t mask; | |
143 | struct in6_addr addr; | |
144 | } __attribute__((packed)); | |
145 | ||
146 | /* clang-format off */ | |
147 | #if PIM_IPV == 4 | |
148 | typedef struct pim_encoded_ipv4_unicast pim_encoded_unicast; | |
149 | typedef struct pim_encoded_group_ipv4 pim_encoded_group; | |
150 | typedef struct pim_encoded_source_ipv4 pim_encoded_source; | |
a5fa9822 | 151 | typedef struct ip ipv_hdr; |
152 | #define IPV_SRC(ip_hdr) ((ip_hdr))->ip_src | |
153 | #define IPV_DST(ip_hdr) ((ip_hdr))->ip_dst | |
154 | #define IPV_LEN(ip_hdr) ((ip_hdr))->ip_len | |
16763d77 DL |
155 | #else |
156 | typedef struct pim_encoded_ipv6_unicast pim_encoded_unicast; | |
157 | typedef struct pim_encoded_group_ipv6 pim_encoded_group; | |
158 | typedef struct pim_encoded_source_ipv6 pim_encoded_source; | |
a5fa9822 | 159 | typedef struct ip6_hdr ipv_hdr; |
160 | #define IPV_SRC(ip_hdr) ((ip_hdr))->ip6_src | |
161 | #define IPV_DST(ip_hdr) ((ip_hdr))->ip6_dst | |
162 | #define IPV_LEN(ip_hdr) ((ip_hdr))->ip6_plen | |
16763d77 DL |
163 | #endif |
164 | /* clang-format on */ | |
165 | ||
74ac496f | 166 | struct pim_jp_groups { |
16763d77 | 167 | pim_encoded_group g; |
d62a17ae | 168 | uint16_t joins; |
169 | uint16_t prunes; | |
16763d77 | 170 | pim_encoded_source s[1]; |
d62a17ae | 171 | } __attribute__((packed)); |
74ac496f DS |
172 | |
173 | struct pim_jp { | |
d62a17ae | 174 | struct pim_msg_header header; |
16763d77 | 175 | pim_encoded_unicast addr; |
d62a17ae | 176 | uint8_t reserved; |
177 | uint8_t num_groups; | |
178 | uint16_t holdtime; | |
179 | struct pim_jp_groups groups[1]; | |
180 | } __attribute__((packed)); | |
74ac496f | 181 | |
d1fd950a MR |
182 | #if PIM_IPV == 4 |
183 | static inline pim_sgaddr pim_sgaddr_from_iphdr(const void *iphdr) | |
184 | { | |
185 | const struct ip *ipv4_hdr = iphdr; | |
186 | pim_sgaddr sg; | |
187 | ||
188 | sg.src = ipv4_hdr->ip_src; | |
189 | sg.grp = ipv4_hdr->ip_dst; | |
190 | ||
191 | return sg; | |
192 | } | |
193 | #else | |
194 | static inline pim_sgaddr pim_sgaddr_from_iphdr(const void *iphdr) | |
195 | { | |
196 | const struct ip6_hdr *ipv6_hdr = iphdr; | |
197 | pim_sgaddr sg; | |
198 | ||
199 | sg.src = ipv6_hdr->ip6_src; | |
200 | sg.grp = ipv6_hdr->ip6_dst; | |
201 | ||
202 | return sg; | |
203 | } | |
204 | #endif | |
205 | ||
145e4c38 DL |
206 | void pim_msg_build_header(pim_addr src, pim_addr dst, uint8_t *pim_msg, |
207 | size_t pim_msg_size, uint8_t pim_msg_type, | |
208 | bool no_fwd); | |
f8e7d799 DS |
209 | uint8_t *pim_msg_addr_encode_ipv4_ucast(uint8_t *buf, struct in_addr addr); |
210 | uint8_t *pim_msg_addr_encode_ipv4_group(uint8_t *buf, struct in_addr addr); | |
984c84f4 DS |
211 | |
212 | #define PIM_ENCODE_SPARSE_BIT 0x04 | |
213 | #define PIM_ENCODE_WC_BIT 0x02 | |
214 | #define PIM_ENCODE_RPT_BIT 0x01 | |
d62a17ae | 215 | uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, struct in_addr addr, |
216 | uint8_t bits); | |
12e41d03 | 217 | |
16763d77 DL |
218 | uint8_t *pim_msg_addr_encode_ipv6_ucast(uint8_t *buf, struct in6_addr addr); |
219 | uint8_t *pim_msg_addr_encode_ipv6_group(uint8_t *buf, struct in6_addr addr); | |
220 | uint8_t *pim_msg_addr_encode_ipv6_source(uint8_t *buf, struct in6_addr addr, | |
221 | uint8_t bits); | |
222 | ||
223 | uint8_t *pim_msg_addr_encode_ucast(uint8_t *buf, pim_addr addr); | |
224 | uint8_t *pim_msg_addr_encode_group(uint8_t *buf, pim_addr addr); | |
225 | uint8_t *pim_msg_addr_encode_source(uint8_t *buf, pim_addr addr, uint8_t bits); | |
346cffe3 | 226 | |
d62a17ae | 227 | size_t pim_msg_get_jp_group_size(struct list *sources); |
228 | size_t pim_msg_build_jp_groups(struct pim_jp_groups *grp, | |
229 | struct pim_jp_agg_group *sgs, size_t size); | |
12e41d03 | 230 | #endif /* PIM_MSG_H */ |