4 * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF")
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
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.
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
26 /* XXX: fix compilation error on Ubuntu 16.04 or older. */
29 #endif /* _UAPI_IPV6_H */
31 #include <linux/filter.h>
32 #include <linux/if_packet.h>
34 #include <netinet/if_ether.h>
37 #include <sys/ioctl.h>
41 /* Berkeley Packet filter code to filter out BFD Echo packets.
42 * tcpdump -dd "(udp dst port 3785)"
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},
55 /* Berkeley Packet filter code to filter out BFD vxlan packets.
56 * tcpdump -dd "(udp dst port 4789)"
58 static struct sock_filter bfd_vxlan_filter
[] = {
59 {0x28, 0, 0, 0x0000000c}, {0x15, 0, 4, 0x000086dd},
60 {0x30, 0, 0, 0x00000014}, {0x15, 0, 11, 0x00000011},
61 {0x28, 0, 0, 0x00000038}, {0x15, 8, 9, 0x000012b5},
62 {0x15, 0, 8, 0x00000800}, {0x30, 0, 0, 0x00000017},
63 {0x15, 0, 6, 0x00000011}, {0x28, 0, 0, 0x00000014},
64 {0x45, 4, 0, 0x00001fff}, {0xb1, 0, 0, 0x0000000e},
65 {0x48, 0, 0, 0x00000010}, {0x15, 0, 1, 0x000012b5},
66 {0x6, 0, 0, 0x0000ffff}, {0x6, 0, 0, 0x00000000},
73 int ptm_bfd_fetch_ifindex(const char *ifname
)
77 if (strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
))
78 > sizeof(ifr
.ifr_name
))
79 log_error("interface-to-index: name truncated ('%s' -> '%s')",
80 ifr
.ifr_name
, ifname
);
82 if (ioctl(bglobal
.bg_shop
, SIOCGIFINDEX
, &ifr
) == -1) {
83 log_error("interface-to-index: %s translation failed: %s",
84 ifname
, strerror(errno
));
88 return ifr
.ifr_ifindex
;
91 void ptm_bfd_fetch_local_mac(const char *ifname
, uint8_t *mac
)
95 if (strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
))
96 > sizeof(ifr
.ifr_name
))
97 log_error("interface-mac: name truncated ('%s' -> '%s')",
98 ifr
.ifr_name
, ifname
);
100 if (ioctl(bglobal
.bg_shop
, SIOCGIFHWADDR
, &ifr
) == -1) {
101 log_error("interface-mac: %s MAC retrieval failed: %s", ifname
,
106 memcpy(mac
, ifr
.ifr_hwaddr
.sa_data
, ETHERNET_ADDRESS_LENGTH
);
110 /* Was _fetch_portname_from_ifindex() */
111 void fetch_portname_from_ifindex(int ifindex
, char *ifname
, size_t ifnamelen
)
117 memset(&ifr
, 0, sizeof(ifr
));
118 ifr
.ifr_ifindex
= ifindex
;
120 if (ioctl(bglobal
.bg_shop
, SIOCGIFNAME
, &ifr
) == -1) {
121 log_error("index-to-interface: index %d failure: %s", ifindex
,
126 if (strlcpy(ifname
, ifr
.ifr_name
, ifnamelen
) >= ifnamelen
)
127 log_debug("index-to-interface: name truncated '%s' -> '%s'",
128 ifr
.ifr_name
, ifname
);
131 int ptm_bfd_echo_sock_init(void)
134 struct sock_fprog bpf
= {.len
= sizeof(bfd_echo_filter
)
135 / sizeof(bfd_echo_filter
[0]),
136 .filter
= bfd_echo_filter
};
138 s
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_IP
));
140 log_error("echo-socket: creation failure: %s", strerror(errno
));
144 if (setsockopt(s
, SOL_SOCKET
, SO_ATTACH_FILTER
, &bpf
, sizeof(bpf
))
146 log_error("echo-socket: setsockopt(SO_ATTACH_FILTER): %s",
155 int ptm_bfd_vxlan_sock_init(void)
158 struct sock_fprog bpf
= {.len
= sizeof(bfd_vxlan_filter
)
159 / sizeof(bfd_vxlan_filter
[0]),
160 .filter
= bfd_vxlan_filter
};
162 s
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_IP
));
164 log_error("vxlan-socket: creation failure: %s",
169 if (setsockopt(s
, SOL_SOCKET
, SO_ATTACH_FILTER
, &bpf
, sizeof(bpf
))
171 log_error("vxlan-socket: setsockopt(SO_ATTACH_FILTER): %s",
180 int bp_bind_dev(int sd
__attribute__((__unused__
)),
181 const char *dev
__attribute__((__unused__
)))
184 * TODO: implement this differently. It is not possible to
185 * SO_BINDTODEVICE after the daemon has dropped its privileges.
188 size_t devlen
= strlen(dev
) + 1;
190 if (setsockopt(sd
, SOL_SOCKET
, SO_BINDTODEVICE
, dev
, devlen
) == -1) {
191 log_warning("%s: setsockopt(SO_BINDTODEVICE, \"%s\"): %s",
192 __func__
, dev
, strerror(errno
));
200 uint16_t udp4_checksum(struct iphdr
*iph
, uint8_t *buf
, int len
)
203 struct udp_psuedo_header pudp_hdr
;
206 pudp_hdr
.saddr
= iph
->saddr
;
207 pudp_hdr
.daddr
= iph
->daddr
;
208 pudp_hdr
.reserved
= 0;
209 pudp_hdr
.protocol
= iph
->protocol
;
210 pudp_hdr
.len
= htons(len
);
212 ptr
= XMALLOC(MTYPE_BFDD_TMP
, UDP_PSUEDO_HDR_LEN
+ len
);
213 memcpy(ptr
, &pudp_hdr
, UDP_PSUEDO_HDR_LEN
);
214 memcpy(ptr
+ UDP_PSUEDO_HDR_LEN
, buf
, len
);
216 csum
= checksum((uint16_t *)ptr
, UDP_PSUEDO_HDR_LEN
+ len
);
217 XFREE(MTYPE_BFDD_TMP
, ptr
);
221 #endif /* BFD_LINUX */