xref: /aosp_15_r20/external/toybox/toys/pending/dhcp6.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* dhcp6.c - DHCP6 client for dynamic network configuration.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2015 Rajni Kant <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  *
5*cf5a6c84SAndroid Build Coastguard Worker  * Not in SUSv4.
6*cf5a6c84SAndroid Build Coastguard Worker USE_DHCP6(NEWTOY(dhcp6, "r:A#<0T#<0t#<0s:p:i:SRvqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
7*cf5a6c84SAndroid Build Coastguard Worker 
8*cf5a6c84SAndroid Build Coastguard Worker config DHCP6
9*cf5a6c84SAndroid Build Coastguard Worker   bool "dhcp6"
10*cf5a6c84SAndroid Build Coastguard Worker   default n
11*cf5a6c84SAndroid Build Coastguard Worker   help
12*cf5a6c84SAndroid Build Coastguard Worker       usage: dhcp6 [-fbnqvR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]
13*cf5a6c84SAndroid Build Coastguard Worker 
14*cf5a6c84SAndroid Build Coastguard Worker       Configure network dynamically using DHCP.
15*cf5a6c84SAndroid Build Coastguard Worker 
16*cf5a6c84SAndroid Build Coastguard Worker       -i Interface to use (default eth0)
17*cf5a6c84SAndroid Build Coastguard Worker       -p Create pidfile
18*cf5a6c84SAndroid Build Coastguard Worker       -s Run PROG at DHCP events
19*cf5a6c84SAndroid Build Coastguard Worker       -t Send up to N Solicit packets
20*cf5a6c84SAndroid Build Coastguard Worker       -T Pause between packets (default 3 seconds)
21*cf5a6c84SAndroid Build Coastguard Worker       -A Wait N seconds after failure (default 20)
22*cf5a6c84SAndroid Build Coastguard Worker       -f Run in foreground
23*cf5a6c84SAndroid Build Coastguard Worker       -b Background if lease is not obtained
24*cf5a6c84SAndroid Build Coastguard Worker       -n Exit if lease is not obtained
25*cf5a6c84SAndroid Build Coastguard Worker       -q Exit after obtaining lease
26*cf5a6c84SAndroid Build Coastguard Worker       -R Release IP on exit
27*cf5a6c84SAndroid Build Coastguard Worker       -S Log to syslog too
28*cf5a6c84SAndroid Build Coastguard Worker       -r Request this IP address
29*cf5a6c84SAndroid Build Coastguard Worker       -v Verbose
30*cf5a6c84SAndroid Build Coastguard Worker 
31*cf5a6c84SAndroid Build Coastguard Worker       Signals:
32*cf5a6c84SAndroid Build Coastguard Worker       USR1  Renew current lease
33*cf5a6c84SAndroid Build Coastguard Worker       USR2  Release current lease
34*cf5a6c84SAndroid Build Coastguard Worker */
35*cf5a6c84SAndroid Build Coastguard Worker #define FOR_dhcp6
36*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
37*cf5a6c84SAndroid Build Coastguard Worker #include <linux/sockios.h>
38*cf5a6c84SAndroid Build Coastguard Worker #include <linux/if_ether.h>
39*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/ip.h>
40*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/ip6.h>
41*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/udp.h>
42*cf5a6c84SAndroid Build Coastguard Worker #include <linux/if_packet.h>
43*cf5a6c84SAndroid Build Coastguard Worker #include <syslog.h>
44*cf5a6c84SAndroid Build Coastguard Worker 
45*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
46*cf5a6c84SAndroid Build Coastguard Worker   char *interface_name, *pidfile, *script;
47*cf5a6c84SAndroid Build Coastguard Worker   long retry, timeout, errortimeout;
48*cf5a6c84SAndroid Build Coastguard Worker   char *req_ip;
49*cf5a6c84SAndroid Build Coastguard Worker   int length, state, request_length, sock, sock1, status, retval, retries;
50*cf5a6c84SAndroid Build Coastguard Worker   struct timeval tv;
51*cf5a6c84SAndroid Build Coastguard Worker   uint8_t transction_id[3];
52*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in6 input_socket6;
53*cf5a6c84SAndroid Build Coastguard Worker )
54*cf5a6c84SAndroid Build Coastguard Worker 
55*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6SOLICIT        1
56*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6ADVERTISE      2   // server -> client
57*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6REQUEST        3
58*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6CONFIRM        4
59*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RENEW          5
60*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6REBIND         6
61*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6REPLY          7   // server -> client
62*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RELEASE        8
63*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6DECLINE        9
64*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RECONFIGURE    10  // server -> client
65*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6INFOREQUEST    11
66*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RELAYFLOW      12  // relay -> relay/server
67*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6RELAYREPLY     13  // server/relay -> relay
68*cf5a6c84SAndroid Build Coastguard Worker 
69*cf5a6c84SAndroid Build Coastguard Worker // DHCPv6 option codes (partial). See RFC 3315
70*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_CLIENTID      1
71*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_SERVERID      2
72*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_IA_NA         3
73*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_IA_ADDR       5
74*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_ORO           6
75*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_PREFERENCE    7
76*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_ELAPSED_TIME  8
77*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_RELAY_MSG     9
78*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_STATUS_CODE   13
79*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_IA_PD         25
80*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_OPT_IA_PREFIX     26
81*cf5a6c84SAndroid Build Coastguard Worker 
82*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_STATUS_SUCCESS        0
83*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_STATUS_NOADDRSAVAIL   2
84*cf5a6c84SAndroid Build Coastguard Worker 
85*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_DUID_LLT    1
86*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_DUID_EN     2
87*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_DUID_LL     3
88*cf5a6c84SAndroid Build Coastguard Worker #define DHCP6_DUID_UUID   4
89*cf5a6c84SAndroid Build Coastguard Worker 
90*cf5a6c84SAndroid Build Coastguard Worker #define DHCPC_SERVER_PORT     547
91*cf5a6c84SAndroid Build Coastguard Worker #define DHCPC_CLIENT_PORT     546
92*cf5a6c84SAndroid Build Coastguard Worker 
93*cf5a6c84SAndroid Build Coastguard Worker #define LOG_SILENT          0x0
94*cf5a6c84SAndroid Build Coastguard Worker #define LOG_CONSOLE         0x1
95*cf5a6c84SAndroid Build Coastguard Worker #define LOG_SYSTEM          0x2
96*cf5a6c84SAndroid Build Coastguard Worker 
97*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((packed)) dhcp6_msg_s {
98*cf5a6c84SAndroid Build Coastguard Worker   uint8_t msgtype, transaction_id[3], options[524];
99*cf5a6c84SAndroid Build Coastguard Worker } dhcp6_msg_t;
100*cf5a6c84SAndroid Build Coastguard Worker 
101*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((packed)) optval_duid_llt {
102*cf5a6c84SAndroid Build Coastguard Worker   uint16_t type;
103*cf5a6c84SAndroid Build Coastguard Worker   uint16_t hwtype;
104*cf5a6c84SAndroid Build Coastguard Worker   uint32_t time;
105*cf5a6c84SAndroid Build Coastguard Worker   uint8_t lladdr[6];
106*cf5a6c84SAndroid Build Coastguard Worker } DUID;
107*cf5a6c84SAndroid Build Coastguard Worker 
108*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((packed)) optval_ia_na {
109*cf5a6c84SAndroid Build Coastguard Worker   uint32_t iaid, t1, t2;
110*cf5a6c84SAndroid Build Coastguard Worker } IA_NA;
111*cf5a6c84SAndroid Build Coastguard Worker 
112*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((packed)) dhcp6_raw_s {
113*cf5a6c84SAndroid Build Coastguard Worker   struct ip6_hdr iph;
114*cf5a6c84SAndroid Build Coastguard Worker   struct udphdr udph;
115*cf5a6c84SAndroid Build Coastguard Worker   dhcp6_msg_t dhcp6;
116*cf5a6c84SAndroid Build Coastguard Worker } dhcp6_raw_t;
117*cf5a6c84SAndroid Build Coastguard Worker 
118*cf5a6c84SAndroid Build Coastguard Worker typedef struct __attribute__((packed)) dhcp_data_client {
119*cf5a6c84SAndroid Build Coastguard Worker   uint16_t  status_code;
120*cf5a6c84SAndroid Build Coastguard Worker   uint32_t iaid , t1,t2, pf_lf, va_lf;
121*cf5a6c84SAndroid Build Coastguard Worker   uint8_t ipaddr[17] ;
122*cf5a6c84SAndroid Build Coastguard Worker } DHCP_DATA;
123*cf5a6c84SAndroid Build Coastguard Worker 
124*cf5a6c84SAndroid Build Coastguard Worker static DHCP_DATA dhcp_data;
125*cf5a6c84SAndroid Build Coastguard Worker static dhcp6_raw_t *mymsg;
126*cf5a6c84SAndroid Build Coastguard Worker static dhcp6_msg_t mesg;
127*cf5a6c84SAndroid Build Coastguard Worker static DUID *duid;
128*cf5a6c84SAndroid Build Coastguard Worker 
129*cf5a6c84SAndroid Build Coastguard Worker static void (*dbg)(char *format, ...);
dummy(char * format,...)130*cf5a6c84SAndroid Build Coastguard Worker static void dummy(char *format, ...)
131*cf5a6c84SAndroid Build Coastguard Worker {
132*cf5a6c84SAndroid Build Coastguard Worker   return;
133*cf5a6c84SAndroid Build Coastguard Worker }
134*cf5a6c84SAndroid Build Coastguard Worker 
logit(char * format,...)135*cf5a6c84SAndroid Build Coastguard Worker static void logit(char *format, ...)
136*cf5a6c84SAndroid Build Coastguard Worker {
137*cf5a6c84SAndroid Build Coastguard Worker   int used;
138*cf5a6c84SAndroid Build Coastguard Worker   char *msg;
139*cf5a6c84SAndroid Build Coastguard Worker   va_list p, t;
140*cf5a6c84SAndroid Build Coastguard Worker   uint8_t infomode = LOG_SILENT;
141*cf5a6c84SAndroid Build Coastguard Worker 
142*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_S) infomode |= LOG_SYSTEM;
143*cf5a6c84SAndroid Build Coastguard Worker   if(toys.optflags & FLAG_v) infomode |= LOG_CONSOLE;
144*cf5a6c84SAndroid Build Coastguard Worker   va_start(p, format);
145*cf5a6c84SAndroid Build Coastguard Worker   va_copy(t, p);
146*cf5a6c84SAndroid Build Coastguard Worker   used = vsnprintf(NULL, 0, format, t);
147*cf5a6c84SAndroid Build Coastguard Worker   used++;
148*cf5a6c84SAndroid Build Coastguard Worker   va_end(t);
149*cf5a6c84SAndroid Build Coastguard Worker 
150*cf5a6c84SAndroid Build Coastguard Worker   msg = xmalloc(used);
151*cf5a6c84SAndroid Build Coastguard Worker   vsnprintf(msg, used, format, p);
152*cf5a6c84SAndroid Build Coastguard Worker   va_end(p);
153*cf5a6c84SAndroid Build Coastguard Worker 
154*cf5a6c84SAndroid Build Coastguard Worker   if (infomode & LOG_SYSTEM) syslog(LOG_INFO, "%s", msg);
155*cf5a6c84SAndroid Build Coastguard Worker   if (infomode & LOG_CONSOLE) printf("%s", msg);
156*cf5a6c84SAndroid Build Coastguard Worker   free(msg);
157*cf5a6c84SAndroid Build Coastguard Worker   return;
158*cf5a6c84SAndroid Build Coastguard Worker }
159*cf5a6c84SAndroid Build Coastguard Worker 
get_mac(uint8_t * mac,char * interface)160*cf5a6c84SAndroid Build Coastguard Worker static void get_mac(uint8_t *mac, char *interface)
161*cf5a6c84SAndroid Build Coastguard Worker {
162*cf5a6c84SAndroid Build Coastguard Worker   int fd;
163*cf5a6c84SAndroid Build Coastguard Worker   struct ifreq req;
164*cf5a6c84SAndroid Build Coastguard Worker 
165*cf5a6c84SAndroid Build Coastguard Worker   if (!mac) return;
166*cf5a6c84SAndroid Build Coastguard Worker   fd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
167*cf5a6c84SAndroid Build Coastguard Worker   req.ifr_addr.sa_family = AF_INET6;
168*cf5a6c84SAndroid Build Coastguard Worker   xstrncpy(req.ifr_name, interface, IFNAMSIZ);
169*cf5a6c84SAndroid Build Coastguard Worker   xioctl(fd, SIOCGIFHWADDR, &req);
170*cf5a6c84SAndroid Build Coastguard Worker   memcpy(mac, req.ifr_hwaddr.sa_data, 6);
171*cf5a6c84SAndroid Build Coastguard Worker   xclose(fd);
172*cf5a6c84SAndroid Build Coastguard Worker }
173*cf5a6c84SAndroid Build Coastguard Worker 
fill_option(uint16_t option_id,uint16_t option_len,uint8_t ** dhmesg)174*cf5a6c84SAndroid Build Coastguard Worker static void fill_option(uint16_t option_id, uint16_t option_len, uint8_t **dhmesg)
175*cf5a6c84SAndroid Build Coastguard Worker {
176*cf5a6c84SAndroid Build Coastguard Worker   uint8_t *tmp = *dhmesg;
177*cf5a6c84SAndroid Build Coastguard Worker 
178*cf5a6c84SAndroid Build Coastguard Worker   *((uint16_t*)tmp) = htons(option_id);
179*cf5a6c84SAndroid Build Coastguard Worker   *(uint16_t*)(tmp+2) = htons(option_len);
180*cf5a6c84SAndroid Build Coastguard Worker   *dhmesg += 4;
181*cf5a6c84SAndroid Build Coastguard Worker   TT.length += 4;
182*cf5a6c84SAndroid Build Coastguard Worker }
183*cf5a6c84SAndroid Build Coastguard Worker 
fill_clientID()184*cf5a6c84SAndroid Build Coastguard Worker static void fill_clientID()
185*cf5a6c84SAndroid Build Coastguard Worker {
186*cf5a6c84SAndroid Build Coastguard Worker   uint8_t *tmp = &mesg.options[TT.length];
187*cf5a6c84SAndroid Build Coastguard Worker 
188*cf5a6c84SAndroid Build Coastguard Worker   if(!duid) {
189*cf5a6c84SAndroid Build Coastguard Worker     uint8_t mac[7] = {0,};
190*cf5a6c84SAndroid Build Coastguard Worker     duid = (DUID*)malloc(sizeof(DUID));
191*cf5a6c84SAndroid Build Coastguard Worker     duid->type = htons(1);
192*cf5a6c84SAndroid Build Coastguard Worker     duid->hwtype = htons(1);
193*cf5a6c84SAndroid Build Coastguard Worker     duid->time = htonl((uint32_t)(time(NULL) - 946684800) & 0xffffffff);
194*cf5a6c84SAndroid Build Coastguard Worker     fill_option(DHCP6_OPT_CLIENTID,14,&tmp);
195*cf5a6c84SAndroid Build Coastguard Worker     get_mac(mac, TT.interface_name);
196*cf5a6c84SAndroid Build Coastguard Worker     memcpy(duid->lladdr,mac, 6);
197*cf5a6c84SAndroid Build Coastguard Worker     memcpy(tmp,(uint8_t*)duid,sizeof(DUID));
198*cf5a6c84SAndroid Build Coastguard Worker   }
199*cf5a6c84SAndroid Build Coastguard Worker   else {
200*cf5a6c84SAndroid Build Coastguard Worker     fill_option(DHCP6_OPT_CLIENTID,14,&tmp);
201*cf5a6c84SAndroid Build Coastguard Worker     memcpy(tmp,(uint8_t*)duid,sizeof(DUID));
202*cf5a6c84SAndroid Build Coastguard Worker   }
203*cf5a6c84SAndroid Build Coastguard Worker   TT.length += sizeof(DUID);
204*cf5a6c84SAndroid Build Coastguard Worker }
205*cf5a6c84SAndroid Build Coastguard Worker 
206*cf5a6c84SAndroid Build Coastguard Worker // TODO: make it generic for multiple options.
fill_optionRequest()207*cf5a6c84SAndroid Build Coastguard Worker static void fill_optionRequest()
208*cf5a6c84SAndroid Build Coastguard Worker {
209*cf5a6c84SAndroid Build Coastguard Worker   uint8_t *tmp = &mesg.options[TT.length];
210*cf5a6c84SAndroid Build Coastguard Worker 
211*cf5a6c84SAndroid Build Coastguard Worker   fill_option(DHCP6_OPT_ORO,4,&tmp);
212*cf5a6c84SAndroid Build Coastguard Worker   *(uint16_t*)(tmp+4) = htons(23);
213*cf5a6c84SAndroid Build Coastguard Worker   *(uint16_t*)(tmp+6) = htons(24);
214*cf5a6c84SAndroid Build Coastguard Worker   TT.length += 4;
215*cf5a6c84SAndroid Build Coastguard Worker }
216*cf5a6c84SAndroid Build Coastguard Worker 
fill_elapsedTime()217*cf5a6c84SAndroid Build Coastguard Worker static void fill_elapsedTime()
218*cf5a6c84SAndroid Build Coastguard Worker {
219*cf5a6c84SAndroid Build Coastguard Worker   uint8_t *tmp = &mesg.options[TT.length];
220*cf5a6c84SAndroid Build Coastguard Worker 
221*cf5a6c84SAndroid Build Coastguard Worker   fill_option(DHCP6_OPT_ELAPSED_TIME, 2, &tmp);
222*cf5a6c84SAndroid Build Coastguard Worker   *(uint16_t*)(tmp+6) = htons(0);
223*cf5a6c84SAndroid Build Coastguard Worker   TT.length += 2;
224*cf5a6c84SAndroid Build Coastguard Worker }
225*cf5a6c84SAndroid Build Coastguard Worker 
fill_iaid()226*cf5a6c84SAndroid Build Coastguard Worker static void fill_iaid()
227*cf5a6c84SAndroid Build Coastguard Worker {
228*cf5a6c84SAndroid Build Coastguard Worker   IA_NA iana;
229*cf5a6c84SAndroid Build Coastguard Worker   uint8_t *tmp = &mesg.options[TT.length];
230*cf5a6c84SAndroid Build Coastguard Worker 
231*cf5a6c84SAndroid Build Coastguard Worker   fill_option(DHCP6_OPT_IA_NA, 12, &tmp);
232*cf5a6c84SAndroid Build Coastguard Worker   iana.iaid = rand();
233*cf5a6c84SAndroid Build Coastguard Worker   iana.t1 = 0xffffffff;
234*cf5a6c84SAndroid Build Coastguard Worker   iana.t2 = 0xffffffff;
235*cf5a6c84SAndroid Build Coastguard Worker   memcpy(tmp, (uint8_t*)&iana, sizeof(IA_NA));
236*cf5a6c84SAndroid Build Coastguard Worker   TT.length += sizeof(IA_NA);
237*cf5a6c84SAndroid Build Coastguard Worker }
238*cf5a6c84SAndroid Build Coastguard Worker 
239*cf5a6c84SAndroid Build Coastguard Worker //static void mode_raw(int *sock_t)
mode_raw()240*cf5a6c84SAndroid Build Coastguard Worker static void mode_raw()
241*cf5a6c84SAndroid Build Coastguard Worker {
242*cf5a6c84SAndroid Build Coastguard Worker   int constone = 1;
243*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_ll sockll;
244*cf5a6c84SAndroid Build Coastguard Worker 
245*cf5a6c84SAndroid Build Coastguard Worker   if (TT.sock > 0) xclose(TT.sock);
246*cf5a6c84SAndroid Build Coastguard Worker   TT.sock = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
247*cf5a6c84SAndroid Build Coastguard Worker 
248*cf5a6c84SAndroid Build Coastguard Worker   memset(&sockll, 0, sizeof(sockll));
249*cf5a6c84SAndroid Build Coastguard Worker   sockll.sll_family = AF_PACKET;
250*cf5a6c84SAndroid Build Coastguard Worker   sockll.sll_protocol = htons(ETH_P_IPV6);
251*cf5a6c84SAndroid Build Coastguard Worker   sockll.sll_ifindex = if_nametoindex(TT.interface_name);
252*cf5a6c84SAndroid Build Coastguard Worker   xbind(TT.sock, (struct sockaddr *) &sockll, sizeof(sockll));
253*cf5a6c84SAndroid Build Coastguard Worker   if (setsockopt(TT.sock, SOL_PACKET, PACKET_HOST,&constone, sizeof(int)) < 0) {
254*cf5a6c84SAndroid Build Coastguard Worker     if (errno != ENOPROTOOPT) error_exit("MODE RAW : Bind fail.\n");
255*cf5a6c84SAndroid Build Coastguard Worker   }
256*cf5a6c84SAndroid Build Coastguard Worker }
257*cf5a6c84SAndroid Build Coastguard Worker 
generate_transection_id()258*cf5a6c84SAndroid Build Coastguard Worker static void generate_transection_id()
259*cf5a6c84SAndroid Build Coastguard Worker {
260*cf5a6c84SAndroid Build Coastguard Worker   int i, r = rand() % 0xffffff;
261*cf5a6c84SAndroid Build Coastguard Worker 
262*cf5a6c84SAndroid Build Coastguard Worker   for (i=0; i<3; i++) {
263*cf5a6c84SAndroid Build Coastguard Worker     TT.transction_id[i] = r%0xff;
264*cf5a6c84SAndroid Build Coastguard Worker     r = r/10;
265*cf5a6c84SAndroid Build Coastguard Worker   }
266*cf5a6c84SAndroid Build Coastguard Worker }
267*cf5a6c84SAndroid Build Coastguard Worker 
set_timeout(int seconds)268*cf5a6c84SAndroid Build Coastguard Worker static void set_timeout(int seconds)
269*cf5a6c84SAndroid Build Coastguard Worker {
270*cf5a6c84SAndroid Build Coastguard Worker   TT.tv.tv_sec = seconds;
271*cf5a6c84SAndroid Build Coastguard Worker   TT.tv.tv_usec = 100000;
272*cf5a6c84SAndroid Build Coastguard Worker }
273*cf5a6c84SAndroid Build Coastguard Worker 
send_msg(int type)274*cf5a6c84SAndroid Build Coastguard Worker static void  send_msg(int type)
275*cf5a6c84SAndroid Build Coastguard Worker {
276*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in6 addr6;
277*cf5a6c84SAndroid Build Coastguard Worker   int sendlength = 0;
278*cf5a6c84SAndroid Build Coastguard Worker 
279*cf5a6c84SAndroid Build Coastguard Worker   memset(&addr6, 0, sizeof(addr6));
280*cf5a6c84SAndroid Build Coastguard Worker   addr6.sin6_family = AF_INET6;
281*cf5a6c84SAndroid Build Coastguard Worker   addr6.sin6_port = htons(DHCPC_SERVER_PORT); //SERVER_PORT
282*cf5a6c84SAndroid Build Coastguard Worker   inet_pton(AF_INET6, "ff02::1:2", &addr6.sin6_addr);
283*cf5a6c84SAndroid Build Coastguard Worker   mesg.msgtype = type;
284*cf5a6c84SAndroid Build Coastguard Worker   generate_transection_id();
285*cf5a6c84SAndroid Build Coastguard Worker   memcpy(mesg.transaction_id, TT.transction_id, 3);
286*cf5a6c84SAndroid Build Coastguard Worker 
287*cf5a6c84SAndroid Build Coastguard Worker   if (type  == DHCP6SOLICIT) {
288*cf5a6c84SAndroid Build Coastguard Worker     TT.length = 0;
289*cf5a6c84SAndroid Build Coastguard Worker     fill_clientID();
290*cf5a6c84SAndroid Build Coastguard Worker     fill_optionRequest();
291*cf5a6c84SAndroid Build Coastguard Worker     fill_elapsedTime();
292*cf5a6c84SAndroid Build Coastguard Worker     fill_iaid();
293*cf5a6c84SAndroid Build Coastguard Worker     sendlength = sizeof(dhcp6_msg_t) - 524 + TT.length;
294*cf5a6c84SAndroid Build Coastguard Worker   } else if (type == DHCP6REQUEST || type == DHCP6RELEASE || type == DHCP6RENEW)
295*cf5a6c84SAndroid Build Coastguard Worker     sendlength = TT.request_length;
296*cf5a6c84SAndroid Build Coastguard Worker   dbg("Sending message type: %d\n", type);
297*cf5a6c84SAndroid Build Coastguard Worker   sendlength = sendto(TT.sock1, &mesg, sendlength , 0,(struct sockaddr *)&addr6,
298*cf5a6c84SAndroid Build Coastguard Worker           sizeof(struct sockaddr_in6 ));
299*cf5a6c84SAndroid Build Coastguard Worker   if (sendlength <= 0) dbg("Error in sending message type: %d\n", type);
300*cf5a6c84SAndroid Build Coastguard Worker }
301*cf5a6c84SAndroid Build Coastguard Worker 
get_msg_ptr(uint8_t * data,int data_length,int msgtype)302*cf5a6c84SAndroid Build Coastguard Worker uint8_t *get_msg_ptr(uint8_t *data, int data_length, int msgtype)
303*cf5a6c84SAndroid Build Coastguard Worker {
304*cf5a6c84SAndroid Build Coastguard Worker   uint16_t type =  *((uint16_t*)data), length = *((uint16_t*)(data+2));
305*cf5a6c84SAndroid Build Coastguard Worker 
306*cf5a6c84SAndroid Build Coastguard Worker   type = ntohs(type);
307*cf5a6c84SAndroid Build Coastguard Worker   if (type == msgtype) return data;
308*cf5a6c84SAndroid Build Coastguard Worker   length = ntohs(length);
309*cf5a6c84SAndroid Build Coastguard Worker   while (type != msgtype) {
310*cf5a6c84SAndroid Build Coastguard Worker     data_length -= (4 + length);
311*cf5a6c84SAndroid Build Coastguard Worker     if (data_length <= 0) break;
312*cf5a6c84SAndroid Build Coastguard Worker     data = data + 4 + length;
313*cf5a6c84SAndroid Build Coastguard Worker     type = ntohs(*((uint16_t*)data));
314*cf5a6c84SAndroid Build Coastguard Worker     length = ntohs(*((uint16_t*)(data+2)));
315*cf5a6c84SAndroid Build Coastguard Worker     if (type == msgtype) return data;
316*cf5a6c84SAndroid Build Coastguard Worker   }
317*cf5a6c84SAndroid Build Coastguard Worker   return NULL;
318*cf5a6c84SAndroid Build Coastguard Worker }
319*cf5a6c84SAndroid Build Coastguard Worker 
check_server_id(uint8_t * data,int data_length)320*cf5a6c84SAndroid Build Coastguard Worker static uint8_t *check_server_id(uint8_t *data, int data_length)
321*cf5a6c84SAndroid Build Coastguard Worker {
322*cf5a6c84SAndroid Build Coastguard Worker   return get_msg_ptr(data,  data_length, DHCP6_OPT_SERVERID);
323*cf5a6c84SAndroid Build Coastguard Worker }
324*cf5a6c84SAndroid Build Coastguard Worker 
check_client_id(uint8_t * data,int data_length)325*cf5a6c84SAndroid Build Coastguard Worker static int check_client_id(uint8_t *data, int data_length)
326*cf5a6c84SAndroid Build Coastguard Worker {
327*cf5a6c84SAndroid Build Coastguard Worker   if ((data = get_msg_ptr(data,  data_length, DHCP6_OPT_CLIENTID))) {
328*cf5a6c84SAndroid Build Coastguard Worker     DUID one = *((DUID*)(data+4));
329*cf5a6c84SAndroid Build Coastguard Worker     DUID two = *((DUID*)&mesg.options[4]);
330*cf5a6c84SAndroid Build Coastguard Worker 
331*cf5a6c84SAndroid Build Coastguard Worker     if (!memcmp(&one, &two, sizeof(DUID))) return 1;
332*cf5a6c84SAndroid Build Coastguard Worker   }
333*cf5a6c84SAndroid Build Coastguard Worker   return 0;
334*cf5a6c84SAndroid Build Coastguard Worker }
335*cf5a6c84SAndroid Build Coastguard Worker 
validate_ids()336*cf5a6c84SAndroid Build Coastguard Worker static int validate_ids()
337*cf5a6c84SAndroid Build Coastguard Worker {
338*cf5a6c84SAndroid Build Coastguard Worker   if (!check_server_id(mymsg->dhcp6.options,
339*cf5a6c84SAndroid Build Coastguard Worker     TT.status - ((char*)&mymsg->dhcp6.options[0] - (char*)mymsg) )) {
340*cf5a6c84SAndroid Build Coastguard Worker     dbg("Invalid server id: %d\n");
341*cf5a6c84SAndroid Build Coastguard Worker     return 0;
342*cf5a6c84SAndroid Build Coastguard Worker   }
343*cf5a6c84SAndroid Build Coastguard Worker   if (!check_client_id(mymsg->dhcp6.options,
344*cf5a6c84SAndroid Build Coastguard Worker     TT.status - ((char*)&mymsg->dhcp6.options[0] - (char*)mymsg) )) {
345*cf5a6c84SAndroid Build Coastguard Worker     dbg("Invalid client id: %d\n");
346*cf5a6c84SAndroid Build Coastguard Worker     return 0;
347*cf5a6c84SAndroid Build Coastguard Worker   }
348*cf5a6c84SAndroid Build Coastguard Worker   return 1;
349*cf5a6c84SAndroid Build Coastguard Worker }
350*cf5a6c84SAndroid Build Coastguard Worker 
parse_ia_na(uint8_t * data,int data_length)351*cf5a6c84SAndroid Build Coastguard Worker static void parse_ia_na(uint8_t *data, int data_length)
352*cf5a6c84SAndroid Build Coastguard Worker {
353*cf5a6c84SAndroid Build Coastguard Worker   uint8_t *t = get_msg_ptr(data, data_length, DHCP6_OPT_IA_NA);
354*cf5a6c84SAndroid Build Coastguard Worker   uint16_t iana_len, content_len = 0;
355*cf5a6c84SAndroid Build Coastguard Worker 
356*cf5a6c84SAndroid Build Coastguard Worker   memset(&dhcp_data,0,sizeof(dhcp_data));
357*cf5a6c84SAndroid Build Coastguard Worker   if (!t) return;
358*cf5a6c84SAndroid Build Coastguard Worker 
359*cf5a6c84SAndroid Build Coastguard Worker   iana_len = ntohs(*((uint16_t*)(t+2)));
360*cf5a6c84SAndroid Build Coastguard Worker   dhcp_data.iaid = ntohl(*((uint32_t*)(t+4)));
361*cf5a6c84SAndroid Build Coastguard Worker   dhcp_data.t1 = ntohl(*((uint32_t*)(t+8)));
362*cf5a6c84SAndroid Build Coastguard Worker   dhcp_data.t2 = ntohl(*((uint32_t*)(t+12)));
363*cf5a6c84SAndroid Build Coastguard Worker   t += 16;
364*cf5a6c84SAndroid Build Coastguard Worker   iana_len -= 12;
365*cf5a6c84SAndroid Build Coastguard Worker 
366*cf5a6c84SAndroid Build Coastguard Worker   while(iana_len > 0) {
367*cf5a6c84SAndroid Build Coastguard Worker     uint16_t sub_type = ntohs(*((uint16_t*)(t)));
368*cf5a6c84SAndroid Build Coastguard Worker 
369*cf5a6c84SAndroid Build Coastguard Worker     switch (sub_type) {
370*cf5a6c84SAndroid Build Coastguard Worker       case DHCP6_OPT_IA_ADDR:
371*cf5a6c84SAndroid Build Coastguard Worker         content_len = ntohs(*((uint16_t*)(t+2)));
372*cf5a6c84SAndroid Build Coastguard Worker         memcpy(dhcp_data.ipaddr,t+4,16);
373*cf5a6c84SAndroid Build Coastguard Worker         if (TT.state == DHCP6SOLICIT) {
374*cf5a6c84SAndroid Build Coastguard Worker           if (TT.req_ip) {
375*cf5a6c84SAndroid Build Coastguard Worker             struct addrinfo *res = NULL;
376*cf5a6c84SAndroid Build Coastguard Worker 
377*cf5a6c84SAndroid Build Coastguard Worker             if(!getaddrinfo(TT.req_ip, NULL, NULL,&res)) {
378*cf5a6c84SAndroid Build Coastguard Worker               dbg("Requesting IP: %s\n", TT.req_ip);
379*cf5a6c84SAndroid Build Coastguard Worker               memcpy (&TT.input_socket6, res->ai_addr, res->ai_addrlen);
380*cf5a6c84SAndroid Build Coastguard Worker               memcpy(t+4, TT.input_socket6.sin6_addr.s6_addr, 16);
381*cf5a6c84SAndroid Build Coastguard Worker             } else xprintf("Invalid IP: %s\n",TT.req_ip);
382*cf5a6c84SAndroid Build Coastguard Worker             freeaddrinfo(res);
383*cf5a6c84SAndroid Build Coastguard Worker           }
384*cf5a6c84SAndroid Build Coastguard Worker         }
385*cf5a6c84SAndroid Build Coastguard Worker         dhcp_data.pf_lf = ntohl(*((uint32_t*)(t+20)));
386*cf5a6c84SAndroid Build Coastguard Worker         dhcp_data.va_lf = ntohl(*((uint32_t*)(t+24)));
387*cf5a6c84SAndroid Build Coastguard Worker         iana_len -= (content_len + 4);
388*cf5a6c84SAndroid Build Coastguard Worker         t += (content_len + 4);
389*cf5a6c84SAndroid Build Coastguard Worker         break;
390*cf5a6c84SAndroid Build Coastguard Worker       case DHCP6_OPT_STATUS_CODE:
391*cf5a6c84SAndroid Build Coastguard Worker         content_len = ntohs(*((uint16_t*)(t+2)));
392*cf5a6c84SAndroid Build Coastguard Worker         dhcp_data.status_code = ntohs(*((uint16_t*)(t+4)));
393*cf5a6c84SAndroid Build Coastguard Worker         iana_len -= (content_len + 4);
394*cf5a6c84SAndroid Build Coastguard Worker         t += (content_len + 4);
395*cf5a6c84SAndroid Build Coastguard Worker         break;
396*cf5a6c84SAndroid Build Coastguard Worker       default:
397*cf5a6c84SAndroid Build Coastguard Worker         content_len = ntohs(*((uint16_t*)(t+2)));
398*cf5a6c84SAndroid Build Coastguard Worker         iana_len -= (content_len + 4);
399*cf5a6c84SAndroid Build Coastguard Worker         t += (content_len + 4);
400*cf5a6c84SAndroid Build Coastguard Worker         break;
401*cf5a6c84SAndroid Build Coastguard Worker     }
402*cf5a6c84SAndroid Build Coastguard Worker   }
403*cf5a6c84SAndroid Build Coastguard Worker }
404*cf5a6c84SAndroid Build Coastguard Worker 
write_pid(char * path)405*cf5a6c84SAndroid Build Coastguard Worker static void write_pid(char *path)
406*cf5a6c84SAndroid Build Coastguard Worker {
407*cf5a6c84SAndroid Build Coastguard Worker   int pidfile = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
408*cf5a6c84SAndroid Build Coastguard Worker 
409*cf5a6c84SAndroid Build Coastguard Worker   if (pidfile > 0) {
410*cf5a6c84SAndroid Build Coastguard Worker     char pidbuf[12];
411*cf5a6c84SAndroid Build Coastguard Worker 
412*cf5a6c84SAndroid Build Coastguard Worker     sprintf(pidbuf, "%u", (unsigned)getpid());
413*cf5a6c84SAndroid Build Coastguard Worker     write(pidfile, pidbuf, strlen(pidbuf));
414*cf5a6c84SAndroid Build Coastguard Worker     close(pidfile);
415*cf5a6c84SAndroid Build Coastguard Worker   }
416*cf5a6c84SAndroid Build Coastguard Worker }
417*cf5a6c84SAndroid Build Coastguard Worker 
418*cf5a6c84SAndroid Build Coastguard Worker // Creates environment pointers from RES to use in script
fill_envp(DHCP_DATA * res)419*cf5a6c84SAndroid Build Coastguard Worker static int fill_envp(DHCP_DATA *res)
420*cf5a6c84SAndroid Build Coastguard Worker {
421*cf5a6c84SAndroid Build Coastguard Worker   int ret = setenv("interface", TT.interface_name, 1);
422*cf5a6c84SAndroid Build Coastguard Worker 
423*cf5a6c84SAndroid Build Coastguard Worker   if (ret) return ret;
424*cf5a6c84SAndroid Build Coastguard Worker   inet_ntop(AF_INET6, res->ipaddr, toybuf, INET6_ADDRSTRLEN);
425*cf5a6c84SAndroid Build Coastguard Worker   ret = setenv("ip",(const char*)toybuf , 1);
426*cf5a6c84SAndroid Build Coastguard Worker   return ret;
427*cf5a6c84SAndroid Build Coastguard Worker }
428*cf5a6c84SAndroid Build Coastguard Worker 
429*cf5a6c84SAndroid Build Coastguard Worker // Executes Script NAME.
run_script(DHCP_DATA * res,char * name)430*cf5a6c84SAndroid Build Coastguard Worker static void run_script(DHCP_DATA *res,  char *name)
431*cf5a6c84SAndroid Build Coastguard Worker {
432*cf5a6c84SAndroid Build Coastguard Worker   volatile int error = 0;
433*cf5a6c84SAndroid Build Coastguard Worker   struct stat sts;
434*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
435*cf5a6c84SAndroid Build Coastguard Worker   char *argv[3];
436*cf5a6c84SAndroid Build Coastguard Worker   char *script = (toys.optflags & FLAG_s) ? TT.script
437*cf5a6c84SAndroid Build Coastguard Worker     : "/usr/share/dhcp/default.script";
438*cf5a6c84SAndroid Build Coastguard Worker 
439*cf5a6c84SAndroid Build Coastguard Worker   if (stat(script, &sts) == -1 && errno == ENOENT) return;
440*cf5a6c84SAndroid Build Coastguard Worker   if (!res || fill_envp(res)) {
441*cf5a6c84SAndroid Build Coastguard Worker     dbg("Failed to create environment variables.\n");
442*cf5a6c84SAndroid Build Coastguard Worker     return;
443*cf5a6c84SAndroid Build Coastguard Worker   }
444*cf5a6c84SAndroid Build Coastguard Worker   dbg("Executing %s %s\n", script, name);
445*cf5a6c84SAndroid Build Coastguard Worker   argv[0] = (char*)script;
446*cf5a6c84SAndroid Build Coastguard Worker   argv[1] = (char*)name;
447*cf5a6c84SAndroid Build Coastguard Worker   argv[2] = NULL;
448*cf5a6c84SAndroid Build Coastguard Worker   fflush(NULL);
449*cf5a6c84SAndroid Build Coastguard Worker 
450*cf5a6c84SAndroid Build Coastguard Worker   pid = vfork();
451*cf5a6c84SAndroid Build Coastguard Worker   if (pid < 0) {
452*cf5a6c84SAndroid Build Coastguard Worker     dbg("Fork failed.\n");
453*cf5a6c84SAndroid Build Coastguard Worker     return;
454*cf5a6c84SAndroid Build Coastguard Worker   }
455*cf5a6c84SAndroid Build Coastguard Worker   if (!pid) {
456*cf5a6c84SAndroid Build Coastguard Worker     execvp(argv[0], argv);
457*cf5a6c84SAndroid Build Coastguard Worker     error = errno;
458*cf5a6c84SAndroid Build Coastguard Worker     _exit(111);
459*cf5a6c84SAndroid Build Coastguard Worker   }
460*cf5a6c84SAndroid Build Coastguard Worker   if (error) {
461*cf5a6c84SAndroid Build Coastguard Worker     waitpid(pid, NULL, 0);
462*cf5a6c84SAndroid Build Coastguard Worker     errno = error;
463*cf5a6c84SAndroid Build Coastguard Worker     perror_msg("script exec failed");
464*cf5a6c84SAndroid Build Coastguard Worker   }
465*cf5a6c84SAndroid Build Coastguard Worker   dbg("script complete.\n");
466*cf5a6c84SAndroid Build Coastguard Worker }
467*cf5a6c84SAndroid Build Coastguard Worker 
lease_fail()468*cf5a6c84SAndroid Build Coastguard Worker static void lease_fail()
469*cf5a6c84SAndroid Build Coastguard Worker {
470*cf5a6c84SAndroid Build Coastguard Worker   dbg("Lease failed.\n");
471*cf5a6c84SAndroid Build Coastguard Worker   run_script(NULL, "leasefail");
472*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_n) {
473*cf5a6c84SAndroid Build Coastguard Worker     xclose(TT.sock);
474*cf5a6c84SAndroid Build Coastguard Worker     xclose(TT.sock1);
475*cf5a6c84SAndroid Build Coastguard Worker     error_exit("Lease Failed, Exiting.");
476*cf5a6c84SAndroid Build Coastguard Worker   }
477*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_b) {
478*cf5a6c84SAndroid Build Coastguard Worker     dbg("Lease failed. Going to daemon mode.\n");
479*cf5a6c84SAndroid Build Coastguard Worker     if (daemon(0,0)) perror_exit("daemonize");
480*cf5a6c84SAndroid Build Coastguard Worker     if (toys.optflags & FLAG_p) write_pid(TT.pidfile);
481*cf5a6c84SAndroid Build Coastguard Worker     toys.optflags &= ~FLAG_b;
482*cf5a6c84SAndroid Build Coastguard Worker     toys.optflags |= FLAG_f;
483*cf5a6c84SAndroid Build Coastguard Worker   }
484*cf5a6c84SAndroid Build Coastguard Worker }
485*cf5a6c84SAndroid Build Coastguard Worker 
486*cf5a6c84SAndroid Build Coastguard Worker // Generic signal handler real handling is done in main funcrion.
signal_handler(int sig)487*cf5a6c84SAndroid Build Coastguard Worker static void signal_handler(int sig)
488*cf5a6c84SAndroid Build Coastguard Worker {
489*cf5a6c84SAndroid Build Coastguard Worker     dbg("Caught signal: %d\n", sig);
490*cf5a6c84SAndroid Build Coastguard Worker     switch (sig) {
491*cf5a6c84SAndroid Build Coastguard Worker     case SIGUSR1:
492*cf5a6c84SAndroid Build Coastguard Worker       dbg("SIGUSR1.\n");
493*cf5a6c84SAndroid Build Coastguard Worker       if (TT.state == DHCP6RELEASE || TT.state == DHCP6REQUEST ) {
494*cf5a6c84SAndroid Build Coastguard Worker         TT.state = DHCP6SOLICIT;
495*cf5a6c84SAndroid Build Coastguard Worker         set_timeout(0);
496*cf5a6c84SAndroid Build Coastguard Worker         return;
497*cf5a6c84SAndroid Build Coastguard Worker       }
498*cf5a6c84SAndroid Build Coastguard Worker       dbg("SIGUSR1 sending renew.\n");
499*cf5a6c84SAndroid Build Coastguard Worker       send_msg(DHCP6RENEW);
500*cf5a6c84SAndroid Build Coastguard Worker       TT.state = DHCP6RENEW;
501*cf5a6c84SAndroid Build Coastguard Worker       TT.retries = 0;
502*cf5a6c84SAndroid Build Coastguard Worker       set_timeout(0);
503*cf5a6c84SAndroid Build Coastguard Worker       break;
504*cf5a6c84SAndroid Build Coastguard Worker     case SIGUSR2:
505*cf5a6c84SAndroid Build Coastguard Worker       dbg("SIGUSR2.\n");
506*cf5a6c84SAndroid Build Coastguard Worker       if (TT.state == DHCP6RELEASE) return;
507*cf5a6c84SAndroid Build Coastguard Worker       if (TT.state != DHCP6CONFIRM ) return;
508*cf5a6c84SAndroid Build Coastguard Worker       dbg("SIGUSR2 sending release.\n");
509*cf5a6c84SAndroid Build Coastguard Worker       send_msg(DHCP6RELEASE);
510*cf5a6c84SAndroid Build Coastguard Worker       TT.state = DHCP6RELEASE;
511*cf5a6c84SAndroid Build Coastguard Worker       TT.retries = 0;
512*cf5a6c84SAndroid Build Coastguard Worker       set_timeout(0);
513*cf5a6c84SAndroid Build Coastguard Worker       break;
514*cf5a6c84SAndroid Build Coastguard Worker     case SIGTERM:
515*cf5a6c84SAndroid Build Coastguard Worker     case SIGINT:
516*cf5a6c84SAndroid Build Coastguard Worker       dbg((sig == SIGTERM)?"SIGTERM.\n":"SIGINT.\n");
517*cf5a6c84SAndroid Build Coastguard Worker       if ((toys.optflags & FLAG_R) && TT.state == DHCP6CONFIRM)
518*cf5a6c84SAndroid Build Coastguard Worker         send_msg(DHCP6RELEASE);
519*cf5a6c84SAndroid Build Coastguard Worker       if(sig == SIGINT) exit(0);
520*cf5a6c84SAndroid Build Coastguard Worker       break;
521*cf5a6c84SAndroid Build Coastguard Worker     default: break;
522*cf5a6c84SAndroid Build Coastguard Worker   }
523*cf5a6c84SAndroid Build Coastguard Worker }
524*cf5a6c84SAndroid Build Coastguard Worker 
525*cf5a6c84SAndroid Build Coastguard Worker // signal setup for SIGUSR1 SIGUSR2 SIGTERM
setup_signal()526*cf5a6c84SAndroid Build Coastguard Worker static int setup_signal()
527*cf5a6c84SAndroid Build Coastguard Worker {
528*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGUSR1, signal_handler);
529*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGUSR2, signal_handler);
530*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGTERM, signal_handler);
531*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGINT, signal_handler);
532*cf5a6c84SAndroid Build Coastguard Worker   return 0;
533*cf5a6c84SAndroid Build Coastguard Worker }
534*cf5a6c84SAndroid Build Coastguard Worker 
dhcp6_main(void)535*cf5a6c84SAndroid Build Coastguard Worker void dhcp6_main(void)
536*cf5a6c84SAndroid Build Coastguard Worker {
537*cf5a6c84SAndroid Build Coastguard Worker   struct sockaddr_in6  sinaddr6;
538*cf5a6c84SAndroid Build Coastguard Worker   int constone = 1;
539*cf5a6c84SAndroid Build Coastguard Worker   fd_set rfds;
540*cf5a6c84SAndroid Build Coastguard Worker 
541*cf5a6c84SAndroid Build Coastguard Worker   srand(time(NULL));
542*cf5a6c84SAndroid Build Coastguard Worker   setlinebuf(stdout);
543*cf5a6c84SAndroid Build Coastguard Worker   dbg = dummy;
544*cf5a6c84SAndroid Build Coastguard Worker   TT.state = DHCP6SOLICIT;
545*cf5a6c84SAndroid Build Coastguard Worker 
546*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_v) dbg = logit;
547*cf5a6c84SAndroid Build Coastguard Worker   if (!TT.interface_name) TT.interface_name = "eth0";
548*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_p) write_pid(TT.pidfile);
549*cf5a6c84SAndroid Build Coastguard Worker   if (!TT.retry) TT.retry = 3;
550*cf5a6c84SAndroid Build Coastguard Worker   if (!TT.timeout) TT.timeout = 3;
551*cf5a6c84SAndroid Build Coastguard Worker   if (!TT.errortimeout) TT.errortimeout = 20;
552*cf5a6c84SAndroid Build Coastguard Worker   if (toys.optflags & FLAG_S) {
553*cf5a6c84SAndroid Build Coastguard Worker     openlog("DHCP6 :", LOG_PID, LOG_DAEMON);
554*cf5a6c84SAndroid Build Coastguard Worker     dbg = logit;
555*cf5a6c84SAndroid Build Coastguard Worker   }
556*cf5a6c84SAndroid Build Coastguard Worker 
557*cf5a6c84SAndroid Build Coastguard Worker   dbg("Interface: %s\n", TT.interface_name);
558*cf5a6c84SAndroid Build Coastguard Worker   dbg("pid file: %s\n", TT.pidfile);
559*cf5a6c84SAndroid Build Coastguard Worker   dbg("Retry count: %d\n", TT.retry);
560*cf5a6c84SAndroid Build Coastguard Worker   dbg("Timeout : %d\n", TT.timeout);
561*cf5a6c84SAndroid Build Coastguard Worker   dbg("Error timeout: %d\n", TT.errortimeout);
562*cf5a6c84SAndroid Build Coastguard Worker 
563*cf5a6c84SAndroid Build Coastguard Worker 
564*cf5a6c84SAndroid Build Coastguard Worker 
565*cf5a6c84SAndroid Build Coastguard Worker   setup_signal();
566*cf5a6c84SAndroid Build Coastguard Worker   TT.sock1 = xsocket(PF_INET6, SOCK_DGRAM, 0);
567*cf5a6c84SAndroid Build Coastguard Worker   memset(&sinaddr6, 0, sizeof(sinaddr6));
568*cf5a6c84SAndroid Build Coastguard Worker   sinaddr6.sin6_family = AF_INET6;
569*cf5a6c84SAndroid Build Coastguard Worker   sinaddr6.sin6_port = htons(DHCPC_CLIENT_PORT);
570*cf5a6c84SAndroid Build Coastguard Worker   sinaddr6.sin6_scope_id = if_nametoindex(TT.interface_name);
571*cf5a6c84SAndroid Build Coastguard Worker   sinaddr6.sin6_addr = in6addr_any ;
572*cf5a6c84SAndroid Build Coastguard Worker 
573*cf5a6c84SAndroid Build Coastguard Worker   xsetsockopt(TT.sock1, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone));
574*cf5a6c84SAndroid Build Coastguard Worker 
575*cf5a6c84SAndroid Build Coastguard Worker   xbind(TT.sock1, (struct sockaddr *)&sinaddr6, sizeof(sinaddr6));
576*cf5a6c84SAndroid Build Coastguard Worker 
577*cf5a6c84SAndroid Build Coastguard Worker   mode_raw();
578*cf5a6c84SAndroid Build Coastguard Worker   set_timeout(0);
579*cf5a6c84SAndroid Build Coastguard Worker   for (;;) {
580*cf5a6c84SAndroid Build Coastguard Worker     int maxfd = TT.sock;
581*cf5a6c84SAndroid Build Coastguard Worker 
582*cf5a6c84SAndroid Build Coastguard Worker     if (TT.sock >= 0) FD_SET(TT.sock, &rfds);
583*cf5a6c84SAndroid Build Coastguard Worker     TT.retval = 0;
584*cf5a6c84SAndroid Build Coastguard Worker     if ((TT.retval = select(maxfd + 1, &rfds, NULL, NULL, &TT.tv)) < 0) {
585*cf5a6c84SAndroid Build Coastguard Worker       if(errno == EINTR) continue;
586*cf5a6c84SAndroid Build Coastguard Worker       perror_exit("Error in select");
587*cf5a6c84SAndroid Build Coastguard Worker     }
588*cf5a6c84SAndroid Build Coastguard Worker     if (!TT.retval) {
589*cf5a6c84SAndroid Build Coastguard Worker       if (TT.state == DHCP6SOLICIT || TT.state == DHCP6CONFIRM) {
590*cf5a6c84SAndroid Build Coastguard Worker         dbg("State is solicit, sending solicit packet\n");
591*cf5a6c84SAndroid Build Coastguard Worker         run_script(NULL, "deconfig");
592*cf5a6c84SAndroid Build Coastguard Worker         send_msg(DHCP6SOLICIT);
593*cf5a6c84SAndroid Build Coastguard Worker         TT.state = DHCP6SOLICIT;
594*cf5a6c84SAndroid Build Coastguard Worker         TT.retries++;
595*cf5a6c84SAndroid Build Coastguard Worker         if(TT.retries > TT.retry) set_timeout(TT.errortimeout);
596*cf5a6c84SAndroid Build Coastguard Worker         else if (TT.retries == TT.retry) {
597*cf5a6c84SAndroid Build Coastguard Worker           dbg("State is solicit, retry count is max.\n");
598*cf5a6c84SAndroid Build Coastguard Worker           lease_fail();
599*cf5a6c84SAndroid Build Coastguard Worker           set_timeout(TT.errortimeout);
600*cf5a6c84SAndroid Build Coastguard Worker         } else set_timeout(TT.timeout);
601*cf5a6c84SAndroid Build Coastguard Worker         continue;
602*cf5a6c84SAndroid Build Coastguard Worker       } else if (TT.state == DHCP6REQUEST || TT.state == DHCP6RENEW ||
603*cf5a6c84SAndroid Build Coastguard Worker               TT.state == DHCP6RELEASE) {
604*cf5a6c84SAndroid Build Coastguard Worker         dbg("State is %d , sending packet\n", TT.state);
605*cf5a6c84SAndroid Build Coastguard Worker         send_msg(TT.state);
606*cf5a6c84SAndroid Build Coastguard Worker         TT.retries++;
607*cf5a6c84SAndroid Build Coastguard Worker         if (TT.retries > TT.retry) set_timeout(TT.errortimeout);
608*cf5a6c84SAndroid Build Coastguard Worker         else if (TT.retries == TT.retry) {
609*cf5a6c84SAndroid Build Coastguard Worker           lease_fail();
610*cf5a6c84SAndroid Build Coastguard Worker           set_timeout(TT.errortimeout);
611*cf5a6c84SAndroid Build Coastguard Worker         } else set_timeout(TT.timeout);
612*cf5a6c84SAndroid Build Coastguard Worker         continue;
613*cf5a6c84SAndroid Build Coastguard Worker       }
614*cf5a6c84SAndroid Build Coastguard Worker     } else if (FD_ISSET(TT.sock, &rfds)) {
615*cf5a6c84SAndroid Build Coastguard Worker       if ((TT.status = read(TT.sock, toybuf, sizeof(toybuf))) <= 0) continue;
616*cf5a6c84SAndroid Build Coastguard Worker       mymsg = (dhcp6_raw_t*)toybuf;
617*cf5a6c84SAndroid Build Coastguard Worker       if (ntohs(mymsg->udph.dest) == 546 &&
618*cf5a6c84SAndroid Build Coastguard Worker               !memcmp(mymsg->dhcp6.transaction_id, TT.transction_id, 3)) {
619*cf5a6c84SAndroid Build Coastguard Worker         if (TT.state == DHCP6SOLICIT) {
620*cf5a6c84SAndroid Build Coastguard Worker           if (mymsg->dhcp6.msgtype == DHCP6ADVERTISE ) {
621*cf5a6c84SAndroid Build Coastguard Worker             if (!validate_ids()) {
622*cf5a6c84SAndroid Build Coastguard Worker               dbg("Invalid id received, solicit.\n");
623*cf5a6c84SAndroid Build Coastguard Worker               TT.state = DHCP6SOLICIT;
624*cf5a6c84SAndroid Build Coastguard Worker               continue;
625*cf5a6c84SAndroid Build Coastguard Worker             }
626*cf5a6c84SAndroid Build Coastguard Worker             dbg("Got reply to request or solicit.\n");
627*cf5a6c84SAndroid Build Coastguard Worker             TT.retries = 0;
628*cf5a6c84SAndroid Build Coastguard Worker             set_timeout(0);
629*cf5a6c84SAndroid Build Coastguard Worker             TT.request_length = TT.status - ((char*)&mymsg->dhcp6 - (char*)mymsg);
630*cf5a6c84SAndroid Build Coastguard Worker             memcpy((uint8_t*)&mesg, &mymsg->dhcp6, TT.request_length);
631*cf5a6c84SAndroid Build Coastguard Worker             parse_ia_na(mesg.options, TT.request_length);
632*cf5a6c84SAndroid Build Coastguard Worker             dbg("Status code:%d\n", dhcp_data.status_code);
633*cf5a6c84SAndroid Build Coastguard Worker             inet_ntop(AF_INET6, dhcp_data.ipaddr, toybuf, INET6_ADDRSTRLEN);
634*cf5a6c84SAndroid Build Coastguard Worker             dbg("Advertiesed IP: %s\n", toybuf);
635*cf5a6c84SAndroid Build Coastguard Worker             TT.state = DHCP6REQUEST;
636*cf5a6c84SAndroid Build Coastguard Worker           } else {
637*cf5a6c84SAndroid Build Coastguard Worker             dbg("Invalid solicit.\n");
638*cf5a6c84SAndroid Build Coastguard Worker             continue;
639*cf5a6c84SAndroid Build Coastguard Worker           }
640*cf5a6c84SAndroid Build Coastguard Worker         } else if (TT.state == DHCP6REQUEST || TT.state == DHCP6RENEW ) {
641*cf5a6c84SAndroid Build Coastguard Worker           if (mymsg->dhcp6.msgtype == DHCP6REPLY) {
642*cf5a6c84SAndroid Build Coastguard Worker             if (!validate_ids()) {
643*cf5a6c84SAndroid Build Coastguard Worker               dbg("Invalid id received, %d.\n", TT.state);
644*cf5a6c84SAndroid Build Coastguard Worker               TT.state = DHCP6REQUEST;
645*cf5a6c84SAndroid Build Coastguard Worker               continue;
646*cf5a6c84SAndroid Build Coastguard Worker             }
647*cf5a6c84SAndroid Build Coastguard Worker             dbg("Got reply to request or renew.\n");
648*cf5a6c84SAndroid Build Coastguard Worker             TT.request_length = TT.status - ((char*)&mymsg->dhcp6 - (char*)mymsg);
649*cf5a6c84SAndroid Build Coastguard Worker             memcpy((uint8_t*)&mesg, &mymsg->dhcp6, TT.request_length);
650*cf5a6c84SAndroid Build Coastguard Worker             parse_ia_na(mymsg->dhcp6.options, TT.request_length);
651*cf5a6c84SAndroid Build Coastguard Worker             dbg("Status code:%d\n", dhcp_data.status_code);
652*cf5a6c84SAndroid Build Coastguard Worker             inet_ntop(AF_INET6, dhcp_data.ipaddr, toybuf, INET6_ADDRSTRLEN);
653*cf5a6c84SAndroid Build Coastguard Worker             dbg("Got IP: %s\n", toybuf);
654*cf5a6c84SAndroid Build Coastguard Worker             TT.retries = 0;
655*cf5a6c84SAndroid Build Coastguard Worker             run_script(&dhcp_data, (TT.state == DHCP6REQUEST) ?
656*cf5a6c84SAndroid Build Coastguard Worker               "request" : "renew");
657*cf5a6c84SAndroid Build Coastguard Worker             if (toys.optflags & FLAG_q) {
658*cf5a6c84SAndroid Build Coastguard Worker               if (toys.optflags & FLAG_R) send_msg(DHCP6RELEASE);
659*cf5a6c84SAndroid Build Coastguard Worker               break;
660*cf5a6c84SAndroid Build Coastguard Worker             }
661*cf5a6c84SAndroid Build Coastguard Worker             TT.state = DHCP6CONFIRM;
662*cf5a6c84SAndroid Build Coastguard Worker             set_timeout((dhcp_data.va_lf)?dhcp_data.va_lf:INT_MAX);
663*cf5a6c84SAndroid Build Coastguard Worker             dbg("Setting timeout to intmax.");
664*cf5a6c84SAndroid Build Coastguard Worker             if (TT.state == DHCP6REQUEST || !(toys.optflags & FLAG_f)) {
665*cf5a6c84SAndroid Build Coastguard Worker               dbg("Making it a daemon\n");
666*cf5a6c84SAndroid Build Coastguard Worker               if (daemon(0,0)) perror_exit("daemonize");
667*cf5a6c84SAndroid Build Coastguard Worker               toys.optflags |= FLAG_f;
668*cf5a6c84SAndroid Build Coastguard Worker               if (toys.optflags & FLAG_p) write_pid(TT.pidfile);
669*cf5a6c84SAndroid Build Coastguard Worker             }
670*cf5a6c84SAndroid Build Coastguard Worker             dbg("Making it a foreground.\n");
671*cf5a6c84SAndroid Build Coastguard Worker             continue;
672*cf5a6c84SAndroid Build Coastguard Worker           } else {
673*cf5a6c84SAndroid Build Coastguard Worker             dbg("Invalid reply.\n");
674*cf5a6c84SAndroid Build Coastguard Worker             continue;
675*cf5a6c84SAndroid Build Coastguard Worker           }
676*cf5a6c84SAndroid Build Coastguard Worker         } else if (TT.state == DHCP6RELEASE) {
677*cf5a6c84SAndroid Build Coastguard Worker           dbg("Got reply to release.\n");
678*cf5a6c84SAndroid Build Coastguard Worker           run_script(NULL, "release");
679*cf5a6c84SAndroid Build Coastguard Worker           set_timeout(INT_MAX);
680*cf5a6c84SAndroid Build Coastguard Worker         }
681*cf5a6c84SAndroid Build Coastguard Worker       }
682*cf5a6c84SAndroid Build Coastguard Worker     }
683*cf5a6c84SAndroid Build Coastguard Worker   }
684*cf5a6c84SAndroid Build Coastguard Worker   xclose(TT.sock1);
685*cf5a6c84SAndroid Build Coastguard Worker   xclose(TT.sock);
686*cf5a6c84SAndroid Build Coastguard Worker }
687