Add support to get PMF information
[platform/upstream/connman.git] / src / ipaddress.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
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 version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <glib.h>
31
32 #include <connman/ipaddress.h>
33
34 #include "connman.h"
35
36 unsigned char connman_ipaddress_calc_netmask_len(const char *netmask)
37 {
38         unsigned char bits;
39         in_addr_t mask;
40         in_addr_t host;
41
42         if (!netmask)
43                 return 32;
44
45         mask = inet_network(netmask);
46         host = ~mask;
47
48         /* a valid netmask must be 2^n - 1 */
49         if ((host & (host + 1)) != 0)
50                 return -1;
51
52         bits = 0;
53         for (; mask; mask <<= 1)
54                 ++bits;
55
56         return bits;
57 }
58
59 struct connman_ipaddress *connman_ipaddress_alloc(int family)
60 {
61         struct connman_ipaddress *ipaddress;
62
63         ipaddress = g_try_new0(struct connman_ipaddress, 1);
64         if (!ipaddress)
65                 return NULL;
66
67         ipaddress->family = family;
68         ipaddress->prefixlen = 0;
69         ipaddress->local = NULL;
70         ipaddress->peer = NULL;
71         ipaddress->broadcast = NULL;
72         ipaddress->gateway = NULL;
73
74         return ipaddress;
75 }
76
77 void connman_ipaddress_free(struct connman_ipaddress *ipaddress)
78 {
79         if (!ipaddress)
80                 return;
81
82         g_free(ipaddress->broadcast);
83         g_free(ipaddress->peer);
84         g_free(ipaddress->local);
85         g_free(ipaddress->gateway);
86         g_free(ipaddress);
87 }
88
89 static bool check_ipv6_address(const char *address)
90 {
91         unsigned char buf[sizeof(struct in6_addr)];
92         int err;
93
94         if (!address)
95                 return false;
96
97         err = inet_pton(AF_INET6, address, buf);
98         if (err > 0)
99                 return true;
100
101         return false;
102 }
103
104 int connman_ipaddress_set_ipv6(struct connman_ipaddress *ipaddress,
105                                 const char *address,
106                                 unsigned char prefix_length,
107                                 const char *gateway)
108 {
109         if (!ipaddress)
110                 return -EINVAL;
111
112         if (!check_ipv6_address(address))
113                 return -EINVAL;
114
115         DBG("prefix_len %d address %s gateway %s",
116                         prefix_length, address, gateway);
117
118         ipaddress->family = AF_INET6;
119
120         ipaddress->prefixlen = prefix_length;
121
122         g_free(ipaddress->local);
123         ipaddress->local = g_strdup(address);
124
125         g_free(ipaddress->gateway);
126         ipaddress->gateway = g_strdup(gateway);
127
128         return 0;
129 }
130
131 int connman_ipaddress_get_ip(struct connman_ipaddress *ipaddress,
132                         const char **address,
133                         unsigned char *netmask_prefix_length)
134 {
135         if (!ipaddress)
136                 return -EINVAL;
137
138         *netmask_prefix_length = ipaddress->prefixlen;
139         *address = ipaddress->local;
140
141         return 0;
142 }
143
144 int connman_ipaddress_set_ipv4(struct connman_ipaddress *ipaddress,
145                 const char *address, const char *netmask, const char *gateway)
146 {
147         if (!ipaddress)
148                 return -EINVAL;
149
150         ipaddress->family = AF_INET;
151
152         ipaddress->prefixlen = connman_ipaddress_calc_netmask_len(netmask);
153
154         g_free(ipaddress->local);
155         ipaddress->local = g_strdup(address);
156
157         g_free(ipaddress->gateway);
158         ipaddress->gateway = g_strdup(gateway);
159
160         return 0;
161 }
162
163 void connman_ipaddress_set_peer(struct connman_ipaddress *ipaddress,
164                                 const char *peer)
165 {
166         if (!ipaddress)
167                 return;
168
169         g_free(ipaddress->peer);
170         ipaddress->peer = g_strdup(peer);
171 }
172
173 void connman_ipaddress_clear(struct connman_ipaddress *ipaddress)
174 {
175         if (!ipaddress)
176                 return;
177
178         ipaddress->prefixlen = 0;
179
180         g_free(ipaddress->local);
181         ipaddress->local = NULL;
182
183         g_free(ipaddress->peer);
184         ipaddress->peer = NULL;
185
186         g_free(ipaddress->broadcast);
187         ipaddress->broadcast = NULL;
188
189         g_free(ipaddress->gateway);
190         ipaddress->gateway = NULL;
191 }
192
193 /*
194  * Note that this copy function only copies the actual address and
195  * prefixlen. Use the other copy function to copy the whole struct.
196  */
197 void connman_ipaddress_copy_address(struct connman_ipaddress *ipaddress,
198                                         struct connman_ipaddress *source)
199 {
200         if (!ipaddress || !source)
201                 return;
202
203         ipaddress->family = source->family;
204         ipaddress->prefixlen = source->prefixlen;
205
206         g_free(ipaddress->local);
207         ipaddress->local = g_strdup(source->local);
208 }
209
210 struct connman_ipaddress *
211 connman_ipaddress_copy(struct connman_ipaddress *ipaddress)
212 {
213         struct connman_ipaddress *copy;
214
215         if (!ipaddress)
216                 return NULL;
217
218         copy = g_new0(struct connman_ipaddress, 1);
219
220         copy->family = ipaddress->family;
221         copy->prefixlen = ipaddress->prefixlen;
222         copy->local = g_strdup(ipaddress->local);
223         copy->peer = g_strdup(ipaddress->peer);
224         copy->broadcast = g_strdup(ipaddress->broadcast);
225         copy->gateway = g_strdup(ipaddress->gateway);
226
227         return copy;
228 }