1 /* 2 * VRRP packet crafting. 3 * Copyright (C) 2018-2019 Cumulus Networks, Inc. 4 * Quentin Young 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 */ 20 #ifndef __VRRP_PACKET_H__ 21 #define __VRRP_PACKET_H__ 22 23 #include <zebra.h> 24 25 #include "lib/ipaddr.h" 26 #include "lib/memory.h" 27 #include "lib/prefix.h" 28 29 #define VRRP_TYPE_ADVERTISEMENT 1 30 31 /* 32 * Shared header for VRRPv2/v3 packets. 33 */ 34 struct vrrp_hdr { 35 /* 36 * H L H L 37 * 0000 0000 38 * ver type 39 */ 40 uint8_t vertype; 41 uint8_t vrid; 42 uint8_t priority; 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 { 51 /* 52 * advertisement interval (in centiseconds) 53 * H L H L 54 * 0000 000000000000 55 * rsvd adver_int 56 */ 57 uint16_t adver_int; 58 } v3; 59 }; 60 uint16_t chksum; 61 } __attribute__((packed)); 62 63 #define VRRP_HDR_SIZE sizeof(struct vrrp_hdr) 64 65 struct vrrp_pkt { 66 struct vrrp_hdr hdr; 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). 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. 75 */ 76 union { 77 struct in_addr v4; 78 struct in6_addr v6; 79 } addrs[]; 80 } __attribute__((packed)); 81 82 #define VRRP_PKT_SIZE(_f, _ver, _naddr) \ 83 ({ \ 84 size_t _asz = ((_f) == AF_INET) ? sizeof(struct in_addr) \ 85 : sizeof(struct in6_addr); \ 86 size_t _auth = 2 * sizeof(uint32_t) * (3 - (_ver)); \ 87 sizeof(struct vrrp_hdr) + (_asz * (_naddr)) + _auth; \ 88 }) 89 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) 94 95 #define VRRP_MIN_PKT_SIZE VRRP_MIN_PKT_SIZE_V4 96 #define VRRP_MAX_PKT_SIZE VRRP_MAX_PKT_SIZE_V6 97 98 /* 99 * Builds a VRRP ADVERTISEMENT packet. 100 * 101 * pkt 102 * Pointer to store pointer to result buffer in 103 * 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 * 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) 130 */ 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); 135 136 /* free memory allocated by vrrp_pkt_adver_build's pkt arg */ 137 void vrrp_pkt_free(struct vrrp_pkt *pkt); 138 139 /* 140 * Dumps a VRRP ADVERTISEMENT packet to a string. 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 */ 156 size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt); 157 158 159 /* 160 * Parses a VRRP packet, checking for illegal or invalid data. 161 * 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. 169 * 170 * family 171 * Address family of received packet 172 * 173 * version 174 * VRRP version to use for validation 175 * 176 * m 177 * msghdr containing results of recvmsg() on VRRP router socket 178 * 179 * read 180 * Return value of recvmsg() on VRRP router socket; must be non-negative 181 * 182 * src 183 * Pointer to struct ipaddr to store address of datagram sender 184 * 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 */ 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); 202 203 #endif /* __VRRP_PACKET_H__ */ 204