]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
5435a2bf | 2 | /* |
63d4bd12 QY |
3 | * VRRP packet crafting. |
4 | * Copyright (C) 2018-2019 Cumulus Networks, Inc. | |
5 | * Quentin Young | |
5435a2bf | 6 | */ |
63d4bd12 QY |
7 | #ifndef __VRRP_PACKET_H__ |
8 | #define __VRRP_PACKET_H__ | |
9 | ||
5435a2bf QY |
10 | #include <zebra.h> |
11 | ||
63d4bd12 QY |
12 | #include "lib/ipaddr.h" |
13 | #include "lib/memory.h" | |
14 | #include "lib/prefix.h" | |
5435a2bf | 15 | |
5435a2bf QY |
16 | #define VRRP_TYPE_ADVERTISEMENT 1 |
17 | ||
ef4cc1eb QY |
18 | /* |
19 | * Shared header for VRRPv2/v3 packets. | |
20 | */ | |
21 | struct vrrp_hdr { | |
3eca3857 QY |
22 | /* |
23 | * H L H L | |
24 | * 0000 0000 | |
25 | * ver type | |
26 | */ | |
27 | uint8_t vertype; | |
5435a2bf QY |
28 | uint8_t vrid; |
29 | uint8_t priority; | |
ef4cc1eb QY |
30 | uint8_t naddr; |
31 | union { | |
32 | struct { | |
33 | uint8_t auth_type; | |
34 | /* advertisement interval (in sec) */ | |
35 | uint8_t adver_int; | |
36 | } v2; | |
37 | struct { | |
3eca3857 QY |
38 | /* |
39 | * advertisement interval (in centiseconds) | |
40 | * H L H L | |
41 | * 0000 000000000000 | |
42 | * rsvd adver_int | |
43 | */ | |
44 | uint16_t adver_int; | |
ef4cc1eb QY |
45 | } v3; |
46 | }; | |
47 | uint16_t chksum; | |
91188ca6 QY |
48 | } __attribute__((packed)); |
49 | ||
50 | #define VRRP_HDR_SIZE sizeof(struct vrrp_hdr) | |
ef4cc1eb QY |
51 | |
52 | struct vrrp_pkt { | |
53 | struct vrrp_hdr hdr; | |
91188ca6 QY |
54 | /* |
55 | * When used, this is actually an array of one or the other, not an | |
56 | * array of union. If N v4 addresses are stored then | |
57 | * sizeof(addrs) == N * sizeof(struct in_addr). | |
c2034b25 QY |
58 | * |
59 | * Under v2, the last 2 entries in this array are the authentication | |
60 | * data fields. We don't support auth in v2 so these are always just 8 | |
61 | * bytes of 0x00. | |
91188ca6 | 62 | */ |
5435a2bf QY |
63 | union { |
64 | struct in_addr v4; | |
65 | struct in6_addr v6; | |
66 | } addrs[]; | |
91188ca6 QY |
67 | } __attribute__((packed)); |
68 | ||
c2034b25 | 69 | #define VRRP_PKT_SIZE(_f, _ver, _naddr) \ |
91188ca6 QY |
70 | ({ \ |
71 | size_t _asz = ((_f) == AF_INET) ? sizeof(struct in_addr) \ | |
72 | : sizeof(struct in6_addr); \ | |
c2034b25 QY |
73 | size_t _auth = 2 * sizeof(uint32_t) * (3 - (_ver)); \ |
74 | sizeof(struct vrrp_hdr) + (_asz * (_naddr)) + _auth; \ | |
91188ca6 QY |
75 | }) |
76 | ||
c2034b25 QY |
77 | #define VRRP_MIN_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 3, 1) |
78 | #define VRRP_MAX_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 2, 255) | |
79 | #define VRRP_MIN_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 3, 1) | |
80 | #define VRRP_MAX_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 3, 255) | |
91188ca6 QY |
81 | |
82 | #define VRRP_MIN_PKT_SIZE VRRP_MIN_PKT_SIZE_V4 | |
83 | #define VRRP_MAX_PKT_SIZE VRRP_MAX_PKT_SIZE_V6 | |
5435a2bf QY |
84 | |
85 | /* | |
d9e01e1c | 86 | * Builds a VRRP ADVERTISEMENT packet. |
3eca3857 QY |
87 | * |
88 | * pkt | |
89 | * Pointer to store pointer to result buffer in | |
90 | * | |
d9e01e1c QY |
91 | * src |
92 | * Source address packet will be transmitted from. This is needed to compute | |
93 | * the VRRP checksum. The returned packet must be sent in an IP datagram with | |
94 | * the source address equal to this field, or the checksum will be invalid. | |
95 | * | |
96 | * version | |
97 | * VRRP version; must be 2 or 3 | |
98 | * | |
3eca3857 QY |
99 | * vrid |
100 | * Virtual Router Identifier | |
101 | * | |
102 | * prio | |
103 | * Virtual Router Priority | |
104 | * | |
105 | * max_adver_int | |
106 | * time between ADVERTISEMENTs | |
107 | * | |
108 | * v6 | |
109 | * whether 'ips' is an array of v4 or v6 addresses | |
110 | * | |
111 | * numip | |
112 | * number of IPvX addresses in 'ips' | |
113 | * | |
114 | * ips | |
115 | * array of pointer to either struct in_addr (v6 = false) or struct in6_addr | |
116 | * (v6 = true) | |
5435a2bf | 117 | */ |
d9e01e1c QY |
118 | ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src, |
119 | uint8_t version, uint8_t vrid, uint8_t prio, | |
120 | uint16_t max_adver_int, uint8_t numip, | |
9f2379bd | 121 | struct ipaddr **ips, bool ipv4_ph); |
91188ca6 | 122 | |
7c136b08 DL |
123 | /* free memory allocated by vrrp_pkt_adver_build's pkt arg */ |
124 | void vrrp_pkt_free(struct vrrp_pkt *pkt); | |
125 | ||
91188ca6 | 126 | /* |
d9e01e1c | 127 | * Dumps a VRRP ADVERTISEMENT packet to a string. |
91188ca6 QY |
128 | * |
129 | * Currently only dumps the header. | |
130 | * | |
131 | * buf | |
132 | * Buffer to store string representation | |
133 | * | |
134 | * buflen | |
135 | * Size of buf | |
136 | * | |
137 | * pkt | |
138 | * Packet to dump to a string | |
139 | * | |
140 | * Returns: | |
141 | * # bytes written to buf | |
142 | */ | |
d9e01e1c | 143 | size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt); |
91188ca6 QY |
144 | |
145 | ||
146 | /* | |
147 | * Parses a VRRP packet, checking for illegal or invalid data. | |
148 | * | |
8cb3d803 QY |
149 | * This function parses both VRRPv2 and VRRPv3 packets. Which version is |
150 | * expected is determined by the version argument. For example, if version is 3 | |
151 | * and the received packet has version field 2 it will fail to parse. | |
152 | * | |
153 | * Note that this function only checks whether the packet itself is a valid | |
154 | * VRRP packet. It is up to the caller to validate whether the VRID is correct, | |
155 | * priority and timer values are correct, etc. | |
91188ca6 QY |
156 | * |
157 | * family | |
158 | * Address family of received packet | |
159 | * | |
8cb3d803 QY |
160 | * version |
161 | * VRRP version to use for validation | |
162 | * | |
91188ca6 QY |
163 | * m |
164 | * msghdr containing results of recvmsg() on VRRP router socket | |
165 | * | |
166 | * read | |
8cb3d803 | 167 | * Return value of recvmsg() on VRRP router socket; must be non-negative |
91188ca6 | 168 | * |
d04bb25a QY |
169 | * src |
170 | * Pointer to struct ipaddr to store address of datagram sender | |
171 | * | |
91188ca6 QY |
172 | * pkt |
173 | * Pointer to pointer to set to location of VRRP packet within buf | |
174 | * | |
175 | * errmsg | |
176 | * Buffer to store human-readable error message in case of error; may be | |
177 | * NULL, in which case no message will be stored | |
178 | * | |
179 | * errmsg_len | |
180 | * Size of errmsg | |
181 | * | |
182 | * Returns: | |
183 | * Size of VRRP packet, or -1 upon error | |
184 | */ | |
9f2379bd SY |
185 | ssize_t vrrp_pkt_parse_datagram(int family, int version, bool ipv4_ph, |
186 | struct msghdr *m, size_t read, | |
187 | struct ipaddr *src, struct vrrp_pkt **pkt, | |
188 | char *errmsg, size_t errmsg_len); | |
63d4bd12 QY |
189 | |
190 | #endif /* __VRRP_PACKET_H__ */ |