10f66f451Sopenharmony_ci/* dhcp6.c - DHCP6 client for dynamic network configuration. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2015 Rajni Kant <rajnikant12345@gmail.com> 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * Not in SUSv4. 60f66f451Sopenharmony_ciUSE_DHCP6(NEWTOY(dhcp6, "r:A#<0T#<0t#<0s:p:i:SRvqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY)) 70f66f451Sopenharmony_ci 80f66f451Sopenharmony_ciconfig DHCP6 90f66f451Sopenharmony_ci bool "dhcp6" 100f66f451Sopenharmony_ci default n 110f66f451Sopenharmony_ci help 120f66f451Sopenharmony_ci usage: dhcp6 [-fbnqvR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE] 130f66f451Sopenharmony_ci 140f66f451Sopenharmony_ci Configure network dynamically using DHCP. 150f66f451Sopenharmony_ci 160f66f451Sopenharmony_ci -i Interface to use (default eth0) 170f66f451Sopenharmony_ci -p Create pidfile 180f66f451Sopenharmony_ci -s Run PROG at DHCP events 190f66f451Sopenharmony_ci -t Send up to N Solicit packets 200f66f451Sopenharmony_ci -T Pause between packets (default 3 seconds) 210f66f451Sopenharmony_ci -A Wait N seconds after failure (default 20) 220f66f451Sopenharmony_ci -f Run in foreground 230f66f451Sopenharmony_ci -b Background if lease is not obtained 240f66f451Sopenharmony_ci -n Exit if lease is not obtained 250f66f451Sopenharmony_ci -q Exit after obtaining lease 260f66f451Sopenharmony_ci -R Release IP on exit 270f66f451Sopenharmony_ci -S Log to syslog too 280f66f451Sopenharmony_ci -r Request this IP address 290f66f451Sopenharmony_ci -v Verbose 300f66f451Sopenharmony_ci 310f66f451Sopenharmony_ci Signals: 320f66f451Sopenharmony_ci USR1 Renew current lease 330f66f451Sopenharmony_ci USR2 Release current lease 340f66f451Sopenharmony_ci*/ 350f66f451Sopenharmony_ci#define FOR_dhcp6 360f66f451Sopenharmony_ci#include "toys.h" 370f66f451Sopenharmony_ci#include <linux/sockios.h> 380f66f451Sopenharmony_ci#include <linux/if_ether.h> 390f66f451Sopenharmony_ci#include <netinet/ip.h> 400f66f451Sopenharmony_ci#include <netinet/ip6.h> 410f66f451Sopenharmony_ci#include <netinet/udp.h> 420f66f451Sopenharmony_ci#include <linux/if_packet.h> 430f66f451Sopenharmony_ci#include <syslog.h> 440f66f451Sopenharmony_ci 450f66f451Sopenharmony_ciGLOBALS( 460f66f451Sopenharmony_ci char *interface_name, *pidfile, *script; 470f66f451Sopenharmony_ci long retry, timeout, errortimeout; 480f66f451Sopenharmony_ci char *req_ip; 490f66f451Sopenharmony_ci int length, state, request_length, sock, sock1, status, retval, retries; 500f66f451Sopenharmony_ci struct timeval tv; 510f66f451Sopenharmony_ci uint8_t transction_id[3]; 520f66f451Sopenharmony_ci struct sockaddr_in6 input_socket6; 530f66f451Sopenharmony_ci) 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_ci#define DHCP6SOLICIT 1 560f66f451Sopenharmony_ci#define DHCP6ADVERTISE 2 // server -> client 570f66f451Sopenharmony_ci#define DHCP6REQUEST 3 580f66f451Sopenharmony_ci#define DHCP6CONFIRM 4 590f66f451Sopenharmony_ci#define DHCP6RENEW 5 600f66f451Sopenharmony_ci#define DHCP6REBIND 6 610f66f451Sopenharmony_ci#define DHCP6REPLY 7 // server -> client 620f66f451Sopenharmony_ci#define DHCP6RELEASE 8 630f66f451Sopenharmony_ci#define DHCP6DECLINE 9 640f66f451Sopenharmony_ci#define DHCP6RECONFIGURE 10 // server -> client 650f66f451Sopenharmony_ci#define DHCP6INFOREQUEST 11 660f66f451Sopenharmony_ci#define DHCP6RELAYFLOW 12 // relay -> relay/server 670f66f451Sopenharmony_ci#define DHCP6RELAYREPLY 13 // server/relay -> relay 680f66f451Sopenharmony_ci 690f66f451Sopenharmony_ci// DHCPv6 option codes (partial). See RFC 3315 700f66f451Sopenharmony_ci#define DHCP6_OPT_CLIENTID 1 710f66f451Sopenharmony_ci#define DHCP6_OPT_SERVERID 2 720f66f451Sopenharmony_ci#define DHCP6_OPT_IA_NA 3 730f66f451Sopenharmony_ci#define DHCP6_OPT_IA_ADDR 5 740f66f451Sopenharmony_ci#define DHCP6_OPT_ORO 6 750f66f451Sopenharmony_ci#define DHCP6_OPT_PREFERENCE 7 760f66f451Sopenharmony_ci#define DHCP6_OPT_ELAPSED_TIME 8 770f66f451Sopenharmony_ci#define DHCP6_OPT_RELAY_MSG 9 780f66f451Sopenharmony_ci#define DHCP6_OPT_STATUS_CODE 13 790f66f451Sopenharmony_ci#define DHCP6_OPT_IA_PD 25 800f66f451Sopenharmony_ci#define DHCP6_OPT_IA_PREFIX 26 810f66f451Sopenharmony_ci 820f66f451Sopenharmony_ci#define DHCP6_STATUS_SUCCESS 0 830f66f451Sopenharmony_ci#define DHCP6_STATUS_NOADDRSAVAIL 2 840f66f451Sopenharmony_ci 850f66f451Sopenharmony_ci#define DHCP6_DUID_LLT 1 860f66f451Sopenharmony_ci#define DHCP6_DUID_EN 2 870f66f451Sopenharmony_ci#define DHCP6_DUID_LL 3 880f66f451Sopenharmony_ci#define DHCP6_DUID_UUID 4 890f66f451Sopenharmony_ci 900f66f451Sopenharmony_ci#define DHCPC_SERVER_PORT 547 910f66f451Sopenharmony_ci#define DHCPC_CLIENT_PORT 546 920f66f451Sopenharmony_ci 930f66f451Sopenharmony_ci#define LOG_SILENT 0x0 940f66f451Sopenharmony_ci#define LOG_CONSOLE 0x1 950f66f451Sopenharmony_ci#define LOG_SYSTEM 0x2 960f66f451Sopenharmony_ci 970f66f451Sopenharmony_citypedef struct __attribute__((packed)) dhcp6_msg_s { 980f66f451Sopenharmony_ci uint8_t msgtype, transaction_id[3], options[524]; 990f66f451Sopenharmony_ci} dhcp6_msg_t; 1000f66f451Sopenharmony_ci 1010f66f451Sopenharmony_citypedef struct __attribute__((packed)) optval_duid_llt { 1020f66f451Sopenharmony_ci uint16_t type; 1030f66f451Sopenharmony_ci uint16_t hwtype; 1040f66f451Sopenharmony_ci uint32_t time; 1050f66f451Sopenharmony_ci uint8_t lladdr[6]; 1060f66f451Sopenharmony_ci} DUID; 1070f66f451Sopenharmony_ci 1080f66f451Sopenharmony_citypedef struct __attribute__((packed)) optval_ia_na { 1090f66f451Sopenharmony_ci uint32_t iaid, t1, t2; 1100f66f451Sopenharmony_ci} IA_NA; 1110f66f451Sopenharmony_ci 1120f66f451Sopenharmony_citypedef struct __attribute__((packed)) dhcp6_raw_s { 1130f66f451Sopenharmony_ci struct ip6_hdr iph; 1140f66f451Sopenharmony_ci struct udphdr udph; 1150f66f451Sopenharmony_ci dhcp6_msg_t dhcp6; 1160f66f451Sopenharmony_ci} dhcp6_raw_t; 1170f66f451Sopenharmony_ci 1180f66f451Sopenharmony_citypedef struct __attribute__((packed)) dhcp_data_client { 1190f66f451Sopenharmony_ci uint16_t status_code; 1200f66f451Sopenharmony_ci uint32_t iaid , t1,t2, pf_lf, va_lf; 1210f66f451Sopenharmony_ci uint8_t ipaddr[17] ; 1220f66f451Sopenharmony_ci} DHCP_DATA; 1230f66f451Sopenharmony_ci 1240f66f451Sopenharmony_cistatic DHCP_DATA dhcp_data; 1250f66f451Sopenharmony_cistatic dhcp6_raw_t *mymsg; 1260f66f451Sopenharmony_cistatic dhcp6_msg_t mesg; 1270f66f451Sopenharmony_cistatic DUID *duid; 1280f66f451Sopenharmony_ci 1290f66f451Sopenharmony_cistatic void (*dbg)(char *format, ...); 1300f66f451Sopenharmony_cistatic void dummy(char *format, ...) 1310f66f451Sopenharmony_ci{ 1320f66f451Sopenharmony_ci return; 1330f66f451Sopenharmony_ci} 1340f66f451Sopenharmony_ci 1350f66f451Sopenharmony_cistatic void logit(char *format, ...) 1360f66f451Sopenharmony_ci{ 1370f66f451Sopenharmony_ci int used; 1380f66f451Sopenharmony_ci char *msg; 1390f66f451Sopenharmony_ci va_list p, t; 1400f66f451Sopenharmony_ci uint8_t infomode = LOG_SILENT; 1410f66f451Sopenharmony_ci 1420f66f451Sopenharmony_ci if (toys.optflags & FLAG_S) infomode |= LOG_SYSTEM; 1430f66f451Sopenharmony_ci if(toys.optflags & FLAG_v) infomode |= LOG_CONSOLE; 1440f66f451Sopenharmony_ci va_start(p, format); 1450f66f451Sopenharmony_ci va_copy(t, p); 1460f66f451Sopenharmony_ci used = vsnprintf(NULL, 0, format, t); 1470f66f451Sopenharmony_ci used++; 1480f66f451Sopenharmony_ci va_end(t); 1490f66f451Sopenharmony_ci 1500f66f451Sopenharmony_ci msg = xmalloc(used); 1510f66f451Sopenharmony_ci vsnprintf(msg, used, format, p); 1520f66f451Sopenharmony_ci va_end(p); 1530f66f451Sopenharmony_ci 1540f66f451Sopenharmony_ci if (infomode & LOG_SYSTEM) syslog(LOG_INFO, "%s", msg); 1550f66f451Sopenharmony_ci if (infomode & LOG_CONSOLE) printf("%s", msg); 1560f66f451Sopenharmony_ci free(msg); 1570f66f451Sopenharmony_ci return; 1580f66f451Sopenharmony_ci} 1590f66f451Sopenharmony_ci 1600f66f451Sopenharmony_cistatic void get_mac(uint8_t *mac, char *interface) 1610f66f451Sopenharmony_ci{ 1620f66f451Sopenharmony_ci int fd; 1630f66f451Sopenharmony_ci struct ifreq req; 1640f66f451Sopenharmony_ci 1650f66f451Sopenharmony_ci if (!mac) return; 1660f66f451Sopenharmony_ci fd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_RAW); 1670f66f451Sopenharmony_ci req.ifr_addr.sa_family = AF_INET6; 1680f66f451Sopenharmony_ci xstrncpy(req.ifr_name, interface, IFNAMSIZ); 1690f66f451Sopenharmony_ci xioctl(fd, SIOCGIFHWADDR, &req); 1700f66f451Sopenharmony_ci memcpy(mac, req.ifr_hwaddr.sa_data, 6); 1710f66f451Sopenharmony_ci xclose(fd); 1720f66f451Sopenharmony_ci} 1730f66f451Sopenharmony_ci 1740f66f451Sopenharmony_cistatic void fill_option(uint16_t option_id, uint16_t option_len, uint8_t **dhmesg) 1750f66f451Sopenharmony_ci{ 1760f66f451Sopenharmony_ci uint8_t *tmp = *dhmesg; 1770f66f451Sopenharmony_ci 1780f66f451Sopenharmony_ci *((uint16_t*)tmp) = htons(option_id); 1790f66f451Sopenharmony_ci *(uint16_t*)(tmp+2) = htons(option_len); 1800f66f451Sopenharmony_ci *dhmesg += 4; 1810f66f451Sopenharmony_ci TT.length += 4; 1820f66f451Sopenharmony_ci} 1830f66f451Sopenharmony_ci 1840f66f451Sopenharmony_cistatic void fill_clientID() 1850f66f451Sopenharmony_ci{ 1860f66f451Sopenharmony_ci uint8_t *tmp = &mesg.options[TT.length]; 1870f66f451Sopenharmony_ci 1880f66f451Sopenharmony_ci if(!duid) { 1890f66f451Sopenharmony_ci uint8_t mac[7] = {0,}; 1900f66f451Sopenharmony_ci duid = (DUID*)malloc(sizeof(DUID)); 1910f66f451Sopenharmony_ci duid->type = htons(1); 1920f66f451Sopenharmony_ci duid->hwtype = htons(1); 1930f66f451Sopenharmony_ci duid->time = htonl((uint32_t)(time(NULL) - 946684800) & 0xffffffff); 1940f66f451Sopenharmony_ci fill_option(DHCP6_OPT_CLIENTID,14,&tmp); 1950f66f451Sopenharmony_ci get_mac(mac, TT.interface_name); 1960f66f451Sopenharmony_ci memcpy(duid->lladdr,mac, 6); 1970f66f451Sopenharmony_ci memcpy(tmp,(uint8_t*)duid,sizeof(DUID)); 1980f66f451Sopenharmony_ci } 1990f66f451Sopenharmony_ci else { 2000f66f451Sopenharmony_ci fill_option(DHCP6_OPT_CLIENTID,14,&tmp); 2010f66f451Sopenharmony_ci memcpy(tmp,(uint8_t*)duid,sizeof(DUID)); 2020f66f451Sopenharmony_ci } 2030f66f451Sopenharmony_ci TT.length += sizeof(DUID); 2040f66f451Sopenharmony_ci} 2050f66f451Sopenharmony_ci 2060f66f451Sopenharmony_ci// TODO: make it generic for multiple options. 2070f66f451Sopenharmony_cistatic void fill_optionRequest() 2080f66f451Sopenharmony_ci{ 2090f66f451Sopenharmony_ci uint8_t *tmp = &mesg.options[TT.length]; 2100f66f451Sopenharmony_ci 2110f66f451Sopenharmony_ci fill_option(DHCP6_OPT_ORO,4,&tmp); 2120f66f451Sopenharmony_ci *(uint16_t*)(tmp+4) = htons(23); 2130f66f451Sopenharmony_ci *(uint16_t*)(tmp+6) = htons(24); 2140f66f451Sopenharmony_ci TT.length += 4; 2150f66f451Sopenharmony_ci} 2160f66f451Sopenharmony_ci 2170f66f451Sopenharmony_cistatic void fill_elapsedTime() 2180f66f451Sopenharmony_ci{ 2190f66f451Sopenharmony_ci uint8_t *tmp = &mesg.options[TT.length]; 2200f66f451Sopenharmony_ci 2210f66f451Sopenharmony_ci fill_option(DHCP6_OPT_ELAPSED_TIME, 2, &tmp); 2220f66f451Sopenharmony_ci *(uint16_t*)(tmp+6) = htons(0); 2230f66f451Sopenharmony_ci TT.length += 2; 2240f66f451Sopenharmony_ci} 2250f66f451Sopenharmony_ci 2260f66f451Sopenharmony_cistatic void fill_iaid() 2270f66f451Sopenharmony_ci{ 2280f66f451Sopenharmony_ci IA_NA iana; 2290f66f451Sopenharmony_ci uint8_t *tmp = &mesg.options[TT.length]; 2300f66f451Sopenharmony_ci 2310f66f451Sopenharmony_ci fill_option(DHCP6_OPT_IA_NA, 12, &tmp); 2320f66f451Sopenharmony_ci iana.iaid = rand(); 2330f66f451Sopenharmony_ci iana.t1 = 0xffffffff; 2340f66f451Sopenharmony_ci iana.t2 = 0xffffffff; 2350f66f451Sopenharmony_ci memcpy(tmp, (uint8_t*)&iana, sizeof(IA_NA)); 2360f66f451Sopenharmony_ci TT.length += sizeof(IA_NA); 2370f66f451Sopenharmony_ci} 2380f66f451Sopenharmony_ci 2390f66f451Sopenharmony_ci//static void mode_raw(int *sock_t) 2400f66f451Sopenharmony_cistatic void mode_raw() 2410f66f451Sopenharmony_ci{ 2420f66f451Sopenharmony_ci int constone = 1; 2430f66f451Sopenharmony_ci struct sockaddr_ll sockll; 2440f66f451Sopenharmony_ci 2450f66f451Sopenharmony_ci if (TT.sock > 0) xclose(TT.sock); 2460f66f451Sopenharmony_ci TT.sock = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)); 2470f66f451Sopenharmony_ci 2480f66f451Sopenharmony_ci memset(&sockll, 0, sizeof(sockll)); 2490f66f451Sopenharmony_ci sockll.sll_family = AF_PACKET; 2500f66f451Sopenharmony_ci sockll.sll_protocol = htons(ETH_P_IPV6); 2510f66f451Sopenharmony_ci sockll.sll_ifindex = if_nametoindex(TT.interface_name); 2520f66f451Sopenharmony_ci xbind(TT.sock, (struct sockaddr *) &sockll, sizeof(sockll)); 2530f66f451Sopenharmony_ci if (setsockopt(TT.sock, SOL_PACKET, PACKET_HOST,&constone, sizeof(int)) < 0) { 2540f66f451Sopenharmony_ci if (errno != ENOPROTOOPT) error_exit("MODE RAW : Bind fail.\n"); 2550f66f451Sopenharmony_ci } 2560f66f451Sopenharmony_ci} 2570f66f451Sopenharmony_ci 2580f66f451Sopenharmony_cistatic void generate_transection_id() 2590f66f451Sopenharmony_ci{ 2600f66f451Sopenharmony_ci int i, r = rand() % 0xffffff; 2610f66f451Sopenharmony_ci 2620f66f451Sopenharmony_ci for (i=0; i<3; i++) { 2630f66f451Sopenharmony_ci TT.transction_id[i] = r%0xff; 2640f66f451Sopenharmony_ci r = r/10; 2650f66f451Sopenharmony_ci } 2660f66f451Sopenharmony_ci} 2670f66f451Sopenharmony_ci 2680f66f451Sopenharmony_cistatic void set_timeout(int seconds) 2690f66f451Sopenharmony_ci{ 2700f66f451Sopenharmony_ci TT.tv.tv_sec = seconds; 2710f66f451Sopenharmony_ci TT.tv.tv_usec = 100000; 2720f66f451Sopenharmony_ci} 2730f66f451Sopenharmony_ci 2740f66f451Sopenharmony_cistatic void send_msg(int type) 2750f66f451Sopenharmony_ci{ 2760f66f451Sopenharmony_ci struct sockaddr_in6 addr6; 2770f66f451Sopenharmony_ci int sendlength = 0; 2780f66f451Sopenharmony_ci 2790f66f451Sopenharmony_ci memset(&addr6, 0, sizeof(addr6)); 2800f66f451Sopenharmony_ci addr6.sin6_family = AF_INET6; 2810f66f451Sopenharmony_ci addr6.sin6_port = htons(DHCPC_SERVER_PORT); //SERVER_PORT 2820f66f451Sopenharmony_ci inet_pton(AF_INET6, "ff02::1:2", &addr6.sin6_addr); 2830f66f451Sopenharmony_ci mesg.msgtype = type; 2840f66f451Sopenharmony_ci generate_transection_id(); 2850f66f451Sopenharmony_ci memcpy(mesg.transaction_id, TT.transction_id, 3); 2860f66f451Sopenharmony_ci 2870f66f451Sopenharmony_ci if (type == DHCP6SOLICIT) { 2880f66f451Sopenharmony_ci TT.length = 0; 2890f66f451Sopenharmony_ci fill_clientID(); 2900f66f451Sopenharmony_ci fill_optionRequest(); 2910f66f451Sopenharmony_ci fill_elapsedTime(); 2920f66f451Sopenharmony_ci fill_iaid(); 2930f66f451Sopenharmony_ci sendlength = sizeof(dhcp6_msg_t) - 524 + TT.length; 2940f66f451Sopenharmony_ci } else if (type == DHCP6REQUEST || type == DHCP6RELEASE || type == DHCP6RENEW) 2950f66f451Sopenharmony_ci sendlength = TT.request_length; 2960f66f451Sopenharmony_ci dbg("Sending message type: %d\n", type); 2970f66f451Sopenharmony_ci sendlength = sendto(TT.sock1, &mesg, sendlength , 0,(struct sockaddr *)&addr6, 2980f66f451Sopenharmony_ci sizeof(struct sockaddr_in6 )); 2990f66f451Sopenharmony_ci if (sendlength <= 0) dbg("Error in sending message type: %d\n", type); 3000f66f451Sopenharmony_ci} 3010f66f451Sopenharmony_ci 3020f66f451Sopenharmony_ciuint8_t *get_msg_ptr(uint8_t *data, int data_length, int msgtype) 3030f66f451Sopenharmony_ci{ 3040f66f451Sopenharmony_ci uint16_t type = *((uint16_t*)data), length = *((uint16_t*)(data+2)); 3050f66f451Sopenharmony_ci 3060f66f451Sopenharmony_ci type = ntohs(type); 3070f66f451Sopenharmony_ci if (type == msgtype) return data; 3080f66f451Sopenharmony_ci length = ntohs(length); 3090f66f451Sopenharmony_ci while (type != msgtype) { 3100f66f451Sopenharmony_ci data_length -= (4 + length); 3110f66f451Sopenharmony_ci if (data_length <= 0) break; 3120f66f451Sopenharmony_ci data = data + 4 + length; 3130f66f451Sopenharmony_ci type = ntohs(*((uint16_t*)data)); 3140f66f451Sopenharmony_ci length = ntohs(*((uint16_t*)(data+2))); 3150f66f451Sopenharmony_ci if (type == msgtype) return data; 3160f66f451Sopenharmony_ci } 3170f66f451Sopenharmony_ci return NULL; 3180f66f451Sopenharmony_ci} 3190f66f451Sopenharmony_ci 3200f66f451Sopenharmony_cistatic uint8_t *check_server_id(uint8_t *data, int data_length) 3210f66f451Sopenharmony_ci{ 3220f66f451Sopenharmony_ci return get_msg_ptr(data, data_length, DHCP6_OPT_SERVERID); 3230f66f451Sopenharmony_ci} 3240f66f451Sopenharmony_ci 3250f66f451Sopenharmony_cistatic int check_client_id(uint8_t *data, int data_length) 3260f66f451Sopenharmony_ci{ 3270f66f451Sopenharmony_ci if ((data = get_msg_ptr(data, data_length, DHCP6_OPT_CLIENTID))) { 3280f66f451Sopenharmony_ci DUID one = *((DUID*)(data+4)); 3290f66f451Sopenharmony_ci DUID two = *((DUID*)&mesg.options[4]); 3300f66f451Sopenharmony_ci 3310f66f451Sopenharmony_ci if (!memcmp(&one, &two, sizeof(DUID))) return 1; 3320f66f451Sopenharmony_ci } 3330f66f451Sopenharmony_ci return 0; 3340f66f451Sopenharmony_ci} 3350f66f451Sopenharmony_ci 3360f66f451Sopenharmony_cistatic int validate_ids() 3370f66f451Sopenharmony_ci{ 3380f66f451Sopenharmony_ci if (!check_server_id(mymsg->dhcp6.options, 3390f66f451Sopenharmony_ci TT.status - ((char*)&mymsg->dhcp6.options[0] - (char*)mymsg) )) { 3400f66f451Sopenharmony_ci dbg("Invalid server id: %d\n"); 3410f66f451Sopenharmony_ci return 0; 3420f66f451Sopenharmony_ci } 3430f66f451Sopenharmony_ci if (!check_client_id(mymsg->dhcp6.options, 3440f66f451Sopenharmony_ci TT.status - ((char*)&mymsg->dhcp6.options[0] - (char*)mymsg) )) { 3450f66f451Sopenharmony_ci dbg("Invalid client id: %d\n"); 3460f66f451Sopenharmony_ci return 0; 3470f66f451Sopenharmony_ci } 3480f66f451Sopenharmony_ci return 1; 3490f66f451Sopenharmony_ci} 3500f66f451Sopenharmony_ci 3510f66f451Sopenharmony_cistatic void parse_ia_na(uint8_t *data, int data_length) 3520f66f451Sopenharmony_ci{ 3530f66f451Sopenharmony_ci uint8_t *t = get_msg_ptr(data, data_length, DHCP6_OPT_IA_NA); 3540f66f451Sopenharmony_ci uint16_t iana_len, content_len = 0; 3550f66f451Sopenharmony_ci 3560f66f451Sopenharmony_ci memset(&dhcp_data,0,sizeof(dhcp_data)); 3570f66f451Sopenharmony_ci if (!t) return; 3580f66f451Sopenharmony_ci 3590f66f451Sopenharmony_ci iana_len = ntohs(*((uint16_t*)(t+2))); 3600f66f451Sopenharmony_ci dhcp_data.iaid = ntohl(*((uint32_t*)(t+4))); 3610f66f451Sopenharmony_ci dhcp_data.t1 = ntohl(*((uint32_t*)(t+8))); 3620f66f451Sopenharmony_ci dhcp_data.t2 = ntohl(*((uint32_t*)(t+12))); 3630f66f451Sopenharmony_ci t += 16; 3640f66f451Sopenharmony_ci iana_len -= 12; 3650f66f451Sopenharmony_ci 3660f66f451Sopenharmony_ci while(iana_len > 0) { 3670f66f451Sopenharmony_ci uint16_t sub_type = ntohs(*((uint16_t*)(t))); 3680f66f451Sopenharmony_ci 3690f66f451Sopenharmony_ci switch (sub_type) { 3700f66f451Sopenharmony_ci case DHCP6_OPT_IA_ADDR: 3710f66f451Sopenharmony_ci content_len = ntohs(*((uint16_t*)(t+2))); 3720f66f451Sopenharmony_ci memcpy(dhcp_data.ipaddr,t+4,16); 3730f66f451Sopenharmony_ci if (TT.state == DHCP6SOLICIT) { 3740f66f451Sopenharmony_ci if (TT.req_ip) { 3750f66f451Sopenharmony_ci struct addrinfo *res = NULL; 3760f66f451Sopenharmony_ci 3770f66f451Sopenharmony_ci if(!getaddrinfo(TT.req_ip, NULL, NULL,&res)) { 3780f66f451Sopenharmony_ci dbg("Requesting IP: %s\n", TT.req_ip); 3790f66f451Sopenharmony_ci memcpy (&TT.input_socket6, res->ai_addr, res->ai_addrlen); 3800f66f451Sopenharmony_ci memcpy(t+4, TT.input_socket6.sin6_addr.s6_addr, 16); 3810f66f451Sopenharmony_ci } else xprintf("Invalid IP: %s\n",TT.req_ip); 3820f66f451Sopenharmony_ci freeaddrinfo(res); 3830f66f451Sopenharmony_ci } 3840f66f451Sopenharmony_ci } 3850f66f451Sopenharmony_ci dhcp_data.pf_lf = ntohl(*((uint32_t*)(t+20))); 3860f66f451Sopenharmony_ci dhcp_data.va_lf = ntohl(*((uint32_t*)(t+24))); 3870f66f451Sopenharmony_ci iana_len -= (content_len + 4); 3880f66f451Sopenharmony_ci t += (content_len + 4); 3890f66f451Sopenharmony_ci break; 3900f66f451Sopenharmony_ci case DHCP6_OPT_STATUS_CODE: 3910f66f451Sopenharmony_ci content_len = ntohs(*((uint16_t*)(t+2))); 3920f66f451Sopenharmony_ci dhcp_data.status_code = ntohs(*((uint16_t*)(t+4))); 3930f66f451Sopenharmony_ci iana_len -= (content_len + 4); 3940f66f451Sopenharmony_ci t += (content_len + 4); 3950f66f451Sopenharmony_ci break; 3960f66f451Sopenharmony_ci default: 3970f66f451Sopenharmony_ci content_len = ntohs(*((uint16_t*)(t+2))); 3980f66f451Sopenharmony_ci iana_len -= (content_len + 4); 3990f66f451Sopenharmony_ci t += (content_len + 4); 4000f66f451Sopenharmony_ci break; 4010f66f451Sopenharmony_ci } 4020f66f451Sopenharmony_ci } 4030f66f451Sopenharmony_ci} 4040f66f451Sopenharmony_ci 4050f66f451Sopenharmony_cistatic void write_pid(char *path) 4060f66f451Sopenharmony_ci{ 4070f66f451Sopenharmony_ci int pidfile = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666); 4080f66f451Sopenharmony_ci 4090f66f451Sopenharmony_ci if (pidfile > 0) { 4100f66f451Sopenharmony_ci char pidbuf[12]; 4110f66f451Sopenharmony_ci 4120f66f451Sopenharmony_ci sprintf(pidbuf, "%u", (unsigned)getpid()); 4130f66f451Sopenharmony_ci write(pidfile, pidbuf, strlen(pidbuf)); 4140f66f451Sopenharmony_ci close(pidfile); 4150f66f451Sopenharmony_ci } 4160f66f451Sopenharmony_ci} 4170f66f451Sopenharmony_ci 4180f66f451Sopenharmony_ci// Creates environment pointers from RES to use in script 4190f66f451Sopenharmony_cistatic int fill_envp(DHCP_DATA *res) 4200f66f451Sopenharmony_ci{ 4210f66f451Sopenharmony_ci int ret = setenv("interface", TT.interface_name, 1); 4220f66f451Sopenharmony_ci 4230f66f451Sopenharmony_ci if (ret) return ret; 4240f66f451Sopenharmony_ci inet_ntop(AF_INET6, res->ipaddr, toybuf, INET6_ADDRSTRLEN); 4250f66f451Sopenharmony_ci ret = setenv("ip",(const char*)toybuf , 1); 4260f66f451Sopenharmony_ci return ret; 4270f66f451Sopenharmony_ci} 4280f66f451Sopenharmony_ci 4290f66f451Sopenharmony_ci// Executes Script NAME. 4300f66f451Sopenharmony_cistatic void run_script(DHCP_DATA *res, char *name) 4310f66f451Sopenharmony_ci{ 4320f66f451Sopenharmony_ci volatile int error = 0; 4330f66f451Sopenharmony_ci struct stat sts; 4340f66f451Sopenharmony_ci pid_t pid; 4350f66f451Sopenharmony_ci char *argv[3]; 4360f66f451Sopenharmony_ci char *script = (toys.optflags & FLAG_s) ? TT.script 4370f66f451Sopenharmony_ci : "/usr/share/dhcp/default.script"; 4380f66f451Sopenharmony_ci 4390f66f451Sopenharmony_ci if (stat(script, &sts) == -1 && errno == ENOENT) return; 4400f66f451Sopenharmony_ci if (!res || fill_envp(res)) { 4410f66f451Sopenharmony_ci dbg("Failed to create environment variables.\n"); 4420f66f451Sopenharmony_ci return; 4430f66f451Sopenharmony_ci } 4440f66f451Sopenharmony_ci dbg("Executing %s %s\n", script, name); 4450f66f451Sopenharmony_ci argv[0] = (char*)script; 4460f66f451Sopenharmony_ci argv[1] = (char*)name; 4470f66f451Sopenharmony_ci argv[2] = NULL; 4480f66f451Sopenharmony_ci fflush(NULL); 4490f66f451Sopenharmony_ci 4500f66f451Sopenharmony_ci pid = vfork(); 4510f66f451Sopenharmony_ci if (pid < 0) { 4520f66f451Sopenharmony_ci dbg("Fork failed.\n"); 4530f66f451Sopenharmony_ci return; 4540f66f451Sopenharmony_ci } 4550f66f451Sopenharmony_ci if (!pid) { 4560f66f451Sopenharmony_ci execvp(argv[0], argv); 4570f66f451Sopenharmony_ci error = errno; 4580f66f451Sopenharmony_ci _exit(111); 4590f66f451Sopenharmony_ci } 4600f66f451Sopenharmony_ci if (error) { 4610f66f451Sopenharmony_ci waitpid(pid, NULL, 0); 4620f66f451Sopenharmony_ci errno = error; 4630f66f451Sopenharmony_ci perror_msg("script exec failed"); 4640f66f451Sopenharmony_ci } 4650f66f451Sopenharmony_ci dbg("script complete.\n"); 4660f66f451Sopenharmony_ci} 4670f66f451Sopenharmony_ci 4680f66f451Sopenharmony_cistatic void lease_fail() 4690f66f451Sopenharmony_ci{ 4700f66f451Sopenharmony_ci dbg("Lease failed.\n"); 4710f66f451Sopenharmony_ci run_script(NULL, "leasefail"); 4720f66f451Sopenharmony_ci if (toys.optflags & FLAG_n) { 4730f66f451Sopenharmony_ci xclose(TT.sock); 4740f66f451Sopenharmony_ci xclose(TT.sock1); 4750f66f451Sopenharmony_ci error_exit("Lease Failed, Exiting."); 4760f66f451Sopenharmony_ci } 4770f66f451Sopenharmony_ci if (toys.optflags & FLAG_b) { 4780f66f451Sopenharmony_ci dbg("Lease failed. Going to daemon mode.\n"); 4790f66f451Sopenharmony_ci if (daemon(0,0)) perror_exit("daemonize"); 4800f66f451Sopenharmony_ci if (toys.optflags & FLAG_p) write_pid(TT.pidfile); 4810f66f451Sopenharmony_ci toys.optflags &= ~FLAG_b; 4820f66f451Sopenharmony_ci toys.optflags |= FLAG_f; 4830f66f451Sopenharmony_ci } 4840f66f451Sopenharmony_ci} 4850f66f451Sopenharmony_ci 4860f66f451Sopenharmony_ci// Generic signal handler real handling is done in main funcrion. 4870f66f451Sopenharmony_cistatic void signal_handler(int sig) 4880f66f451Sopenharmony_ci{ 4890f66f451Sopenharmony_ci dbg("Caught signal: %d\n", sig); 4900f66f451Sopenharmony_ci switch (sig) { 4910f66f451Sopenharmony_ci case SIGUSR1: 4920f66f451Sopenharmony_ci dbg("SIGUSR1.\n"); 4930f66f451Sopenharmony_ci if (TT.state == DHCP6RELEASE || TT.state == DHCP6REQUEST ) { 4940f66f451Sopenharmony_ci TT.state = DHCP6SOLICIT; 4950f66f451Sopenharmony_ci set_timeout(0); 4960f66f451Sopenharmony_ci return; 4970f66f451Sopenharmony_ci } 4980f66f451Sopenharmony_ci dbg("SIGUSR1 sending renew.\n"); 4990f66f451Sopenharmony_ci send_msg(DHCP6RENEW); 5000f66f451Sopenharmony_ci TT.state = DHCP6RENEW; 5010f66f451Sopenharmony_ci TT.retries = 0; 5020f66f451Sopenharmony_ci set_timeout(0); 5030f66f451Sopenharmony_ci break; 5040f66f451Sopenharmony_ci case SIGUSR2: 5050f66f451Sopenharmony_ci dbg("SIGUSR2.\n"); 5060f66f451Sopenharmony_ci if (TT.state == DHCP6RELEASE) return; 5070f66f451Sopenharmony_ci if (TT.state != DHCP6CONFIRM ) return; 5080f66f451Sopenharmony_ci dbg("SIGUSR2 sending release.\n"); 5090f66f451Sopenharmony_ci send_msg(DHCP6RELEASE); 5100f66f451Sopenharmony_ci TT.state = DHCP6RELEASE; 5110f66f451Sopenharmony_ci TT.retries = 0; 5120f66f451Sopenharmony_ci set_timeout(0); 5130f66f451Sopenharmony_ci break; 5140f66f451Sopenharmony_ci case SIGTERM: 5150f66f451Sopenharmony_ci case SIGINT: 5160f66f451Sopenharmony_ci dbg((sig == SIGTERM)?"SIGTERM.\n":"SIGINT.\n"); 5170f66f451Sopenharmony_ci if ((toys.optflags & FLAG_R) && TT.state == DHCP6CONFIRM) 5180f66f451Sopenharmony_ci send_msg(DHCP6RELEASE); 5190f66f451Sopenharmony_ci if(sig == SIGINT) exit(0); 5200f66f451Sopenharmony_ci break; 5210f66f451Sopenharmony_ci default: break; 5220f66f451Sopenharmony_ci } 5230f66f451Sopenharmony_ci} 5240f66f451Sopenharmony_ci 5250f66f451Sopenharmony_ci// signal setup for SIGUSR1 SIGUSR2 SIGTERM 5260f66f451Sopenharmony_cistatic int setup_signal() 5270f66f451Sopenharmony_ci{ 5280f66f451Sopenharmony_ci signal(SIGUSR1, signal_handler); 5290f66f451Sopenharmony_ci signal(SIGUSR2, signal_handler); 5300f66f451Sopenharmony_ci signal(SIGTERM, signal_handler); 5310f66f451Sopenharmony_ci signal(SIGINT, signal_handler); 5320f66f451Sopenharmony_ci return 0; 5330f66f451Sopenharmony_ci} 5340f66f451Sopenharmony_ci 5350f66f451Sopenharmony_civoid dhcp6_main(void) 5360f66f451Sopenharmony_ci{ 5370f66f451Sopenharmony_ci struct sockaddr_in6 sinaddr6; 5380f66f451Sopenharmony_ci int constone = 1; 5390f66f451Sopenharmony_ci fd_set rfds; 5400f66f451Sopenharmony_ci 5410f66f451Sopenharmony_ci srand(time(NULL)); 5420f66f451Sopenharmony_ci setlinebuf(stdout); 5430f66f451Sopenharmony_ci dbg = dummy; 5440f66f451Sopenharmony_ci TT.state = DHCP6SOLICIT; 5450f66f451Sopenharmony_ci 5460f66f451Sopenharmony_ci if (toys.optflags & FLAG_v) dbg = logit; 5470f66f451Sopenharmony_ci if (!TT.interface_name) TT.interface_name = "eth0"; 5480f66f451Sopenharmony_ci if (toys.optflags & FLAG_p) write_pid(TT.pidfile); 5490f66f451Sopenharmony_ci if (!TT.retry) TT.retry = 3; 5500f66f451Sopenharmony_ci if (!TT.timeout) TT.timeout = 3; 5510f66f451Sopenharmony_ci if (!TT.errortimeout) TT.errortimeout = 20; 5520f66f451Sopenharmony_ci if (toys.optflags & FLAG_S) { 5530f66f451Sopenharmony_ci openlog("DHCP6 :", LOG_PID, LOG_DAEMON); 5540f66f451Sopenharmony_ci dbg = logit; 5550f66f451Sopenharmony_ci } 5560f66f451Sopenharmony_ci 5570f66f451Sopenharmony_ci dbg("Interface: %s\n", TT.interface_name); 5580f66f451Sopenharmony_ci dbg("pid file: %s\n", TT.pidfile); 5590f66f451Sopenharmony_ci dbg("Retry count: %d\n", TT.retry); 5600f66f451Sopenharmony_ci dbg("Timeout : %d\n", TT.timeout); 5610f66f451Sopenharmony_ci dbg("Error timeout: %d\n", TT.errortimeout); 5620f66f451Sopenharmony_ci 5630f66f451Sopenharmony_ci 5640f66f451Sopenharmony_ci 5650f66f451Sopenharmony_ci setup_signal(); 5660f66f451Sopenharmony_ci TT.sock1 = xsocket(PF_INET6, SOCK_DGRAM, 0); 5670f66f451Sopenharmony_ci memset(&sinaddr6, 0, sizeof(sinaddr6)); 5680f66f451Sopenharmony_ci sinaddr6.sin6_family = AF_INET6; 5690f66f451Sopenharmony_ci sinaddr6.sin6_port = htons(DHCPC_CLIENT_PORT); 5700f66f451Sopenharmony_ci sinaddr6.sin6_scope_id = if_nametoindex(TT.interface_name); 5710f66f451Sopenharmony_ci sinaddr6.sin6_addr = in6addr_any ; 5720f66f451Sopenharmony_ci 5730f66f451Sopenharmony_ci xsetsockopt(TT.sock1, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone)); 5740f66f451Sopenharmony_ci 5750f66f451Sopenharmony_ci xbind(TT.sock1, (struct sockaddr *)&sinaddr6, sizeof(sinaddr6)); 5760f66f451Sopenharmony_ci 5770f66f451Sopenharmony_ci mode_raw(); 5780f66f451Sopenharmony_ci set_timeout(0); 5790f66f451Sopenharmony_ci for (;;) { 5800f66f451Sopenharmony_ci int maxfd = TT.sock; 5810f66f451Sopenharmony_ci 5820f66f451Sopenharmony_ci if (TT.sock >= 0) FD_SET(TT.sock, &rfds); 5830f66f451Sopenharmony_ci TT.retval = 0; 5840f66f451Sopenharmony_ci if ((TT.retval = select(maxfd + 1, &rfds, NULL, NULL, &TT.tv)) < 0) { 5850f66f451Sopenharmony_ci if(errno == EINTR) continue; 5860f66f451Sopenharmony_ci perror_exit("Error in select"); 5870f66f451Sopenharmony_ci } 5880f66f451Sopenharmony_ci if (!TT.retval) { 5890f66f451Sopenharmony_ci if (TT.state == DHCP6SOLICIT || TT.state == DHCP6CONFIRM) { 5900f66f451Sopenharmony_ci dbg("State is solicit, sending solicit packet\n"); 5910f66f451Sopenharmony_ci run_script(NULL, "deconfig"); 5920f66f451Sopenharmony_ci send_msg(DHCP6SOLICIT); 5930f66f451Sopenharmony_ci TT.state = DHCP6SOLICIT; 5940f66f451Sopenharmony_ci TT.retries++; 5950f66f451Sopenharmony_ci if(TT.retries > TT.retry) set_timeout(TT.errortimeout); 5960f66f451Sopenharmony_ci else if (TT.retries == TT.retry) { 5970f66f451Sopenharmony_ci dbg("State is solicit, retry count is max.\n"); 5980f66f451Sopenharmony_ci lease_fail(); 5990f66f451Sopenharmony_ci set_timeout(TT.errortimeout); 6000f66f451Sopenharmony_ci } else set_timeout(TT.timeout); 6010f66f451Sopenharmony_ci continue; 6020f66f451Sopenharmony_ci } else if (TT.state == DHCP6REQUEST || TT.state == DHCP6RENEW || 6030f66f451Sopenharmony_ci TT.state == DHCP6RELEASE) { 6040f66f451Sopenharmony_ci dbg("State is %d , sending packet\n", TT.state); 6050f66f451Sopenharmony_ci send_msg(TT.state); 6060f66f451Sopenharmony_ci TT.retries++; 6070f66f451Sopenharmony_ci if (TT.retries > TT.retry) set_timeout(TT.errortimeout); 6080f66f451Sopenharmony_ci else if (TT.retries == TT.retry) { 6090f66f451Sopenharmony_ci lease_fail(); 6100f66f451Sopenharmony_ci set_timeout(TT.errortimeout); 6110f66f451Sopenharmony_ci } else set_timeout(TT.timeout); 6120f66f451Sopenharmony_ci continue; 6130f66f451Sopenharmony_ci } 6140f66f451Sopenharmony_ci } else if (FD_ISSET(TT.sock, &rfds)) { 6150f66f451Sopenharmony_ci if ((TT.status = read(TT.sock, toybuf, sizeof(toybuf))) <= 0) continue; 6160f66f451Sopenharmony_ci mymsg = (dhcp6_raw_t*)toybuf; 6170f66f451Sopenharmony_ci if (ntohs(mymsg->udph.dest) == 546 && 6180f66f451Sopenharmony_ci !memcmp(mymsg->dhcp6.transaction_id, TT.transction_id, 3)) { 6190f66f451Sopenharmony_ci if (TT.state == DHCP6SOLICIT) { 6200f66f451Sopenharmony_ci if (mymsg->dhcp6.msgtype == DHCP6ADVERTISE ) { 6210f66f451Sopenharmony_ci if (!validate_ids()) { 6220f66f451Sopenharmony_ci dbg("Invalid id received, solicit.\n"); 6230f66f451Sopenharmony_ci TT.state = DHCP6SOLICIT; 6240f66f451Sopenharmony_ci continue; 6250f66f451Sopenharmony_ci } 6260f66f451Sopenharmony_ci dbg("Got reply to request or solicit.\n"); 6270f66f451Sopenharmony_ci TT.retries = 0; 6280f66f451Sopenharmony_ci set_timeout(0); 6290f66f451Sopenharmony_ci TT.request_length = TT.status - ((char*)&mymsg->dhcp6 - (char*)mymsg); 6300f66f451Sopenharmony_ci memcpy((uint8_t*)&mesg, &mymsg->dhcp6, TT.request_length); 6310f66f451Sopenharmony_ci parse_ia_na(mesg.options, TT.request_length); 6320f66f451Sopenharmony_ci dbg("Status code:%d\n", dhcp_data.status_code); 6330f66f451Sopenharmony_ci inet_ntop(AF_INET6, dhcp_data.ipaddr, toybuf, INET6_ADDRSTRLEN); 6340f66f451Sopenharmony_ci dbg("Advertiesed IP: %s\n", toybuf); 6350f66f451Sopenharmony_ci TT.state = DHCP6REQUEST; 6360f66f451Sopenharmony_ci } else { 6370f66f451Sopenharmony_ci dbg("Invalid solicit.\n"); 6380f66f451Sopenharmony_ci continue; 6390f66f451Sopenharmony_ci } 6400f66f451Sopenharmony_ci } else if (TT.state == DHCP6REQUEST || TT.state == DHCP6RENEW ) { 6410f66f451Sopenharmony_ci if (mymsg->dhcp6.msgtype == DHCP6REPLY) { 6420f66f451Sopenharmony_ci if (!validate_ids()) { 6430f66f451Sopenharmony_ci dbg("Invalid id received, %d.\n", TT.state); 6440f66f451Sopenharmony_ci TT.state = DHCP6REQUEST; 6450f66f451Sopenharmony_ci continue; 6460f66f451Sopenharmony_ci } 6470f66f451Sopenharmony_ci dbg("Got reply to request or renew.\n"); 6480f66f451Sopenharmony_ci TT.request_length = TT.status - ((char*)&mymsg->dhcp6 - (char*)mymsg); 6490f66f451Sopenharmony_ci memcpy((uint8_t*)&mesg, &mymsg->dhcp6, TT.request_length); 6500f66f451Sopenharmony_ci parse_ia_na(mymsg->dhcp6.options, TT.request_length); 6510f66f451Sopenharmony_ci dbg("Status code:%d\n", dhcp_data.status_code); 6520f66f451Sopenharmony_ci inet_ntop(AF_INET6, dhcp_data.ipaddr, toybuf, INET6_ADDRSTRLEN); 6530f66f451Sopenharmony_ci dbg("Got IP: %s\n", toybuf); 6540f66f451Sopenharmony_ci TT.retries = 0; 6550f66f451Sopenharmony_ci run_script(&dhcp_data, (TT.state == DHCP6REQUEST) ? 6560f66f451Sopenharmony_ci "request" : "renew"); 6570f66f451Sopenharmony_ci if (toys.optflags & FLAG_q) { 6580f66f451Sopenharmony_ci if (toys.optflags & FLAG_R) send_msg(DHCP6RELEASE); 6590f66f451Sopenharmony_ci break; 6600f66f451Sopenharmony_ci } 6610f66f451Sopenharmony_ci TT.state = DHCP6CONFIRM; 6620f66f451Sopenharmony_ci set_timeout((dhcp_data.va_lf)?dhcp_data.va_lf:INT_MAX); 6630f66f451Sopenharmony_ci dbg("Setting timeout to intmax."); 6640f66f451Sopenharmony_ci if (TT.state == DHCP6REQUEST || !(toys.optflags & FLAG_f)) { 6650f66f451Sopenharmony_ci dbg("Making it a daemon\n"); 6660f66f451Sopenharmony_ci if (daemon(0,0)) perror_exit("daemonize"); 6670f66f451Sopenharmony_ci toys.optflags |= FLAG_f; 6680f66f451Sopenharmony_ci if (toys.optflags & FLAG_p) write_pid(TT.pidfile); 6690f66f451Sopenharmony_ci } 6700f66f451Sopenharmony_ci dbg("Making it a foreground.\n"); 6710f66f451Sopenharmony_ci continue; 6720f66f451Sopenharmony_ci } else { 6730f66f451Sopenharmony_ci dbg("Invalid reply.\n"); 6740f66f451Sopenharmony_ci continue; 6750f66f451Sopenharmony_ci } 6760f66f451Sopenharmony_ci } else if (TT.state == DHCP6RELEASE) { 6770f66f451Sopenharmony_ci dbg("Got reply to release.\n"); 6780f66f451Sopenharmony_ci run_script(NULL, "release"); 6790f66f451Sopenharmony_ci set_timeout(INT_MAX); 6800f66f451Sopenharmony_ci } 6810f66f451Sopenharmony_ci } 6820f66f451Sopenharmony_ci } 6830f66f451Sopenharmony_ci } 6840f66f451Sopenharmony_ci xclose(TT.sock1); 6850f66f451Sopenharmony_ci xclose(TT.sock); 6860f66f451Sopenharmony_ci} 687