cdac93eb396cc020c8ddf00982c0d06a34764f99
[olsrd.git] / src / bsd / net.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: net.c,v 1.13 2005/02/17 07:19:49 kattemat Exp $
40  */
41
42 #include "../defs.h"
43 #include "../net_os.h"
44 #include "../parser.h" /* dnc: needed for call to packet_parser() */
45 #include "net.h"
46
47 #ifdef __NetBSD__
48 #include <sys/param.h>
49 #endif
50
51 #include <net/if.h>
52 #include <net/if_var.h>
53 #include <net/ethernet.h>
54
55 #include <net80211/ieee80211.h>
56 #include <net80211/ieee80211_ioctl.h>
57 #include <dev/wi/if_wavelan_ieee.h>
58 #include <dev/wi/if_wireg.h>
59
60 //#define       SIOCGIFGENERIC  _IOWR('i', 58, struct ifreq)    /* generic IF get op */
61 //#define SIOCGWAVELAN SIOCGIFGENERIC
62
63 #include <sys/sysctl.h>
64
65 static int ignore_redir;
66 static int send_redir;
67 static int gateway;
68
69 static int first_time = 1;
70
71 static int set_sysctl_int(char *name, int new)
72 {
73   int old;
74   unsigned int len = sizeof (old);
75
76   if (sysctlbyname(name, &old, &len, &new, sizeof (new)) < 0)
77     return -1;
78
79   return old;
80 }
81
82 int enable_ip_forwarding(int version)
83 {
84   char *name;
85
86   if (olsr_cnf->ip_version == AF_INET)
87     name = "net.inet.ip.forwarding";
88
89   else
90     name = "net.inet6.ip6.forwarding";
91
92   gateway = set_sysctl_int(name, 1);
93
94   if (gateway < 0)
95     {
96       fprintf(stderr, "Cannot enable IP forwarding. Please enable IP forwarding manually. Continuing in 3 seconds...\n");
97       sleep(3);
98     }
99
100   return 1;
101 }
102
103 int disable_redirects(char *if_name, int index, int version)
104 {
105   char *name;
106
107   // this function gets called for each interface olsrd uses; however,
108   // FreeBSD can only globally control ICMP redirects, and not on a
109   // per-interface basis; hence, only disable ICMP redirects on the first
110   // invocation
111
112   if (first_time == 0)
113     return 1;
114
115   first_time = 0;
116
117   // do not accept ICMP redirects
118
119   if (olsr_cnf->ip_version == AF_INET)
120     name = "net.inet.icmp.drop_redirect";
121
122   else
123     name = "net.inet6.icmp6.drop_redirect";
124
125   ignore_redir = set_sysctl_int(name, 1);
126
127   if (ignore_redir < 0)
128     {
129       fprintf(stderr, "Cannot disable incoming ICMP redirect messages. Please disable them manually. Continuing in 3 seconds...\n");
130       sleep(3);
131     }
132
133   // do not send ICMP redirects
134
135   if (olsr_cnf->ip_version == AF_INET)
136     name = "net.inet.ip.redirect";
137
138   else
139     name = "net.inet6.ip6.redirect";
140
141   send_redir = set_sysctl_int(name, 0);
142
143   if (send_redir < 0)
144     {
145       fprintf(stderr, "Cannot disable outgoing ICMP redirect messages. Please disable them manually. Continuing in 3 seconds...\n");
146       sleep(3);
147     }
148
149   return 1;
150 }
151
152 int deactivate_spoof(char *if_name, int index, int version)
153 {
154   return 1;
155 }
156
157 int restore_settings(int version)
158 {
159   char *name;
160
161   // reset IP forwarding
162
163   if (olsr_cnf->ip_version == AF_INET)
164     name = "net.inet.ip.forwarding";
165
166   else
167     name = "net.inet6.ip6.forwarding";
168
169   set_sysctl_int(name, gateway);
170
171   // reset incoming ICMP redirects
172
173   if (olsr_cnf->ip_version == AF_INET)
174     name = "net.inet.icmp.drop_redirect";
175
176   else
177     name = "net.inet6.icmp6.drop_redirect";
178
179   set_sysctl_int(name, ignore_redir);
180
181   // reset outgoing ICMP redirects
182
183   if (olsr_cnf->ip_version == AF_INET)
184     name = "net.inet.ip.redirect";
185
186   else
187     name = "net.inet6.ip6.redirect";
188
189   set_sysctl_int(name, send_redir);
190
191   return 1;
192 }
193
194 int
195 getsocket(struct sockaddr *sa, int bufspace, char *int_name)
196 {
197   struct sockaddr_in *sin = (struct sockaddr_in *)sa;
198   int sock, on = 1;
199
200   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
201     {
202       perror("socket");
203       syslog(LOG_ERR, "socket: %m");
204       return (-1);
205     }
206
207   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
208     {
209       perror("setsockopt");
210       syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
211       close(sock);
212       return (-1);
213     }
214
215   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
216     {
217       perror("SO_REUSEADDR failed");
218       return (-1);
219     }
220
221   for (on = bufspace; ; on -= 1024) 
222     {
223       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
224                      &on, sizeof (on)) == 0)
225         break;
226       if (on <= 8*1024) 
227         {
228           perror("setsockopt");
229           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
230           break;
231         }
232     }
233
234   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
235     {
236       perror("bind");
237       syslog(LOG_ERR, "bind: %m");
238       close(sock);
239       return (-1);
240     }
241
242   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
243     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
244
245   return (sock);
246 }
247
248 int getsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name)
249 {
250   int sock, on = 1;
251
252   if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 
253     {
254       perror("socket");
255       syslog(LOG_ERR, "socket: %m");
256       return (-1);
257     }
258
259   for (on = bufspace; ; on -= 1024) 
260     {
261       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
262                      &on, sizeof (on)) == 0)
263         break;
264       if (on <= 8*1024) 
265         {
266           perror("setsockopt");
267           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
268           break;
269         }
270     }
271
272   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
273     {
274       perror("SO_REUSEADDR failed");
275       return (-1);
276     }
277
278   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
279     {
280       perror("bind");
281       syslog(LOG_ERR, "bind: %m");
282       close(sock);
283       return (-1);
284     }
285
286   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
287     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
288
289   return (sock);
290 }
291
292 int get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
293 {
294   return 0;
295 }
296
297
298
299
300 /**
301  * Wrapper for sendto(2)
302  */
303
304 ssize_t
305 olsr_sendto(int s, 
306             const void *buf, 
307             size_t len, 
308             int flags, 
309             const struct sockaddr *to, 
310             socklen_t tolen)
311 {
312   return sendto(s, buf, len, flags, to, tolen);
313 }
314
315
316 /**
317  * Wrapper for recvfrom(2)
318  */
319
320 ssize_t  
321 olsr_recvfrom(int  s, 
322               void *buf, 
323               size_t len, 
324               int flags, 
325               struct sockaddr *from,
326               socklen_t *fromlen)
327 {
328   return recvfrom(s, 
329                   buf, 
330                   len, 
331                   0, 
332                   from, 
333                   fromlen);
334 }
335
336
337 int 
338 check_wireless_interface(char *ifname)
339 {
340   struct wi_req wreq;
341   struct ifreq ifr;
342
343   memset((char *)&wreq, 0, sizeof(wreq));
344   memset((char *)&ifr, 0, sizeof(ifr));
345
346   wreq.wi_len = WI_MAX_DATALEN;
347   wreq.wi_type = WI_RID_IFACE_STATS;
348
349   strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
350   ifr.ifr_data = (caddr_t)&wreq;
351
352   return (ioctl(ioctl_s, SIOCGWAVELAN, &ifr) >= 0) ? 1 : 0;
353 }
354
355
356 int
357 calculate_if_metric(char *ifname)
358 {
359   if(check_wireless_interface(ifname))
360     {
361       /* Wireless */
362       return 1;
363     }
364   else
365     {
366       /* Ethernet */
367       return 0;
368     }
369 }