Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (5.57 KB)

1
/*
2
 *        BIRD Internet Routing Daemon -- Linux Multicasting and Network Includes
3
 *
4
 *        (c) 1998--2000 Martin Mares <mj@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9

    
10
#ifndef HAVE_STRUCT_IP_MREQN
11
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
12
struct ip_mreqn
13
{
14
  struct in_addr imr_multiaddr;                        /* IP multicast address of group */
15
  struct in_addr imr_address;                        /* local IP address of interface */
16
  int                 imr_ifindex;                        /* Interface index */
17
};
18
#endif
19

    
20
#ifndef IP_MINTTL
21
#define IP_MINTTL 21
22
#endif
23

    
24
#ifndef IPV6_TCLASS
25
#define IPV6_TCLASS 67
26
#endif
27

    
28
#ifndef IPV6_MINHOPCOUNT
29
#define IPV6_MINHOPCOUNT 73
30
#endif
31

    
32

    
33
#ifndef TCP_MD5SIG
34

    
35
#define TCP_MD5SIG  14
36
#define TCP_MD5SIG_MAXKEYLEN 80
37

    
38
struct tcp_md5sig {
39
  struct  sockaddr_storage tcpm_addr;             /* address associated */
40
  u16   __tcpm_pad1;                              /* zero */
41
  u16   tcpm_keylen;                              /* key length */
42
  u32   __tcpm_pad2;                              /* zero */
43
  u8    tcpm_key[TCP_MD5SIG_MAXKEYLEN];           /* key (binary) */
44
};
45

    
46
#endif
47

    
48

    
49
/* Linux does not care if sa_len is larger than needed */
50
#define SA_LEN(x) sizeof(sockaddr)
51

    
52

    
53
/*
54
 *        Linux IPv4 multicast syscalls
55
 */
56

    
57
#define INIT_MREQ4(maddr,ifa) \
58
  { .imr_multiaddr = ipa_to_in4(maddr), .imr_ifindex = ifa->index }
59

    
60
static inline int
61
sk_setup_multicast4(sock *s)
62
{
63
  struct ip_mreqn mr = { .imr_ifindex = s->iface->index };
64
  int ttl = s->ttl;
65
  int n = 0;
66

    
67
  /* This defines where should we send _outgoing_ multicasts */
68
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mr, sizeof(mr)) < 0)
69
    ERR("IP_MULTICAST_IF");
70

    
71
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
72
    ERR("IP_MULTICAST_TTL");
73

    
74
  if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
75
    ERR("IP_MULTICAST_LOOP");
76

    
77
  return 0;
78
}
79

    
80
static inline int
81
sk_join_group4(sock *s, ip_addr maddr)
82
{
83
  struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
84

    
85
  if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
86
    ERR("IP_ADD_MEMBERSHIP");
87

    
88
  return 0;
89
}
90

    
91
static inline int
92
sk_leave_group4(sock *s, ip_addr maddr)
93
{
94
  struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
95

    
96
  if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
97
    ERR("IP_DROP_MEMBERSHIP");
98

    
99
  return 0;
100
}
101

    
102

    
103
/*
104
 *        Linux IPv4 packet control messages
105
 */
106

    
107
/* Mostly similar to standardized IPv6 code */
108

    
109
#define CMSG4_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in_pktinfo))
110
#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(int))
111

    
112
static inline int
113
sk_request_cmsg4_pktinfo(sock *s)
114
{
115
  int y = 1;
116

    
117
  if (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &y, sizeof(y)) < 0)
118
    ERR("IP_PKTINFO");
119

    
120
  return 0;
121
}
122

    
123
static inline int
124
sk_request_cmsg4_ttl(sock *s)
125
{
126
  int y = 1;
127

    
128
  if (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
129
    ERR("IP_RECVTTL");
130

    
131
  return 0;
132
}
133

    
134
static inline void
135
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
136
{
137
  if (cm->cmsg_type == IP_PKTINFO)
138
  {
139
    struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm);
140
    s->laddr = ipa_from_in4(pi->ipi_addr);
141
    s->lifindex = pi->ipi_ifindex;
142
  }
143
}
144

    
145
static inline void
146
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
147
{
148
  if (cm->cmsg_type == IP_TTL)
149
    s->rcv_ttl = * (int *) CMSG_DATA(cm);
150
}
151

    
152
static inline void
153
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
154
{
155
  struct cmsghdr *cm;
156
  struct in_pktinfo *pi;
157

    
158
  msg->msg_control = cbuf;
159
  msg->msg_controllen = cbuflen;
160

    
161
  cm = CMSG_FIRSTHDR(msg);
162
  cm->cmsg_level = SOL_IP;
163
  cm->cmsg_type = IP_PKTINFO;
164
  cm->cmsg_len = CMSG_LEN(sizeof(*pi));
165

    
166
  pi = (struct in_pktinfo *) CMSG_DATA(cm);
167
  pi->ipi_ifindex = s->iface ? s->iface->index : 0;
168
  pi->ipi_spec_dst = ipa_to_in4(s->saddr);
169
  pi->ipi_addr = ipa_to_in4(IPA_NONE);
170

    
171
  msg->msg_controllen = cm->cmsg_len;
172
}
173

    
174

    
175
/*
176
 *        Miscellaneous Linux socket syscalls
177
 */
178

    
179
int
180
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
181
{
182
  struct tcp_md5sig md5;
183

    
184
  memset(&md5, 0, sizeof(md5));
185
  sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, a, ifa, 0);
186

    
187
  if (passwd)
188
  {
189
    int len = strlen(passwd);
190

    
191
    if (len > TCP_MD5SIG_MAXKEYLEN)
192
      ERR_MSG("MD5 password too long");
193

    
194
    md5.tcpm_keylen = len;
195
    memcpy(&md5.tcpm_key, passwd, len);
196
  }
197

    
198
  if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
199
  {
200
    if (errno == ENOPROTOOPT)
201
      ERR_MSG("Kernel does not support TCP MD5 signatures");
202
    else
203
      ERR("TCP_MD5SIG");
204
  }
205

    
206
  return 0;
207
}
208

    
209
static inline int
210
sk_set_min_ttl4(sock *s, int ttl)
211
{
212
  if (setsockopt(s->fd, SOL_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
213
  {
214
    if (errno == ENOPROTOOPT)
215
      ERR_MSG("Kernel does not support IPv4 TTL security");
216
    else
217
      ERR("IP_MINTTL");
218
  }
219

    
220
  return 0;
221
}
222

    
223
static inline int
224
sk_set_min_ttl6(sock *s, int ttl)
225
{
226
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
227
  {
228
    if (errno == ENOPROTOOPT)
229
      ERR_MSG("Kernel does not support IPv6 TTL security");
230
    else
231
      ERR("IPV6_MINHOPCOUNT");
232
  }
233

    
234
  return 0;
235
}
236

    
237
static inline int
238
sk_disable_mtu_disc4(sock *s)
239
{
240
  int dont = IP_PMTUDISC_DONT;
241

    
242
  if (setsockopt(s->fd, SOL_IP, IP_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
243
    ERR("IP_MTU_DISCOVER");
244

    
245
  return 0;
246
}
247

    
248
static inline int
249
sk_disable_mtu_disc6(sock *s)
250
{
251
  int dont = IPV6_PMTUDISC_DONT;
252

    
253
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
254
    ERR("IPV6_MTU_DISCOVER");
255

    
256
  return 0;
257
}
258

    
259
int sk_priority_control = 7;
260

    
261
static inline int
262
sk_set_priority(sock *s, int prio)
263
{
264
  if (setsockopt(s->fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0)
265
    ERR("SO_PRIORITY");
266

    
267
  return 0;
268
}
269