]> git.ipfire.org Git - thirdparty/bird.git/blame - sysdep/bsd/sysio.h
BGP: Support for MD5SIG together with remote range
[thirdparty/bird.git] / sysdep / bsd / sysio.h
CommitLineData
b1a1faba 1/*
05476c4d 2 * BIRD Internet Routing Daemon -- BSD Multicasting and Network Includes
b1a1faba
OF
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
05476c4d
OZ
9#include <net/if_dl.h>
10#include <netinet/in_systm.h> // Workaround for some BSDs
11#include <netinet/ip.h>
f6e6c3b5 12#include <sys/param.h>
05476c4d
OZ
13
14
318acb0f
OZ
15#ifdef __FreeBSD__
16/* Should be defined in sysdep/cf/bsd.h, but it is flavor-specific */
17#define CONFIG_DONTROUTE_UNICAST
18#endif
19
354496ac
OZ
20#ifdef __NetBSD__
21
22#ifndef IP_RECVTTL
23#define IP_RECVTTL 23
24#endif
25
26#ifndef IP_MINTTL
27#define IP_MINTTL 24
28#endif
29
30#endif
31
d760229a
OF
32#ifdef __DragonFly__
33#define TCP_MD5SIG TCP_SIGNATURE_ENABLE
34#endif
354496ac 35
b1a1faba 36
7eec3988 37#undef SA_LEN
05476c4d 38#define SA_LEN(x) (x).sa.sa_len
353729f5 39
b1a1faba 40
05476c4d
OZ
41/*
42 * BSD IPv4 multicast syscalls
43 */
353729f5 44
05476c4d 45#define INIT_MREQ4(maddr,ifa) \
153f02da 46 { .imr_multiaddr = ipa_to_in4(maddr), .imr_interface = ip4_to_in4(ifa->sysdep) }
353729f5 47
05476c4d
OZ
48static inline int
49sk_setup_multicast4(sock *s)
b1a1faba 50{
153f02da 51 struct in_addr ifa = ip4_to_in4(s->iface->sysdep);
05476c4d
OZ
52 u8 ttl = s->ttl;
53 u8 n = 0;
b1a1faba 54
05476c4d
OZ
55 /* This defines where should we send _outgoing_ multicasts */
56 if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &ifa, sizeof(ifa)) < 0)
57 ERR("IP_MULTICAST_IF");
b1a1faba 58
05476c4d
OZ
59 if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
60 ERR("IP_MULTICAST_TTL");
f9c799a0 61
05476c4d
OZ
62 if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
63 ERR("IP_MULTICAST_LOOP");
b1a1faba 64
05476c4d 65 return 0;
b1a1faba
OF
66}
67
05476c4d
OZ
68static inline int
69sk_join_group4(sock *s, ip_addr maddr)
b1a1faba 70{
05476c4d 71 struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
b1a1faba 72
05476c4d
OZ
73 if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
74 ERR("IP_ADD_MEMBERSHIP");
b1a1faba 75
05476c4d 76 return 0;
f9c799a0 77}
b1a1faba 78
05476c4d
OZ
79static inline int
80sk_leave_group4(sock *s, ip_addr maddr)
f9c799a0 81{
05476c4d 82 struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
b1a1faba 83
05476c4d
OZ
84 if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
85 ERR("IP_ADD_MEMBERSHIP");
f9c799a0 86
05476c4d 87 return 0;
b1a1faba
OF
88}
89
353729f5 90
05476c4d
OZ
91/*
92 * BSD IPv4 packet control messages
93 */
353729f5 94
05476c4d 95/* It uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
353729f5 96
05476c4d
OZ
97#define CMSG4_SPACE_PKTINFO (CMSG_SPACE(sizeof(struct in_addr)) + \
98 CMSG_SPACE(sizeof(struct sockaddr_dl)))
99#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(char))
70e212f9 100
05476c4d
OZ
101static inline int
102sk_request_cmsg4_pktinfo(sock *s)
103{
104 int y = 1;
70e212f9 105
05476c4d
OZ
106 if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &y, sizeof(y)) < 0)
107 ERR("IP_RECVDSTADDR");
353729f5 108
05476c4d
OZ
109 if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &y, sizeof(y)) < 0)
110 ERR("IP_RECVIF");
353729f5 111
05476c4d 112 return 0;
353729f5
OZ
113}
114
05476c4d
OZ
115static inline int
116sk_request_cmsg4_ttl(sock *s)
353729f5 117{
05476c4d 118 int y = 1;
70e212f9 119
05476c4d
OZ
120 if (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
121 ERR("IP_RECVTTL");
70e212f9 122
05476c4d
OZ
123 return 0;
124}
70e212f9 125
05476c4d
OZ
126static inline void
127sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
128{
129 if (cm->cmsg_type == IP_RECVDSTADDR)
130 s->laddr = ipa_from_in4(* (struct in_addr *) CMSG_DATA(cm));
353729f5 131
05476c4d
OZ
132 if (cm->cmsg_type == IP_RECVIF)
133 s->lifindex = ((struct sockaddr_dl *) CMSG_DATA(cm))->sdl_index;
353729f5
OZ
134}
135
05476c4d
OZ
136static inline void
137sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
138{
139 if (cm->cmsg_type == IP_RECVTTL)
e348ef01 140 s->rcv_ttl = * (byte *) CMSG_DATA(cm);
05476c4d 141}
48e5f32d 142
3e236955 143#ifdef IP_SENDSRCADDR
48e5f32d 144static inline void
05476c4d 145sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
353729f5 146{
05476c4d
OZ
147 /* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
148
353729f5
OZ
149 struct cmsghdr *cm;
150 struct in_addr *sa;
8945f73d 151 int controllen = 0;
353729f5 152
bed41728
OZ
153 msg->msg_control = cbuf;
154 msg->msg_controllen = cbuflen;
353729f5 155
353729f5
OZ
156 cm = CMSG_FIRSTHDR(msg);
157 cm->cmsg_level = IPPROTO_IP;
158 cm->cmsg_type = IP_SENDSRCADDR;
159 cm->cmsg_len = CMSG_LEN(sizeof(*sa));
8945f73d 160 controllen += CMSG_SPACE(sizeof(*sa));
353729f5
OZ
161
162 sa = (struct in_addr *) CMSG_DATA(cm);
05476c4d 163 *sa = ipa_to_in4(s->saddr);
353729f5 164
8945f73d 165 msg->msg_controllen = controllen;
48e5f32d 166}
3e236955
JMM
167#else
168static inline void
169sk_prepare_cmsgs4(sock *s UNUSED, struct msghdr *msg UNUSED, void *cbuf UNUSED, size_t cbuflen UNUSED) { }
170#endif
48e5f32d 171
3e236955 172static void UNUSED
05476c4d 173sk_prepare_ip_header(sock *s, void *hdr, int dlen)
48e5f32d
OZ
174{
175 struct ip *ip = hdr;
176
177 bzero(ip, 20);
178
179 ip->ip_v = 4;
180 ip->ip_hl = 5;
181 ip->ip_tos = (s->tos < 0) ? 0 : s->tos;
182 ip->ip_len = 20 + dlen;
183 ip->ip_ttl = (s->ttl < 0) ? 64 : s->ttl;
184 ip->ip_p = s->dport;
05476c4d
OZ
185 ip->ip_src = ipa_to_in4(s->saddr);
186 ip->ip_dst = ipa_to_in4(s->daddr);
48e5f32d 187
f6e6c3b5
OZ
188#if (defined __OpenBSD__) || (defined __DragonFly__) || (defined __FreeBSD__ && (__FreeBSD_version >= 1100030))
189 /* Different BSDs have different expectations of ip_len endianity */
48e5f32d
OZ
190 ip->ip_len = htons(ip->ip_len);
191#endif
353729f5
OZ
192}
193
2b70f074 194
05476c4d
OZ
195/*
196 * Miscellaneous BSD socket syscalls
197 */
2b70f074 198
2b70f074
OF
199#ifndef TCP_KEYLEN_MAX
200#define TCP_KEYLEN_MAX 80
201#endif
a7baa098 202
2b70f074
OF
203#ifndef TCP_SIG_SPI
204#define TCP_SIG_SPI 0x1000
205#endif
206
a7baa098
OZ
207#if defined(__FreeBSD__)
208#define USE_MD5SIG_SETKEY
925aa149 209#include "sysdep/bsd/setkey.h"
a7baa098 210#endif
2b70f074 211
05476c4d 212int
757cab18 213sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote UNUSED, int pxlen UNUSED, struct iface *ifa UNUSED, char *passwd, int setkey UNUSED)
2b70f074 214{
a7baa098
OZ
215#ifdef USE_MD5SIG_SETKEY
216 if (setkey)
757cab18 217 if (sk_set_md5_in_sasp_db(s, local, remote, pxlen, ifa, passwd) < 0)
a7baa098
OZ
218 return -1;
219#endif
05476c4d 220
a7baa098 221 int enable = (passwd && *passwd) ? TCP_SIG_SPI : 0;
05476c4d
OZ
222 if (setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable)) < 0)
223 {
224 if (errno == ENOPROTOOPT)
225 ERR_MSG("Kernel does not support TCP MD5 signatures");
226 else
227 ERR("TCP_MD5SIG");
228 }
b1b19433 229
05476c4d
OZ
230 return 0;
231}
b1b19433 232
05476c4d 233static inline int
b1b19433
OZ
234sk_set_min_ttl4(sock *s, int ttl)
235{
236 if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
237 {
238 if (errno == ENOPROTOOPT)
05476c4d 239 ERR_MSG("Kernel does not support IPv4 TTL security");
b1b19433 240 else
05476c4d 241 ERR("IP_MINTTL");
b1b19433
OZ
242 }
243
244 return 0;
245}
246
05476c4d 247static inline int
3e236955 248sk_set_min_ttl6(sock *s, int ttl UNUSED)
b1b19433 249{
05476c4d 250 ERR_MSG("Kernel does not support IPv6 TTL security");
b1b19433
OZ
251}
252
05476c4d 253static inline int
3e236955 254sk_disable_mtu_disc4(sock *s UNUSED)
05476c4d
OZ
255{
256 /* TODO: Set IP_DONTFRAG to 0 ? */
257 return 0;
258}
b1b19433 259
05476c4d 260static inline int
3e236955 261sk_disable_mtu_disc6(sock *s UNUSED)
05476c4d
OZ
262{
263 /* TODO: Set IPV6_DONTFRAG to 0 ? */
264 return 0;
265}
ef4a50be
OZ
266
267int sk_priority_control = -1;
268
05476c4d 269static inline int
ef4a50be
OZ
270sk_set_priority(sock *s, int prio UNUSED)
271{
05476c4d 272 ERR_MSG("Socket priority not supported");
ef4a50be 273}