service: Disconnect the connecting service when needed
[platform/upstream/connman.git] / src / ipaddress.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  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 struct connman_ipaddress *connman_ipaddress_alloc(int family)
37 {
38         struct connman_ipaddress *ipaddress;
39
40         ipaddress = g_try_new0(struct connman_ipaddress, 1);
41         if (ipaddress == NULL)
42                 return NULL;
43
44         ipaddress->family = family;
45         ipaddress->prefixlen = 0;
46         ipaddress->local = NULL;
47         ipaddress->peer = NULL;
48         ipaddress->broadcast = NULL;
49         ipaddress->gateway = NULL;
50
51         return ipaddress;
52 }
53
54 void connman_ipaddress_free(struct connman_ipaddress *ipaddress)
55 {
56         if (ipaddress == NULL)
57                 return;
58
59         g_free(ipaddress->broadcast);
60         g_free(ipaddress->peer);
61         g_free(ipaddress->local);
62         g_free(ipaddress->gateway);
63         g_free(ipaddress);
64 }
65
66 unsigned char __connman_ipaddress_netmask_prefix_len(const char *netmask)
67 {
68         unsigned char bits;
69         in_addr_t mask;
70         in_addr_t host;
71
72         if (netmask == NULL)
73                 return 32;
74
75         mask = inet_network(netmask);
76         host = ~mask;
77
78         /* a valid netmask must be 2^n - 1 */
79         if ((host & (host + 1)) != 0)
80                 return -1;
81
82         bits = 0;
83         for (; mask; mask <<= 1)
84                 ++bits;
85
86         return bits;
87 }
88
89 static gboolean check_ipv6_address(const char *address)
90 {
91         unsigned char buf[sizeof(struct in6_addr)];
92         int err;
93
94         if (address == NULL)
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 == NULL)
110                 return -EINVAL;
111
112         if (check_ipv6_address(address) == FALSE)
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_set_ipv4(struct connman_ipaddress *ipaddress,
132                 const char *address, const char *netmask, const char *gateway)
133 {
134         if (ipaddress == NULL)
135                 return -EINVAL;
136
137         ipaddress->family = AF_INET;
138
139         ipaddress->prefixlen = __connman_ipaddress_netmask_prefix_len(netmask);
140
141         g_free(ipaddress->local);
142         ipaddress->local = g_strdup(address);
143
144         g_free(ipaddress->gateway);
145         ipaddress->gateway = g_strdup(gateway);
146
147         return 0;
148 }
149
150 void connman_ipaddress_set_peer(struct connman_ipaddress *ipaddress,
151                                 const char *peer)
152 {
153         if (ipaddress == NULL)
154                 return;
155
156         g_free(ipaddress->peer);
157         ipaddress->peer = g_strdup(peer);
158 }
159
160 void connman_ipaddress_clear(struct connman_ipaddress *ipaddress)
161 {
162         if (ipaddress == NULL)
163                 return;
164
165         ipaddress->prefixlen = 0;
166
167         g_free(ipaddress->local);
168         ipaddress->local = NULL;
169
170         g_free(ipaddress->peer);
171         ipaddress->peer = NULL;
172
173         g_free(ipaddress->broadcast);
174         ipaddress->broadcast = NULL;
175
176         g_free(ipaddress->gateway);
177         ipaddress->gateway = NULL;
178 }
179
180 /*
181  * Note that this copy function only copies the actual address and
182  * prefixlen. If you need full copy of ipaddress struct, then you need
183  * to create a new function that does that.
184  */
185 void connman_ipaddress_copy_address(struct connman_ipaddress *ipaddress,
186                                         struct connman_ipaddress *source)
187 {
188         if (ipaddress == NULL || source == NULL)
189                 return;
190
191         ipaddress->family = source->family;
192         ipaddress->prefixlen = source->prefixlen;
193
194         g_free(ipaddress->local);
195         ipaddress->local = g_strdup(source->local);
196 }