trivial: netlink header cleanup
[NetworkManager.git] / src / nm-netlink.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /* NetworkManager -- Network link manager
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * Copyright (C) 2007 - 2008 Red Hat, Inc.
19  */
20
21 #include "config.h"
22
23 #include "nm-netlink.h"
24 #include "nm-logging.h"
25
26 #include <glib.h>
27 #include <signal.h>
28 #include <pthread.h>
29 #include <unistd.h>
30 #include <netlink/object-api.h>
31 #include <netlink/route/addr.h>
32
33 static struct nl_cache * link_cache = NULL;
34 static struct nl_handle * def_nl_handle = NULL;
35
36
37 static struct nl_cache *
38 get_link_cache (void)
39 {
40         struct nl_handle * nlh;
41
42         nlh = nm_netlink_get_default_handle ();
43         if (G_UNLIKELY (!nlh)) {
44                 nm_log_err (LOGD_HW, "couldn't allocate netlink handle.");
45                 return NULL;
46         }
47
48         if (G_UNLIKELY (!link_cache))
49                 link_cache = rtnl_link_alloc_cache (nlh);
50
51         if (G_UNLIKELY (!link_cache)) {
52                 nm_log_err (LOGD_HW, "couldn't allocate netlink link cache: %s", nl_geterror ());
53                 return NULL;
54         }
55
56         nl_cache_update (nlh, link_cache);
57         return link_cache;
58 }
59
60
61 struct nl_handle *
62 nm_netlink_get_default_handle (void)
63 {
64         struct nl_cb *cb;
65 #ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND
66         struct nl_cache *addr_cache;
67 #endif
68
69         if (def_nl_handle)
70                 return def_nl_handle;
71
72         cb = nl_cb_alloc(NL_CB_VERBOSE);
73         def_nl_handle = nl_handle_alloc_cb (cb);
74         if (!def_nl_handle) {
75                 nm_log_err (LOGD_HW, "couldn't allocate netlink handle.");
76                 return NULL;
77         }
78
79         if (nl_connect (def_nl_handle, NETLINK_ROUTE) < 0) {
80                 nm_log_err (LOGD_HW, "couldn't connect to netlink: %s", nl_geterror ());
81                 return NULL;
82         }
83
84 #ifdef LIBNL_NEEDS_ADDR_CACHING_WORKAROUND
85         /* Work around apparent libnl bug; rtnl_addr requires that all
86          * addresses have the "peer" attribute set in order to be compared
87          * for equality, but this attribute is not normally set. As a
88          * result, most addresses will not compare as equal even to
89          * themselves, busting caching.
90          */
91         addr_cache = rtnl_addr_alloc_cache (def_nl_handle);
92         nl_cache_get_ops (addr_cache)->co_obj_ops->oo_id_attrs &= ~0x80;
93         nl_cache_free (addr_cache);
94 #endif
95
96         return def_nl_handle;
97 }
98
99 int
100 nm_netlink_iface_to_index (const char *iface)
101 {
102         struct nl_cache * cache;
103
104         g_return_val_if_fail (iface != NULL, -1);
105
106         cache = get_link_cache ();
107         if (!cache)
108                 return RTNL_LINK_NOT_FOUND;
109
110         return rtnl_link_name2i (cache, iface);
111 }
112
113
114 #define MAX_IFACE_LEN   33
115 char *
116 nm_netlink_index_to_iface (int idx)
117 {
118         struct nl_cache * cache;
119         char * buf = NULL;
120
121         cache = get_link_cache ();
122         if (!cache)
123                 return NULL;
124
125         buf = g_malloc0 (MAX_IFACE_LEN);
126         if (buf == NULL) {
127                 nm_log_warn (LOGD_HW, "Not enough memory to allocate interface name buffer.");
128                 return NULL;
129         }
130
131         if (rtnl_link_i2name (cache, idx, buf, MAX_IFACE_LEN - 1) == NULL) {
132                 g_free (buf);
133                 buf = NULL;
134         }
135
136         return buf;
137 }
138
139 struct rtnl_link *
140 nm_netlink_index_to_rtnl_link (int idx)
141 {
142         struct nl_cache *cache;
143
144         cache = get_link_cache ();
145         if (!cache)
146                 return NULL;
147
148         return rtnl_link_get (cache, idx);
149 }
150