notifier: Add proxy changed hook
[platform/upstream/connman.git] / src / ipv4.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  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 <unistd.h>
27 #include <string.h>
28 #include <sys/ioctl.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <net/if.h>
33 #include <asm/types.h>
34 #include <linux/netlink.h>
35 #include <linux/rtnetlink.h>
36
37 #include "connman.h"
38
39 static int ipv4_probe(struct connman_element *element)
40 {
41         struct connman_service *service;
42         struct connman_ipconfig *ipconfig;
43         struct connman_element *connection;
44         const char *address = NULL, *netmask = NULL, *broadcast = NULL;
45         const char *peer = NULL, *nameserver = NULL, *pac = NULL;
46         char *timeserver = NULL;
47         unsigned char prefixlen;
48
49         DBG("element %p name %s", element, element->name);
50         connman_element_get_value(element,
51                                 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address);
52         connman_element_get_value(element,
53                                 CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
54         connman_element_get_value(element,
55                                 CONNMAN_PROPERTY_ID_IPV4_BROADCAST, &broadcast);
56         connman_element_get_value(element,
57                                 CONNMAN_PROPERTY_ID_IPV4_PEER, &peer);
58
59         connman_element_get_value(element,
60                         CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
61         connman_element_get_value(element,
62                         CONNMAN_PROPERTY_ID_IPV4_TIMESERVER, &timeserver);
63         connman_element_get_value(element,
64                         CONNMAN_PROPERTY_ID_IPV4_PAC, &pac);
65
66         DBG("address %s", address);
67         DBG("peer %s", peer);
68         DBG("netmask %s", netmask);
69         DBG("broadcast %s", broadcast);
70
71         if (address == NULL)
72                 return -EINVAL;
73
74         prefixlen = __connman_ipconfig_netmask_prefix_len(netmask);
75
76         if ((__connman_inet_modify_address(RTM_NEWADDR,
77                         NLM_F_REPLACE | NLM_F_ACK, element->index,
78                         AF_INET, address, peer, prefixlen, broadcast)) < 0)
79                 DBG("address setting failed");
80
81         service = __connman_element_get_service(element);
82
83         if (pac != NULL)
84                 __connman_service_set_proxy_autoconfig(service, pac);
85
86         if (nameserver != NULL)
87                 __connman_service_append_nameserver(service, nameserver);
88
89         connman_timeserver_append(timeserver);
90
91         connection = connman_element_create(NULL);
92
93         connection->type    = CONNMAN_ELEMENT_TYPE_CONNECTION;
94         connection->index   = element->index;
95         connection->devname = connman_inet_ifname(element->index);
96
97         ipconfig = __connman_service_get_ip6config(service);
98         if (ipconfig != NULL)
99                 __connman_ipconfig_set_element_ipv6_gateway(
100                                                 ipconfig, connection);
101
102         if (connman_element_register(connection, element) < 0)
103                 connman_element_unref(connection);
104
105         return 0;
106 }
107
108 static void ipv4_remove(struct connman_element *element)
109 {
110         const char *address = NULL, *netmask = NULL, *broadcast = NULL;
111         const char *peer = NULL, *nameserver = NULL;
112         char *timeserver = NULL;
113         unsigned char prefixlen;
114
115         DBG("element %p name %s", element, element->name);
116
117         connman_element_get_value(element,
118                                 CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address);
119         connman_element_get_value(element,
120                                 CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask);
121         connman_element_get_value(element,
122                                 CONNMAN_PROPERTY_ID_IPV4_BROADCAST, &broadcast);
123         connman_element_get_value(element,
124                                 CONNMAN_PROPERTY_ID_IPV4_PEER, &peer);
125
126         connman_element_get_value(element,
127                         CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, &nameserver);
128         connman_element_get_value(element,
129                         CONNMAN_PROPERTY_ID_IPV4_TIMESERVER, &timeserver);
130
131         connman_timeserver_remove(timeserver);
132
133         DBG("address %s", address);
134         DBG("peer %s", peer);
135         DBG("netmask %s", netmask);
136         DBG("broadcast %s", broadcast);
137
138         if (nameserver != NULL) {
139                 struct connman_service *service;
140
141                 service = __connman_element_get_service(element);
142                 __connman_service_remove_nameserver(service, nameserver);
143         }
144
145         prefixlen = __connman_ipconfig_netmask_prefix_len(netmask);
146
147         if ((__connman_inet_modify_address(RTM_DELADDR, 0, element->index,
148                         AF_INET, address, peer, prefixlen, broadcast) < 0))
149                 DBG("address removal failed");
150
151         connman_element_unref(element);
152 }
153
154 static struct connman_driver ipv4_driver = {
155         .name           = "ipv4",
156         .type           = CONNMAN_ELEMENT_TYPE_IPV4,
157         .priority       = CONNMAN_DRIVER_PRIORITY_LOW,
158         .probe          = ipv4_probe,
159         .remove         = ipv4_remove,
160 };
161
162 int __connman_ipv4_init(void)
163 {
164         return connman_driver_register(&ipv4_driver);
165 }
166
167 void __connman_ipv4_cleanup(void)
168 {
169         connman_driver_unregister(&ipv4_driver);
170 }