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},
59 int ptm_bfd_fetch_ifindex(const char *ifname
)
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
);
68 if (ioctl(bglobal
.bg_shop
, SIOCGIFINDEX
, &ifr
) == -1) {
69 log_error("interface-to-index: %s translation failed: %s",
70 ifname
, strerror(errno
));
74 return ifr
.ifr_ifindex
;
77 void ptm_bfd_fetch_local_mac(const char *ifname
, uint8_t *mac
)
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
);
86 if (ioctl(bglobal
.bg_shop
, SIOCGIFHWADDR
, &ifr
) == -1) {
87 log_error("interface-mac: %s MAC retrieval failed: %s", ifname
,
92 memcpy(mac
, ifr
.ifr_hwaddr
.sa_data
, ETHERNET_ADDRESS_LENGTH
);
96 /* Was _fetch_portname_from_ifindex() */
97 void fetch_portname_from_ifindex(int ifindex
, char *ifname
, size_t ifnamelen
)
103 memset(&ifr
, 0, sizeof(ifr
));
104 ifr
.ifr_ifindex
= ifindex
;
106 if (ioctl(bglobal
.bg_shop
, SIOCGIFNAME
, &ifr
) == -1) {
107 log_error("index-to-interface: index %d failure: %s", ifindex
,
112 if (strlcpy(ifname
, ifr
.ifr_name
, ifnamelen
) >= ifnamelen
)
113 log_debug("index-to-interface: name truncated '%s' -> '%s'",
114 ifr
.ifr_name
, ifname
);
117 int ptm_bfd_echo_sock_init(void)
120 struct sock_fprog bpf
= {.len
= sizeof(bfd_echo_filter
)
121 / sizeof(bfd_echo_filter
[0]),
122 .filter
= bfd_echo_filter
};
124 s
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_IP
));
126 log_error("echo-socket: creation failure: %s", strerror(errno
));
130 if (setsockopt(s
, SOL_SOCKET
, SO_ATTACH_FILTER
, &bpf
, sizeof(bpf
))
132 log_error("echo-socket: setsockopt(SO_ATTACH_FILTER): %s",
141 int bp_bind_dev(int sd
__attribute__((__unused__
)),
142 const char *dev
__attribute__((__unused__
)))
145 * TODO: implement this differently. It is not possible to
146 * SO_BINDTODEVICE after the daemon has dropped its privileges.
149 size_t devlen
= strlen(dev
) + 1;
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
));
161 uint16_t udp4_checksum(struct iphdr
*iph
, uint8_t *buf
, int len
)
164 struct udp_psuedo_header pudp_hdr
;
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
);
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
);
177 csum
= checksum((uint16_t *)ptr
, UDP_PSUEDO_HDR_LEN
+ len
);
178 XFREE(MTYPE_BFDD_TMP
, ptr
);
182 #endif /* BFD_LINUX */