]> git.proxmox.com Git - mirror_frr.git/blame - nhrpd/linux.c
Merge pull request #11805 from opensourcerouting/fix/treat_as_withdraw_if_as_set
[mirror_frr.git] / nhrpd / linux.c
CommitLineData
2fb975da
TT
1/* NHRP daemon Linux specific glue
2 * Copyright (c) 2014-2015 Timo Teräs
3 *
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
372b8878 10#include "zebra.h"
5b4f4e62
DL
11
12#include <errno.h>
aea6c49e 13#include <linux/if_packet.h>
2fb975da
TT
14
15#include "nhrp_protocol.h"
16#include "os.h"
2fb975da 17
ca317495
RD
18#ifndef HAVE_STRLCPY
19size_t strlcpy(char *__restrict dest,
c2bb9917 20 const char *__restrict src, size_t destsize);
ca317495
RD
21#endif
22
2fb975da
TT
23static int nhrp_socket_fd = -1;
24
25int os_socket(void)
26{
27 if (nhrp_socket_fd < 0)
996c9314
LB
28 nhrp_socket_fd =
29 socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_NHRP));
2fb975da
TT
30 return nhrp_socket_fd;
31}
32
996c9314 33int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
fa31fcf2 34 size_t addrlen, uint16_t protocol)
2fb975da
TT
35{
36 struct sockaddr_ll lladdr;
37 struct iovec iov = {
996c9314 38 .iov_base = (void *)buf, .iov_len = len,
2fb975da
TT
39 };
40 struct msghdr msg = {
41 .msg_name = &lladdr,
42 .msg_namelen = sizeof(lladdr),
43 .msg_iov = &iov,
44 .msg_iovlen = 1,
45 };
f5a1fb4f 46 int status, fd;
2fb975da
TT
47
48 if (addrlen > sizeof(lladdr.sll_addr))
49 return -1;
50
51 memset(&lladdr, 0, sizeof(lladdr));
52 lladdr.sll_family = AF_PACKET;
fa31fcf2 53 lladdr.sll_protocol = htons(protocol);
2fb975da
TT
54 lladdr.sll_ifindex = ifindex;
55 lladdr.sll_halen = addrlen;
56 memcpy(lladdr.sll_addr, addr, addrlen);
57
f5a1fb4f
MS
58 fd = os_socket();
59 if (fd < 0)
60 return -1;
61
62 status = sendmsg(fd, &msg, 0);
2fb975da 63 if (status < 0)
fa31fcf2 64 return -errno;
2fb975da 65
fa31fcf2 66 return status;
2fb975da
TT
67}
68
996c9314
LB
69int os_recvmsg(uint8_t *buf, size_t *len, int *ifindex, uint8_t *addr,
70 size_t *addrlen)
2fb975da
TT
71{
72 struct sockaddr_ll lladdr;
73 struct iovec iov = {
996c9314 74 .iov_base = buf, .iov_len = *len,
2fb975da
TT
75 };
76 struct msghdr msg = {
77 .msg_name = &lladdr,
78 .msg_namelen = sizeof(lladdr),
79 .msg_iov = &iov,
80 .msg_iovlen = 1,
81 };
82 int r;
83
84 r = recvmsg(nhrp_socket_fd, &msg, MSG_DONTWAIT);
85 if (r < 0)
86 return r;
87
88 *len = r;
89 *ifindex = lladdr.sll_ifindex;
90
996c9314 91 if (*addrlen <= (size_t)lladdr.sll_addr) {
2fb975da
TT
92 if (memcmp(lladdr.sll_addr, "\x00\x00\x00\x00", 4) != 0) {
93 memcpy(addr, lladdr.sll_addr, lladdr.sll_halen);
94 *addrlen = lladdr.sll_halen;
95 } else {
96 *addrlen = 0;
97 }
98 }
99
100 return 0;
101}
102
103static int linux_configure_arp(const char *iface, int on)
104{
105 struct ifreq ifr;
106
ca317495 107 strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
2fb975da
TT
108 if (ioctl(nhrp_socket_fd, SIOCGIFFLAGS, &ifr))
109 return -1;
110
111 if (on)
112 ifr.ifr_flags &= ~IFF_NOARP;
113 else
114 ifr.ifr_flags |= IFF_NOARP;
115
116 if (ioctl(nhrp_socket_fd, SIOCSIFFLAGS, &ifr))
117 return -1;
118
119 return 0;
120}
121
122static int linux_icmp_redirect_off(const char *iface)
123{
2b7165e7 124 char fname[PATH_MAX];
2fb975da
TT
125 int fd, ret = -1;
126
772270f3
QY
127 snprintf(fname, sizeof(fname),
128 "/proc/sys/net/ipv4/conf/%s/send_redirects", iface);
2fb975da
TT
129 fd = open(fname, O_WRONLY);
130 if (fd < 0)
131 return -1;
132 if (write(fd, "0\n", 2) == 2)
133 ret = 0;
134 close(fd);
135
136 return ret;
137}
138
139int os_configure_dmvpn(unsigned int ifindex, const char *ifname, int af)
140{
896868a6 141 int ret = 0;
2fb975da
TT
142
143 switch (af) {
144 case AF_INET:
896868a6 145 ret |= linux_icmp_redirect_off("all");
2fb975da 146 ret |= linux_icmp_redirect_off(ifname);
2fb975da
TT
147 break;
148 }
896868a6 149 ret |= linux_configure_arp(ifname, 1);
2fb975da
TT
150
151 return ret;
152}