]> git.proxmox.com Git - mirror_frr.git/blob - bfdd/linux.c
bfdd: remove VxLAN code
[mirror_frr.git] / bfdd / linux.c
1 /*
2 * Linux specific code
3 *
4 * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF")
5 *
6 * FRR is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * FRR is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with FRR; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23
24 #ifdef BFD_LINUX
25
26 /* XXX: fix compilation error on Ubuntu 16.04 or older. */
27 #ifndef _UAPI_IPV6_H
28 #define _UAPI_IPV6_H
29 #endif /* _UAPI_IPV6_H */
30
31 #include <linux/filter.h>
32 #include <linux/if_packet.h>
33
34 #include <netinet/if_ether.h>
35
36 #include <net/if.h>
37 #include <sys/ioctl.h>
38
39 #include "bfd.h"
40
41 /* Berkeley Packet filter code to filter out BFD Echo packets.
42 * tcpdump -dd "(udp dst port 3785)"
43 */
44 static struct sock_filter bfd_echo_filter[] = {
45 {0x28, 0, 0, 0x0000000c}, {0x15, 0, 4, 0x000086dd},
46 {0x30, 0, 0, 0x00000014}, {0x15, 0, 11, 0x00000011},
47 {0x28, 0, 0, 0x00000038}, {0x15, 8, 9, 0x00000ec9},
48 {0x15, 0, 8, 0x00000800}, {0x30, 0, 0, 0x00000017},
49 {0x15, 0, 6, 0x00000011}, {0x28, 0, 0, 0x00000014},
50 {0x45, 4, 0, 0x00001fff}, {0xb1, 0, 0, 0x0000000e},
51 {0x48, 0, 0, 0x00000010}, {0x15, 0, 1, 0x00000ec9},
52 {0x6, 0, 0, 0x0000ffff}, {0x6, 0, 0, 0x00000000},
53 };
54
55
56 /*
57 * Definitions.
58 */
59 int ptm_bfd_fetch_ifindex(const char *ifname)
60 {
61 struct ifreq ifr;
62
63 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name))
64 > sizeof(ifr.ifr_name))
65 log_error("interface-to-index: name truncated ('%s' -> '%s')",
66 ifr.ifr_name, ifname);
67
68 if (ioctl(bglobal.bg_shop, SIOCGIFINDEX, &ifr) == -1) {
69 log_error("interface-to-index: %s translation failed: %s",
70 ifname, strerror(errno));
71 return -1;
72 }
73
74 return ifr.ifr_ifindex;
75 }
76
77 void ptm_bfd_fetch_local_mac(const char *ifname, uint8_t *mac)
78 {
79 struct ifreq ifr;
80
81 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name))
82 > sizeof(ifr.ifr_name))
83 log_error("interface-mac: name truncated ('%s' -> '%s')",
84 ifr.ifr_name, ifname);
85
86 if (ioctl(bglobal.bg_shop, SIOCGIFHWADDR, &ifr) == -1) {
87 log_error("interface-mac: %s MAC retrieval failed: %s", ifname,
88 strerror(errno));
89 return;
90 }
91
92 memcpy(mac, ifr.ifr_hwaddr.sa_data, ETHERNET_ADDRESS_LENGTH);
93 }
94
95
96 /* Was _fetch_portname_from_ifindex() */
97 void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen)
98 {
99 struct ifreq ifr;
100
101 ifname[0] = 0;
102
103 memset(&ifr, 0, sizeof(ifr));
104 ifr.ifr_ifindex = ifindex;
105
106 if (ioctl(bglobal.bg_shop, SIOCGIFNAME, &ifr) == -1) {
107 log_error("index-to-interface: index %d failure: %s", ifindex,
108 strerror(errno));
109 return;
110 }
111
112 if (strlcpy(ifname, ifr.ifr_name, ifnamelen) >= ifnamelen)
113 log_debug("index-to-interface: name truncated '%s' -> '%s'",
114 ifr.ifr_name, ifname);
115 }
116
117 int ptm_bfd_echo_sock_init(void)
118 {
119 int s;
120 struct sock_fprog bpf = {.len = sizeof(bfd_echo_filter)
121 / sizeof(bfd_echo_filter[0]),
122 .filter = bfd_echo_filter};
123
124 s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
125 if (s == -1) {
126 log_error("echo-socket: creation failure: %s", strerror(errno));
127 return -1;
128 }
129
130 if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))
131 == -1) {
132 log_error("echo-socket: setsockopt(SO_ATTACH_FILTER): %s",
133 strerror(errno));
134 close(s);
135 return -1;
136 }
137
138 return s;
139 }
140
141 int bp_bind_dev(int sd __attribute__((__unused__)),
142 const char *dev __attribute__((__unused__)))
143 {
144 /*
145 * TODO: implement this differently. It is not possible to
146 * SO_BINDTODEVICE after the daemon has dropped its privileges.
147 */
148 #if 0
149 size_t devlen = strlen(dev) + 1;
150
151 if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, dev, devlen) == -1) {
152 log_warning("%s: setsockopt(SO_BINDTODEVICE, \"%s\"): %s",
153 __func__, dev, strerror(errno));
154 return -1;
155 }
156 #endif
157
158 return 0;
159 }
160
161 uint16_t udp4_checksum(struct iphdr *iph, uint8_t *buf, int len)
162 {
163 char *ptr;
164 struct udp_psuedo_header pudp_hdr;
165 uint16_t csum;
166
167 pudp_hdr.saddr = iph->saddr;
168 pudp_hdr.daddr = iph->daddr;
169 pudp_hdr.reserved = 0;
170 pudp_hdr.protocol = iph->protocol;
171 pudp_hdr.len = htons(len);
172
173 ptr = XMALLOC(MTYPE_BFDD_TMP, UDP_PSUEDO_HDR_LEN + len);
174 memcpy(ptr, &pudp_hdr, UDP_PSUEDO_HDR_LEN);
175 memcpy(ptr + UDP_PSUEDO_HDR_LEN, buf, len);
176
177 csum = checksum((uint16_t *)ptr, UDP_PSUEDO_HDR_LEN + len);
178 XFREE(MTYPE_BFDD_TMP, ptr);
179 return csum;
180 }
181
182 #endif /* BFD_LINUX */