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