octopus: remove include to flounder file in public include
[barrelfish] / lib / net / dhcp.c
1 /*
2  * Copyright (c) 2017, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 // stdlib includes
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14
15 // barrelfish includes
16
17 // lwip includes
18 #include <lwip/ip.h>
19 #include <lwip/dhcp.h>
20 #include <lwip/prot/dhcp.h>
21 #include <lwip/timeouts.h>
22
23 #include <octopus/octopus.h>
24
25
26 #include <net_interfaces/flags.h>
27 #include "networking_internal.h"
28
29 ///< the debug subsystem
30 #define debug_printf_SUBSYSTEM "dhcpd"
31
32 ///< the DHCP timeout in milli seconds
33 #define DHCP_TIMEOUT_MSECS (120UL * 1000)
34
35
36 static void dhcpd_timer_callback(void *data)
37 {
38     struct net_state *st = data;
39
40     dhcp_fine_tmr();
41     if ((st->dhcp_ticks % (DHCP_COARSE_TIMER_MSECS / DHCP_FINE_TIMER_MSECS)) == 0) {
42         dhcp_coarse_tmr();
43     }
44     st->dhcp_ticks++;
45 }
46
47 static void dhcpd_timer_callback_polling(void *data)
48 {
49     dhcpd_timer_callback(data);
50     sys_timeout(DHCP_FINE_TIMER_MSECS, dhcpd_timer_callback_polling, data);
51 }
52
53 static bool dhcpd_has_ip(void)
54 {
55     struct net_state *st = get_default_net_state();
56     return !ip_addr_cmp(&st->netif.ip_addr, IP_ADDR_ANY);
57 }
58
59
60 /**
61  * @brief starts the dhcpd service on the interface
62  *
63  * @param flags flags to provide
64  *
65  * @return SYS_ERR_OK on success, errval on failure
66  */
67 errval_t dhcpd_start(net_flags_t flags)
68 {
69     errval_t err;
70
71     struct net_state *st = get_default_net_state();
72
73     // initialize octopus if not already done
74     err = oct_init();
75     if (err_is_fail(err)) {
76         return err;
77     }
78
79     debug_printf("starting DHCP...\n");
80     err_t lwip_err = dhcp_start(&st->netif);
81     if(lwip_err != ERR_OK) {
82         printf("ERRRRRR dhcp start: %i\n", lwip_err);
83         return -1;
84     }
85
86     st->dhcp_ticks = 1;
87     st->dhcp_running = 1;
88
89     if (flags & NET_FLAGS_POLLING) {
90         sys_timeout(DHCP_FINE_TIMER_MSECS, dhcpd_timer_callback_polling, st);
91     } else {
92         /* DHCP fine timer */
93         err = periodic_event_create(&st->dhcp_timer, st->waitset,
94                                     (DHCP_FINE_TIMER_MSECS * 1000),
95                                     MKCLOSURE(dhcpd_timer_callback, st));
96     }
97
98
99     if (err_is_fail(err)) {
100         dhcp_stop(&st->netif);
101         return err;
102     }
103
104     if (flags & NET_FLAGS_BLOCKING_INIT) {
105         printf("waiting for DHCP to complete \n");
106         while (!dhcpd_has_ip()) {
107             networking_poll();
108             if (st->dhcp_ticks > DHCP_TIMEOUT_MSECS / DHCP_FINE_TIMER_MSECS) {
109                 dhcpd_stop();
110                 return -1;
111             }
112         }
113         printf("OK\nDHCP completed.\n");
114     }
115
116     return SYS_ERR_OK;
117 }
118
119
120 /**
121  * @brief stops the dhcpd service
122  */
123 errval_t dhcpd_stop(void)
124 {
125     struct net_state *st = get_default_net_state();
126
127     periodic_event_cancel(&st->dhcp_timer);
128
129     dhcp_stop(&st->netif);
130
131     st->dhcp_ticks = 0;
132     st->dhcp_running = 0;
133
134     return SYS_ERR_OK;
135 }
136
137
138 /**
139  * @brief queries the current ip setting of the machine
140  *
141  * @return SYS_ERR_OK on success, errval on failure
142  */
143 errval_t net_config_current_ip_query(net_flags_t flags)
144 {
145     errval_t err;
146
147     NETDEBUG("query current IP...\n");
148
149     // initialize octopus if not already done
150     err = oct_init();
151     if (err_is_fail(err)) {
152         return err;
153     }
154
155     char* record = NULL;
156     err = oct_get(&record, "net.current_ip");
157     if (err_no(err) == OCT_ERR_NO_RECORD && (flags & NET_FLAGS_BLOCKING_INIT)) {
158         printf("waiting for DHCP to complete");
159         err = oct_wait_for(&record, NET_CONFIG_CURRENT_IP_RECORD_REGEX);
160         if (err_is_fail(err)) {
161             return err;
162         }
163     } else if (err_is_fail(err)) {
164         DEBUG_ERR(err, "cannot get static ip record\n");
165         return err;
166     }
167
168     uint64_t ip, nm, gw;
169     err = oct_read(record, "_" NET_CONFIG_IP_RECORD_FIELDS, &ip, &gw, &nm);
170     if (err_is_fail(err)) {
171         DEBUG_ERR(err, "cannot read current ip record '%s\n", record);
172         free(record);
173         return err;
174     }
175     free(record);
176
177     struct in_addr ipaddr, netmask, gateway;
178     ipaddr.s_addr = (uint32_t)ip;
179     netmask.s_addr = (uint32_t)nm;
180     gateway.s_addr = (uint32_t)gw;
181
182     debug_printf("Got current IP set: %s\n", inet_ntoa(ipaddr));
183     debug_printf("Got current GW set: %s\n", inet_ntoa(gateway));
184     debug_printf("Got current NM set: %s\n", inet_ntoa(netmask));
185
186     return SYS_ERR_OK;
187 }
188
189
190 /**
191  * @brief queries the static ip setting of the machine and sets it
192  *
193  * @return SYS_ERR_OK on success, errval on failure
194  */
195 errval_t net_config_static_ip_query(net_flags_t flags)
196 {
197     errval_t err;
198
199     NETDEBUG("query static IP...\n");
200
201     // initialize octopus if not already done
202     err = oct_init();
203     if (err_is_fail(err)) {
204         return err;
205     }
206
207     struct net_state *st = get_default_net_state();
208     assert(st);
209
210     char* record = NULL;
211     err = oct_get(&record, "net.static_ip");
212     if (err_is_fail(err)) {
213         DEBUG_ERR(err, "cannot get static ip record\n");
214         return err;
215     }
216
217     uint64_t ip, nm, gw;
218     err = oct_read(record, "_" NET_CONFIG_IP_RECORD_FIELDS, &ip, &gw, &nm);
219     if (err_is_fail(err)) {
220         DEBUG_ERR(err, "cannot read static ip record '%s\n", record);
221         free(record);
222         return err;
223     }
224     free(record);
225
226     struct in_addr ipaddr, netmask, gateway;
227     ipaddr.s_addr = (uint32_t)ip;
228     netmask.s_addr = (uint32_t)nm;
229     gateway.s_addr = (uint32_t)gw;
230
231     debug_printf("Got static IP set: %s\n", inet_ntoa(ipaddr));
232     debug_printf("Got static GW set: %s\n", inet_ntoa(gateway));
233     debug_printf("Got static NM set: %s\n", inet_ntoa(netmask));
234
235     err = netif_set_ipconfig(&ipaddr, &gateway, &netmask);
236     if (err_is_fail(err)) {
237         DEBUG_ERR(err, "cannot set static ip\n");
238         return err;
239     }
240
241     return SYS_ERR_OK;
242 }
243
244
245 /**
246  * @brief returns the IP configuration
247  *
248  * @param ip    return the IP address
249  * @param gw    returns the gateway
250  * @param nm    returns the netmask
251  *
252  * @return
253  */
254 errval_t netif_get_ipconfig(struct in_addr *ip, struct in_addr *gw, struct in_addr *nm)
255 {
256     struct net_state *st = get_default_net_state();
257     if (ip) {
258         ip->s_addr = netif_ip4_addr(&st->netif)->addr;
259     }
260
261     if (gw) {
262         gw->s_addr = netif_ip4_gw(&st->netif)->addr;
263     }
264
265     if (nm) {
266         nm->s_addr = netif_ip4_netmask(&st->netif)->addr;
267     }
268
269     return SYS_ERR_OK;
270 }
271
272 /**
273  * @brief sets the IP configuration, overrides DHCP
274  *
275  * @param ip    the IP address
276  * @param gw    the Gateway
277  * @param nm    the Netmask
278  *
279  * @return SYS_ERR_OK on success, errval on failure
280  */
281 errval_t netif_set_ipconfig(struct in_addr *ip, struct in_addr *gw, struct in_addr *nm)
282 {
283     errval_t err;
284     struct net_state *st = get_default_net_state();
285
286     if (st->dhcp_running == 1) { // stop dhcp, if it's running
287         err = dhcpd_stop();
288         if (err_is_fail(err)) {
289             return err;
290         }
291     }
292
293     ip_addr_t _ipaddr, _netmask, _gateway;
294     _ipaddr.addr = ip->s_addr;
295     _netmask.addr = nm->s_addr;
296     _gateway.addr = gw->s_addr;
297     netif_set_addr(&st->netif, &_ipaddr, &_netmask, &_gateway);
298     netif_set_up(&st->netif);
299
300     return SYS_ERR_OK;
301 }