Initial dhcp-lib based dhcp plugin
[framework/connectivity/connman.git] / plugins / dhcp.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 <stdio.h>
27 #include <errno.h>
28 #include <string.h>
29
30 #define CONNMAN_API_SUBJECT_TO_CHANGE
31 #include <connman/plugin.h>
32 #include <connman/dhcp.h>
33 #include <connman/utsname.h>
34 #include <connman/log.h>
35
36 #include <gdhcp.h>
37
38 static void no_lease_cb(GDHCPClient *dhcp_client, gpointer user_data)
39 {
40         struct connman_dhcp *dhcp = user_data;
41
42         DBG("No Lease Available!");
43
44         connman_dhcp_fail(dhcp);
45 }
46
47 static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
48 {
49         struct connman_dhcp *dhcp = user_data;
50         GList *list, *option = NULL;
51         char *address, *nameservers;
52         size_t ns_strlen = 0;
53
54         address = g_dhcp_client_get_address(dhcp_client);
55         if (address != NULL)
56                 connman_dhcp_set_value(dhcp, "Address", address);
57
58         option = g_dhcp_client_get_option(dhcp_client, G_DHCP_SUBNET);
59         if (option != NULL)
60                 connman_dhcp_set_value(dhcp, "Netmask", (char *) option->data);
61
62         option = g_dhcp_client_get_option(dhcp_client, G_DHCP_DNS_SERVER);
63         for (list = option; list; list = list->next)
64                 ns_strlen += strlen((char *) list->data) + 2;
65         nameservers = g_try_malloc0(ns_strlen);
66         if (nameservers) {
67                 char *ns_index = nameservers;
68
69                 for (list = option; list; list = list->next) {
70                         sprintf(ns_index, "%s ", (char *) list->data);
71                         ns_index += strlen((char *) list->data) + 1;
72                 }
73
74                 connman_dhcp_set_value(dhcp, "Nameserver", nameservers);
75         }
76         g_free(nameservers);
77
78         option = g_dhcp_client_get_option(dhcp_client, G_DHCP_ROUTER);
79         if (option != NULL)
80                 connman_dhcp_set_value(dhcp, "Gateway", (char *) option->data);
81
82         option = g_dhcp_client_get_option(dhcp_client, G_DHCP_HOST_NAME);
83         if (option != NULL)
84                 connman_dhcp_set_value(dhcp, "Hostname", (char *) option->data);
85
86         connman_dhcp_bound(dhcp);
87 }
88
89 static int dhcp_request(struct connman_dhcp *dhcp)
90 {
91         GDHCPClient *dhcp_client;
92         GDHCPClientError error;
93         int index;
94
95         DBG("dhcp %p", dhcp);
96
97         index = connman_dhcp_get_index(dhcp);
98
99         dhcp_client = g_dhcp_client_new(G_DHCP_IPV4, index, &error);
100         if (error != G_DHCP_CLIENT_ERROR_NONE)
101                 return -EINVAL;
102
103         g_dhcp_client_set_send(dhcp_client, G_DHCP_HOST_NAME,
104                                 connman_utsname_get_hostname());
105
106         g_dhcp_client_set_request(dhcp_client, G_DHCP_HOST_NAME);
107         g_dhcp_client_set_request(dhcp_client, G_DHCP_SUBNET);
108         g_dhcp_client_set_request(dhcp_client, G_DHCP_DNS_SERVER);
109         g_dhcp_client_set_request(dhcp_client, G_DHCP_NTP_SERVER);
110         g_dhcp_client_set_request(dhcp_client, G_DHCP_ROUTER);
111
112         g_dhcp_client_register_event(dhcp_client,
113                         G_DHCP_CLIENT_EVENT_LEASE_AVAILABLE,
114                                                 lease_available_cb, dhcp);
115
116         g_dhcp_client_register_event(dhcp_client,
117                         G_DHCP_CLIENT_EVENT_NO_LEASE, no_lease_cb, dhcp);
118
119         connman_dhcp_set_data(dhcp, dhcp_client);
120
121         g_dhcp_client_ref(dhcp_client);
122
123         return g_dhcp_client_start(dhcp_client);
124 }
125
126 static int dhcp_release(struct connman_dhcp *dhcp)
127 {
128         GDHCPClient *dhcp_client = connman_dhcp_get_data(dhcp);
129
130         DBG("dhcp %p", dhcp);
131
132         g_dhcp_client_stop(dhcp_client);
133         g_dhcp_client_unref(dhcp_client);
134
135         return 0;
136 }
137
138 static struct connman_dhcp_driver dhcp_driver = {
139         .name           = "dhcp",
140         .priority       = CONNMAN_DHCP_PRIORITY_DEFAULT,
141         .request        = dhcp_request,
142         .release        = dhcp_release,
143 };
144
145 static int dhcp_init(void)
146 {
147         return connman_dhcp_driver_register(&dhcp_driver);
148 }
149
150 static void dhcp_exit(void)
151 {
152         connman_dhcp_driver_unregister(&dhcp_driver);
153 }
154
155 CONNMAN_PLUGIN_DEFINE(dhcp, "Generic DHCP plugin", VERSION,
156                         CONNMAN_PLUGIN_PRIORITY_LOW, dhcp_init, dhcp_exit)