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// 31#define NETDEBUG_SUBSYSTEM "dhcpd" 32 33///< the DHCP timeout in milli seconds 34#define DHCP_TIMEOUT_MSECS (120UL * 1000) 35 36 37static void dhcpd_timer_callback(void *data) 38{ 39 struct net_state *st = data; 40 41 dhcp_fine_tmr(); 42 if ((st->dhcp_ticks % (DHCP_COARSE_TIMER_MSECS / DHCP_FINE_TIMER_MSECS)) == 0) { 43 dhcp_coarse_tmr(); 44 } 45 st->dhcp_ticks++; 46} 47 48/* 49static void dhcpd_timer_callback_polling(void *data) 50{ 51 dhcpd_timer_callback(data); 52 sys_timeout(DHCP_FINE_TIMER_MSECS, dhcpd_timer_callback_polling, data); 53} 54*/ 55 56static bool dhcpd_has_ip(void) 57{ 58 struct net_state *st = get_default_net_state(); 59 return !ip_addr_cmp(&st->netif.ip_addr, IP_ADDR_ANY); 60} 61 62 63/** 64 * @brief starts the dhcpd service on the interface 65 * 66 * @param flags flags to provide 67 * 68 * @return SYS_ERR_OK on success, errval on failure 69 */ 70errval_t dhcpd_start(net_flags_t flags) 71{ 72 errval_t err; 73 74 struct net_state *st = get_default_net_state(); 75 76 // initialize octopus if not already done 77 err = oct_init(); 78 if (err_is_fail(err)) { 79 return err; 80 } 81 82 debug_printf("starting DHCP...\n"); 83 err_t lwip_err = dhcp_start(&st->netif); 84 if(lwip_err != ERR_OK) { 85 printf("ERRRRRR dhcp start: %i\n", lwip_err); 86 return -1; 87 } 88 89 st->dhcp_ticks = 1; 90 st->dhcp_running = 1; 91 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 if (err_is_fail(err)) { 99 dhcp_stop(&st->netif); 100 return err; 101 } 102 103 if (flags & NET_FLAGS_BLOCKING_INIT) { 104 printf("waiting for DHCP to complete \n"); 105 while (!dhcpd_has_ip()) { 106 // will call event_dispatch()/event_dispatch_nonblock() 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 */ 123errval_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 */ 143errval_t net_config_current_ip_query(net_flags_t flags, uint32_t* ip_address) 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 \n"); 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 *ip_address = (uint32_t)ip; 182 183 debug_printf("Got current IP set: %s\n", inet_ntoa(ipaddr)); 184 debug_printf("Got current GW set: %s\n", inet_ntoa(gateway)); 185 debug_printf("Got current NM set: %s\n", inet_ntoa(netmask)); 186 187 return SYS_ERR_OK; 188} 189 190 191/** 192 * @brief queries the static ip setting of the machine and sets it 193 * 194 * @return SYS_ERR_OK on success, errval on failure 195 */ 196errval_t net_config_static_ip_query(net_flags_t flags) 197{ 198 errval_t err; 199 200 NETDEBUG("query static IP...\n"); 201 202 // initialize octopus if not already done 203 err = oct_init(); 204 if (err_is_fail(err)) { 205 return err; 206 } 207 208 struct net_state *st = get_default_net_state(); 209 assert(st); 210 211 char* record = NULL; 212 err = oct_get(&record, "net.static_ip"); 213 if (err_is_fail(err)) { 214 DEBUG_ERR(err, "cannot get static ip record\n"); 215 return err; 216 } 217 218 uint64_t ip, nm, gw; 219 err = oct_read(record, "_" NET_CONFIG_IP_RECORD_FIELDS, &ip, &gw, &nm); 220 if (err_is_fail(err)) { 221 DEBUG_ERR(err, "cannot read static ip record '%s\n", record); 222 free(record); 223 return err; 224 } 225 free(record); 226 227 struct in_addr ipaddr, netmask, gateway; 228 ipaddr.s_addr = (uint32_t)ip; 229 netmask.s_addr = (uint32_t)nm; 230 gateway.s_addr = (uint32_t)gw; 231 232 debug_printf("Got static IP set: %s\n", inet_ntoa(ipaddr)); 233 debug_printf("Got static GW set: %s\n", inet_ntoa(gateway)); 234 debug_printf("Got static NM set: %s\n", inet_ntoa(netmask)); 235 236 err = netif_set_ipconfig(&ipaddr, &gateway, &netmask); 237 if (err_is_fail(err)) { 238 DEBUG_ERR(err, "cannot set static ip\n"); 239 return err; 240 } 241 242 return SYS_ERR_OK; 243} 244 245 246/** 247 * @brief returns the IP configuration 248 * 249 * @param ip return the IP address 250 * @param gw returns the gateway 251 * @param nm returns the netmask 252 * 253 * @return 254 */ 255errval_t netif_get_ipconfig(struct in_addr *ip, struct in_addr *gw, struct in_addr *nm) 256{ 257 struct net_state *st = get_default_net_state(); 258 if (ip) { 259 ip->s_addr = netif_ip4_addr(&st->netif)->addr; 260 } 261 262 if (gw) { 263 gw->s_addr = netif_ip4_gw(&st->netif)->addr; 264 } 265 266 if (nm) { 267 nm->s_addr = netif_ip4_netmask(&st->netif)->addr; 268 } 269 270 return SYS_ERR_OK; 271} 272 273/** 274 * @brief sets the IP configuration, overrides DHCP 275 * 276 * @param ip the IP address 277 * @param gw the Gateway 278 * @param nm the Netmask 279 * 280 * @return SYS_ERR_OK on success, errval on failure 281 */ 282errval_t netif_set_ipconfig(struct in_addr *ip, struct in_addr *gw, struct in_addr *nm) 283{ 284 errval_t err; 285 struct net_state *st = get_default_net_state(); 286 287 if (st->dhcp_running == 1) { // stop dhcp, if it's running 288 err = dhcpd_stop(); 289 if (err_is_fail(err)) { 290 return err; 291 } 292 } 293 294 ip_addr_t _ipaddr, _netmask, _gateway; 295 _ipaddr.addr = ip->s_addr; 296 _netmask.addr = nm->s_addr; 297 _gateway.addr = gw->s_addr; 298 netif_set_addr(&st->netif, &_ipaddr, &_netmask, &_gateway); 299 netif_set_up(&st->netif); 300 301 return SYS_ERR_OK; 302} 303