Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / bsd / sysio.h @ 153f02da

History | View | Annotate | Download (5.66 KB)

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