Added NetBSD patch
[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.8 2004/12/12 17:54:00 kattemat Exp $
40  */
41
42 #include "../defs.h"
43 #include "../net_os.h"
44 #include "net.h"
45
46 #ifdef __NetBSD__
47 #include <sys/param.h>
48 #endif
49
50 #include <sys/sysctl.h>
51
52 static int ignore_redir;
53 static int send_redir;
54 static int gateway;
55
56 static int first_time = 1;
57
58 static int set_sysctl_int(char *name, int new)
59 {
60   int old;
61   unsigned int len = sizeof (old);
62
63   if (sysctlbyname(name, &old, &len, &new, sizeof (new)) < 0)
64     return -1;
65
66   return old;
67 }
68
69 int enable_ip_forwarding(int version)
70 {
71   char *name;
72
73   if (olsr_cnf->ip_version == AF_INET)
74     name = "net.inet.ip.forwarding";
75
76   else
77     name = "net.inet6.ip6.forwarding";
78
79   gateway = set_sysctl_int(name, 1);
80
81   if (gateway < 0)
82     {
83       fprintf(stderr, "Cannot enable IP forwarding. Please enable IP forwarding manually. Continuing in 3 seconds...\n");
84       sleep(3);
85     }
86
87   return 1;
88 }
89
90 int disable_redirects(char *if_name, int index, int version)
91 {
92   char *name;
93
94   // this function gets called for each interface olsrd uses; however,
95   // FreeBSD can only globally control ICMP redirects, and not on a
96   // per-interface basis; hence, only disable ICMP redirects on the first
97   // invocation
98
99   if (first_time == 0)
100     return 1;
101
102   first_time = 0;
103
104   // do not accept ICMP redirects
105
106   if (olsr_cnf->ip_version == AF_INET)
107     name = "net.inet.icmp.drop_redirect";
108
109   else
110     name = "net.inet6.icmp6.drop_redirect";
111
112   ignore_redir = set_sysctl_int(name, 1);
113
114   if (ignore_redir < 0)
115     {
116       fprintf(stderr, "Cannot disable incoming ICMP redirect messages. Please disable them manually. Continuing in 3 seconds...\n");
117       sleep(3);
118     }
119
120   // do not send ICMP redirects
121
122   if (olsr_cnf->ip_version == AF_INET)
123     name = "net.inet.ip.redirect";
124
125   else
126     name = "net.inet6.ip6.redirect";
127
128   send_redir = set_sysctl_int(name, 0);
129
130   if (send_redir < 0)
131     {
132       fprintf(stderr, "Cannot disable outgoing ICMP redirect messages. Please disable them manually. Continuing in 3 seconds...\n");
133       sleep(3);
134     }
135
136   return 1;
137 }
138
139 int deactivate_spoof(char *if_name, int index, int version)
140 {
141   return 1;
142 }
143
144 int restore_settings(int version)
145 {
146   char *name;
147
148   // reset IP forwarding
149
150   if (olsr_cnf->ip_version == AF_INET)
151     name = "net.inet.ip.forwarding";
152
153   else
154     name = "net.inet6.ip6.forwarding";
155
156   set_sysctl_int(name, gateway);
157
158   // reset incoming ICMP redirects
159
160   if (olsr_cnf->ip_version == AF_INET)
161     name = "net.inet.icmp.drop_redirect";
162
163   else
164     name = "net.inet6.icmp6.drop_redirect";
165
166   set_sysctl_int(name, ignore_redir);
167
168   // reset outgoing ICMP redirects
169
170   if (olsr_cnf->ip_version == AF_INET)
171     name = "net.inet.ip.redirect";
172
173   else
174     name = "net.inet6.ip6.redirect";
175
176   set_sysctl_int(name, send_redir);
177
178   return 1;
179 }
180
181 int
182 getsocket(struct sockaddr *sa, int bufspace, char *int_name)
183 {
184   struct sockaddr_in *sin = (struct sockaddr_in *)sa;
185   int sock, on = 1;
186
187   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
188     {
189       perror("socket");
190       syslog(LOG_ERR, "socket: %m");
191       return (-1);
192     }
193
194   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
195     {
196       perror("setsockopt");
197       syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
198       close(sock);
199       return (-1);
200     }
201
202   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
203     {
204       perror("SO_REUSEADDR failed");
205       return (-1);
206     }
207
208   for (on = bufspace; ; on -= 1024) 
209     {
210       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
211                      &on, sizeof (on)) == 0)
212         break;
213       if (on <= 8*1024) 
214         {
215           perror("setsockopt");
216           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
217           break;
218         }
219     }
220
221   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
222     {
223       perror("bind");
224       syslog(LOG_ERR, "bind: %m");
225       close(sock);
226       return (-1);
227     }
228
229   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
230     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
231
232   return (sock);
233 }
234
235 int getsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name)
236 {
237   int sock, on = 1;
238
239   if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 
240     {
241       perror("socket");
242       syslog(LOG_ERR, "socket: %m");
243       return (-1);
244     }
245
246   for (on = bufspace; ; on -= 1024) 
247     {
248       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
249                      &on, sizeof (on)) == 0)
250         break;
251       if (on <= 8*1024) 
252         {
253           perror("setsockopt");
254           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
255           break;
256         }
257     }
258
259   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
260     {
261       perror("SO_REUSEADDR failed");
262       return (-1);
263     }
264
265   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
266     {
267       perror("bind");
268       syslog(LOG_ERR, "bind: %m");
269       close(sock);
270       return (-1);
271     }
272
273   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
274     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
275
276   return (sock);
277 }
278
279 int get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
280 {
281   return 0;
282 }