Refactoring of olsr_interface data to if_index instead of name
[oonf.git] / src-api / core / os_linux / os_net_linux.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include <net/if.h>
43 #include <netinet/in.h>
44 #include <sys/ioctl.h>
45 #include <errno.h>
46 #include <ifaddrs.h>
47
48 #include "common/common_types.h"
49
50 #include "olsr_cfg.h"
51 #include "olsr_interface.h"
52 #include "olsr_logging.h"
53 #include "olsr.h"
54 #include "os_net.h"
55
56 static int _ioctl_v4, _ioctl_v6;
57
58 OLSR_SUBSYSTEM_STATE(_os_net_state);
59
60 /**
61  * Initialize os_net subsystem
62  * @return -1 if an error happened, 0 otherwise
63  */
64 int
65 os_net_init(void) {
66   if (olsr_subsystem_is_initialized(&_os_net_state))
67     return 0;
68
69   _ioctl_v4 = socket(AF_INET, SOCK_DGRAM, 0);
70   if (_ioctl_v4 == -1) {
71     OLSR_WARN(LOG_OS_NET, "Cannot open ipv4 ioctl socket: %s (%d)",
72         strerror(errno), errno);
73     return -1;
74   }
75
76   if (config_global.ipv6) {
77     _ioctl_v6 = socket(AF_INET6, SOCK_DGRAM, 0);
78     if (_ioctl_v6 == -1) {
79       OLSR_WARN(LOG_OS_NET, "Cannot open ipv6 ioctl socket: %s (%d)",
80           strerror(errno), errno);
81       close(_ioctl_v4);
82       return -1;
83     }
84   }
85   else {
86     _ioctl_v6 = -1;
87   }
88
89   olsr_subsystem_init(&_os_net_state);
90   return 0;
91 }
92
93 /**
94  * Cleanup os_net subsystem
95  */
96 void
97 os_net_cleanup(void) {
98   if (olsr_subsystem_cleanup(&_os_net_state))
99     return;
100
101   close (_ioctl_v4);
102   if (_ioctl_v6 != -1) {
103     close (_ioctl_v6);
104   }
105 }
106
107 /**
108  * Updates the data of an interface.
109  * @param interf pointer to interface object.
110  * @param name name of interface
111  * @return -1 if an error happened, 0 otherwise
112  */
113 int
114 os_net_update_interface(struct olsr_interface_data *data,
115     uint32_t if_index) {
116   struct ifaddrs *ifaddr, *ifa;
117   union netaddr_socket *sock;
118   struct netaddr addr;
119   struct ifreq ifr;
120
121   memset(data, 0, sizeof(*data));
122
123   data->index = if_index;
124
125   /* get interface index */
126   if_indextoname(if_index, data->name);
127
128   if (getifaddrs(&ifaddr) == -1) {
129     OLSR_WARN(LOG_OS_NET, "Cannot get interface addresses: %s (%d)",
130         strerror(errno), errno);
131     return -1;
132   }
133
134   for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
135     if (strcmp(ifa->ifa_name, data->name) != 0) {
136       continue;
137     }
138
139     sock = (union netaddr_socket *)ifa->ifa_addr;
140
141     if (netaddr_from_socket(&addr, sock)) {
142       /* just ignore other interfaces */
143       continue;
144     }
145
146     if (addr.type == AF_INET) {
147       memcpy(&data->if_v4, &addr, sizeof(data->if_v4));
148     }
149     else if (addr.type == AF_INET6) {
150       if (IN6_IS_ADDR_LINKLOCAL(addr.addr)) {
151         memcpy(&data->linklocal_v6, &addr, sizeof(data->linklocal_v6));
152       }
153       else if (!(IN6_IS_ADDR_LOOPBACK(addr.addr)
154           || IN6_IS_ADDR_MULTICAST(addr.addr)
155           || IN6_IS_ADDR_UNSPECIFIED(addr.addr)
156           || IN6_IS_ADDR_V4COMPAT(addr.addr)
157           || IN6_IS_ADDR_V4MAPPED(addr.addr))) {
158         memcpy(&data->if_v6, &addr, sizeof(data->if_v6));
159       }
160     }
161   }
162   freeifaddrs(ifaddr);
163
164   memset(&ifr, 0, sizeof(ifr));
165   strscpy(ifr.ifr_name, data->name, IF_NAMESIZE);
166
167   if (ioctl(_ioctl_v4, SIOCGIFFLAGS, &ifr) < 0) {
168     OLSR_WARN(LOG_OS_NET,
169         "ioctl SIOCGIFFLAGS (get flags) error on device %s: %s (%d)\n",
170         data->name, strerror(errno), errno);
171     return -1;
172   }
173
174   if ((ifr.ifr_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) {
175     data->up = true;
176   }
177
178   memset(&ifr, 0, sizeof(ifr));
179   strscpy(ifr.ifr_name, data->name, IF_NAMESIZE);
180
181   if (ioctl(_ioctl_v4, SIOCGIFHWADDR, &ifr) < 0) {
182     OLSR_WARN(LOG_OS_NET,
183         "ioctl SIOCGIFHWADDR (get flags) error on device %s: %s (%d)\n",
184         data->name, strerror(errno), errno);
185     return -1;
186   }
187
188   netaddr_from_binary(&data->mac, ifr.ifr_hwaddr.sa_data, 6, AF_MAC48);
189   return 0;
190 }