]> git.ipfire.org Git - thirdparty/bird.git/blame - sysdep/bsd/sysio.h
The generalized TTL security mechanism (RFC 5082) support.
[thirdparty/bird.git] / sysdep / bsd / sysio.h
CommitLineData
b1a1faba
OF
1/*
2 * BIRD Internet Routing Daemon -- NetBSD Multicasting and Network Includes
3 *
4 * (c) 2004 Ondrej Filip <feela@network.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9#ifdef IPV6
10
11static inline void
12set_inaddr(struct in6_addr * ia, ip_addr a)
13{
353729f5
OZ
14 ipa_hton(a);
15 memcpy(ia, &a, sizeof(a));
16}
17
18static inline void
19get_inaddr(ip_addr *a, struct in6_addr *ia)
20{
21 memcpy(a, ia, sizeof(*a));
22 ipa_ntoh(*a);
b1a1faba
OF
23}
24
e7b09e4a
OZ
25static inline char *
26sysio_bind_to_iface(sock *s)
27{
28 /* Unfortunately not available */
29 return NULL;
30}
31
32
b1a1faba
OF
33#else
34
35#include <net/if.h>
353729f5 36#include <net/if_dl.h>
b1a1faba
OF
37
38static inline void
39set_inaddr(struct in_addr * ia, ip_addr a)
40{
353729f5
OZ
41 ipa_hton(a);
42 memcpy(&ia->s_addr, &a, sizeof(a));
43}
44
45static inline void
46get_inaddr(ip_addr *a, struct in_addr *ia)
47{
48 memcpy(a, &ia->s_addr, sizeof(*a));
49 ipa_ntoh(*a);
b1a1faba
OF
50}
51
353729f5
OZ
52
53/* BSD Multicast handling for IPv4 */
54
b1a1faba 55static inline char *
f9c799a0 56sysio_setup_multicast(sock *s)
b1a1faba 57{
f9c799a0
OZ
58 struct in_addr m;
59 u8 zero = 0;
60 u8 ttl = s->ttl;
b1a1faba 61
f9c799a0
OZ
62 if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
63 return "IP_MULTICAST_LOOP";
b1a1faba 64
f9c799a0
OZ
65 if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
66 return "IP_MULTICAST_TTL";
67
68 /* This defines where should we send _outgoing_ multicasts */
69 set_inaddr(&m, s->iface->addr->ip);
70 if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
71 return "IP_MULTICAST_IF";
b1a1faba 72
b1a1faba
OF
73 return NULL;
74}
75
76
77static inline char *
f9c799a0 78sysio_join_group(sock *s, ip_addr maddr)
b1a1faba 79{
b1a1faba 80 struct ip_mreq mreq;
b1a1faba 81
e85bd57a 82 bzero(&mreq, sizeof(mreq));
b1a1faba 83 set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
f9c799a0 84 set_inaddr(&mreq.imr_multiaddr, maddr);
b1a1faba
OF
85
86 /* And this one sets interface for _receiving_ multicasts from */
f9c799a0 87 if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
b1a1faba 88 return "IP_ADD_MEMBERSHIP";
b1a1faba 89
f9c799a0
OZ
90 return NULL;
91}
b1a1faba 92
f9c799a0
OZ
93static inline char *
94sysio_leave_group(sock *s, ip_addr maddr)
95{
96 struct ip_mreq mreq;
b1a1faba 97
f9c799a0
OZ
98 bzero(&mreq, sizeof(mreq));
99 set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
100 set_inaddr(&mreq.imr_multiaddr, maddr);
101
102 /* And this one sets interface for _receiving_ multicasts from */
103 if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
104 return "IP_DROP_MEMBERSHIP";
b1a1faba
OF
105
106 return NULL;
107}
108
353729f5
OZ
109
110/* BSD RX/TX packet info handling for IPv4 */
111/* it uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
112
113#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_addr)) + CMSG_SPACE(sizeof(struct sockaddr_dl)))
114#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
115
116static char *
117sysio_register_cmsgs(sock *s)
118{
119 int ok = 1;
120 if (s->flags & SKF_LADDR_RX)
121 {
122 if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0)
123 return "IP_RECVDSTADDR";
124
125 if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &ok, sizeof(ok)) < 0)
126 return "IP_RECVIF";
127 }
128
129 return NULL;
130}
131
132static void
133sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
134{
135 struct cmsghdr *cm;
136
137 if (!(s->flags & SKF_LADDR_RX))
138 return;
139
140 s->laddr = IPA_NONE;
141 s->lifindex = 0;
142
143 for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
144 {
145 if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
146 {
147 struct in_addr *ra = (struct in_addr *) CMSG_DATA(cm);
148 get_inaddr(&s->laddr, ra);
149 }
150
151 if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF)
152 {
153 struct sockaddr_dl *ri = (struct sockaddr_dl *) CMSG_DATA(cm);
154 s->lifindex = ri->sdl_index;
155 }
156 }
157
158 // log(L_WARN "RX %I %d", s->laddr, s->lifindex);
159}
160
bed41728 161/* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
646b24d9 162/*
bed41728
OZ
163static void
164sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
353729f5
OZ
165{
166 struct cmsghdr *cm;
167 struct in_addr *sa;
168
169 if (!(s->flags & SKF_LADDR_TX))
bed41728
OZ
170 return;
171
172 msg->msg_control = cbuf;
173 msg->msg_controllen = cbuflen;
353729f5
OZ
174
175 if (s->iface)
176 {
177 struct in_addr m;
353729f5
OZ
178 set_inaddr(&m, s->saddr);
179 setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m));
180 }
181
182 cm = CMSG_FIRSTHDR(msg);
183 cm->cmsg_level = IPPROTO_IP;
184 cm->cmsg_type = IP_SENDSRCADDR;
185 cm->cmsg_len = CMSG_LEN(sizeof(*sa));
186
187 sa = (struct in_addr *) CMSG_DATA(cm);
188 set_inaddr(sa, s->saddr);
189
190 msg->msg_controllen = cm->cmsg_len;
191}
646b24d9 192*/
353729f5 193
b1a1faba 194#endif
2b70f074
OF
195
196
197#include <netinet/tcp.h>
198#ifndef TCP_KEYLEN_MAX
199#define TCP_KEYLEN_MAX 80
200#endif
201#ifndef TCP_SIG_SPI
202#define TCP_SIG_SPI 0x1000
203#endif
204
205/*
206 * FIXME: Passwords has to be set by setkey(8) command. This is the same
207 * behaviour like Quagga. We need to add code for SA/SP entries
208 * management.
209 */
210
211static int
212sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd)
213{
214 int enable = 0;
215 if (passwd)
216 {
217 int len = strlen(passwd);
218
219 enable = len ? TCP_SIG_SPI : 0;
220
221 if (len > TCP_KEYLEN_MAX)
222 {
223 log(L_ERR "MD5 password too long");
224 return -1;
225 }
226 }
227
228 int rv = setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable));
229
230 if (rv < 0)
231 {
232 if (errno == ENOPROTOOPT)
233 log(L_ERR "Kernel does not support TCP MD5 signatures");
234 else
235 log(L_ERR "sk_set_md5_auth_int: setsockopt: %m");
236 }
237
238 return rv;
239}
b1b19433
OZ
240
241
242#ifndef IPV6
243
244static int
245sk_set_min_ttl4(sock *s, int ttl)
246{
247 if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
248 {
249 if (errno == ENOPROTOOPT)
250 log(L_ERR "Kernel does not support IPv4 TTL security");
251 else
252 log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
253
254 return -1;
255 }
256
257 return 0;
258}
259
260#else
261
262static int
263sk_set_min_ttl6(sock *s, int ttl)
264{
265 log(L_ERR "IPv6 TTL security not supported");
266 return -1;
267}
268
269#endif
270