2008-04-15 Dan Williams <dcbw@redhat.com>
[NetworkManager.git] / src / backends / NetworkManagerGeneric.c
1 /* NetworkManager -- Network link manager
2  *
3  * Timothee Lecomte <timothee.lecomte@ens.fr>
4  *
5  * Heavily based on NetworkManagerRedhat.c by Dan Williams <dcbw@redhat.com>
6  *
7  * This program 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  * This program 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 this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * (C) Copyright 2004 Red Hat, Inc.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <signal.h>
31 #include <arpa/inet.h>
32 #include <string.h>
33
34 #include "NetworkManagerGeneric.h"
35 #include "NetworkManagerSystem.h"
36 #include "NetworkManagerUtils.h"
37 #include "nm-device.h"
38 #include "nm-device-802-3-ethernet.h"
39 #include "nm-device-802-11-wireless.h"
40 #include "nm-utils.h"
41
42 /*
43  * nm_generic_init
44  *
45  * Initializes the distribution-specific system backend
46  *
47  */
48 void nm_generic_init (void)
49 {
50         /* Kill any dhclients lying around */
51         nm_system_kill_all_dhcp_daemons ();
52 }
53
54 /*
55  * nm_generic_replace_default_route
56  *
57  * Replace default route with one via the current device
58  *
59  */
60 void
61 nm_generic_device_replace_default_route (const char *iface, guint32 gw, guint32 mss)
62 {
63         char *buf, *addr_str = NULL, *mss_str = NULL;
64
65         g_return_if_fail (iface != NULL);
66
67         if (gw > 0) {
68                 struct in_addr addr = { .s_addr = gw };
69                 char buf2[INET_ADDRSTRLEN + 1];
70
71                 memset (buf2, 0, sizeof (buf2));
72                 inet_ntop (AF_INET, &addr, buf2, INET_ADDRSTRLEN);      
73                 addr_str = g_strdup_printf ("via %s", buf2);
74         }
75
76         if (mss > 0)
77                 mss_str = g_strdup_printf ("advmss %d", mss);
78
79         buf = g_strdup_printf (IP_BINARY_PATH" route replace default %s %s dev %s",
80                                addr_str ? addr_str : "",
81                                mss_str ? mss_str : "",
82                                iface);
83         nm_spawn_process (buf);
84         g_free (buf);
85 }
86
87 /*
88  * nm_generic_device_add_route_via_device_with_iface
89  *
90  * Add route to the given device
91  *
92  */
93 void nm_generic_device_add_route_via_device_with_iface (const char *iface, const char *route)
94 {
95         char    *buf;
96
97         g_return_if_fail (iface != NULL);
98
99         /* Add default gateway */
100         buf = g_strdup_printf (IP_BINARY_PATH" route add %s dev %s", route, iface);
101         nm_spawn_process (buf);
102         g_free (buf);
103 }
104
105
106 /*
107  * nm_generic_device_flush_ip4_addresses
108  *
109  * Flush all network addresses associated with a network device
110  *
111  */
112 void nm_generic_device_flush_ip4_routes (NMDevice *dev)
113 {
114         g_return_if_fail (dev != NULL);
115
116         nm_system_device_flush_ip4_routes_with_iface (nm_device_get_iface (dev));
117 }
118
119 /*
120  * nm_generic_device_flush_ip4_routes_with_iface
121  *
122  * Flush all routes associated with a network device
123  *
124  */
125 void nm_generic_device_flush_ip4_routes_with_iface (const char *iface)
126 {
127         char    *buf;
128
129         g_return_if_fail (iface != NULL);
130
131         /* Remove routing table entries */
132         buf = g_strdup_printf (IP_BINARY_PATH" -4 route flush dev %s", iface);
133         nm_spawn_process (buf);
134         g_free (buf);
135 }
136
137 /*
138  * nm_generic_device_flush_ip4_addresses
139  *
140  * Flush all network addresses associated with a network device
141  *
142  */
143 void nm_generic_device_flush_ip4_addresses (NMDevice *dev)
144 {
145         g_return_if_fail (dev != NULL);
146
147         nm_system_device_flush_ip4_addresses_with_iface (nm_device_get_iface (dev));
148 }
149
150
151 /*
152  * nm_generic_device_flush_ip4_addresses_with_iface
153  *
154  * Flush all network addresses associated with a network device
155  *
156  */
157 void nm_generic_device_flush_ip4_addresses_with_iface (const char *iface)
158 {
159         char    *buf;
160
161         g_return_if_fail (iface != NULL);
162
163         /* Remove all IP addresses for a device */
164         buf = g_strdup_printf (IP_BINARY_PATH" -4 addr flush dev %s", iface);
165         nm_spawn_process (buf);
166         g_free (buf);
167 }
168
169 /*
170  * nm_generic_enable_loopback
171  *
172  * Bring up the loopback interface
173  *
174  */
175 void nm_generic_enable_loopback (void)
176 {
177         nm_spawn_process (IP_BINARY_PATH" link set dev lo up");
178         nm_spawn_process (IP_BINARY_PATH" addr add 127.0.0.1/8 brd 127.255.255.255 dev lo scope host label lo");
179 }
180
181
182 /*
183  * nm_generic_flush_loopback_routes
184  *
185  * Flush all routes associated with the loopback device, because it
186  * sometimes gets the first route for ZeroConf/Link-Local traffic.
187  *
188  */
189 void nm_generic_flush_loopback_routes (void)
190 {
191         nm_system_device_flush_ip4_routes_with_iface ("lo");
192 }
193
194
195 /*
196  * nm_generic_flush_arp_cache
197  *
198  * Flush all entries in the arp cache.
199  *
200  */
201 void nm_generic_flush_arp_cache (void)
202 {
203         nm_spawn_process (IP_BINARY_PATH" neigh flush all");
204 }
205
206
207 /*
208  * nm_generic_kill_all_dhcp_daemons
209  *
210  * Kill all DHCP daemons currently running, done at startup.
211  *
212  */
213 void nm_generic_kill_all_dhcp_daemons (void)
214 {
215 }
216
217
218 /*
219  * nm_generic_update_dns
220  *
221  * Make glibc/nscd aware of any changes to the resolv.conf file by
222  * restarting nscd.
223  *
224  */
225 void nm_generic_update_dns (void)
226 {
227 }
228
229
230 /*
231  * nm_generic_restart_mdns_responder
232  *
233  * Restart the multicast DNS responder so that it knows about new
234  * network interfaces and IP addresses.
235  *
236  */
237 void nm_generic_restart_mdns_responder (void)
238 {
239 }
240
241
242 /*
243  * nm_generic_device_add_ip6_link_address
244  *
245  * Add a default link-local IPv6 address to a device.
246  *
247  */
248 void nm_generic_device_add_ip6_link_address (NMDevice *dev)
249 {
250         char *buf;
251         struct ether_addr hw_addr;
252         unsigned char eui[8];
253
254         if (NM_IS_DEVICE_802_3_ETHERNET (dev))
255                 nm_device_802_3_ethernet_get_address (NM_DEVICE_802_3_ETHERNET (dev), &hw_addr);
256         else if (NM_IS_DEVICE_802_11_WIRELESS (dev))
257                 nm_device_802_11_wireless_get_address (NM_DEVICE_802_11_WIRELESS (dev), &hw_addr);
258
259         memcpy (eui, &(hw_addr.ether_addr_octet), sizeof (hw_addr.ether_addr_octet));
260         memmove(eui+5, eui+3, 3);
261         eui[3] = 0xff;
262         eui[4] = 0xfe;
263         eui[0] ^= 2;
264
265         /* Add the default link-local IPv6 address to a device */
266         buf = g_strdup_printf (IP_BINARY_PATH" -6 addr add fe80::%x%02x:%x%02x:%x%02x:%x%02x/64 dev %s",
267                          eui[0], eui[1], eui[2], eui[3],
268                          eui[4], eui[5],
269                          eui[6], eui[7], nm_device_get_iface (dev));
270         nm_spawn_process (buf);
271         g_free (buf);
272 }
273
274 /*
275  * nm_generic_set_ip4_config_from_resolv_conf
276  *
277  * Add nameservers and search names from a resolv.conf format file.
278  *
279  */
280 void nm_generic_set_ip4_config_from_resolv_conf (const char *filename, NMIP4Config *ip4_config)
281 {
282         char *  contents = NULL;
283         char ** split_contents = NULL;
284         int             i, len;
285
286         g_return_if_fail (filename != NULL);
287         g_return_if_fail (ip4_config != NULL);
288
289         if (!g_file_get_contents (filename, &contents, NULL, NULL) || (contents == NULL))
290                 return;
291
292         if (!(split_contents = g_strsplit (contents, "\n", 0)))
293                 goto out;
294         
295         len = g_strv_length (split_contents);
296         for (i = 0; i < len; i++)
297         {
298                 char *line = split_contents[i];
299
300                 /* Ignore comments */
301                 if (!line || (line[0] == ';') || (line[0] == '#'))
302                         continue;
303
304                 line = g_strstrip (line);
305                 if ((strncmp (line, "search", 6) == 0) && (strlen (line) > 6))
306                 {
307                         char *searches = g_strdup (line + 7);
308                         char **split_searches = NULL;
309
310                         if (!searches || !strlen (searches))
311                                 continue;
312
313                         /* Allow space-separated search domains */
314                         if ((split_searches = g_strsplit (searches, " ", 0)))
315                         {
316                                 int m, srch_len;
317
318                                 srch_len = g_strv_length (split_searches);
319                                 for (m = 0; m < srch_len; m++)
320                                 {
321                                         if (split_searches[m])
322                                                 nm_ip4_config_add_domain        (ip4_config, split_searches[m]);
323                                 }
324                                 g_strfreev (split_searches);
325                         }
326                         else
327                         {
328                                 /* Only 1 item, add the whole line */
329                                 nm_ip4_config_add_domain        (ip4_config, searches);
330                         }
331
332                         g_free (searches);
333                 }
334                 else if ((strncmp (line, "nameserver", 10) == 0) && (strlen (line) > 10))
335                 {
336                         guint32 addr = (guint32) (inet_addr (line + 11));
337
338                         if (addr != (guint32) -1)
339                                 nm_ip4_config_add_nameserver (ip4_config, addr);
340                 }
341         }
342
343         g_strfreev (split_contents);
344
345 out:
346         g_free (contents);
347 }
348
349
350 /*
351  * nm_generic_device_get_system_config
352  *
353  * Retrieve any relevant configuration info for a particular device
354  * from the system network configuration information.  Clear out existing
355  * info before setting stuff too.
356  *
357  */
358 void* nm_generic_device_get_system_config (NMDevice *dev)
359 {
360         return NULL;
361 }
362
363 /*
364  * nm_generic_device_free_system_config
365  *
366  * Free stored system config data
367  *
368  */
369 void nm_generic_device_free_system_config (NMDevice *dev, void *system_config_data)
370 {
371         return;
372 }
373
374
375 /*
376  * nm_generic_device_get_disabled
377  *
378  * Return whether the distro-specific system config tells us to use
379  * dhcp for this device.
380  *
381  */
382 gboolean nm_generic_device_get_disabled (NMDevice *dev)
383 {
384         return FALSE;
385 }
386
387
388 NMIP4Config *nm_generic_device_new_ip4_system_config (NMDevice *dev)
389 {
390         return NULL;
391 }
392
393 /*
394  * nm_generic_activate_nis
395  *
396  * set up the nis domain and write a yp.conf
397  *
398  */
399 void nm_generic_activate_nis (NMIP4Config *config)
400 {
401 }
402
403 /*
404  * nm_generic_shutdown_nis
405  *
406  * shutdown ypbind
407  *
408  */
409 void nm_generic_shutdown_nis (void)
410 {
411 }
412
413 /*
414  * nm_generic_set_hostname
415  *
416  * set the hostname
417  *
418  */
419 void nm_generic_set_hostname (NMIP4Config *config)
420 {
421 }
422
423 /*
424  * nm_generic_should_modify_resolv_conf
425  *
426  * Can NM update resolv.conf, or is it locked down?
427  */
428 gboolean nm_generic_should_modify_resolv_conf (void)
429 {
430         return TRUE;
431 }
432