]> git.proxmox.com Git - mirror_frr.git/blame - vrrpd/vrrp_arp.c
lib: Fix overlapping memory type
[mirror_frr.git] / vrrpd / vrrp_arp.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
41ee5442 2/*
63d4bd12 3 * VRRP ARP handling.
41ee5442
QY
4 * Copyright (C) 2001-2017 Alexandre Cassen
5 * Portions:
63d4bd12
QY
6 * Copyright (C) 2018-2019 Cumulus Networks, Inc.
7 * Quentin Young
41ee5442 8 */
41ee5442
QY
9#include <zebra.h>
10
41ee5442 11#include <linux/if_packet.h>
63d4bd12 12#include <net/if_arp.h>
41ee5442
QY
13#include <netinet/if_ether.h>
14
15#include "lib/if.h"
16#include "lib/linklist.h"
17#include "lib/log.h"
18#include "lib/memory.h"
19#include "lib/prefix.h"
20
21#include "vrrp.h"
22#include "vrrp_arp.h"
b637bcd4 23#include "vrrp_debug.h"
41ee5442 24
4ec94408
QY
25#define VRRP_LOGPFX "[ARP] "
26
41ee5442
QY
27/*
28 * The size of the garp packet buffer should be the large enough to hold the
29 * largest arp packet to be sent + the size of the link layer header for the
30 * corresponding protocol. In this case we hardcode for Ethernet.
31 */
32#define GARP_BUFFER_SIZE \
33 sizeof(struct ether_header) + sizeof(struct arphdr) + 2 * ETH_ALEN \
34 + 2 * sizeof(struct in_addr)
35
36/* static vars */
37static int garp_fd = -1;
38
39/* Send the gratuitous ARP message */
354b49d6
QY
40static ssize_t vrrp_send_garp(struct interface *ifp, uint8_t *buf,
41 ssize_t pack_len)
41ee5442
QY
42{
43 struct sockaddr_ll sll;
44 ssize_t len;
45
46 /* Build the dst device */
47 memset(&sll, 0, sizeof(sll));
48 sll.sll_family = AF_PACKET;
49 sll.sll_protocol = ETH_P_ARP;
354b49d6 50 sll.sll_ifindex = (int)ifp->ifindex;
41ee5442
QY
51 sll.sll_halen = ifp->hw_addr_len;
52 memset(sll.sll_addr, 0xFF, ETH_ALEN);
53
54 /* Send packet */
55 len = sendto(garp_fd, buf, pack_len, 0, (struct sockaddr *)&sll,
56 sizeof(sll));
57
58 return len;
59}
60
61/* Build a gratuitous ARP message over a specific interface */
62static ssize_t vrrp_build_garp(uint8_t *buf, struct interface *ifp,
63 struct in_addr *v4)
64{
65 uint8_t *arp_ptr;
66
67 if (ifp->hw_addr_len == 0)
68 return -1;
69
70 /* Build Ethernet header */
354b49d6 71 struct ether_header *eth = (struct ether_header *)buf;
41ee5442
QY
72
73 memset(eth->ether_dhost, 0xFF, ETH_ALEN);
74 memcpy(eth->ether_shost, ifp->hw_addr, ETH_ALEN);
75 eth->ether_type = htons(ETHERTYPE_ARP);
76
77 /* Build ARP payload */
354b49d6 78 struct arphdr *arph = (struct arphdr *)(buf + ETHER_HDR_LEN);
41ee5442
QY
79
80 arph->ar_hrd = htons(HWTYPE_ETHER);
81 arph->ar_pro = htons(ETHERTYPE_IP);
82 arph->ar_hln = ifp->hw_addr_len;
83 arph->ar_pln = sizeof(struct in_addr);
84 arph->ar_op = htons(ARPOP_REQUEST);
c23edd74 85 arp_ptr = (uint8_t *)(arph + 1);
41ee5442
QY
86 /* Source MAC: us */
87 memcpy(arp_ptr, ifp->hw_addr, ifp->hw_addr_len);
88 arp_ptr += ifp->hw_addr_len;
89 /* Source IP: us */
c23edd74 90 memcpy(arp_ptr, v4, sizeof(struct in_addr));
41ee5442
QY
91 arp_ptr += sizeof(struct in_addr);
92 /* Dest MAC: broadcast */
93 memset(arp_ptr, 0xFF, ETH_ALEN);
94 arp_ptr += ifp->hw_addr_len;
95 /* Dest IP: us */
c23edd74 96 memcpy(arp_ptr, v4, sizeof(struct in_addr));
41ee5442
QY
97 arp_ptr += sizeof(struct in_addr);
98
99 return arp_ptr - buf;
100}
101
862f2f37 102void vrrp_garp_send(struct vrrp_router *r, struct in_addr *v4)
41ee5442 103{
dad18a2f 104 struct interface *ifp = r->mvl_ifp;
41ee5442
QY
105 uint8_t garpbuf[GARP_BUFFER_SIZE];
106 ssize_t garpbuf_len;
107 ssize_t sent_len;
108 char astr[INET_ADDRSTRLEN];
109
110 /* If the interface doesn't support ARP, don't try sending */
111 if (ifp->flags & IFF_NOARP) {
112 zlog_warn(
613b45b0 113 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
ab059def 114 "Unable to send gratuitous ARP on %s; has IFF_NOARP",
613b45b0 115 r->vr->vrid, family2str(r->family), ifp->name);
41ee5442
QY
116 return;
117 }
118
119 /* Build garp */
120 garpbuf_len = vrrp_build_garp(garpbuf, ifp, v4);
121
ab059def
QY
122 if (garpbuf_len < 0) {
123 zlog_warn(
124 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
125 "Unable to send gratuitous ARP on %s; MAC address unknown",
126 r->vr->vrid, family2str(r->family), ifp->name);
127 return;
128 };
129
41ee5442
QY
130 /* Send garp */
131 inet_ntop(AF_INET, v4, astr, sizeof(astr));
b637bcd4
QY
132
133 DEBUGD(&vrrp_dbg_arp,
613b45b0 134 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
b637bcd4 135 "Sending gratuitous ARP on %s for %s",
613b45b0 136 r->vr->vrid, family2str(r->family), ifp->name, astr);
b637bcd4
QY
137 if (DEBUG_MODE_CHECK(&vrrp_dbg_arp, DEBUG_MODE_ALL))
138 zlog_hexdump(garpbuf, garpbuf_len);
139
41ee5442
QY
140 sent_len = vrrp_send_garp(ifp, garpbuf, garpbuf_len);
141
142 if (sent_len < 0)
613b45b0 143 zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
4ec94408 144 "Error sending gratuitous ARP on %s for %s",
613b45b0 145 r->vr->vrid, family2str(r->family), ifp->name, astr);
6332c77f
QY
146 else
147 ++r->stats.garp_tx_cnt;
41ee5442
QY
148}
149
862f2f37 150void vrrp_garp_send_all(struct vrrp_router *r)
41ee5442 151{
862f2f37
QY
152 assert(r->family == AF_INET);
153
dad18a2f 154 struct interface *ifp = r->mvl_ifp;
41ee5442
QY
155
156 /* If the interface doesn't support ARP, don't try sending */
157 if (ifp->flags & IFF_NOARP) {
158 zlog_warn(
613b45b0 159 VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
1d5453d6 160 "Unable to send gratuitous ARP on %s; has IFF_NOARP",
613b45b0 161 r->vr->vrid, family2str(r->family), ifp->name);
41ee5442
QY
162 return;
163 }
164
165 struct listnode *ln;
862f2f37 166 struct ipaddr *ip;
41ee5442 167
862f2f37
QY
168 for (ALL_LIST_ELEMENTS_RO(r->addrs, ln, ip))
169 vrrp_garp_send(r, &ip->ipaddr_v4);
41ee5442
QY
170}
171
172
173void vrrp_garp_init(void)
174{
175 /* Create the socket descriptor */
176 /* FIXME: why ETH_P_RARP? */
40744000 177 errno = 0;
0cf6db21 178 frr_with_privs(&vrrp_privs) {
40744000
QY
179 garp_fd = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC,
180 htons(ETH_P_RARP));
181 }
41ee5442 182
b637bcd4
QY
183 if (garp_fd > 0) {
184 DEBUGD(&vrrp_dbg_sock,
185 VRRP_LOGPFX "Initialized gratuitous ARP socket");
186 DEBUGD(&vrrp_dbg_arp,
187 VRRP_LOGPFX "Initialized gratuitous ARP subsystem");
188 } else {
4ec94408 189 zlog_err(VRRP_LOGPFX
b637bcd4 190 "Error initializing gratuitous ARP subsystem");
41ee5442
QY
191 }
192}
193
194void vrrp_garp_fini(void)
195{
196 close(garp_fd);
197 garp_fd = -1;
b637bcd4
QY
198
199 DEBUGD(&vrrp_dbg_arp,
200 VRRP_LOGPFX "Deinitialized gratuitous ARP subsystem");
41ee5442 201}
40744000
QY
202
203bool vrrp_garp_is_init(void)
204{
205 return garp_fd > 0;
206}