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