]>
git.proxmox.com Git - mirror_frr.git/blob - vrrpd/vrrp_arp.c
4 * Copyright (C) 2001-2017 Alexandre Cassen
6 * Copyright (C) 2018 Cumulus Networks
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License along with
20 * this program; see the file COPYING; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <net/if_arp.h>
27 #include <linux/if_packet.h>
28 #include <netinet/if_ether.h>
31 #include "lib/linklist.h"
33 #include "lib/memory.h"
34 #include "lib/prefix.h"
40 * The size of the garp packet buffer should be the large enough to hold the
41 * largest arp packet to be sent + the size of the link layer header for the
42 * corresponding protocol. In this case we hardcode for Ethernet.
44 #define GARP_BUFFER_SIZE \
45 sizeof(struct ether_header) + sizeof(struct arphdr) + 2 * ETH_ALEN \
46 + 2 * sizeof(struct in_addr)
49 static int garp_fd
= -1;
51 /* Send the gratuitous ARP message */
52 static ssize_t
vrrp_send_garp(struct interface
*ifp
, uint8_t *buf
, ssize_t pack_len
)
54 struct sockaddr_ll sll
;
57 /* Build the dst device */
58 memset(&sll
, 0, sizeof(sll
));
59 sll
.sll_family
= AF_PACKET
;
60 sll
.sll_protocol
= ETH_P_ARP
;
61 sll
.sll_ifindex
= (int) ifp
->ifindex
;
62 sll
.sll_halen
= ifp
->hw_addr_len
;
63 memset(sll
.sll_addr
, 0xFF, ETH_ALEN
);
66 len
= sendto(garp_fd
, buf
, pack_len
, 0, (struct sockaddr
*)&sll
,
72 /* Build a gratuitous ARP message over a specific interface */
73 static ssize_t
vrrp_build_garp(uint8_t *buf
, struct interface
*ifp
,
78 if (ifp
->hw_addr_len
== 0)
81 /* Build Ethernet header */
82 struct ether_header
*eth
= (struct ether_header
*) buf
;
84 memset(eth
->ether_dhost
, 0xFF, ETH_ALEN
);
85 memcpy(eth
->ether_shost
, ifp
->hw_addr
, ETH_ALEN
);
86 eth
->ether_type
= htons(ETHERTYPE_ARP
);
88 /* Build ARP payload */
89 struct arphdr
*arph
= (struct arphdr
*) (buf
+ ETHER_HDR_LEN
);
91 arph
->ar_hrd
= htons(HWTYPE_ETHER
);
92 arph
->ar_pro
= htons(ETHERTYPE_IP
);
93 arph
->ar_hln
= ifp
->hw_addr_len
;
94 arph
->ar_pln
= sizeof(struct in_addr
);
95 arph
->ar_op
= htons(ARPOP_REQUEST
);
96 arp_ptr
= (uint8_t *)(arph
+ sizeof(struct arphdr
));
98 memcpy(arp_ptr
, ifp
->hw_addr
, ifp
->hw_addr_len
);
99 arp_ptr
+= ifp
->hw_addr_len
;
101 memcpy(arp_ptr
, &v4
, sizeof(struct in_addr
));
102 arp_ptr
+= sizeof(struct in_addr
);
103 /* Dest MAC: broadcast */
104 memset(arp_ptr
, 0xFF, ETH_ALEN
);
105 arp_ptr
+= ifp
->hw_addr_len
;
107 memcpy(arp_ptr
, &v4
, sizeof(struct in_addr
));
108 arp_ptr
+= sizeof(struct in_addr
);
110 return arp_ptr
- buf
;
113 void vrrp_garp_send(struct vrrp_vrouter
*vr
, struct in_addr
*v4
)
115 struct interface
*ifp
= vr
->ifp
;
116 uint8_t garpbuf
[GARP_BUFFER_SIZE
];
119 char astr
[INET_ADDRSTRLEN
];
121 /* If the interface doesn't support ARP, don't try sending */
122 if (ifp
->flags
& IFF_NOARP
) {
124 "Unable to send gratuitous ARP on %s; has IFF_NOARP\n",
130 garpbuf_len
= vrrp_build_garp(garpbuf
, ifp
, v4
);
133 inet_ntop(AF_INET
, v4
, astr
, sizeof(astr
));
134 zlog_info("Sending gratuitous ARP on %s for %s", ifp
->name
, astr
);
135 sent_len
= vrrp_send_garp(ifp
, garpbuf
, garpbuf_len
);
138 zlog_warn("Error sending gratuitous ARP on %s for %s",
142 void vrrp_garp_send_all(struct vrrp_vrouter
*vr
)
144 struct interface
*ifp
= vr
->ifp
;
146 /* If the interface doesn't support ARP, don't try sending */
147 if (ifp
->flags
& IFF_NOARP
) {
149 "Unable to send gratuitous ARP on %s; has IFF_NOARP\n",
157 for (ALL_LIST_ELEMENTS_RO(vr
->v4
, ln
, v4
))
158 vrrp_garp_send(vr
, v4
);
162 void vrrp_garp_init(void)
164 /* Create the socket descriptor */
165 /* FIXME: why ETH_P_RARP? */
167 frr_elevate_privs(&vrrp_privs
) {
168 garp_fd
= socket(PF_PACKET
, SOCK_RAW
| SOCK_CLOEXEC
,
173 zlog_info("Initialized gratuitous ARP socket");
175 perror("Error initializing gratuitous ARP socket");
176 zlog_err("Error initializing gratuitous ARP socket");
181 void vrrp_garp_fini(void)
187 bool vrrp_garp_is_init(void)