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