5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
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.
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.
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
33 enum connman_dhcp_state state;
35 struct connman_element *element;
37 struct connman_dhcp_driver *driver;
43 * @dhcp: DHCP structure
45 * Increase reference counter of DHCP
47 struct connman_dhcp *connman_dhcp_ref(struct connman_dhcp *dhcp)
49 g_atomic_int_inc(&dhcp->refcount);
56 * @dhcp: DHCP structure
58 * Decrease reference counter of DHCP
60 void connman_dhcp_unref(struct connman_dhcp *dhcp)
62 if (g_atomic_int_dec_and_test(&dhcp->refcount) == TRUE)
67 * connman_dhcp_get_index:
68 * @dhcp: DHCP structure
70 * Get network index of DHCP
72 int connman_dhcp_get_index(struct connman_dhcp *dhcp)
78 * connman_dhcp_get_interface:
79 * @dhcp: DHCP structure
81 * Get network interface of DHCP
83 char *connman_dhcp_get_interface(struct connman_dhcp *dhcp)
85 return connman_inet_ifname(dhcp->index);
89 * connman_dhcp_set_value:
90 * @dhcp: DHCP structure
91 * @key: unique identifier
92 * @value: string value
94 * Set string value for specific key
96 void connman_dhcp_set_value(struct connman_dhcp *dhcp,
97 const char *key, const char *value)
101 if (g_strcmp0(key, "Address") == 0) {
102 g_free(dhcp->element->ipv4.address);
103 dhcp->element->ipv4.address = g_strdup(value);
104 } else if (g_strcmp0(key, "Netmask") == 0) {
105 g_free(dhcp->element->ipv4.netmask);
106 dhcp->element->ipv4.netmask = g_strdup(value);
107 } else if (g_strcmp0(key, "Gateway") == 0) {
108 g_free(dhcp->element->ipv4.gateway);
109 dhcp->element->ipv4.gateway = g_strdup(value);
110 } else if (g_strcmp0(key, "Network") == 0) {
111 g_free(dhcp->element->ipv4.network);
112 dhcp->element->ipv4.network = g_strdup(value);
113 } else if (g_strcmp0(key, "Broadcast") == 0) {
114 g_free(dhcp->element->ipv4.broadcast);
115 dhcp->element->ipv4.broadcast = g_strdup(value);
116 } else if (g_strcmp0(key, "Nameserver") == 0) {
117 g_free(dhcp->element->ipv4.nameserver);
118 nameservers = g_strsplit_set(value, " ", 0);
119 /* FIXME: The ipv4 structure can only hold one nameserver, so
120 * we are only able to pass along the first nameserver sent by
121 * the DHCP server. If this situation changes, we should
122 * retain all of them.
124 dhcp->element->ipv4.nameserver = g_strdup(nameservers[0]);
125 g_strfreev(nameservers);
126 } else if (g_strcmp0(key, "Domainname") == 0) {
127 g_free(dhcp->element->domainname);
128 dhcp->element->domainname = g_strdup(value);
130 __connman_utsname_set_domainname(value);
131 } else if (g_strcmp0(key, "Hostname") == 0) {
132 g_free(dhcp->element->hostname);
133 dhcp->element->hostname = g_strdup(value);
135 __connman_utsname_set_hostname(value);
136 } else if (g_strcmp0(key, "Timeserver") == 0) {
137 connman_info("Timeserver %s", value);
139 g_free(dhcp->element->ipv4.timeserver);
140 dhcp->element->ipv4.timeserver = g_strdup(value);
141 } else if (g_strcmp0(key, "MTU") == 0) {
142 } else if (g_strcmp0(key, "PAC") == 0) {
143 connman_info("PAC configuration %s", value);
145 g_free(dhcp->element->ipv4.pac);
146 dhcp->element->ipv4.pac = g_strdup(value);
151 * connman_dhcp_bound:
152 * @dhcp: DHCP structure
154 * Report successful bound of the interface
156 void connman_dhcp_bound(struct connman_dhcp *dhcp)
158 struct connman_element *element;
160 DBG("dhcp %p", dhcp);
162 element = connman_element_create(NULL);
166 element->type = CONNMAN_ELEMENT_TYPE_IPV4;
167 element->index = dhcp->index;
169 connman_element_update(dhcp->element);
171 if (connman_element_register(element, dhcp->element) < 0)
172 connman_element_unref(element);
176 * connman_dhcp_renew:
177 * @dhcp: DHCP structure
179 * Report successful renew of the interface
181 void connman_dhcp_renew(struct connman_dhcp *dhcp)
183 DBG("dhcp %p", dhcp);
185 connman_element_update(dhcp->element);
190 * @dhcp: DHCP structure
192 * Report DHCP failure of the interface
194 void connman_dhcp_fail(struct connman_dhcp *dhcp)
196 DBG("dhcp %p", dhcp);
198 connman_element_set_error(dhcp->element,
199 CONNMAN_ELEMENT_ERROR_FAILED);
203 * connman_dhcp_get_data:
204 * @dhcp: DHCP structure
206 * Get private DHCP data pointer
208 void *connman_dhcp_get_data(struct connman_dhcp *dhcp)
210 return dhcp->driver_data;
214 * connman_dhcp_set_data:
215 * @dhcp: DHCP structure
216 * @data: data pointer
218 * Set private DHCP data pointer
220 void connman_dhcp_set_data(struct connman_dhcp *dhcp, void *data)
222 dhcp->driver_data = data;
225 static GSList *driver_list = NULL;
227 static gint compare_priority(gconstpointer a, gconstpointer b)
229 const struct connman_dhcp_driver *driver1 = a;
230 const struct connman_dhcp_driver *driver2 = b;
232 return driver2->priority - driver1->priority;
236 * connman_dhcp_driver_register:
237 * @driver: DHCP driver definition
239 * Register a new DHCP driver
241 * Returns: %0 on success
243 int connman_dhcp_driver_register(struct connman_dhcp_driver *driver)
245 DBG("driver %p name %s", driver, driver->name);
247 driver_list = g_slist_insert_sorted(driver_list, driver,
254 * connman_dhcp_driver_unregister:
255 * @driver: DHCP driver definition
257 * Remove a previously registered DHCP driver
259 void connman_dhcp_driver_unregister(struct connman_dhcp_driver *driver)
261 DBG("driver %p name %s", driver, driver->name);
263 driver_list = g_slist_remove(driver_list, driver);
266 static int dhcp_probe(struct connman_element *element)
268 struct connman_dhcp *dhcp;
271 DBG("element %p name %s", element, element->name);
273 dhcp = g_try_new0(struct connman_dhcp, 1);
278 dhcp->index = element->index;
279 dhcp->state = CONNMAN_DHCP_STATE_IDLE;
281 dhcp->element = element;
283 connman_element_set_data(element, dhcp);
285 for (list = driver_list; list; list = list->next) {
286 struct connman_dhcp_driver *driver = list->data;
288 DBG("driver %p name %s", driver, driver->name);
290 if (driver->request(dhcp) == 0) {
291 dhcp->driver = driver;
296 if (dhcp->driver == NULL) {
297 connman_dhcp_unref(dhcp);
304 static void dhcp_remove(struct connman_element *element)
306 struct connman_dhcp *dhcp = connman_element_get_data(element);
308 DBG("element %p name %s", element, element->name);
310 connman_element_set_data(element, NULL);
313 dhcp->driver->release(dhcp);
317 connman_dhcp_unref(dhcp);
320 static void dhcp_change(struct connman_element *element)
322 DBG("element %p name %s", element, element->name);
324 if (element->state == CONNMAN_ELEMENT_STATE_ERROR)
325 connman_element_set_error(element->parent,
326 CONNMAN_ELEMENT_ERROR_DHCP_FAILED);
329 static struct connman_driver dhcp_driver = {
331 .type = CONNMAN_ELEMENT_TYPE_DHCP,
332 .priority = CONNMAN_DRIVER_PRIORITY_LOW,
334 .remove = dhcp_remove,
335 .change = dhcp_change,
338 int __connman_dhcp_init(void)
340 return connman_driver_register(&dhcp_driver);
343 void __connman_dhcp_cleanup(void)
345 connman_driver_unregister(&dhcp_driver);