2006-07-24 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 "NetworkManagerGeneric.h"
33 #include "NetworkManagerSystem.h"
34 #include "NetworkManagerUtils.h"
35 #include "nm-device.h"
36 #include "nm-device-802-3-ethernet.h"
37 #include "nm-device-802-11-wireless.h"
38 #include "nm-utils.h"
39
40 /*
41  * nm_generic_init
42  *
43  * Initializes the distribution-specific system backend
44  *
45  */
46 void nm_generic_init (void)
47 {
48         /* Kill any dhclients lying around */
49         nm_system_kill_all_dhcp_daemons ();
50 }
51
52 /*
53  * nm_generic_device_add_default_route_via_device
54  *
55  * Add default route to the given device
56  *
57  */
58 void nm_generic_device_add_default_route_via_device (NMDevice *dev)
59 {
60         g_return_if_fail (dev != NULL);
61
62         /* Not really applicable for test devices */
63         if (nm_device_is_test_device (dev))
64                 return;
65
66         nm_system_device_add_default_route_via_device_with_iface (nm_device_get_iface (dev));
67 }
68
69
70 /*
71  * nm_generic_device_add_default_route_via_device_with_iface
72  *
73  * Add default route to the given device
74  *
75  */
76 void nm_generic_device_add_default_route_via_device_with_iface (const char *iface)
77 {
78         char    *buf;
79
80         g_return_if_fail (iface != NULL);
81
82         /* Add default gateway */
83         buf = g_strdup_printf (IP_BINARY_PATH" route add default dev %s", iface);
84         nm_spawn_process (buf);
85         g_free (buf);
86 }
87
88 /*
89  * nm_generic_device_add_route_via_device_with_iface
90  *
91  * Add route to the given device
92  *
93  */
94 void nm_generic_device_add_route_via_device_with_iface (const char *iface, const char *route)
95 {
96         char    *buf;
97
98         g_return_if_fail (iface != NULL);
99
100         /* Add default gateway */
101         buf = g_strdup_printf (IP_BINARY_PATH" route add %s dev %s", route, iface);
102         nm_spawn_process (buf);
103         g_free (buf);
104 }
105
106
107 /*
108  * nm_generic_device_flush_addresses
109  *
110  * Flush all network addresses associated with a network device
111  *
112  */
113 void nm_generic_device_flush_routes (NMDevice *dev)
114 {
115         g_return_if_fail (dev != NULL);
116
117         /* Not really applicable for test devices */
118         if (nm_device_is_test_device (dev))
119                 return;
120
121         nm_system_device_flush_routes_with_iface (nm_device_get_iface (dev));
122 }
123
124 /*
125  * nm_generic_device_flush_routes_with_iface
126  *
127  * Flush all routes associated with a network device
128  *
129  */
130 void nm_generic_device_flush_routes_with_iface (const char *iface)
131 {
132         char    *buf;
133
134         g_return_if_fail (iface != NULL);
135
136         /* Remove routing table entries */
137         buf = g_strdup_printf (IP_BINARY_PATH" route flush dev %s", iface);
138         nm_spawn_process (buf);
139         g_free (buf);
140 }
141
142 /*
143  * nm_generic_device_flush_addresses
144  *
145  * Flush all network addresses associated with a network device
146  *
147  */
148 void nm_generic_device_flush_addresses (NMDevice *dev)
149 {
150         g_return_if_fail (dev != NULL);
151
152         /* Not really applicable for test devices */
153         if (nm_device_is_test_device (dev))
154                 return;
155
156         nm_system_device_flush_addresses_with_iface (nm_device_get_iface (dev));
157 }
158
159
160 /*
161  * nm_generic_device_flush_addresses_with_iface
162  *
163  * Flush all network addresses associated with a network device
164  *
165  */
166 void nm_generic_device_flush_addresses_with_iface (const char *iface)
167 {
168         char    *buf;
169
170         g_return_if_fail (iface != NULL);
171
172         /* Remove all IP addresses for a device */
173         buf = g_strdup_printf (IP_BINARY_PATH" addr flush dev %s", iface);
174         nm_spawn_process (buf);
175         g_free (buf);
176 }
177
178 /*
179  * nm_generic_enable_loopback
180  *
181  * Bring up the loopback interface
182  *
183  */
184 void nm_generic_enable_loopback (void)
185 {
186         nm_spawn_process (IP_BINARY_PATH" link set dev lo up");
187         nm_spawn_process (IP_BINARY_PATH" addr add 127.0.0.1/8 brd 127.255.255.255 dev lo scope host label loopback");
188 }
189
190
191 /*
192  * nm_generic_flush_loopback_routes
193  *
194  * Flush all routes associated with the loopback device, because it
195  * sometimes gets the first route for ZeroConf/Link-Local traffic.
196  *
197  */
198 void nm_generic_flush_loopback_routes (void)
199 {
200         nm_system_device_flush_routes_with_iface ("lo");
201 }
202
203
204 /*
205  * nm_generic_delete_default_route
206  *
207  * Remove the old default route in preparation for a new one
208  *
209  */
210 void nm_generic_delete_default_route (void)
211 {
212         nm_spawn_process (IP_BINARY_PATH" route del default");
213 }
214
215
216 /*
217  * nm_generic_flush_arp_cache
218  *
219  * Flush all entries in the arp cache.
220  *
221  */
222 void nm_generic_flush_arp_cache (void)
223 {
224         nm_spawn_process (IP_BINARY_PATH" neigh flush all");
225 }
226
227
228 /*
229  * nm_generic_kill_all_dhcp_daemons
230  *
231  * Kill all DHCP daemons currently running, done at startup.
232  *
233  */
234 void nm_generic_kill_all_dhcp_daemons (void)
235 {
236 }
237
238
239 /*
240  * nm_generic_update_dns
241  *
242  * Make glibc/nscd aware of any changes to the resolv.conf file by
243  * restarting nscd.
244  *
245  */
246 void nm_generic_update_dns (void)
247 {
248 }
249
250
251 /*
252  * nm_generic_restart_mdns_responder
253  *
254  * Restart the multicast DNS responder so that it knows about new
255  * network interfaces and IP addresses.
256  *
257  */
258 void nm_generic_restart_mdns_responder (void)
259 {
260 }
261
262
263 /*
264  * nm_generic_device_add_ip6_link_address
265  *
266  * Add a default link-local IPv6 address to a device.
267  *
268  */
269 void nm_generic_device_add_ip6_link_address (NMDevice *dev)
270 {
271         char *buf;
272         struct ether_addr hw_addr;
273         unsigned char eui[8];
274
275         if (nm_device_is_802_3_ethernet (dev))
276                 nm_device_802_3_ethernet_get_address (NM_DEVICE_802_3_ETHERNET (dev), &hw_addr);
277         else if (nm_device_is_802_11_wireless (dev))
278                 nm_device_802_11_wireless_get_address (NM_DEVICE_802_11_WIRELESS (dev), &hw_addr);
279
280         memcpy (eui, &(hw_addr.ether_addr_octet), sizeof (hw_addr.ether_addr_octet));
281         memmove(eui+5, eui+3, 3);
282         eui[3] = 0xff;
283         eui[4] = 0xfe;
284         eui[0] ^= 2;
285
286         /* Add the default link-local IPv6 address to a device */
287         buf = g_strdup_printf (IP_BINARY_PATH" -6 addr add fe80::%x%02x:%x%02x:%x%02x:%x%02x/64 dev %s",
288                          eui[0], eui[1], eui[2], eui[3],
289                          eui[4], eui[5],
290                          eui[6], eui[7], nm_device_get_iface (dev));
291         nm_spawn_process (buf);
292         g_free (buf);
293 }
294
295 /*
296  * nm_generic_set_ip4_config_from_resolv_conf
297  *
298  * Add nameservers and search names from a resolv.conf format file.
299  *
300  */
301 void nm_generic_set_ip4_config_from_resolv_conf (const char *filename, NMIP4Config *ip4_config)
302 {
303         char *  contents = NULL;
304         char ** split_contents = NULL;
305         int             i, len;
306
307         g_return_if_fail (filename != NULL);
308         g_return_if_fail (ip4_config != NULL);
309
310         if (!g_file_get_contents (filename, &contents, NULL, NULL) || (contents == NULL))
311                 return;
312
313         if (!(split_contents = g_strsplit (contents, "\n", 0)))
314                 goto out;
315         
316         len = g_strv_length (split_contents);
317         for (i = 0; i < len; i++)
318         {
319                 char *line = split_contents[i];
320
321                 /* Ignore comments */
322                 if (!line || (line[0] == ';') || (line[0] == '#'))
323                         continue;
324
325                 line = g_strstrip (line);
326                 if ((strncmp (line, "search", 6) == 0) && (strlen (line) > 6))
327                 {
328                         char *searches = g_strdup (line + 7);
329                         char **split_searches = NULL;
330
331                         if (!searches || !strlen (searches))
332                                 continue;
333
334                         /* Allow space-separated search domains */
335                         if ((split_searches = g_strsplit (searches, " ", 0)))
336                         {
337                                 int m, srch_len;
338
339                                 srch_len = g_strv_length (split_searches);
340                                 for (m = 0; m < srch_len; m++)
341                                 {
342                                         if (split_searches[m])
343                                                 nm_ip4_config_add_domain        (ip4_config, split_searches[m]);
344                                 }
345                                 g_strfreev (split_searches);
346                         }
347                         else
348                         {
349                                 /* Only 1 item, add the whole line */
350                                 nm_ip4_config_add_domain        (ip4_config, searches);
351                         }
352
353                         g_free (searches);
354                 }
355                 else if ((strncmp (line, "nameserver", 10) == 0) && (strlen (line) > 10))
356                 {
357                         guint32 addr = (guint32) (inet_addr (line + 11));
358
359                         if (addr != (guint32) -1)
360                                 nm_ip4_config_add_nameserver (ip4_config, addr);
361                 }
362         }
363
364         g_strfreev (split_contents);
365
366 out:
367         g_free (contents);
368 }
369
370
371 /*
372  * nm_generic_device_get_system_config
373  *
374  * Retrieve any relevant configuration info for a particular device
375  * from the system network configuration information.  Clear out existing
376  * info before setting stuff too.
377  *
378  */
379 void* nm_generic_device_get_system_config (NMDevice *dev, NMData *app_data)
380 {
381         return NULL;
382 }
383
384 /*
385  * nm_generic_device_free_system_config
386  *
387  * Free stored system config data
388  *
389  */
390 void nm_generic_device_free_system_config (NMDevice *dev, void *system_config_data)
391 {
392         return;
393 }
394
395
396 /*
397  * nm_generic_device_get_use_dhcp
398  *
399  * Return whether the distro-specific system config tells us to use
400  * dhcp for this device.
401  *
402  */
403 gboolean nm_generic_device_get_use_dhcp (NMDevice *dev)
404 {
405         return TRUE;
406 }
407
408
409 /*
410  * nm_generic_device_get_disabled
411  *
412  * Return whether the distro-specific system config tells us to use
413  * dhcp for this device.
414  *
415  */
416 gboolean nm_generic_device_get_disabled (NMDevice *dev)
417 {
418         return FALSE;
419 }
420
421
422 NMIP4Config *nm_generic_device_new_ip4_system_config (NMDevice *dev)
423 {
424         return NULL;
425 }
426
427 void nm_generic_deactivate_all_dialup (GSList *list)
428 {
429 }
430
431 gboolean nm_generic_deactivate_dialup (GSList *list, const char *dialup)
432 {
433         return FALSE;
434 }
435
436 gboolean nm_generic_activate_dialup (GSList *list, const char *dialup)
437 {
438         return FALSE;
439 }
440
441 GSList * nm_generic_get_dialup_config (void)
442 {
443         return NULL;
444 }
445
446 /*
447  * nm_generic_activate_nis
448  *
449  * set up the nis domain and write a yp.conf
450  *
451  */
452 void nm_generic_activate_nis (NMIP4Config *config)
453 {
454 }
455
456 /*
457  * nm_generic_shutdown_nis
458  *
459  * shutdown ypbind
460  *
461  */
462 void nm_generic_shutdown_nis (void)
463 {
464 }
465
466 /*
467  * nm_generic_set_hostname
468  *
469  * set the hostname
470  *
471  */
472 void nm_generic_set_hostname (NMIP4Config *config)
473 {
474 }
475
476 /*
477  * nm_generic_should_modify_resolv_conf
478  *
479  * Can NM update resolv.conf, or is it locked down?
480  */
481 gboolean nm_generic_should_modify_resolv_conf (void)
482 {
483         return TRUE;
484 }
485
486
487 /*
488  * nm_generic_get_mtu
489  *
490  * Return a user-provided or system-mandated MTU for this device or zero if
491  * no such MTU is provided.
492  */
493 guint32 nm_generic_get_mtu (NMDevice *dev)
494 {
495         return 0;
496 }