1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2008 Everton da Silva Marques
10 #include <netinet/in.h>
12 #include <netinet/ip6.h>
15 #include "pim_jp_agg.h"
17 #define PIM_HDR_LEN sizeof(struct pim_msg_header)
20 ---------- ------------------
26 http://www.iana.org/assignments/address-family-numbers
28 enum pim_msg_address_family
{
29 PIM_MSG_ADDRESS_FAMILY_RESERVED
,
30 PIM_MSG_ADDRESS_FAMILY_IPV4
,
31 PIM_MSG_ADDRESS_FAMILY_IPV6
,
36 * =========================
37 * PIM Header definition as per RFC 5059. N bit introduced to indicate
38 * do-not-forward option in PIM Boot strap Message.
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 struct pim_msg_header
{
46 #if (BYTE_ORDER == LITTLE_ENDIAN)
50 uint8_t Nbit
: 1; /* No Fwd Bit */
51 #elif (BYTE_ORDER == BIG_ENDIAN)
54 uint8_t Nbit
: 1; /* No Fwd Bit */
57 #error"Please set byte order"
60 } __attribute__((packed
));
62 struct pim_encoded_ipv4_unicast
{
66 } __attribute__((packed
));
68 struct pim_encoded_ipv6_unicast
{
72 } __attribute__((packed
));
75 * Encoded Group format. RFC 4601 Sec 4.9.1
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+...
84 struct pim_encoded_group_ipv4
{
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)
92 uint8_t bidir
: 1; /* Bidir bit */
93 uint8_t reserved
: 6; /* Reserved */
94 uint8_t sz
: 1; /* scope zone bit */
96 #error"Please set byte order"
100 } __attribute__((packed
));
102 struct pim_encoded_group_ipv6
{
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 */
114 #error "Please set byte order"
117 struct in6_addr addr
;
118 } __attribute__((packed
));
121 * Encoded Source format. RFC 4601 Sec 4.9.1
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...
130 struct pim_encoded_source_ipv4
{
136 } __attribute__((packed
));
138 struct pim_encoded_source_ipv6
{
143 struct in6_addr addr
;
144 } __attribute__((packed
));
146 /* clang-format off */
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
;
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
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
;
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
164 /* clang-format on */
166 struct pim_jp_groups
{
170 pim_encoded_source s
[1];
171 } __attribute__((packed
));
174 struct pim_msg_header header
;
175 pim_encoded_unicast addr
;
179 struct pim_jp_groups groups
[1];
180 } __attribute__((packed
));
183 static inline pim_sgaddr
pim_sgaddr_from_iphdr(const void *iphdr
)
185 const struct ip
*ipv4_hdr
= iphdr
;
188 sg
.src
= ipv4_hdr
->ip_src
;
189 sg
.grp
= ipv4_hdr
->ip_dst
;
194 static inline pim_sgaddr
pim_sgaddr_from_iphdr(const void *iphdr
)
196 const struct ip6_hdr
*ipv6_hdr
= iphdr
;
199 sg
.src
= ipv6_hdr
->ip6_src
;
200 sg
.grp
= ipv6_hdr
->ip6_dst
;
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
,
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
);
212 #define PIM_ENCODE_SPARSE_BIT 0x04
213 #define PIM_ENCODE_WC_BIT 0x02
214 #define PIM_ENCODE_RPT_BIT 0x01
215 uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf
, struct in_addr addr
,
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
,
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
);
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
);
230 #endif /* PIM_MSG_H */