mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 15:36:25 +00:00
vrrpd: implement gratuitous ARP
Implement gratuitous ARP functionality. Ethernet only. Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
5435a2bf61
commit
41ee544212
@ -11,18 +11,20 @@ man8 += $(MANBUILD)/vrrpd.8
|
||||
endif
|
||||
|
||||
vrrpd_libvrrp_a_SOURCES = \
|
||||
vrrpd/vrrp_memory.c \
|
||||
vrrpd/vrrp_zebra.c \
|
||||
vrrpd/vrrp_vty.c \
|
||||
vrrpd/vrrp_packet.c \
|
||||
vrrpd/vrrp.c \
|
||||
vrrpd/vrrp_arp.c \
|
||||
vrrpd/vrrp_memory.c \
|
||||
vrrpd/vrrp_packet.c \
|
||||
vrrpd/vrrp_vty.c \
|
||||
vrrpd/vrrp_zebra.c \
|
||||
# end
|
||||
|
||||
noinst_HEADERS += \
|
||||
vrrpd/vrrp_memory.h \
|
||||
vrrpd/vrrp_zebra.h \
|
||||
vrrpd/vrrp_vty.h \
|
||||
vrrpd/vrrp.h \
|
||||
vrrpd/vrrp_arp.h \
|
||||
vrrpd/vrrp_memory.h \
|
||||
vrrpd/vrrp_vty.h \
|
||||
vrrpd/vrrp_zebra.h \
|
||||
# end
|
||||
|
||||
vrrpd/vrrp_vty_clippy.c: $(CLIPPY_DEPS)
|
||||
|
@ -17,6 +17,8 @@
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <zebra.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "if.h"
|
||||
#include "linklist.h"
|
||||
|
@ -17,8 +17,8 @@
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef __VRRP_H__
|
||||
#define __VRRP_H_
|
||||
#ifndef _VRRP_H
|
||||
#define _VRRP_H
|
||||
|
||||
#include <zebra.h>
|
||||
#include "linklist.h"
|
||||
@ -159,4 +159,4 @@ struct vrrp_vrouter *vrrp_lookup(uint8_t vrid);
|
||||
*/
|
||||
void vrrp_event(struct vrrp_vrouter *vr, int event);
|
||||
|
||||
#endif
|
||||
#endif /* _VRRP_H */
|
||||
|
180
vrrpd/vrrp_arp.c
Normal file
180
vrrpd/vrrp_arp.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* VRRP ARP primitives.
|
||||
*
|
||||
* Copyright (C) 2001-2017 Alexandre Cassen
|
||||
* Portions:
|
||||
* Copyright (C) 2018 Cumulus Networks
|
||||
* Quentin Young
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include <net/if_arp.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#include "lib/if.h"
|
||||
#include "lib/linklist.h"
|
||||
#include "lib/log.h"
|
||||
#include "lib/memory.h"
|
||||
#include "lib/prefix.h"
|
||||
|
||||
#include "vrrp.h"
|
||||
#include "vrrp_arp.h"
|
||||
|
||||
/*
|
||||
* The size of the garp packet buffer should be the large enough to hold the
|
||||
* largest arp packet to be sent + the size of the link layer header for the
|
||||
* corresponding protocol. In this case we hardcode for Ethernet.
|
||||
*/
|
||||
#define GARP_BUFFER_SIZE \
|
||||
sizeof(struct ether_header) + sizeof(struct arphdr) + 2 * ETH_ALEN \
|
||||
+ 2 * sizeof(struct in_addr)
|
||||
|
||||
/* static vars */
|
||||
static int garp_fd = -1;
|
||||
|
||||
/* Send the gratuitous ARP message */
|
||||
static ssize_t vrrp_send_garp(struct interface *ifp, uint8_t *buf, ssize_t pack_len)
|
||||
{
|
||||
struct sockaddr_ll sll;
|
||||
ssize_t len;
|
||||
|
||||
/* Build the dst device */
|
||||
memset(&sll, 0, sizeof(sll));
|
||||
sll.sll_family = AF_PACKET;
|
||||
sll.sll_protocol = ETH_P_ARP;
|
||||
sll.sll_ifindex = (int) ifp->ifindex;
|
||||
sll.sll_halen = ifp->hw_addr_len;
|
||||
memset(sll.sll_addr, 0xFF, ETH_ALEN);
|
||||
|
||||
/* Send packet */
|
||||
len = sendto(garp_fd, buf, pack_len, 0, (struct sockaddr *)&sll,
|
||||
sizeof(sll));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Build a gratuitous ARP message over a specific interface */
|
||||
static ssize_t vrrp_build_garp(uint8_t *buf, struct interface *ifp,
|
||||
struct in_addr *v4)
|
||||
{
|
||||
uint8_t *arp_ptr;
|
||||
|
||||
if (ifp->hw_addr_len == 0)
|
||||
return -1;
|
||||
|
||||
/* Build Ethernet header */
|
||||
struct ether_header *eth = (struct ether_header *) buf;
|
||||
|
||||
memset(eth->ether_dhost, 0xFF, ETH_ALEN);
|
||||
memcpy(eth->ether_shost, ifp->hw_addr, ETH_ALEN);
|
||||
eth->ether_type = htons(ETHERTYPE_ARP);
|
||||
|
||||
/* Build ARP payload */
|
||||
struct arphdr *arph = (struct arphdr *) (buf + ETHER_HDR_LEN);
|
||||
|
||||
arph->ar_hrd = htons(HWTYPE_ETHER);
|
||||
arph->ar_pro = htons(ETHERTYPE_IP);
|
||||
arph->ar_hln = ifp->hw_addr_len;
|
||||
arph->ar_pln = sizeof(struct in_addr);
|
||||
arph->ar_op = htons(ARPOP_REQUEST);
|
||||
arp_ptr = (uint8_t *)(arph + sizeof(struct arphdr));
|
||||
/* Source MAC: us */
|
||||
memcpy(arp_ptr, ifp->hw_addr, ifp->hw_addr_len);
|
||||
arp_ptr += ifp->hw_addr_len;
|
||||
/* Source IP: us */
|
||||
memcpy(arp_ptr, &v4, sizeof(struct in_addr));
|
||||
arp_ptr += sizeof(struct in_addr);
|
||||
/* Dest MAC: broadcast */
|
||||
memset(arp_ptr, 0xFF, ETH_ALEN);
|
||||
arp_ptr += ifp->hw_addr_len;
|
||||
/* Dest IP: us */
|
||||
memcpy(arp_ptr, &v4, sizeof(struct in_addr));
|
||||
arp_ptr += sizeof(struct in_addr);
|
||||
|
||||
return arp_ptr - buf;
|
||||
}
|
||||
|
||||
void vrrp_garp_send(struct vrrp_vrouter *vr, struct in_addr *v4)
|
||||
{
|
||||
struct interface *ifp = vr->ifp;
|
||||
uint8_t garpbuf[GARP_BUFFER_SIZE];
|
||||
ssize_t garpbuf_len;
|
||||
ssize_t sent_len;
|
||||
char astr[INET_ADDRSTRLEN];
|
||||
|
||||
/* If the interface doesn't support ARP, don't try sending */
|
||||
if (ifp->flags & IFF_NOARP) {
|
||||
zlog_warn(
|
||||
"Unable to send gratuitous ARP on %s; has IFF_NOARP\n",
|
||||
ifp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build garp */
|
||||
garpbuf_len = vrrp_build_garp(garpbuf, ifp, v4);
|
||||
|
||||
/* Send garp */
|
||||
inet_ntop(AF_INET, v4, astr, sizeof(astr));
|
||||
zlog_info("Sending gratuitous ARP on %s for %s", ifp->name, astr);
|
||||
sent_len = vrrp_send_garp(ifp, garpbuf, garpbuf_len);
|
||||
|
||||
if (sent_len < 0)
|
||||
zlog_warn("Error sending gratuitous ARP on %s for %s",
|
||||
ifp->name, astr);
|
||||
}
|
||||
|
||||
void vrrp_garp_send_all(struct vrrp_vrouter *vr)
|
||||
{
|
||||
struct interface *ifp = vr->ifp;
|
||||
|
||||
/* If the interface doesn't support ARP, don't try sending */
|
||||
if (ifp->flags & IFF_NOARP) {
|
||||
zlog_warn(
|
||||
"Unable to send gratuitous ARP on %s; has IFF_NOARP\n",
|
||||
ifp->name);
|
||||
return;
|
||||
}
|
||||
|
||||
struct listnode *ln;
|
||||
struct in_addr *v4;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(vr->v4, ln, v4))
|
||||
vrrp_garp_send(vr, v4);
|
||||
}
|
||||
|
||||
|
||||
void vrrp_garp_init(void)
|
||||
{
|
||||
/* Create the socket descriptor */
|
||||
/* FIXME: why ETH_P_RARP? */
|
||||
garp_fd = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC, htons(ETH_P_RARP));
|
||||
|
||||
if (garp_fd > 0)
|
||||
zlog_info("Initialized gratuitous ARP socket");
|
||||
else {
|
||||
zlog_err("Error initializing gratuitous ARP socket");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void vrrp_garp_fini(void)
|
||||
{
|
||||
close(garp_fd);
|
||||
garp_fd = -1;
|
||||
}
|
35
vrrpd/vrrp_arp.h
Normal file
35
vrrpd/vrrp_arp.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* VRRPD global definitions
|
||||
* Copyright (C) 2018 Cumulus Networks, Inc.
|
||||
* Quentin Young
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _VRRP_ARP_H
|
||||
#define _VRRP_ARP_H
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "vrrp.h"
|
||||
|
||||
/* FIXME: Use the kernel define for this */
|
||||
#define HWTYPE_ETHER 1
|
||||
|
||||
/* prototypes */
|
||||
extern void vrrp_garp_init(void);
|
||||
extern void vrrp_garp_fini(void);
|
||||
extern void vrrp_garp_send(struct vrrp_vrouter *vr, struct in_addr *v4);
|
||||
extern void vrrp_garp_send_all(struct vrrp_vrouter *vr);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user