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