1a9771948SGleb Smirnoff /* $OpenBSD: ip_carp.h,v 1.8 2004/07/29 22:12:15 mcbride Exp $ */ 2a9771948SGleb Smirnoff 3fe267a55SPedro F. Giffuni /*- 4fe267a55SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause 5fe267a55SPedro F. Giffuni * 6a9771948SGleb Smirnoff * Copyright (c) 2002 Michael Shalayeff. All rights reserved. 7a9771948SGleb Smirnoff * Copyright (c) 2003 Ryan McBride. All rights reserved. 8a9771948SGleb Smirnoff * 9a9771948SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 10a9771948SGleb Smirnoff * modification, are permitted provided that the following conditions 11a9771948SGleb Smirnoff * are met: 12a9771948SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 13a9771948SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 14a9771948SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 15a9771948SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 16a9771948SGleb Smirnoff * documentation and/or other materials provided with the distribution. 17a9771948SGleb Smirnoff * 18a9771948SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19a9771948SGleb Smirnoff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20a9771948SGleb Smirnoff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21a9771948SGleb Smirnoff * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 22a9771948SGleb Smirnoff * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23a9771948SGleb Smirnoff * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24a9771948SGleb Smirnoff * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25a9771948SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26a9771948SGleb Smirnoff * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27a9771948SGleb Smirnoff * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28a9771948SGleb Smirnoff * THE POSSIBILITY OF SUCH DAMAGE. 29a9771948SGleb Smirnoff */ 30a9771948SGleb Smirnoff 31a9771948SGleb Smirnoff #ifndef _IP_CARP_H 32a9771948SGleb Smirnoff #define _IP_CARP_H 33a9771948SGleb Smirnoff 34*37115154SKristof Provost #ifdef _KERNEL 35a9771948SGleb Smirnoff /* 36a9771948SGleb Smirnoff * The CARP header layout is as follows: 37a9771948SGleb Smirnoff * 38a9771948SGleb Smirnoff * 0 1 2 3 39a9771948SGleb Smirnoff * 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 40a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 41a9771948SGleb Smirnoff * |Version| Type | VirtualHostID | AdvSkew | Auth Len | 42a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 43a9771948SGleb Smirnoff * | Reserved | AdvBase | Checksum | 44a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 45a9771948SGleb Smirnoff * | Counter (1) | 46a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 47a9771948SGleb Smirnoff * | Counter (2) | 48a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 49a9771948SGleb Smirnoff * | SHA-1 HMAC (1) | 50a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51a9771948SGleb Smirnoff * | SHA-1 HMAC (2) | 52a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 53a9771948SGleb Smirnoff * | SHA-1 HMAC (3) | 54a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 55a9771948SGleb Smirnoff * | SHA-1 HMAC (4) | 56a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 57a9771948SGleb Smirnoff * | SHA-1 HMAC (5) | 58a9771948SGleb Smirnoff * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 59a9771948SGleb Smirnoff * 60a9771948SGleb Smirnoff */ 61a9771948SGleb Smirnoff 62a9771948SGleb Smirnoff struct carp_header { 63a9771948SGleb Smirnoff #if BYTE_ORDER == LITTLE_ENDIAN 64a9771948SGleb Smirnoff u_int8_t carp_type:4, 65a9771948SGleb Smirnoff carp_version:4; 66a9771948SGleb Smirnoff #endif 67a9771948SGleb Smirnoff #if BYTE_ORDER == BIG_ENDIAN 68a9771948SGleb Smirnoff u_int8_t carp_version:4, 69a9771948SGleb Smirnoff carp_type:4; 70a9771948SGleb Smirnoff #endif 71a9771948SGleb Smirnoff u_int8_t carp_vhid; /* virtual host id */ 72a9771948SGleb Smirnoff u_int8_t carp_advskew; /* advertisement skew */ 73a9771948SGleb Smirnoff u_int8_t carp_authlen; /* size of counter+md, 32bit chunks */ 74a9771948SGleb Smirnoff u_int8_t carp_pad1; /* reserved */ 75a9771948SGleb Smirnoff u_int8_t carp_advbase; /* advertisement interval */ 76a9771948SGleb Smirnoff u_int16_t carp_cksum; 77a9771948SGleb Smirnoff u_int32_t carp_counter[2]; 78a9771948SGleb Smirnoff unsigned char carp_md[20]; /* SHA1 HMAC */ 79a9771948SGleb Smirnoff } __packed; 80a9771948SGleb Smirnoff 81850adc0cSWarner Losh CTASSERT(sizeof(struct carp_header) == 36); 82*37115154SKristof Provost 83*37115154SKristof Provost /* 84*37115154SKristof Provost * The VRRPv3 header layout is as follows: 85*37115154SKristof Provost * See RFC9568, 5.1. VRRP Packet Format 86*37115154SKristof Provost * 87*37115154SKristof Provost * 0 1 2 3 88*37115154SKristof Provost * 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 89*37115154SKristof Provost * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 90*37115154SKristof Provost * |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr| 91*37115154SKristof Provost * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 92*37115154SKristof Provost * |(rsvd) | Max Adver Int | Checksum | 93*37115154SKristof Provost * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 94*37115154SKristof Provost * | | 95*37115154SKristof Provost * + + 96*37115154SKristof Provost * | IPvX Address(es) | 97*37115154SKristof Provost * + + 98*37115154SKristof Provost * + + 99*37115154SKristof Provost * + + 100*37115154SKristof Provost * + + 101*37115154SKristof Provost * | | 102*37115154SKristof Provost * + + 103*37115154SKristof Provost * | | 104*37115154SKristof Provost * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 105*37115154SKristof Provost * 106*37115154SKristof Provost */ 107*37115154SKristof Provost 108*37115154SKristof Provost struct vrrpv3_header { 109*37115154SKristof Provost #if BYTE_ORDER == LITTLE_ENDIAN 110*37115154SKristof Provost uint8_t vrrp_type:4, 111*37115154SKristof Provost vrrp_version:4; 112850adc0cSWarner Losh #endif 113*37115154SKristof Provost #if BYTE_ORDER == BIG_ENDIAN 114*37115154SKristof Provost uint8_t vrrp_version:4, 115*37115154SKristof Provost vrrp_type:4; 116*37115154SKristof Provost #endif 117*37115154SKristof Provost uint8_t vrrp_vrtid; 118*37115154SKristof Provost uint8_t vrrp_priority; 119*37115154SKristof Provost uint8_t vrrp_count_addr; 120*37115154SKristof Provost uint16_t vrrp_max_adver_int; 121*37115154SKristof Provost uint16_t vrrp_checksum; 122*37115154SKristof Provost } __packed; 123*37115154SKristof Provost 124*37115154SKristof Provost CTASSERT(sizeof(struct vrrpv3_header) == 8); 125*37115154SKristof Provost #endif /* _KERNEL */ 126850adc0cSWarner Losh 127a9771948SGleb Smirnoff #define CARP_DFLTTL 255 128a9771948SGleb Smirnoff 129a9771948SGleb Smirnoff /* carp_type */ 130a9771948SGleb Smirnoff #define CARP_ADVERTISEMENT 0x01 131a9771948SGleb Smirnoff 132a9771948SGleb Smirnoff #define CARP_KEY_LEN 20 /* a sha1 hash of a passphrase */ 133a9771948SGleb Smirnoff 134a9771948SGleb Smirnoff /* carp_advbase */ 135a9771948SGleb Smirnoff #define CARP_DFLTINTV 1 136a9771948SGleb Smirnoff 137*37115154SKristof Provost #define VRRP_TYPE_ADVERTISEMENT 0x01 138*37115154SKristof Provost #define VRRP_MAX_INTERVAL (0x1000 - 1) 139a9771948SGleb Smirnoff /* 140a9771948SGleb Smirnoff * Statistics. 141a9771948SGleb Smirnoff */ 142a9771948SGleb Smirnoff struct carpstats { 143a9771948SGleb Smirnoff uint64_t carps_ipackets; /* total input packets, IPv4 */ 144a9771948SGleb Smirnoff uint64_t carps_ipackets6; /* total input packets, IPv6 */ 145a9771948SGleb Smirnoff uint64_t carps_badif; /* wrong interface */ 146a9771948SGleb Smirnoff uint64_t carps_badttl; /* TTL is not CARP_DFLTTL */ 147a9771948SGleb Smirnoff uint64_t carps_hdrops; /* packets shorter than hdr */ 148a9771948SGleb Smirnoff uint64_t carps_badsum; /* bad checksum */ 149a9771948SGleb Smirnoff uint64_t carps_badver; /* bad (incl unsupp) version */ 150a9771948SGleb Smirnoff uint64_t carps_badlen; /* data length does not match */ 151a9771948SGleb Smirnoff uint64_t carps_badauth; /* bad authentication */ 152a9771948SGleb Smirnoff uint64_t carps_badvhid; /* bad VHID */ 153a9771948SGleb Smirnoff uint64_t carps_badaddrs; /* bad address list */ 154a9771948SGleb Smirnoff 155a9771948SGleb Smirnoff uint64_t carps_opackets; /* total output packets, IPv4 */ 156a9771948SGleb Smirnoff uint64_t carps_opackets6; /* total output packets, IPv6 */ 157a9771948SGleb Smirnoff uint64_t carps_onomem; /* no memory for an mbuf */ 158a9771948SGleb Smirnoff uint64_t carps_ostates; /* total state updates sent */ 159a9771948SGleb Smirnoff 160a9771948SGleb Smirnoff uint64_t carps_preempt; /* if enabled, preemptions */ 161a9771948SGleb Smirnoff }; 162a9771948SGleb Smirnoff 163a9771948SGleb Smirnoff /* 164a9771948SGleb Smirnoff * Configuration structure for SIOCSVH SIOCGVH 165a9771948SGleb Smirnoff */ 166a9771948SGleb Smirnoff struct carpreq { 16708b68b0eSGleb Smirnoff int carpr_count; 16808b68b0eSGleb Smirnoff int carpr_vhid; 16908b68b0eSGleb Smirnoff #define CARP_MAXVHID 255 170a9771948SGleb Smirnoff int carpr_state; 171a9771948SGleb Smirnoff #define CARP_STATES "INIT", "BACKUP", "MASTER" 172a9771948SGleb Smirnoff #define CARP_MAXSTATE 2 173a9771948SGleb Smirnoff int carpr_advskew; 174f08535f8SGleb Smirnoff #define CARP_MAXSKEW 240 175a9771948SGleb Smirnoff int carpr_advbase; 176a9771948SGleb Smirnoff unsigned char carpr_key[CARP_KEY_LEN]; 177a9771948SGleb Smirnoff }; 178a9771948SGleb Smirnoff #define SIOCSVH _IOWR('i', 245, struct ifreq) 179a9771948SGleb Smirnoff #define SIOCGVH _IOWR('i', 246, struct ifreq) 180a9771948SGleb Smirnoff 181*37115154SKristof Provost typedef enum carp_version { 182*37115154SKristof Provost CARP_VERSION_CARP = 2, 183*37115154SKristof Provost CARP_VERSION_VRRPv3 = 3, 184*37115154SKristof Provost } carp_version_t; 185*37115154SKristof Provost 186a9771948SGleb Smirnoff #ifdef _KERNEL 18708b68b0eSGleb Smirnoff int carp_ioctl(struct ifreq *, u_long, struct thread *); 18808b68b0eSGleb Smirnoff int carp_attach(struct ifaddr *, int); 189338e227aSLuiz Otavio O Souza void carp_detach(struct ifaddr *, bool); 19054bfbd51SWill Andrews void carp_carpdev_state(struct ifnet *); 19147e8d432SGleb Smirnoff int carp_output (struct ifnet *, struct mbuf *, 19247e8d432SGleb Smirnoff const struct sockaddr *); 19324421c1cSGleb Smirnoff int carp_master(struct ifaddr *); 19408b68b0eSGleb Smirnoff int carp_iamatch(struct ifaddr *, uint8_t **); 19554bfbd51SWill Andrews struct ifaddr *carp_iamatch6(struct ifnet *, struct in6_addr *); 196dad68fc3SBjoern A. Zeeb char * carp_macmatch6(struct ifnet *, struct mbuf *, const struct in6_addr *); 19708b68b0eSGleb Smirnoff int carp_forus(struct ifnet *, u_char *); 1989963e8a5SWill Andrews 1999963e8a5SWill Andrews /* These are external networking stack hooks for CARP */ 2009963e8a5SWill Andrews /* net/if.c */ 20108b68b0eSGleb Smirnoff extern int (*carp_ioctl_p)(struct ifreq *, u_long, struct thread *); 20208b68b0eSGleb Smirnoff extern int (*carp_attach_p)(struct ifaddr *, int); 203338e227aSLuiz Otavio O Souza extern void (*carp_detach_p)(struct ifaddr *, bool); 2049963e8a5SWill Andrews extern void (*carp_linkstate_p)(struct ifnet *); 205f08535f8SGleb Smirnoff extern void (*carp_demote_adj_p)(int, char *); 20624421c1cSGleb Smirnoff extern int (*carp_master_p)(struct ifaddr *); 2079963e8a5SWill Andrews /* net/if_bridge.c net/if_ethersubr.c */ 20808b68b0eSGleb Smirnoff extern int (*carp_forus_p)(struct ifnet *, u_char *); 2099963e8a5SWill Andrews /* net/if_ethersubr.c */ 2109963e8a5SWill Andrews extern int (*carp_output_p)(struct ifnet *, struct mbuf *, 21147e8d432SGleb Smirnoff const struct sockaddr *); 21208b68b0eSGleb Smirnoff /* net/rtsock.c */ 21308b68b0eSGleb Smirnoff extern int (*carp_get_vhid_p)(struct ifaddr *); 2149963e8a5SWill Andrews #ifdef INET 2159963e8a5SWill Andrews /* netinet/if_ether.c */ 21608b68b0eSGleb Smirnoff extern int (*carp_iamatch_p)(struct ifaddr *, uint8_t **); 2179963e8a5SWill Andrews #endif 2189963e8a5SWill Andrews #ifdef INET6 2199963e8a5SWill Andrews /* netinet6/nd6_nbr.c */ 2209963e8a5SWill Andrews extern struct ifaddr *(*carp_iamatch6_p)(struct ifnet *, struct in6_addr *); 221dad68fc3SBjoern A. Zeeb extern char * (*carp_macmatch6_p)(struct ifnet *, struct mbuf *, 2229963e8a5SWill Andrews const struct in6_addr *); 2239963e8a5SWill Andrews #endif 224a9771948SGleb Smirnoff #endif 225a9771948SGleb Smirnoff #endif /* _IP_CARP_H */ 226