~kvalo/connman/bug-734339

« back to all changes in this revision

Viewing changes to src/connection.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-05-20 15:35:24 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20100520153524-pnl48c2qpz37z6yx
Tags: 0.52+dfsg-0ubuntu1
New upstream release 0.52

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *
3
3
 *  Connection Manager
4
4
 *
5
 
 *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
 
5
 *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6
6
 *
7
7
 *  This program is free software; you can redistribute it and/or modify
8
8
 *  it under the terms of the GNU General Public License version 2 as
23
23
#include <config.h>
24
24
#endif
25
25
 
26
 
#include <errno.h>
27
 
#include <unistd.h>
28
 
#include <string.h>
29
 
#include <sys/ioctl.h>
30
 
#include <arpa/inet.h>
31
26
#include <net/if.h>
32
 
#include <net/route.h>
33
27
 
34
28
#include <gdbus.h>
35
29
 
69
63
        return NULL;
70
64
}
71
65
 
72
 
static int add_vpn_host(struct connman_element *element,
73
 
                        const char *gateway,
74
 
                        const char *host)
75
 
{
76
 
        struct ifreq ifr;
77
 
        struct rtentry rt;
78
 
        struct sockaddr_in addr;
79
 
        int sk, err;
80
 
 
81
 
        DBG("element %p", element);
82
 
 
83
 
        sk = socket(PF_INET, SOCK_DGRAM, 0);
84
 
        if (sk < 0)
85
 
                return -1;
86
 
 
87
 
        memset(&ifr, 0, sizeof(ifr));
88
 
        ifr.ifr_ifindex = element->index;
89
 
 
90
 
        if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
91
 
                close(sk);
92
 
                return -1;
93
 
        }
94
 
        DBG("ifname %s", ifr.ifr_name);
95
 
 
96
 
        memset(&rt, 0, sizeof(rt));
97
 
        rt.rt_flags = RTF_UP | RTF_HOST | RTF_GATEWAY;
98
 
 
99
 
        memset(&addr, 0, sizeof(addr));
100
 
        addr.sin_family = AF_INET;
101
 
        addr.sin_addr.s_addr = inet_addr(host);
102
 
        memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
103
 
 
104
 
        memset(&addr, 0, sizeof(addr));
105
 
        addr.sin_family = AF_INET;
106
 
        addr.sin_addr.s_addr = inet_addr(gateway);
107
 
        memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
108
 
 
109
 
        memset(&addr, 0, sizeof(addr));
110
 
        addr.sin_family = AF_INET;
111
 
        addr.sin_addr.s_addr = INADDR_NONE;
112
 
        memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
113
 
 
114
 
        rt.rt_dev = ifr.ifr_name;
115
 
 
116
 
        err = ioctl(sk, SIOCADDRT, &rt);
117
 
        if (err < 0)
118
 
                connman_error("Setting VPN host failed (%s)",
119
 
                              strerror(errno));
120
 
 
121
 
        close(sk);
122
 
 
123
 
        return err;
124
 
}
125
 
 
126
 
static int del_vpn_host(const char *host)
127
 
{
128
 
        struct rtentry rt;
129
 
        struct sockaddr_in addr;
130
 
        int sk, err;
131
 
 
132
 
        sk = socket(PF_INET, SOCK_DGRAM, 0);
133
 
        if (sk < 0)
134
 
                return -1;
135
 
 
136
 
        memset(&rt, 0, sizeof(rt));
137
 
        rt.rt_flags = RTF_UP | RTF_HOST;
138
 
 
139
 
        memset(&addr, 0, sizeof(addr));
140
 
        addr.sin_family = AF_INET;
141
 
        addr.sin_addr.s_addr = inet_addr(host);
142
 
        memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
143
 
 
144
 
        err = ioctl(sk, SIOCDELRT, &rt);
145
 
        if (err < 0)
146
 
                connman_error("Del vpn route failed (%s)",
147
 
                              strerror(errno));
148
 
 
149
 
        close(sk);
150
 
 
151
 
        return err;
152
 
}
153
 
 
154
 
static int set_vpn_route(struct connman_element *element, const char *gateway)
155
 
{
156
 
        struct ifreq ifr;
157
 
        struct rtentry rt;
158
 
        struct sockaddr_in addr;
159
 
        int sk, err;
160
 
 
161
 
        DBG("set_rout1: element %p", element);
162
 
 
163
 
        sk = socket(PF_INET, SOCK_DGRAM, 0);
164
 
        if (sk < 0)
165
 
                return -1;
166
 
 
167
 
        memset(&ifr, 0, sizeof(ifr));
168
 
        ifr.ifr_ifindex = element->index;
169
 
 
170
 
        if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
171
 
                close(sk);
172
 
                return -1;
173
 
        }
174
 
 
175
 
        DBG("ifname %s", ifr.ifr_name);
176
 
 
177
 
        memset(&ifr, 0, sizeof(ifr));
178
 
        ifr.ifr_ifindex = element->index;
179
 
 
180
 
        memset(&rt, 0, sizeof(rt));
181
 
        rt.rt_flags = RTF_UP | RTF_GATEWAY;
182
 
 
183
 
        memset(&addr, 0, sizeof(addr));
184
 
        addr.sin_family = AF_INET;
185
 
        addr.sin_addr.s_addr = INADDR_ANY;
186
 
        memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
187
 
 
188
 
        memset(&addr, 0, sizeof(addr));
189
 
        addr.sin_family = AF_INET;
190
 
        addr.sin_addr.s_addr = inet_addr(gateway);
191
 
        memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
192
 
 
193
 
        memset(&addr, 0, sizeof(addr));
194
 
        addr.sin_family = AF_INET;
195
 
        addr.sin_addr.s_addr = INADDR_ANY;
196
 
        memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
197
 
 
198
 
        err = ioctl(sk, SIOCADDRT, &rt);
199
 
        if (err < 0)
200
 
                connman_error("Setting VPN route failed (%s)",
201
 
                               strerror(errno));
202
 
 
203
 
        close(sk);
204
 
 
205
 
        return err;
206
 
}
207
 
 
208
 
static int del_route(struct connman_element *element, const char *gateway)
209
 
{
210
 
        struct ifreq ifr;
211
 
        struct rtentry rt;
212
 
        struct sockaddr_in addr;
213
 
        int sk, err;
214
 
 
215
 
        DBG("element %p", element);
216
 
 
217
 
        sk = socket(PF_INET, SOCK_DGRAM, 0);
218
 
        if (sk < 0)
219
 
                return -1;
220
 
 
221
 
        memset(&ifr, 0, sizeof(ifr));
222
 
        ifr.ifr_ifindex = element->index;
223
 
 
224
 
        if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
225
 
                close(sk);
226
 
                return -1;
227
 
        }
228
 
 
229
 
        DBG("ifname %s", ifr.ifr_name);
230
 
 
231
 
        memset(&rt, 0, sizeof(rt));
232
 
        rt.rt_flags = RTF_UP | RTF_GATEWAY;
233
 
 
234
 
        memset(&addr, 0, sizeof(addr));
235
 
        addr.sin_family = AF_INET;
236
 
        addr.sin_addr.s_addr = INADDR_ANY;
237
 
        memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
238
 
 
239
 
        memset(&addr, 0, sizeof(addr));
240
 
        addr.sin_family = AF_INET;
241
 
        addr.sin_addr.s_addr = inet_addr(gateway);
242
 
        memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
243
 
 
244
 
        memset(&addr, 0, sizeof(addr));
245
 
        addr.sin_family = AF_INET;
246
 
        addr.sin_addr.s_addr = INADDR_ANY;
247
 
        memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
248
 
 
249
 
        err = ioctl(sk, SIOCDELRT, &rt);
250
 
        if (err < 0)
251
 
                connman_error("Removing default route failed (%s)",
252
 
                                                        strerror(errno));
253
 
 
254
 
        close(sk);
255
 
 
256
 
        return err;
257
 
}
258
 
 
259
 
static int del_route_all(struct gateway_data *data)
260
 
{
261
 
        int err = 0;
262
 
 
263
 
        if (data->vpn) {
264
 
                del_vpn_host(data->gateway);
265
 
 
266
 
                err = del_route(data->element, data->vpn_ip);
267
 
        } else
268
 
                err = del_route(data->element, data->gateway);
269
 
 
270
 
        return err;
 
66
static int del_routes(struct gateway_data *data)
 
67
{
 
68
        const char *address;
 
69
 
 
70
        connman_inet_del_host_route(data->index, data->gateway);
 
71
 
 
72
        if (data->vpn)
 
73
                address = data->vpn_ip;
 
74
        else
 
75
                address = data->gateway;
 
76
 
 
77
        return connman_inet_clear_gateway_address(data->index, address);
271
78
}
272
79
 
273
80
static void find_element(struct connman_element *element, gpointer user_data)
334
141
        DBG("gateway %s", data->gateway);
335
142
 
336
143
        if (data->vpn == TRUE) {
337
 
 
338
 
                set_vpn_route(element, data->vpn_ip);
 
144
                connman_inet_set_gateway_address(data->index, data->vpn_ip);
339
145
                /* vpn gateway going away no changes in services */
340
146
                return;
341
147
        }
352
158
                goto done;
353
159
        }
354
160
 
 
161
        connman_inet_add_host_route(element->index, data->gateway);
 
162
 
355
163
        if (connman_inet_set_gateway_address(element->index, data->gateway) < 0)
356
164
                return;
357
165
 
385
193
        gateway_list = g_slist_remove(gateway_list, data);
386
194
 
387
195
        if (data->active == TRUE)
388
 
                del_route_all(data);
 
196
                del_routes(data);
389
197
 
390
198
        g_free(data->gateway);
391
199
        g_free(data->vpn_ip);
441
249
        if (element->parent == NULL)
442
250
                return -ENODEV;
443
251
 
444
 
        if (element->parent->type != CONNMAN_ELEMENT_TYPE_IPV4)
445
 
                return -ENODEV;
 
252
        /* FIXME: Remove temporarily for the static gateway support */
 
253
        /* if (element->parent->type != CONNMAN_ELEMENT_TYPE_IPV4)
 
254
                return -ENODEV; */
446
255
 
447
256
        connman_element_get_value(element,
448
257
                                CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway);
478
287
        }
479
288
 
480
289
        if (new_gateway->vpn == TRUE) {
481
 
                add_vpn_host(active_gateway->element,
482
 
                             active_gateway->gateway,
483
 
                             new_gateway->gateway);
 
290
                connman_inet_add_host_route_vpn(active_gateway->index,
 
291
                                                active_gateway->gateway,
 
292
                                                new_gateway->gateway);
484
293
 
 
294
                connman_inet_set_gateway_address(new_gateway->index,
 
295
                                                        new_gateway->gateway);
485
296
        }
486
297
 
487
298
        if (new_gateway->order >= active_gateway->order) {
488
 
                del_route_all(active_gateway);
 
299
                del_routes(active_gateway);
489
300
                return 0;
490
301
        }
491
302
 
522
333
        set_default = data->vpn;
523
334
 
524
335
        if (data->vpn == TRUE)
525
 
                del_vpn_host(data->gateway);
 
336
                connman_inet_del_host_route(data->index, data->gateway);
526
337
 
527
338
        remove_gateway(data);
528
339
 
607
418
        default_gateway = find_default_gateway();
608
419
 
609
420
        if (active_gateway && active_gateway != default_gateway) {
610
 
                del_route_all(active_gateway);
 
421
                del_routes(active_gateway);
611
422
                updated = TRUE;
612
423
        }
613
424