9652629f914382840c123df555fa644858ce1246
[olsrd.git] / src / bsd / net.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of olsr.org.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: net.c,v 1.4 2004/11/17 16:17:41 tlopatic Exp $
23  *
24  */
25
26 #include "../defs.h"
27 #include "net.h"
28
29 #include <sys/sysctl.h>
30
31 static int ignore_redir;
32 static int send_redir;
33 static int gateway;
34
35 static int first_time = 1;
36
37 static int set_sysctl_int(char *name, int new)
38 {
39   int old;
40   unsigned int len = sizeof (old);
41
42   if (sysctlbyname(name, &old, &len, &new, sizeof (new)) < 0)
43     return -1;
44
45   return old;
46 }
47
48 int enable_ip_forwarding(int version)
49 {
50   char *name;
51
52   if (olsr_cnf->ip_version == AF_INET)
53     name = "net.inet.ip.forwarding";
54
55   else
56     name = "net.inet6.ip6.forwarding";
57
58   gateway = set_sysctl_int(name, 1);
59
60   if (gateway < 0)
61     {
62       fprintf(stderr, "Cannot enable IP forwarding. Please enable IP forwarding manually. Continuing in 3 seconds...\n");
63       sleep(3);
64     }
65
66   return 1;
67 }
68
69 int disable_redirects(char *if_name, int index, int version)
70 {
71   char *name;
72
73   // this function gets called for each interface olsrd uses; however,
74   // FreeBSD can only globally control ICMP redirects, and not on a
75   // per-interface basis; hence, only disable ICMP redirects on the first
76   // invocation
77
78   if (first_time == 0)
79     return 1;
80
81   first_time = 0;
82
83   // do not accept ICMP redirects
84
85   if (olsr_cnf->ip_version == AF_INET)
86     name = "net.inet.icmp.drop_redirect";
87
88   else
89     name = "net.inet6.icmp6.drop_redirect";
90
91   ignore_redir = set_sysctl_int(name, 1);
92
93   if (ignore_redir < 0)
94     {
95       fprintf(stderr, "Cannot disable incoming ICMP redirect messages. Please disable them manually. Continuing in 3 seconds...\n");
96       sleep(3);
97     }
98
99   // do not send ICMP redirects
100
101   if (olsr_cnf->ip_version == AF_INET)
102     name = "net.inet.ip.redirect";
103
104   else
105     name = "net.inet6.ip6.redirect";
106
107   send_redir = set_sysctl_int(name, 0);
108
109   if (send_redir < 0)
110     {
111       fprintf(stderr, "Cannot disable outgoing ICMP redirect messages. Please disable them manually. Continuing in 3 seconds...\n");
112       sleep(3);
113     }
114
115   return 1;
116 }
117
118 int deactivate_spoof(char *if_name, int index, int version)
119 {
120   return 1;
121 }
122
123 int restore_settings(int version)
124 {
125   char *name;
126
127   // reset IP forwarding
128
129   if (olsr_cnf->ip_version == AF_INET)
130     name = "net.inet.ip.forwarding";
131
132   else
133     name = "net.inet6.ip6.forwarding";
134
135   set_sysctl_int(name, gateway);
136
137   // reset incoming ICMP redirects
138
139   if (olsr_cnf->ip_version == AF_INET)
140     name = "net.inet.icmp.drop_redirect";
141
142   else
143     name = "net.inet6.icmp6.drop_redirect";
144
145   set_sysctl_int(name, ignore_redir);
146
147   // reset outgoing ICMP redirects
148
149   if (olsr_cnf->ip_version == AF_INET)
150     name = "net.inet.ip.redirect";
151
152   else
153     name = "net.inet6.ip6.redirect";
154
155   set_sysctl_int(name, send_redir);
156
157   return 1;
158 }
159
160 int
161 getsocket(struct sockaddr *sa, int bufspace, char *int_name)
162 {
163   struct sockaddr_in *sin = (struct sockaddr_in *)sa;
164   int sock, on = 1;
165
166   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
167     {
168       perror("socket");
169       syslog(LOG_ERR, "socket: %m");
170       return (-1);
171     }
172
173   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
174     {
175       perror("setsockopt");
176       syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
177       close(sock);
178       return (-1);
179     }
180
181   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
182     {
183       perror("SO_REUSEADDR failed");
184       return (-1);
185     }
186
187   for (on = bufspace; ; on -= 1024) 
188     {
189       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
190                      &on, sizeof (on)) == 0)
191         break;
192       if (on <= 8*1024) 
193         {
194           perror("setsockopt");
195           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
196           break;
197         }
198     }
199
200   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
201     {
202       perror("bind");
203       syslog(LOG_ERR, "bind: %m");
204       close(sock);
205       return (-1);
206     }
207
208   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
209     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
210
211   return (sock);
212 }
213
214 int getsocket6(struct sockaddr_in6 *sin, int bufspace, char *int_name)
215 {
216   int sock, on = 1;
217
218   if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 
219     {
220       perror("socket");
221       syslog(LOG_ERR, "socket: %m");
222       return (-1);
223     }
224
225   for (on = bufspace; ; on -= 1024) 
226     {
227       if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
228                      &on, sizeof (on)) == 0)
229         break;
230       if (on <= 8*1024) 
231         {
232           perror("setsockopt");
233           syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
234           break;
235         }
236     }
237
238   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 
239     {
240       perror("SO_REUSEADDR failed");
241       return (-1);
242     }
243
244   if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) 
245     {
246       perror("bind");
247       syslog(LOG_ERR, "bind: %m");
248       close(sock);
249       return (-1);
250     }
251
252   if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
253     syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
254
255   return (sock);
256 }
257
258 int get_ipv6_address(char *ifname, struct sockaddr_in6 *saddr6, int scope_in)
259 {
260   return 0;
261 }