uint16_t mdiadv = r->vr->version == 3 ? r->master_adver_interval
: r->vr->advertisement_interval;
uint16_t skm = (r->vr->version == 3) ? r->master_adver_interval : 100;
+
r->skew_time = ((256 - r->vr->priority) * skm) / 256;
r->master_down_interval = 3 * mdiadv;
r->master_down_interval += r->skew_time;
{
struct ethaddr vmac4;
struct ethaddr vmac6;
+
vrrp_mac_set(&vmac4, 0, 0x00);
vrrp_mac_set(&vmac6, 1, 0x00);
#endif
/* Must have at least one VIP configured */
start = start && r->addrs->count > 0;
- whynot = (!start && !whynot) ? "No Virtual IP address configured" : NULL;
+ whynot =
+ (!start && !whynot) ? "No Virtual IP address configured" : NULL;
if (start)
vrrp_event(r, VRRP_EVENT_STARTUP);
else if (whynot)
start = start && CHECK_FLAG(r->mvl_ifp->flags, IFF_UP);
/* Macvlan interface must have a link local */
start = start && connected_get_linklocal(r->mvl_ifp);
- whynot = (!start && !whynot) ? "No link local address configured" : NULL;
+ whynot =
+ (!start && !whynot) ? "No link local address configured" : NULL;
/* Macvlan interface must have a v6 IP besides the link local */
start = start && (r->mvl_ifp->connected->count >= 2);
- whynot = (!start && !whynot) ? "No Virtual IP configured on macvlan device" : NULL;
+ whynot = (!start && !whynot)
+ ? "No Virtual IP configured on macvlan device"
+ : NULL;
#endif
/* Must have at least one VIP configured */
start = start && r->addrs->count > 0;
- whynot = (!start && !whynot) ? "No Virtual IP address configured" : NULL;
+ whynot =
+ (!start && !whynot) ? "No Virtual IP address configured" : NULL;
if (start)
vrrp_event(r, VRRP_EVENT_STARTUP);
else if (whynot)
if (!vrrp_is_owner(r->vr->ifp, ip) && r->is_owner) {
char ipbuf[INET6_ADDRSTRLEN];
+
inet_ntop(r->family, &ip->ip, ipbuf, sizeof(ipbuf));
zlog_err(
VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4)
{
struct ipaddr ip;
+
ip.ipa_type = IPADDR_V4;
ip.ipaddr_v4 = v4;
return vrrp_add_ip(vr->v4, &ip);
assert(vr->version != 2);
struct ipaddr ip;
+
ip.ipa_type = IPADDR_V6;
ip.ipaddr_v6 = v6;
return vrrp_add_ip(vr->v6, &ip);
int vrrp_del_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6)
{
struct ipaddr ip;
+
ip.ipa_type = IPADDR_V6;
ip.ipaddr_v6 = v6;
return vrrp_del_ip(vr->v6, &ip);
int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4)
{
struct ipaddr ip;
+
ip.ipa_type = IPADDR_V4;
ip.ipaddr_v4 = v4;
return vrrp_del_ip(vr->v4, &ip);
static void vrrp_router_addr_list_del_cb(void *val)
{
struct ipaddr *ip = val;
+
XFREE(MTYPE_VRRP_IP, ip);
}
{
/* Search for existing interface with computed MAC address */
struct interface **ifps;
+
size_t ifps_cnt = if_lookup_by_hwaddr(
r->vmac.octet, sizeof(r->vmac.octet), &ifps, VRF_DEFAULT);
*/
unsigned int candidates = 0;
struct interface *selection = NULL;
+
for (unsigned int i = 0; i < ifps_cnt; i++) {
if (ifps[i]->link_ifindex != r->vr->ifp->ifindex)
ifps[i] = NULL;
XFREE(MTYPE_TMP, ifps);
char ethstr[ETHER_ADDR_STRLEN];
+
prefix_mac2str(&r->vmac, ethstr, sizeof(ethstr));
assert(!!selection == !!candidates);
if (r->is_active)
vrrp_event(r, VRRP_EVENT_SHUTDOWN);
- if (r->sock_rx >= 0) {
+ if (r->sock_rx >= 0)
close(r->sock_rx);
- }
- if (r->sock_tx >= 0) {
+ if (r->sock_tx >= 0)
close(r->sock_tx);
- }
/* FIXME: also delete list elements */
list_delete(&r->addrs);
struct vrrp_vrouter *vrrp_lookup(struct interface *ifp, uint8_t vrid)
{
struct vrrp_vrouter vr;
+
vr.vrid = vrid;
vr.ifp = ifp;
struct listnode *ln;
struct connected *c = NULL;
+
for (ALL_LIST_ELEMENTS_RO(ifp->connected, ln, c))
if (c->address->family == r->family) {
if (r->family == AF_INET6
}
union sockunion su;
+
memset(&su, 0x00, sizeof(su));
switch (r->family) {
struct vrrp_pkt *pkt, size_t pktsize)
{
char sipstr[INET6_ADDRSTRLEN];
- ipaddr2str(src, sipstr, sizeof(sipstr));
char dipstr[INET6_ADDRSTRLEN];
+
+ ipaddr2str(src, sipstr, sizeof(sipstr));
ipaddr2str(&r->src, dipstr, sizeof(dipstr));
char dumpbuf[BUFSIZ];
+
vrrp_pkt_adver_dump(dumpbuf, sizeof(dumpbuf), pkt);
DEBUGD(&vrrp_dbg_proto,
VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
struct msghdr m;
struct iovec iov;
+
iov.iov_base = r->ibuf;
iov.iov_len = sizeof(r->ibuf);
m.msg_name = &sa;
if (r->sock_rx < 0 || r->sock_tx < 0) {
const char *rxtx = r->sock_rx < 0 ? "Rx" : "Tx";
+
zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
"Can't create VRRP %s socket",
r->vr->vrid, family2str(r->family), rxtx);
if (r->family == AF_INET) {
/* Set Tx socket to always Tx with TTL set to 255 */
int ttl = 255;
+
ret = setsockopt(r->sock_tx, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
sizeof(ttl));
if (ret < 0) {
/* Bind Rx socket to v4 multicast address */
struct sockaddr_in sa = {0};
+
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl(VRRP_MCASTV4_GROUP);
if (bind(r->sock_rx, (struct sockaddr *)&sa, sizeof(sa))) {
/* Join Rx socket to VRRP IPv4 multicast group */
struct connected *c = listhead(r->vr->ifp->connected)->data;
struct in_addr v4 = c->address->u.prefix4;
+
ret = setsockopt_ipv4_multicast(r->sock_rx, IP_ADD_MEMBERSHIP,
v4, htonl(VRRP_MCASTV4_GROUP),
r->vr->ifp->ifindex);
/* Set outgoing interface for advertisements */
struct ip_mreqn mreqn = {};
+
mreqn.imr_ifindex = r->mvl_ifp->ifindex;
ret = setsockopt(r->sock_tx, IPPROTO_IP, IP_MULTICAST_IF,
(void *)&mreqn, sizeof(mreqn));
/* Bind Rx socket to v6 multicast address */
struct sockaddr_in6 sa = {0};
+
sa.sin6_family = AF_INET6;
inet_pton(AF_INET6, VRRP_MCASTV6_GROUP_STR, &sa.sin6_addr);
if (bind(r->sock_rx, (struct sockaddr *)&sa, sizeof(sa))) {
/* Join VRRP IPv6 multicast group */
struct ipv6_mreq mreq;
+
inet_pton(AF_INET6, VRRP_MCASTV6_GROUP_STR,
&mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = r->vr->ifp->ifindex;
/* State machine ----------------------------------------------------------- */
-DEFINE_HOOK(vrrp_change_state_hook, (struct vrrp_router * r, int to), (r, to));
+DEFINE_HOOK(vrrp_change_state_hook, (struct vrrp_router *r, int to), (r, to));
/*
* Handle any necessary actions during state change to MASTER state.
/* Create socket */
if (r->sock_rx < 0 || r->sock_tx < 0) {
int ret = vrrp_socket(r);
+
if (ret < 0 || r->sock_tx < 0 || r->sock_rx < 0)
return ret;
}
/* Configure effective priority */
struct ipaddr *primary = (struct ipaddr *)listhead(r->addrs)->data;
-
char ipbuf[INET6_ADDRSTRLEN];
+
inet_ntop(r->family, &primary->ip.addr, ipbuf, sizeof(ipbuf));
if (r->vr->priority == VRRP_PRIO_MASTER
* in this function should be protected by a check that the interface
* is up.
*/
- if (if_is_operative(ifp)) {
+ if (if_is_operative(ifp))
vrrp_autoconfig_if_address_del(ifp);
- }
}
/* Other ------------------------------------------------------------------- */
for (ALL_LIST_ELEMENTS_RO(vr->v4->addrs, ipln, ip)) {
char ipbuf[INET6_ADDRSTRLEN];
+
ipaddr2str(ip, ipbuf, sizeof(ipbuf));
vty_out(vty, " vrrp %" PRIu8 " ip %s\n", vr->vrid,
ipbuf);
for (ALL_LIST_ELEMENTS_RO(vr->v6->addrs, ipln, ip)) {
char ipbuf[INET6_ADDRSTRLEN];
+
ipaddr2str(ip, ipbuf, sizeof(ipbuf));
vty_out(vty, " vrrp %" PRIu8 " ipv6 %s\n", vr->vrid,
ipbuf);
static unsigned int vrrp_hash_key(void *arg)
{
struct vrrp_vrouter *vr = arg;
-
char key[IFNAMSIZ + 64];
+
snprintf(key, sizeof(key), "%s@%" PRIu8, vr->ifp->name, vr->vrid);
return string_hash_make(key);
bool v6 = (src->ipa_type == IPADDR_V6);
uint16_t chksum_pre = pkt->hdr.chksum;
+
pkt->hdr.chksum = 0;
if (v6) {
struct ipv6_ph ph = {};
+
ph.src = src->ipaddr_v6;
inet_pton(AF_INET6, VRRP_MCASTV6_GROUP_STR, &ph.dst);
ph.ulpl = htons(pktsize);
chksum = in_cksum_with_ph6(&ph, pkt, pktsize);
} else if (!v6 && ((pkt->hdr.vertype >> 4) == 3)) {
struct ipv4_ph ph = {};
+
ph.src = src->ipaddr_v4;
inet_pton(AF_INET, VRRP_MCASTV4_GROUP_STR, &ph.dst);
ph.proto = 112;
assert(!(version == 2 && v6));
size_t pktsize = VRRP_PKT_SIZE(v6 ? AF_INET6 : AF_INET, version, numip);
+
*pkt = XCALLOC(MTYPE_VRRP_PKT, pktsize);
(*pkt)->hdr.vertype |= version << 4;
/* Extract source address */
struct sockaddr_in *sa = m->msg_name;
+
src->ipa_type = IPADDR_V4;
src->ipaddr_v4 = sa->sin_addr;
} else if (family == AF_INET6) {
struct cmsghdr *c;
+
for (c = CMSG_FIRSTHDR(m); c != NULL; CMSG_NXTHDR(m, c)) {
if (c->cmsg_level == IPPROTO_IPV6
&& c->cmsg_type == IPV6_HOPLIMIT)
VRRP_PKT_VCHECK(!!c, "IPv6 Hop Limit not received");
uint8_t *hoplimit = CMSG_DATA(c);
+
VRRP_PKT_VCHECK(*hoplimit == 255,
"IPv6 Hop Limit is %" PRIu8 "; should be 255",
*hoplimit);
/* Extract source address */
struct sockaddr_in6 *sa = m->msg_name;
+
src->ipa_type = IPADDR_V6;
memcpy(&src->ipaddr_v6, &sa->sin6_addr,
sizeof(struct in6_addr));
/* Version check */
uint8_t pktver = (*pkt)->hdr.vertype >> 4;
+
VRRP_PKT_VCHECK(pktver == version, "Bad version %u", pktver);
/* Checksum check */
uint16_t chksum = vrrp_pkt_checksum(*pkt, pktsize, src);
+
VRRP_PKT_VCHECK((*pkt)->hdr.chksum == chksum,
"Bad VRRP checksum %" PRIx16 "; should be %" PRIx16 "",
(*pkt)->hdr.chksum, chksum);
/* Exact size check */
size_t ves = VRRP_PKT_SIZE(family, pktver, (*pkt)->hdr.naddr);
+
VRRP_PKT_VCHECK(pktsize == ves, "Packet has incorrect # addresses%s",
pktver == 2 ? " or missing auth fields" : "");
/* Addresses check */
char vbuf[INET6_ADDRSTRLEN];
uint8_t *p = (uint8_t *)(*pkt)->addrs;
+
for (uint8_t i = 0; i < (*pkt)->hdr.naddr; i++) {
VRRP_PKT_VCHECK(inet_ntop(family, p, vbuf, sizeof(vbuf)),
"Bad IP address, #%" PRIu8, i);
(unsigned int)_vrid); \
return CMD_WARNING_CONFIG_FAILED; \
} \
- } while (0);
+ } while (0)
/* clang-format off */
bool activated = false;
bool failed = false;
int ret = CMD_SUCCESS;
+ int oldstate;
VROUTER_GET_VTY(vty, ifp, vrid, vr);
bool will_activate = (vr->v4->fsm.state == VRRP_STATE_INITIALIZE);
if (no) {
- int oldstate = vr->v4->fsm.state;
+ oldstate = vr->v4->fsm.state;
failed = vrrp_del_ipv4(vr, ip);
vrrp_check_start(vr);
deactivated = (vr->v4->fsm.state == VRRP_STATE_INITIALIZE
&& oldstate != VRRP_STATE_INITIALIZE);
} else {
- int oldstate = vr->v4->fsm.state;
+ oldstate = vr->v4->fsm.state;
failed = vrrp_add_ipv4(vr, ip);
vrrp_check_start(vr);
activated = (vr->v4->fsm.state != VRRP_STATE_INITIALIZE
bool activated = false;
bool failed = false;
int ret = CMD_SUCCESS;
+ int oldstate;
VROUTER_GET_VTY(vty, ifp, vrid, vr);
bool will_activate = (vr->v6->fsm.state == VRRP_STATE_INITIALIZE);
if (no) {
- int oldstate = vr->v6->fsm.state;
+ oldstate = vr->v6->fsm.state;
failed = vrrp_del_ipv6(vr, ipv6);
vrrp_check_start(vr);
deactivated = (vr->v6->fsm.state == VRRP_STATE_INITIALIZE
&& oldstate != VRRP_STATE_INITIALIZE);
} else {
- int oldstate = vr->v6->fsm.state;
+ oldstate = vr->v6->fsm.state;
failed = vrrp_add_ipv6(vr, ipv6);
vrrp_check_start(vr);
activated = (vr->v6->fsm.state != VRRP_STATE_INITIALIZE
ttable_add_row(tt, "%s|%u", "IPv4 Addresses", vr->v4->addrs->count);
char fill[35];
+
memset(fill, '.', sizeof(fill));
fill[sizeof(fill) - 1] = 0x00;
if (vr->v4->addrs->count) {
}
char *table = ttable_dump(tt, "\n");
+
vty_out(vty, "\n%s\n", table);
XFREE(MTYPE_TMP, table);
ttable_del(tt);