Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / bsd / sysio.h @ 05476c4d

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