2adc60d0dbb2f852dd32e0d091ef9587307028c8
[platform/upstream/toybox.git] / toys / pending / dhcpd.c
1 /* dhcpd.c - DHCP server for dynamic network configuration.
2  *
3  * Copyright 2013 Madhur Verma <mad.flexi@gmail.com>
4  * Copyright 2013 Kyungwan Han <asura321@gamil.com>
5  * Copyright 2015 Yeongdeok Suh <skyducks111@gmail.com>
6  *
7  * No Standard
8 USE_DHCPD(NEWTOY(dhcpd, ">1P#<0>65535=67fi:S46[!46]", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
9
10 config DHCPD
11   bool "dhcpd"
12   default n
13   help
14    usage: dhcpd [-46fS] [-i IFACE] [-P N] [CONFFILE]
15
16     -f    Run in foreground
17     -i Interface to use
18     -S    Log to syslog too
19     -P N  Use port N (default ipv4 67, ipv6 547)
20     -4, -6    Run as a DHCPv4 or DHCPv6 server
21
22 config DEBUG_DHCP
23   bool "debugging messeges ON/OFF"
24   default n
25   depends on DHCPD
26 */
27
28 /*
29  * Things to do
30  *
31  * - Working as an relay agent
32  * - Rapid commit option support
33  * - Additional packet options (commented on the middle of sources)
34  * - Create common modules
35  */
36
37 #define FOR_dhcpd
38
39 #include "toys.h"
40 #include <linux/sockios.h>
41 #include <linux/if_ether.h>
42
43 // Todo: headers not in posix
44 #include <netinet/ip.h>
45 #include <netinet/ip6.h>
46 #include <netinet/udp.h>
47 #include <netpacket/packet.h>
48
49 # define dbg(fmt, arg...)   printf(fmt, ##arg)
50
51 #define flag_get(f,v,d)     ((toys.optflags & (f)) ? (v) : (d))
52 #define flag_chk(f)         ((toys.optflags & (f)) ? 1 : 0)
53
54 #define LOG_SILENT          0x0
55 #define LOG_CONSOLE         0x1
56 #define LOG_SYSTEM          0x2
57
58 #define DHCP_MAGIC          0x63825363
59
60 #define DHCPDISCOVER        1
61 #define DHCPOFFER           2
62 #define DHCPREQUEST         3
63 #define DHCPDECLINE         4
64 #define DHCPACK             5
65 #define DHCPNAK             6
66 #define DHCPRELEASE         7
67 #define DHCPINFORM          8
68
69 #define DHCP6SOLICIT        1
70 #define DHCP6ADVERTISE      2   // server -> client
71 #define DHCP6REQUEST        3
72 #define DHCP6CONFIRM        4
73 #define DHCP6RENEW          5
74 #define DHCP6REBIND         6
75 #define DHCP6REPLY          7   // server -> client
76 #define DHCP6RELEASE        8
77 #define DHCP6DECLINE        9
78 #define DHCP6RECONFIGURE    10  // server -> client
79 #define DHCP6INFOREQUEST    11
80 #define DHCP6RELAYFLOW      12  // relay -> relay/server
81 #define DHCP6RELAYREPLY     13  // server/relay -> relay
82
83 #define DHCP_NUM8           (1<<8)
84 #define DHCP_NUM16          (1<<9)
85 #define DHCP_NUM32          DHCP_NUM16 | DHCP_NUM8
86 #define DHCP_STRING         (1<<10)
87 #define DHCP_STRLST         (1<<11)
88 #define DHCP_IP             (1<<12)
89 #define DHCP_IPLIST         (1<<13)
90 #define DHCP_IPPLST         (1<<14)
91 #define DHCP_STCRTS         (1<<15)
92
93 // DHCP option codes (partial list). See RFC 2132 and
94 #define DHCP_OPT_PADDING                          0x00
95 #define DHCP_OPT_HOST_NAME          DHCP_STRING | 0x0c // either client informs server or server gives name to client
96 #define DHCP_OPT_REQUESTED_IP       DHCP_IP     | 0x32 // sent by client if specific IP is wanted
97 #define DHCP_OPT_LEASE_TIME         DHCP_NUM32  | 0x33
98 #define DHCP_OPT_OPTION_OVERLOAD                  0x34
99 #define DHCP_OPT_MESSAGE_TYPE       DHCP_NUM8   | 0x35
100 #define DHCP_OPT_SERVER_ID          DHCP_IP     | 0x36 // by default server's IP
101 #define DHCP_OPT_PARAM_REQ          DHCP_STRING | 0x37 // list of options client wants
102 #define DHCP_OPT_END                              0xff
103
104 // DHCPv6 option codes (partial). See RFC 3315
105 #define DHCP6_OPT_CLIENTID      1
106 #define DHCP6_OPT_SERVERID      2
107 #define DHCP6_OPT_IA_NA         3
108 #define DHCP6_OPT_IA_ADDR       5
109 #define DHCP6_OPT_ORO           6
110 #define DHCP6_OPT_PREFERENCE    7
111 #define DHCP6_OPT_ELAPSED_TIME  8
112 #define DHCP6_OPT_RELAY_MSG     9
113 #define DHCP6_OPT_STATUS_CODE   13
114 #define DHCP6_OPT_IA_PD         25
115 #define DHCP6_OPT_IA_PREFIX     26
116
117 #define DHCP6_STATUS_SUCCESS        0
118 #define DHCP6_STATUS_NOADDRSAVAIL   2
119
120 #define DHCP6_DUID_LLT    1
121 #define DHCP6_DUID_EN     2
122 #define DHCP6_DUID_LL     3
123 #define DHCP6_DUID_UUID   4
124
125 GLOBALS(
126     char *iface;
127     long port;
128 );
129
130 struct config_keyword {
131   char *keyword;
132   int (*handler)(const char *str, void *var);
133   void *var;
134   char *def;
135 };
136
137 typedef struct __attribute__((packed)) dhcp_msg_s {
138   uint8_t op;
139   uint8_t htype;
140   uint8_t hlen;
141   uint8_t hops;
142   uint32_t xid;
143   uint16_t secs;
144   uint16_t flags;
145   uint32_t ciaddr;
146   uint32_t yiaddr;
147   uint32_t nsiaddr;
148   uint32_t ngiaddr;
149   uint8_t chaddr[16];
150   uint8_t sname[64];
151   uint8_t file[128];
152   uint32_t cookie;
153   uint8_t options[308];
154 } dhcp_msg_t;
155
156 typedef struct __attribute__((packed)) dhcp6_msg_s {
157   uint8_t msgtype;
158   uint8_t transaction_id[3];
159   uint8_t options[524];
160 } dhcp6_msg_t;
161
162 typedef struct __attribute__((packed)) dhcp_raw_s {
163   struct iphdr iph;
164   struct udphdr udph;
165   dhcp_msg_t dhcp;
166 } dhcp_raw_t;
167
168 typedef struct __attribute__((packed)) dhcp6_raw_s {
169   struct ip6_hdr iph;
170   struct udphdr udph;
171   dhcp6_msg_t dhcp6;
172 } dhcp6_raw_t;
173
174 typedef struct static_lease_s {
175   struct static_lease_s *next;
176   uint32_t nip;
177   int mac[6];
178 } static_lease;
179
180 typedef struct static_lease6_s {
181   struct static_lease6_s *next;
182   uint16_t duid_len;
183   uint16_t ia_type;
184   uint32_t iaid;
185   uint32_t nip6[4];
186   uint8_t duid[20];
187 } static_lease6;
188
189 typedef struct {
190   uint32_t expires;
191   uint32_t lease_nip;
192   uint8_t lease_mac[6];
193   char hostname[20];
194   uint8_t pad[2];
195 } dyn_lease;
196
197 typedef struct {
198   uint16_t duid_len;
199   uint16_t ia_type;
200   uint32_t expires;
201   uint32_t iaid;
202   uint32_t lease_nip6[4];
203   uint8_t duid[20];
204 } dyn_lease6;
205
206 typedef struct option_val_s {
207   char *key;
208   uint16_t code;
209   void *val;
210   size_t len;
211 } option_val_t;
212
213 struct __attribute__((packed)) optval_duid_llt {
214   uint16_t type;
215   uint16_t hwtype;
216   uint32_t time;
217   uint8_t *lladdr;
218 };
219
220 struct __attribute__((packed)) optval_ia_na {
221   uint32_t iaid;
222   uint32_t t1, t2;
223   uint8_t *optval;
224 };
225 struct __attribute__((packed)) optval_ia_addr {
226   uint32_t ipv6_addr[4];
227   uint32_t pref_lifetime;
228   uint32_t valid_lifetime;
229 };
230 struct __attribute__((packed)) optval_status_code {
231   uint16_t status_code;
232   uint8_t *status_msg;
233 };
234
235 typedef struct __attribute__((__may_alias__)) server_config_s {
236   char *interface;                // interface to use
237   int ifindex;
238   uint32_t server_nip6[4];
239   uint32_t server_nip;
240   uint32_t port;
241   uint8_t server_mac[6];          // our MAC address (used only for ARP probing)
242   void *options[256];             // list of DHCP options loaded from the config file
243   /* start,end are in host order: we need to compare start <= ip <= end*/
244   uint32_t start_ip;              // start address of leases, in host order
245   uint32_t end_ip;                // end of leases, in host order
246   uint32_t start_ip6[4];          // start address of leases, in IPv6 mode
247   uint32_t end_ip6[4];            // end of leases, in IPv6 mode
248   uint32_t max_lease_sec;         // maximum lease time (host order)
249   uint32_t min_lease_sec;         // minimum lease time a client can request
250   uint32_t max_leases;            // maximum number of leases (including reserved addresses)
251   uint32_t auto_time;             // how long should dhcpd wait before writing a config file.
252                                   // if this is zero, it will only write one on SIGUSR1
253   uint32_t decline_time;          // how long an address is reserved if a client returns a
254                                   // decline message
255   uint32_t conflict_time;         // how long an arp conflict offender is leased for
256   uint32_t offer_time;            // how long an offered address is reserved
257   uint32_t siaddr_nip;            // "next server" bootp option
258   char *lease_file;
259   char *lease6_file;
260   char *pidfile;
261   char *notify_file;              // what to run whenever leases are written
262   char *sname;                    // bootp server name
263   char *boot_file;                // bootp boot file option
264   uint32_t pref_lifetime;
265   uint32_t valid_lifetime;
266   uint32_t t1,t2;
267   struct static_lease *static_leases; // List of ip/mac pairs to assign static leases
268 } server_config_t;
269
270 typedef struct __attribute__((__may_alias__)) server_state_s {
271   uint8_t rqcode;
272   int listensock;
273   union {
274     dhcp_msg_t rcvd_pkt;
275     dhcp6_msg_t rcvd_pkt6;
276   } rcvd;
277   uint8_t* rqopt;
278   union {
279     dhcp_msg_t send_pkt;
280     dhcp6_msg_t send_pkt6;
281   } send;
282   union {
283     static_lease *sleases;
284     static_lease6 *sleases6;
285   } leases;
286   struct arg_list *dleases;
287 } server_state_t;
288
289 static option_val_t options_list[] = {
290     {"lease"          , DHCP_NUM32  | 0x33, NULL, 0},
291     {"subnet"         , DHCP_IP     | 0x01, NULL, 0},
292     {"broadcast"      , DHCP_IP     | 0x1c, NULL, 0},
293     {"router"         , DHCP_IP     | 0x03, NULL, 0},
294     {"ipttl"          , DHCP_NUM8   | 0x17, NULL, 0},
295     {"mtu"            , DHCP_NUM16  | 0x1a, NULL, 0},
296     {"hostname"       , DHCP_STRING | 0x0c, NULL, 0},
297     {"domain"         , DHCP_STRING | 0x0f, NULL, 0},
298     {"search"         , DHCP_STRLST | 0x77, NULL, 0},
299     {"nisdomain"      , DHCP_STRING | 0x28, NULL, 0},
300     {"timezone"       , DHCP_NUM32  | 0x02, NULL, 0},
301     {"tftp"           , DHCP_STRING | 0x42, NULL, 0},
302     {"bootfile"       , DHCP_STRING | 0x43, NULL, 0},
303     {"bootsize"       , DHCP_NUM16  | 0x0d, NULL, 0},
304     {"rootpath"       , DHCP_STRING | 0x11, NULL, 0},
305     {"wpad"           , DHCP_STRING | 0xfc, NULL, 0},
306     {"serverid"       , DHCP_IP     | 0x36, NULL, 0},
307     {"message"        , DHCP_STRING | 0x38, NULL, 0},
308     {"vlanid"         , DHCP_NUM32  | 0x84, NULL, 0},
309     {"vlanpriority"   , DHCP_NUM32  | 0x85, NULL, 0},
310     {"dns"            , DHCP_IPLIST | 0x06, NULL, 0},
311     {"wins"           , DHCP_IPLIST | 0x2c, NULL, 0},
312     {"nissrv"         , DHCP_IPLIST | 0x29, NULL, 0},
313     {"ntpsrv"         , DHCP_IPLIST | 0x2a, NULL, 0},
314     {"lprsrv"         , DHCP_IPLIST | 0x09, NULL, 0},
315     {"swapsrv"        , DHCP_IP     | 0x10, NULL, 0},
316     {"routes"         , DHCP_STCRTS | 0x21, NULL, 0},
317     {"staticroutes"   , DHCP_STCRTS | 0x79, NULL, 0},
318     {"msstaticroutes" , DHCP_STCRTS | 0xf9, NULL, 0},
319 };
320
321 struct fd_pair { int rd; int wr; };
322 static server_config_t gconfig;
323 static server_state_t gstate;
324 static uint8_t infomode;
325 static struct fd_pair sigfd;
326 static int constone = 1;
327 static sa_family_t addr_version = AF_INET;
328
329 static void htonl6(uint32_t *host_order, uint32_t *network_order)
330 {
331   int i;
332   if(!host_order) {
333     error_msg("NULL ipv6 address");
334   } else {
335     for(i=0;i<4;i++) network_order[i] = htonl(host_order[i]);
336   }
337 }
338
339 static void ntohl6(uint32_t *network_order, uint32_t *host_order)
340 {
341   int i;
342   if(!network_order) {
343     error_msg("NULL ipv6 address");
344   } else {
345     for(i=0;i<4;i++) host_order[i] = ntohl(network_order[i]);
346   }
347 }
348
349 // calculate options size.
350 static int dhcp_opt_size(uint8_t *optionptr)
351 {
352   int i = 0;
353   for(;optionptr[i] != 0xff; i++)
354     if(optionptr[i] != 0x00) i += optionptr[i + 1] + 2 -1;
355   return i;
356 }
357
358 // calculates checksum for dhcp messeges.
359 static uint16_t dhcp_checksum(void *addr, int count)
360 {
361   int32_t sum = 0;
362   uint16_t tmp = 0, *source = (uint16_t *)addr;
363
364   while (count > 1)  {
365     sum += *source++;
366     count -= 2;
367   }
368   if (count > 0) {
369     *(uint8_t*)&tmp = *(uint8_t*)source;
370     sum += tmp;
371   }
372   while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
373   return ~sum;
374 }
375
376 // gets information of INTERFACE and updates IFINDEX, MAC and IP
377 static int get_interface(const char *interface, int *ifindex, uint32_t *oip,
378     uint8_t *mac)
379 {
380   struct ifreq req;
381   struct sockaddr_in *ip;
382   struct sockaddr_in6 ip6;
383   int fd = xsocket(addr_version, SOCK_RAW, IPPROTO_RAW);
384   char ipv6_addr[40] = {0,};
385
386   req.ifr_addr.sa_family = addr_version;
387   xstrncpy(req.ifr_name, (char *)interface, IFNAMSIZ);
388
389   xioctl(fd, SIOCGIFFLAGS, &req);
390
391   if (!(req.ifr_flags & IFF_UP)) return -1;
392
393   if (addr_version == AF_INET6) {
394
395     FILE *fd6 = fopen("/proc/net/if_inet6", "r");
396     int i;
397
398     while(fgets(toybuf, sizeof(toybuf), fd6)) {
399       if (!strstr(toybuf, interface))
400         continue;
401
402       if (sscanf(toybuf, "%32s \n", ipv6_addr) != 1)
403         continue;
404
405       if (strstr(ipv6_addr, "fe80")) break;
406     }
407     fclose(fd6);
408
409     if (oip) {
410       char *ptr = ipv6_addr+sizeof(ipv6_addr)-1;
411
412       // convert giant hex string into colon-spearated ipv6 address by
413       // inserting ':' every 4 characters.
414       for (i = 32; i; i--)
415         if ((*(ptr--) = ipv6_addr[i])) if (!(i&3)) *(ptr--) = ':';
416
417       dbg("ipv6 %s\n", ipv6_addr);
418       if(inet_pton(AF_INET6, ipv6_addr, &ip6.sin6_addr) <= 0)
419         error_msg("inet : the ipv6 address is not proper");
420       else
421         ntohl6(ip6.sin6_addr.s6_addr32, oip);
422     }
423   } else {
424     if (oip) {
425       xioctl(fd, SIOCGIFADDR, &req);
426       ip = (struct sockaddr_in*) &req.ifr_addr;
427       dbg("IP %s\n", inet_ntoa(ip->sin_addr));
428       *oip = ntohl(ip->sin_addr.s_addr);
429     }
430   }
431
432   if (ifindex) {
433     xioctl(fd, SIOCGIFINDEX, &req);
434     dbg("Adapter index %d\n", req.ifr_ifindex);
435     *ifindex = req.ifr_ifindex;
436   }
437   if (mac) {
438     xioctl(fd, SIOCGIFHWADDR, &req);
439     memcpy(mac, req.ifr_hwaddr.sa_data, 6);
440     dbg("MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
441   }
442
443   close(fd);
444   return 0;
445 }
446
447 /*
448  *logs messeges to syslog or console
449  *opening the log is still left with applet.
450  *FIXME: move to more relevent lib. probably libc.c
451  */
452 static void infomsg(uint8_t infomode, char *s, ...)
453 {
454   int used;
455   char *msg;
456   va_list p, t;
457
458   if (infomode == LOG_SILENT) return;
459   va_start(p, s);
460   va_copy(t, p);
461   used = vsnprintf(NULL, 0, s, t);
462   used++;
463   va_end(t);
464
465   msg = xmalloc(used);
466   vsnprintf(msg, used, s, p);
467   va_end(p);
468
469   if (infomode & LOG_SYSTEM) syslog(LOG_INFO, "%s", msg);
470   if (infomode & LOG_CONSOLE) printf("%s\n", msg);
471   free(msg);
472 }
473
474 /*
475  * Writes self PID in file PATH
476  * FIXME: libc implementation only writes in /var/run
477  * this is more generic as some implemenation may provide
478  * arguments to write in specific file. as dhcpd does.
479  */
480 static void write_pid(char *path)
481 {
482   int pidfile = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
483   if (pidfile > 0) {
484     char pidbuf[12];
485
486     sprintf(pidbuf, "%u", (unsigned)getpid());
487     write(pidfile, pidbuf, strlen(pidbuf));
488     close(pidfile);
489   }
490 }
491
492 // Generic signal handler real handling is done in main funcrion.
493 static void signal_handler(int sig)
494 {
495   unsigned char ch = sig;
496   if (write(sigfd.wr, &ch, 1) != 1) {
497           dbg("can't send signal\n");
498           exit(0);
499   }
500 }
501
502 // signal setup for SIGUSR1 SIGTERM
503 static int setup_signal()
504 {
505   if (pipe((int *)&sigfd) < 0) {
506     dbg("signal pipe failed\n");
507     return -1;
508   }
509   fcntl(sigfd.wr , F_SETFD, FD_CLOEXEC);
510   fcntl(sigfd.rd , F_SETFD, FD_CLOEXEC);
511   int flags = fcntl(sigfd.wr, F_GETFL);
512   fcntl(sigfd.wr, F_SETFL, flags | O_NONBLOCK);
513   signal(SIGUSR1, signal_handler);
514   signal(SIGTERM, signal_handler);
515   return 0;
516 }
517
518 // String STR to UINT32 conversion strored in VAR
519 static int strtou32(const char *str, void *var)
520 {
521   char *endptr = NULL;
522   int base = 10;
523   errno=0;
524   *((uint32_t*)(var)) = 0;
525   if (str[0]=='0' && (str[1]=='x' || str[1]=='X')) {
526     base = 16;
527     str+=2;
528   }
529
530   long ret_val = strtol(str, &endptr, base);
531   if (errno) infomsg(infomode, "config : Invalid num %s",str);
532   else if (endptr && (*endptr!='\0'||endptr == str))
533       infomsg(infomode, "config : Not a valid num %s",str);
534   else *((uint32_t*)(var)) = (uint32_t)ret_val;
535   return 0;
536 }
537
538 // copy string STR in variable VAR
539 static int strinvar(const char *str, void *var)
540 {
541   char **dest = var;
542   if (*dest) free(*dest);
543   *dest = strdup(str);
544   return 0;
545 }
546
547 // IP String STR to binary data.
548 static int striptovar(const char *str, void *var)
549 {
550   *((uint32_t*)(var)) = 0;
551   if(!str) {
552     error_msg("config : NULL address string \n");
553     return -1;
554   }
555   if((inet_pton(AF_INET6, str, var)<=0) && (inet_pton(AF_INET, str, var)<=0)) {
556     error_msg("config : wrong address %s \n", str);
557     return -1;
558   }
559   return 0;
560 }
561
562 // String to dhcp option conversion
563 static int strtoopt(const char *str, void *var)
564 {
565   char *option, *valstr, *grp, *tp;
566   uint32_t optcode = 0, inf = infomode, convtmp, mask, nip, router;
567   uint16_t flag = 0;
568   int count, size = ARRAY_LEN(options_list);
569
570   if (!*str) return 0;
571   if (!(option = strtok((char*)str, " \t="))) return -1;
572
573   infomode = LOG_SILENT;
574   strtou32(option, (uint32_t*)&optcode);
575   infomode = inf;
576
577   if (optcode > 0 && optcode < 256) { // raw option
578     for (count = 0; count < size; count++) {
579       if ((options_list[count].code & 0X00FF) == optcode) {
580         flag = (options_list[count].code & 0XFF00);
581         break;
582       }
583     }
584   } else { //string option
585     for (count = 0; count < size; count++) {
586       if (!strncmp(options_list[count].key, option, strlen(options_list[count].key))) {
587         flag = (options_list[count].code & 0XFF00);
588         optcode = (options_list[count].code & 0X00FF);
589         break;
590       }
591     }
592   }
593   if (count == size) {
594     infomsg(inf, "config : Obsolete OR Unknown Option : %s", option);
595     return -1;
596   }
597
598   if (!flag || !optcode) return -1;
599
600   if (!(valstr = strtok(NULL, " \t"))) {
601     dbg("config : option %s has no value defined.\n", option);
602     return -1;
603   }
604   dbg(" value : %-20s : ", valstr);
605   switch (flag) {
606   case DHCP_NUM32:
607     options_list[count].len = sizeof(uint32_t);
608     options_list[count].val = xmalloc(sizeof(uint32_t));
609     strtou32(valstr, &convtmp);
610     memcpy(options_list[count].val, &convtmp, sizeof(uint32_t));
611     break;
612   case DHCP_NUM16:
613     options_list[count].len = sizeof(uint16_t);
614     options_list[count].val = xmalloc(sizeof(uint16_t));
615     strtou32(valstr, &convtmp);
616     memcpy(options_list[count].val, &convtmp, sizeof(uint16_t));
617     break;
618   case DHCP_NUM8:
619     options_list[count].len = sizeof(uint8_t);
620     options_list[count].val = xmalloc(sizeof(uint8_t));
621     strtou32(valstr, &convtmp);
622     memcpy(options_list[count].val, &convtmp, sizeof(uint8_t));
623     break;
624   case DHCP_IP:
625     options_list[count].len = sizeof(uint32_t);
626     options_list[count].val = xmalloc(sizeof(uint32_t));
627     striptovar(valstr, options_list[count].val);
628     break;
629   case DHCP_STRING:
630     options_list[count].len = strlen(valstr);
631     options_list[count].val = strdup(valstr);
632     break;
633   case DHCP_IPLIST:
634     while(valstr){
635       options_list[count].val = xrealloc(options_list[count].val, options_list[count].len + sizeof(uint32_t));
636       striptovar(valstr, ((uint8_t*)options_list[count].val)+options_list[count].len);
637       options_list[count].len += sizeof(uint32_t);
638       valstr = strtok(NULL," \t");
639     }
640     break;
641   case DHCP_IPPLST:
642     break;
643   case DHCP_STCRTS:
644     /* Option binary format:
645      * mask [one byte, 0..32]
646      * ip [0..4 bytes depending on mask]
647      * router [4 bytes]
648      * may be repeated
649      * staticroutes 10.0.0.0/8 10.127.0.1, 10.11.12.0/24 10.11.12.1
650      */
651     grp = strtok(valstr, ",");;
652     while(grp){
653       while(*grp == ' ' || *grp == '\t') grp++;
654       tp = strchr(grp, '/');
655       if (!tp) error_exit("wrong formated static route option");
656       *tp = '\0';
657       mask = strtol(++tp, &tp, 10);
658       if (striptovar(grp, (uint8_t*)&nip)<0) error_exit("wrong formated static route option");
659       while(*tp == ' ' || *tp == '\t' || *tp == '-') tp++;
660       if (striptovar(tp, (uint8_t*)&router)<0) error_exit("wrong formated static route option");
661       options_list[count].val = xrealloc(options_list[count].val, options_list[count].len + 1 + mask/8 + 4);
662       memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &mask, 1);
663       options_list[count].len += 1;
664       memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &nip, mask/8);
665       options_list[count].len += mask/8;
666       memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &router, 4);
667       options_list[count].len += 4;
668       tp = NULL;
669       grp = strtok(NULL, ",");
670     }
671     break;
672   }
673   return 0;
674 }
675
676 // Reads Static leases from STR and updates inner structures.
677 static int get_staticlease(const char *str, void *var)
678 {
679   struct static_lease_s *sltmp;
680   char *tkmac, *tkip;
681   int count;
682
683   if (!*str) return 0;
684
685   if (!(tkmac = strtok((char*)str, " \t"))) {
686     infomsg(infomode, "config : static lease : mac not found");
687     return 0;
688   }
689   if (!(tkip = strtok(NULL, " \t"))) {
690     infomsg(infomode, "config : static lease : no ip bind to mac %s", tkmac);
691     return 0;
692   }
693   sltmp = xzalloc(sizeof(struct static_lease_s));
694   for (count = 0; count < 6; count++, tkmac++) {
695     errno = 0;
696     sltmp->mac[count] = strtol(tkmac, &tkmac, 16);
697     if (sltmp->mac[count]>255 || sltmp->mac[count]<0 || (*tkmac && *tkmac!=':') || errno) {
698       infomsg(infomode, "config : static lease : mac address wrong format");
699       free(sltmp);
700       return 0;
701     }
702   }
703   striptovar(tkip, &sltmp->nip);
704   sltmp->next = gstate.leases.sleases;
705   gstate.leases.sleases = sltmp;
706
707   return 0;
708 }
709
710 static struct config_keyword keywords[] = {
711 // keyword          handler           variable address                default
712   {"start"        , striptovar      , (void*)&gconfig.start_ip     , "192.168.0.20"},
713   {"end"          , striptovar      , (void*)&gconfig.end_ip       , "192.168.0.254"},
714   {"interface"    , strinvar        , (void*)&gconfig.interface    , "eth0"},
715   {"port"         , strtou32        , (void*)&gconfig.port         , "67"},
716   {"min_lease"    , strtou32        , (void*)&gconfig.min_lease_sec, "60"},
717   {"max_leases"   , strtou32        , (void*)&gconfig.max_leases   , "235"},
718   {"auto_time"    , strtou32        , (void*)&gconfig.auto_time    , "7200"},
719   {"decline_time" , strtou32        , (void*)&gconfig.decline_time , "3600"},
720   {"conflict_time", strtou32        , (void*)&gconfig.conflict_time, "3600"},
721   {"offer_time"   , strtou32        , (void*)&gconfig.offer_time   , "60"},
722   {"lease_file"   , strinvar        , (void*)&gconfig.lease_file   , "/var/lib/misc/dhcpd.leases"}, //LEASES_FILE
723   {"lease6_file"  , strinvar        , (void*)&gconfig.lease6_file  , "/var/lib/misc/dhcpd6.leases"}, //LEASES_FILE
724   {"pidfile"      , strinvar        , (void*)&gconfig.pidfile      , "/var/run/dhcpd.pid"}, //DPID_FILE
725   {"siaddr"       , striptovar      , (void*)&gconfig.siaddr_nip   , "0.0.0.0"},
726   {"option"       , strtoopt        , (void*)&gconfig.options      , ""},
727   {"opt"          , strtoopt        , (void*)&gconfig.options      , ""},
728   {"notify_file"  , strinvar        , (void*)&gconfig.notify_file  , ""},
729   {"sname"        , strinvar        , (void*)&gconfig.sname        , ""},
730   {"boot_file"    , strinvar        , (void*)&gconfig.boot_file    , ""},
731   {"static_lease" , get_staticlease , (void*)&gconfig.static_leases, ""},
732   {"start6"       , striptovar      , (void*)&gconfig.start_ip6    , "2001:620:40b:555::100"},
733   {"end6"         , striptovar      , (void*)&gconfig.end_ip6      , "2001:620:40b:555::200"},
734   {"preferred_lifetime" , strtou32  , (void*)&gconfig.pref_lifetime, "3600"},
735   {"valid_lifetime"     , strtou32  , (void*)&gconfig.valid_lifetime, "7200"},
736   {"t1"           , strtou32        , (void*)&gconfig.t1           , "3600"},
737   {"t2"           , strtou32        , (void*)&gconfig.t2           , "5400"},
738 };
739
740 // Parses the server config file and updates the global server config accordingly.
741 static int parse_server_config(char *config_file, struct config_keyword *confkey)
742 {
743   FILE *fs = NULL;
744   char *confline_temp = NULL,*confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL};
745   int len, linelen, tcount, count, size = ARRAY_LEN(keywords);
746
747   for (count = 0; count < size; count++)
748     if (confkey[count].handler)
749       confkey[count].handler(confkey[count].def, confkey[count].var);
750
751   if (!(fs = fopen(config_file, "r"))) perror_msg("%s", config_file);
752   for (len = 0, linelen = 0; fs;) {
753     len = getline(&confline_temp, (size_t*) &linelen, fs);
754     confline = confline_temp;
755     if (len <= 0) break;
756     for (; *confline == ' '; confline++, len--);
757     if ((confline[0] == '#') || (confline[0] == '\n')) goto free_conf_continue;
758     tk = strchr(confline, '#');
759     if (tk) {
760       for (; *(tk-1)==' ' || *(tk-1)=='\t'; tk--);
761       *tk = '\0';
762     }
763     tk = strchr(confline, '\n');
764     if (tk) {
765       for (; *(tk-1)==' ' || *(tk-1)=='\t'; tk--);
766       *tk = '\0';
767     }
768     for (tcount=0, tk=strtok(confline, " \t"); tk && (tcount < 2);
769         tcount++, tk=strtok(NULL,(tcount==1)?"":" \t")) {
770       while ((*tk == '\t') || (*tk == ' ')) tk++;
771       tokens[tcount] = xstrdup(tk);
772     }
773     if (tcount<=1) goto free_tk0_continue;
774     for (count = 0; count < size; count++) {
775       if (!strcmp(confkey[count].keyword,tokens[0])) {
776         dbg("got config : %15s : ", confkey[count].keyword);
777         if (confkey[count].handler(tokens[1], confkey[count].var) == 0)
778           dbg("%s \n", tokens[1]);
779         break;
780       }
781     }
782     if (tokens[1]) { free(tokens[1]); tokens[1] = NULL; }
783 free_tk0_continue:
784     if (tokens[0]) { free(tokens[0]); tokens[0] = NULL; }
785 free_conf_continue:
786     free(confline_temp);
787     confline_temp = NULL;
788   }
789   if (fs) fclose(fs);
790   return 0;
791 }
792
793 // opens UDP socket for listen ipv6 packets
794 static int open_listensock6(void)
795 {
796   struct sockaddr_in6 addr6;
797   struct ipv6_mreq mreq;
798
799   if (gstate.listensock > 0) close(gstate.listensock);
800
801   dbg("Opening listen socket on *:%d %s\n", gconfig.port, gconfig.interface);
802
803   gstate.listensock = xsocket(PF_INET6, SOCK_DGRAM, 0);
804   setsockopt(gstate.listensock, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone));
805
806   if (setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &constone,
807         sizeof(constone)) == -1) {
808     error_msg("failed to receive ipv6 packets.\n");
809     close(gstate.listensock);
810     return -1;
811   }
812
813   setsockopt(gstate.listensock, SOL_SOCKET, SO_BINDTODEVICE, gconfig.interface, strlen(gconfig.interface)+1);
814
815   memset(&addr6, 0, sizeof(addr6));
816   addr6.sin6_family = AF_INET6;
817   addr6.sin6_port = (flag_chk(FLAG_P))?htons(TT.port):htons(gconfig.port); //SERVER_PORT
818   addr6.sin6_scope_id = if_nametoindex(gconfig.interface);
819   //Listening for multicast packet
820   inet_pton(AF_INET6, "ff02::1:2", &addr6.sin6_addr);
821
822   if (bind(gstate.listensock, (struct sockaddr *) &addr6, sizeof(addr6)) == -1) {
823     close(gstate.listensock);
824     perror_exit("bind failed");
825   }
826
827   memset(&mreq, 0, sizeof(mreq));
828   mreq.ipv6mr_interface = if_nametoindex(gconfig.interface);
829   memcpy(&mreq.ipv6mr_multiaddr, &addr6.sin6_addr, sizeof(addr6.sin6_addr));
830
831   if(setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1) {
832     error_msg("failed to join a multicast group.\n");
833     close(gstate.listensock);
834     return -1;
835   }
836
837   dbg("OPEN : success\n");
838   return 0;
839 }
840
841 // opens UDP socket for listen
842 static int open_listensock(void)
843 {
844   struct sockaddr_in addr;
845   struct ifreq ifr;
846
847   if (gstate.listensock > 0) close(gstate.listensock);
848
849   dbg("Opening listen socket on *:%d %s\n", gconfig.port, gconfig.interface);
850   gstate.listensock = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
851   setsockopt(gstate.listensock, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone));
852   if (setsockopt(gstate.listensock, SOL_SOCKET, SO_BROADCAST, &constone, sizeof(constone)) == -1) {
853     error_msg("failed to receive brodcast packets.\n");
854     close(gstate.listensock);
855     return -1;
856   }
857   memset(&ifr, 0, sizeof(ifr));
858   xstrncpy(ifr.ifr_name, gconfig.interface, IFNAMSIZ);
859   setsockopt(gstate.listensock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
860
861   memset(&addr, 0, sizeof(addr));
862   addr.sin_family = AF_INET;
863   addr.sin_port = (flag_chk(FLAG_P))?htons(TT.port):htons(gconfig.port); //SERVER_PORT
864   addr.sin_addr.s_addr = INADDR_ANY ;
865
866   if (bind(gstate.listensock, (struct sockaddr *) &addr, sizeof(addr))) {
867     close(gstate.listensock);
868     perror_exit("bind failed");
869   }
870   dbg("OPEN : success\n");
871   return 0;
872 }
873
874 static int send_packet6(uint8_t relay, uint8_t *client_lla, uint16_t optlen)
875 {
876   struct sockaddr_ll dest_sll;
877   dhcp6_raw_t packet;
878   unsigned padding;
879   int fd, result = -1;
880   uint32_t front, back;
881
882   memset(&packet, 0, sizeof(dhcp6_raw_t));
883   memcpy(&packet.dhcp6, &gstate.send.send_pkt6, sizeof(dhcp6_msg_t));
884   padding = sizeof(packet.dhcp6.options) - optlen;
885
886   if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6))) < 0) {
887     dbg("SEND : ipv6 socket failed\n");
888     return -1;
889   }
890   memset(&dest_sll, 0, sizeof(dest_sll));
891   dest_sll.sll_family = AF_PACKET;
892   dest_sll.sll_protocol = htons(ETH_P_IPV6);
893   dest_sll.sll_ifindex = gconfig.ifindex;
894   dest_sll.sll_halen = ETH_ALEN;
895   memcpy(dest_sll.sll_addr, client_lla, sizeof(client_lla));
896
897   if (bind(fd, (struct sockaddr *) &dest_sll, sizeof(dest_sll)) < 0) {
898     dbg("SEND : bind failed\n");
899     close(fd);
900     return -1;
901   }
902   memcpy(&packet.iph.ip6_src, &gconfig.server_nip6, sizeof(uint32_t)*4);
903   //HW addr to Link-Local addr
904   inet_pton(AF_INET6, "fe80::0200:00ff:fe00:0000", &packet.iph.ip6_dst);
905   ntohl6(packet.iph.ip6_dst.__in6_u.__u6_addr32,packet.iph.ip6_dst.__in6_u.__u6_addr32);
906   front = ntohl(*(uint32_t*)(client_lla+3) & 0x00ffffff) >> 8;
907   back = ntohl(*(uint32_t*)(client_lla) & 0x00ffffff);
908   packet.iph.ip6_dst.__in6_u.__u6_addr32[3] =
909     packet.iph.ip6_dst.__in6_u.__u6_addr32[3] | front;
910   packet.iph.ip6_dst.__in6_u.__u6_addr32[2] =
911     packet.iph.ip6_dst.__in6_u.__u6_addr32[2] | back;
912   htonl6(packet.iph.ip6_dst.__in6_u.__u6_addr32,packet.iph.ip6_dst.__in6_u.__u6_addr32);
913
914   packet.udph.source = htons(gconfig.port);
915   packet.udph.dest = htons(546);
916   packet.udph.len = htons(sizeof(dhcp6_raw_t) - sizeof(struct ip6_hdr) - padding);
917   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(ntohs(packet.udph.len) + 0x11);
918   packet.udph.check = dhcp_checksum(&packet, sizeof(dhcp6_raw_t) - padding);
919   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000);
920   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_plen = packet.udph.len;
921   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
922   packet.iph.ip6_ctlun.ip6_un1.ip6_un1_hlim = 0x64;
923
924   result = sendto(fd, &packet, sizeof(dhcp6_raw_t)-padding,
925       0, (struct sockaddr *) &dest_sll, sizeof(dest_sll));
926
927   dbg("sendto %d\n", result);
928   close(fd);
929   if (result < 0) dbg("PACKET send error\n");
930   return result;
931 }
932
933 // Sends data through raw socket.
934 static int send_packet(uint8_t broadcast)
935 {
936   struct sockaddr_ll dest_sll;
937   dhcp_raw_t packet;
938   unsigned padding;
939   int fd, result = -1;
940   uint8_t bmacaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
941
942   memset(&packet, 0, sizeof(dhcp_raw_t));
943   memcpy(&packet.dhcp, &gstate.send.send_pkt, sizeof(dhcp_msg_t));
944
945   if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
946     dbg("SEND : socket failed\n");
947     return -1;
948   }
949   memset(&dest_sll, 0, sizeof(dest_sll));
950   dest_sll.sll_family = AF_PACKET;
951   dest_sll.sll_protocol = htons(ETH_P_IP);
952   dest_sll.sll_ifindex = gconfig.ifindex;
953   dest_sll.sll_halen = 6;
954   memcpy(dest_sll.sll_addr, (broadcast)?bmacaddr:gstate.rcvd.rcvd_pkt.chaddr , 6);
955
956   if (bind(fd, (struct sockaddr *) &dest_sll, sizeof(dest_sll)) < 0) {
957     dbg("SEND : bind failed\n");
958     close(fd);
959     return -1;
960   }
961   padding = 308 - 1 - dhcp_opt_size(gstate.send.send_pkt.options);
962   packet.iph.protocol = IPPROTO_UDP;
963   packet.iph.saddr = gconfig.server_nip;
964   packet.iph.daddr = (broadcast || (gstate.rcvd.rcvd_pkt.ciaddr == 0))?INADDR_BROADCAST:gstate.rcvd.rcvd_pkt.ciaddr;
965   packet.udph.source = htons(67);//SERVER_PORT
966   packet.udph.dest = htons(68); //CLIENT_PORT
967   packet.udph.len = htons(sizeof(dhcp_raw_t) - sizeof(struct iphdr) - padding);
968   packet.iph.tot_len = packet.udph.len;
969   packet.udph.check = dhcp_checksum(&packet, sizeof(dhcp_raw_t) - padding);
970   packet.iph.tot_len = htons(sizeof(dhcp_raw_t) - padding);
971   packet.iph.ihl = sizeof(packet.iph) >> 2;
972   packet.iph.version = IPVERSION;
973   packet.iph.ttl = IPDEFTTL;
974   packet.iph.check = dhcp_checksum(&packet.iph, sizeof(packet.iph));
975
976   result = sendto(fd, &packet, sizeof(dhcp_raw_t) - padding, 0,
977       (struct sockaddr *) &dest_sll, sizeof(dest_sll));
978
979   dbg("sendto %d\n", result);
980   close(fd);
981   if (result < 0) dbg("PACKET send error\n");
982   return result;
983 }
984
985 static int read_packet6(void)
986 {
987   int ret;
988
989   memset(&gstate.rcvd.rcvd_pkt6, 0, sizeof(dhcp6_msg_t));
990   ret = read(gstate.listensock, &gstate.rcvd.rcvd_pkt6, sizeof(dhcp6_msg_t));
991   if (ret < 0) {
992     dbg("Packet read error, ignoring. \n");
993     return ret; // returns -1
994   }
995   if (gstate.rcvd.rcvd_pkt6.msgtype < 1) {
996     dbg("Bad message type, igroning. \n");
997     return -2;
998   }
999
1000   dbg("Received an ipv6 packet. Size : %d \n", ret);
1001   return ret;
1002 }
1003
1004 // Reads from UDP socket
1005 static int read_packet(void)
1006 {
1007   int ret;
1008
1009   memset(&gstate.rcvd.rcvd_pkt, 0, sizeof(dhcp_msg_t));
1010   ret = read(gstate.listensock, &gstate.rcvd.rcvd_pkt, sizeof(dhcp_msg_t));
1011   if (ret < 0) {
1012     dbg("Packet read error, ignoring. \n");
1013     return ret; // returns -1
1014   }
1015   if (gstate.rcvd.rcvd_pkt.cookie != htonl(DHCP_MAGIC)) {
1016     dbg("Packet with bad magic, ignoring. \n");
1017     return -2;
1018   }
1019   if (gstate.rcvd.rcvd_pkt.op != 1) { //BOOTPREQUEST
1020     dbg("Not a BOOT REQUEST ignoring. \n");
1021     return -2;
1022   }
1023   if (gstate.rcvd.rcvd_pkt.hlen != 6) {
1024     dbg("hlen != 6 ignoring. \n");
1025     return -2;
1026   }
1027   dbg("Received a packet. Size : %d \n", ret);
1028   return ret;
1029 }
1030
1031 // Preapres a dhcp packet with defaults and configs
1032 static uint8_t* prepare_send_pkt(void)
1033 {
1034   memset((void*)&gstate.send.send_pkt, 0, sizeof(gstate.send.send_pkt));
1035   gstate.send.send_pkt.op = 2; //BOOTPREPLY
1036   gstate.send.send_pkt.htype = 1;
1037   gstate.send.send_pkt.hlen = 6;
1038   gstate.send.send_pkt.xid = gstate.rcvd.rcvd_pkt.xid;
1039   gstate.send.send_pkt.cookie = htonl(DHCP_MAGIC);
1040   gstate.send.send_pkt.nsiaddr = gconfig.server_nip;
1041   memcpy(gstate.send.send_pkt.chaddr, gstate.rcvd.rcvd_pkt.chaddr, 16);
1042   gstate.send.send_pkt.options[0] = DHCP_OPT_END;
1043   return gstate.send.send_pkt.options;
1044 }
1045
1046 static uint8_t* prepare_send_pkt6(uint16_t opt)
1047 {
1048   memset((void*)&gstate.send.send_pkt6, 0, sizeof(gstate.send.send_pkt6));
1049   gstate.send.send_pkt6.msgtype = opt;
1050   memcpy(gstate.send.send_pkt6.transaction_id, gstate.rcvd.rcvd_pkt6.transaction_id, 3);
1051   return gstate.send.send_pkt6.options;
1052 }
1053
1054 // Sets a option value in dhcp packet's option field
1055 static uint8_t* set_optval(uint8_t *optptr, uint16_t opt, void *var, size_t len)
1056 {
1057   while (*optptr != DHCP_OPT_END) optptr++;
1058   *optptr++ = (uint8_t)(opt & 0x00FF);
1059   *optptr++ = (uint8_t) len;
1060   memcpy(optptr, var, len);
1061   optptr += len;
1062   *optptr = DHCP_OPT_END;
1063   return optptr;
1064 }
1065
1066 static uint8_t* set_optval6(uint8_t *optptr, uint16_t opt, void *var, size_t len)
1067 {
1068   *((uint16_t*)optptr) = htons(opt);
1069   *(uint16_t*)(optptr+2) = htons(len);
1070   memcpy(optptr+4, var, len);
1071   optptr += len+4;
1072   return optptr;
1073 }
1074
1075 // Gets a option value from dhcp packet's option field
1076 static uint8_t* get_optval(uint8_t *optptr, uint16_t opt, void *var)
1077 {
1078   size_t len;
1079   uint8_t overloaded = 0;
1080
1081   while (1) {
1082     while (*optptr == DHCP_OPT_PADDING) optptr++;
1083     if ((*optptr & 0x00FF) == DHCP_OPT_END) break;
1084     if ((*optptr & 0x00FF) == DHCP_OPT_OPTION_OVERLOAD) {
1085       overloaded = optptr[2];
1086       optptr += optptr[1] + 2;
1087     }
1088     len = optptr[1];
1089     if (*optptr == (opt & 0x00FF))
1090       switch (opt & 0xFF00) {
1091         case DHCP_NUM32: // FALLTHROUGH
1092         case DHCP_IP:
1093           memcpy(var, optptr+2, sizeof(uint32_t));
1094           optptr += len + 2;
1095           return optptr;
1096           break;
1097         case DHCP_NUM16:
1098           memcpy(var, optptr+2, sizeof(uint16_t));
1099           optptr += len + 2;
1100           return optptr;
1101           break;
1102         case DHCP_NUM8:
1103           memcpy(var, optptr+2, sizeof(uint8_t));
1104           optptr += len + 2;
1105           return optptr;
1106           break;
1107         case DHCP_STRING:
1108           var = xstrndup((char*) optptr, len);
1109           optptr += len + 2;
1110           return optptr;
1111           break;
1112       }
1113     optptr += len + 2;
1114   }
1115   if ((overloaded == 1) | (overloaded == 3)) get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.file, opt, var);
1116   if ((overloaded == 2) | (overloaded == 3)) get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.sname, opt, var);
1117   return optptr;
1118 }
1119
1120 static uint8_t* get_optval6(uint8_t *optptr, uint16_t opt, uint16_t *datalen, void **var)
1121 {
1122   uint16_t optcode;
1123   uint16_t len;
1124
1125   memcpy(&optcode, optptr, sizeof(uint16_t));
1126   memcpy(&len, optptr+2, sizeof(uint16_t));
1127   if(!optcode) {
1128     dbg("Option %d is not exist.\n", opt);
1129     return optptr;
1130   }
1131   optcode = ntohs(optcode);
1132   len = ntohs(len);
1133
1134   if (opt == optcode) {
1135     *var = xmalloc(len);
1136     memcpy(*var, optptr+4, len);
1137     optptr = optptr + len + 4;
1138     memcpy(datalen, &len, sizeof(uint16_t));
1139   }
1140   else {
1141     optptr = get_optval6(optptr+len+4, opt, datalen, var);
1142   }
1143
1144   return optptr;
1145 }
1146
1147 // Retrives Requested Parameter list from dhcp req packet.
1148 static uint8_t get_reqparam(uint8_t **list)
1149 {
1150   uint8_t len, *optptr;
1151   if(*list) free(*list);
1152   for (optptr = gstate.rcvd.rcvd_pkt.options;
1153       *optptr && *optptr!=((DHCP_OPT_PARAM_REQ) & 0x00FF); optptr+=optptr[1]+2);
1154   len = *++optptr;
1155   *list = xzalloc(len+1);
1156   memcpy(*list, ++optptr, len);
1157   return len;
1158 }
1159
1160 // Sets values of req param in dhcp offer packet.
1161 static uint8_t* set_reqparam(uint8_t *optptr, uint8_t *list)
1162 {
1163   uint8_t reqcode;
1164   int count, size = ARRAY_LEN(options_list);
1165
1166   while (*list) {
1167     reqcode = *list++;
1168     for (count = 0; count < size; count++) {
1169       if ((options_list[count].code & 0X00FF)==reqcode) {
1170         if (!(options_list[count].len) || !(options_list[count].val)) break;
1171         for (; *optptr && *optptr!=DHCP_OPT_END; optptr+=optptr[1]+2);
1172         *optptr++ = (uint8_t) (options_list[count].code & 0x00FF);
1173         *optptr++ = (uint8_t) options_list[count].len;
1174         memcpy(optptr, options_list[count].val, options_list[count].len);
1175         optptr += options_list[count].len;
1176         *optptr = DHCP_OPT_END;
1177         break;
1178       }
1179     }
1180   }
1181   return optptr;
1182 }
1183
1184 static void run_notify(char **argv)
1185 {
1186   struct stat sts;
1187   volatile int error = 0;
1188   pid_t pid;
1189
1190   if (stat(argv[0], &sts) == -1 && errno == ENOENT) {
1191     infomsg(infomode, "notify file: %s : not exist.", argv[0]);
1192     return;
1193   }
1194   fflush(NULL);
1195
1196   pid = vfork();
1197   if (pid < 0) {
1198     dbg("Fork failed.\n");
1199     return;
1200   }
1201   if (!pid) {
1202     execvp(argv[0], argv);
1203     error = errno;
1204     _exit(111);
1205   }
1206   if (error) {
1207     waitpid(pid, NULL, 0);
1208     errno = error;
1209   }
1210   dbg("script complete.\n");
1211 }
1212
1213 static void write_leasefile(void)
1214 {
1215   int fd;
1216   uint32_t curr, tmp_time;
1217   int64_t timestamp;
1218   struct arg_list *listdls = gstate.dleases;
1219   dyn_lease *dls;
1220
1221   if ((fd = open(gconfig.lease_file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
1222     perror_msg("can't open %s ", gconfig.lease_file);
1223   } else {
1224     curr = timestamp = time(NULL);
1225     timestamp = SWAP_BE64(timestamp);
1226     writeall(fd, &timestamp, sizeof(timestamp));
1227
1228     while (listdls) {
1229       dls = (dyn_lease*)listdls->arg;
1230       tmp_time = dls->expires;
1231       dls->expires -= curr;
1232       if ((int32_t) dls->expires < 0) goto skip;
1233       dls->expires = htonl(dls->expires);
1234       writeall(fd, dls, sizeof(dyn_lease));
1235 skip:
1236       dls->expires = tmp_time;
1237       listdls = listdls->next;
1238     }
1239     close(fd);
1240     if (gconfig.notify_file) {
1241       char *argv[3];
1242       argv[0] = gconfig.notify_file;
1243       argv[1] = gconfig.lease_file;
1244       argv[2] = NULL;
1245       run_notify(argv);
1246     }
1247   }
1248 }
1249
1250 static void write_lease6file(void)
1251 {
1252   int fd;
1253   uint32_t curr, tmp_time;
1254   int64_t timestamp;
1255   struct arg_list *listdls = gstate.dleases;
1256   dyn_lease6 *dls6;
1257
1258   if ((fd = open(gconfig.lease6_file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
1259     perror_msg("can't open %s ", gconfig.lease6_file);
1260   } else {
1261     curr = timestamp = time(NULL);
1262     timestamp = SWAP_BE64(timestamp);
1263     writeall(fd, &timestamp, sizeof(timestamp));
1264
1265     while (listdls) {
1266       dls6 = (dyn_lease6*)listdls->arg;
1267       tmp_time = dls6->expires;
1268       dls6->expires -= curr;
1269       if ((int32_t) dls6->expires < 0) goto skip;
1270       dls6->expires = htonl(dls6->expires);
1271       writeall(fd, dls6, sizeof(dyn_lease6));
1272 skip:
1273       dls6->expires = tmp_time;
1274       listdls = listdls->next;
1275     }
1276     close(fd);
1277     if (gconfig.notify_file) {
1278       char *argv[3];
1279       argv[0] = gconfig.notify_file;
1280       argv[1] = gconfig.lease6_file;
1281       argv[2] = NULL;
1282       run_notify(argv);
1283     }
1284   }
1285 }
1286
1287 // Update max lease time from options.
1288 static void set_maxlease(void)
1289 {
1290   int count, size = ARRAY_LEN(options_list);
1291   for (count = 0; count < size; count++)
1292     if (options_list[count].val && options_list[count].code == (DHCP_OPT_LEASE_TIME)) {
1293       gconfig.max_lease_sec = *((uint32_t*)options_list[count].val);
1294       break;
1295     }
1296   if (!gconfig.max_lease_sec) gconfig.max_lease_sec = (60*60*24*10);// DEFAULT_LEASE_TIME;
1297 }
1298
1299 // Returns lease time for client.
1300 static uint32_t get_lease(uint32_t req_exp)
1301 {
1302   uint32_t now = time(NULL);
1303   req_exp = req_exp - now;
1304   if(addr_version == AF_INET6) {
1305     if ((req_exp <= 0) || req_exp > gconfig.pref_lifetime ||
1306         req_exp > gconfig.valid_lifetime) {
1307       if ((gconfig.pref_lifetime > gconfig.valid_lifetime)) {
1308         error_msg("The valid lifetime must be greater than the preferred lifetime, \
1309             setting to valid lifetime", gconfig.valid_lifetime);
1310         return gconfig.valid_lifetime;
1311       }
1312       return gconfig.pref_lifetime;
1313     }
1314   } else {
1315     if ((req_exp <= 0) || (req_exp > gconfig.max_lease_sec))
1316       return gconfig.max_lease_sec;
1317
1318     if (req_exp < gconfig.min_lease_sec)
1319       return gconfig.min_lease_sec;
1320   }
1321
1322   return req_exp;
1323 }
1324
1325 static int verifyip6_in_lease(uint32_t *nip6, uint8_t *duid, uint16_t ia_type, uint32_t iaid)
1326 {
1327   static_lease6 *sls6;
1328   struct arg_list *listdls;
1329   uint32_t tmpnip6[4] = {0,};
1330
1331   for (listdls = gstate.dleases; listdls; listdls = listdls->next) {
1332     if (!memcmp(((dyn_lease6*) listdls->arg)->lease_nip6, nip6, sizeof(uint32_t)*4))
1333       return -1;
1334
1335     if (!memcmp(((dyn_lease6*) listdls->arg)->duid, duid, ((dyn_lease6*) listdls->arg)->duid_len)
1336         && ((dyn_lease6*) listdls->arg)->ia_type == ia_type)
1337       return -1;
1338   }
1339   for (sls6 = gstate.leases.sleases6; sls6; sls6 = sls6->next)
1340     if (memcmp(sls6->nip6, nip6, sizeof(uint32_t)*4)==0) return -2;
1341
1342   ntohl6(nip6, tmpnip6);
1343   if (memcmp(tmpnip6, gconfig.start_ip6, sizeof(tmpnip6)) < 0 ||
1344       memcmp(tmpnip6, gconfig.end_ip6, sizeof(tmpnip6)) > 0)
1345     return -3;
1346
1347   return 0;
1348 }
1349
1350 // Verify ip NIP in current leases ( assigned or not)
1351 static int verifyip_in_lease(uint32_t nip, uint8_t mac[6])
1352 {
1353   static_lease *sls;
1354   struct arg_list *listdls;
1355
1356   for (listdls = gstate.dleases; listdls; listdls = listdls->next) {
1357     if (((dyn_lease*) listdls->arg)->lease_nip == nip) {
1358       if (((int32_t)(((dyn_lease*) listdls->arg)->expires) - time(NULL)) < 0)
1359         return 0;
1360       return -1;
1361     }
1362     if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) return -1;
1363   }
1364   for (sls = gstate.leases.sleases; sls; sls = sls->next)
1365     if (sls->nip == nip) return -2;
1366
1367   if ((ntohl(nip) < gconfig.start_ip) || (ntohl(nip) > gconfig.end_ip))
1368     return -3;
1369
1370   return 0;
1371 }
1372
1373 // add ip assigned_nip to dynamic lease.
1374 static int addip_to_lease(uint32_t assigned_nip, uint8_t mac[6], uint32_t *req_exp, char *hostname, uint8_t update)
1375 {
1376   dyn_lease *dls;
1377   struct arg_list *listdls = gstate.dleases;
1378   uint32_t now = time(NULL);
1379
1380   while (listdls) {
1381     if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) {
1382       if (update) *req_exp = get_lease(*req_exp + ((dyn_lease*) listdls->arg)->expires);
1383       ((dyn_lease*) listdls->arg)->expires = *req_exp + now;
1384       return 0;
1385     }
1386     listdls = listdls->next;
1387   }
1388
1389   dls = xzalloc(sizeof(dyn_lease));
1390   memcpy(dls->lease_mac, mac, 6);
1391   dls->lease_nip = assigned_nip;
1392   if (hostname) memcpy(dls->hostname, hostname, 20);
1393
1394   if (update) *req_exp = get_lease(*req_exp + now);
1395   dls->expires = *req_exp + now;
1396
1397   listdls = xzalloc(sizeof(struct arg_list));
1398   listdls->next = gstate.dleases;
1399   listdls->arg = (char*)dls;
1400   gstate.dleases = listdls;
1401
1402   return 0;
1403 }
1404
1405 static int addip6_to_lease(uint32_t *assigned_nip, uint8_t *duid, uint16_t ia_type, uint32_t iaid, uint32_t *lifetime, uint8_t update)
1406 {
1407   dyn_lease6 *dls6;
1408   struct arg_list *listdls = gstate.dleases;
1409   uint32_t now = time(NULL);
1410
1411   while (listdls) {
1412     if (!memcmp(((dyn_lease6*) listdls->arg)->duid, duid, ((dyn_lease6*) listdls->arg)->duid_len)) {
1413       if (update) *lifetime = get_lease(*lifetime + ((dyn_lease6*) listdls->arg)->expires);
1414       ((dyn_lease6*) listdls->arg)->expires = *lifetime + now;
1415       return 0;
1416     }
1417     listdls = listdls->next;
1418   }
1419
1420   dls6 = xzalloc(sizeof(dyn_lease6));
1421   dls6->duid_len = sizeof(duid);
1422   memcpy(dls6->duid, duid, dls6->duid_len);
1423   dls6->ia_type = ia_type;
1424   dls6->iaid = iaid;
1425   memcpy(dls6->lease_nip6, assigned_nip, sizeof(uint32_t)*4);
1426
1427   if (update) *lifetime = get_lease(*lifetime + now);
1428   dls6->expires = *lifetime + now;
1429
1430   listdls = xzalloc(sizeof(struct arg_list));
1431   listdls->next = gstate.dleases;
1432   listdls->arg = (char*)dls6;
1433   gstate.dleases = listdls;
1434
1435   return 0;
1436 }
1437
1438 // delete ip assigned_nip from dynamic lease.
1439 static int delip_from_lease(uint32_t assigned_nip, uint8_t mac[6], uint32_t del_time)
1440 {
1441   struct arg_list *listdls = gstate.dleases;
1442
1443   while (listdls) {
1444     if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) {
1445       ((dyn_lease*) listdls->arg)->expires = del_time + time(NULL);
1446       return 0;
1447     }
1448     listdls = listdls->next;
1449   }
1450   return -1;
1451 }
1452
1453 // returns a IP from static, dynamic leases or free ip pool, 0 otherwise.
1454 static uint32_t getip_from_pool(uint32_t req_nip, uint8_t mac[6], uint32_t *req_exp, char *hostname)
1455 {
1456   uint32_t nip = 0;
1457   static_lease *sls = gstate.leases.sleases;
1458   struct arg_list *listdls = gstate.dleases, *tmp = NULL;
1459
1460   if (req_nip && (!verifyip_in_lease(req_nip, mac))) nip = req_nip;
1461
1462   if (!nip) {
1463     while (listdls) {
1464       if (!memcmp(((dyn_lease*)listdls->arg)->lease_mac, mac, 6)) {
1465         nip = ((dyn_lease*)listdls->arg)->lease_nip;
1466         if (tmp) tmp->next = listdls->next;
1467         else gstate.dleases = listdls->next;
1468         free(listdls->arg);
1469         free(listdls);
1470         if (verifyip_in_lease(nip, mac) < 0) nip = 0;
1471         break;
1472       }
1473       tmp = listdls;
1474       listdls = listdls->next;
1475     }
1476   }
1477   if (!nip) {
1478     while (sls) {
1479       if (memcmp(sls->mac, mac, 6) == 0) {
1480         nip = sls->nip;
1481         break;
1482       }
1483       sls = sls->next;
1484     }
1485   }
1486   if (!nip) {
1487     for (nip = htonl(gconfig.start_ip); ntohl(nip) <= gconfig.end_ip; ) {
1488       if (!verifyip_in_lease(nip, mac)) break;
1489       nip = ntohl(nip);
1490       nip = htonl(++nip);
1491     }
1492     if (ntohl(nip) > gconfig.end_ip) {
1493       nip = 0;
1494       infomsg(infomode, "can't find free IP in IP Pool.");
1495     }
1496   }
1497   if (nip) addip_to_lease(nip, mac, req_exp, hostname, 1);
1498   return nip;
1499 }
1500
1501 static uint32_t *getip6_from_pool(uint8_t *duid, uint16_t duid_len, uint16_t ia_type, uint32_t iaid, uint32_t *lifetime)
1502 {
1503   uint32_t nip6[4] = {0,};
1504   static_lease6 *sls6 = gstate.leases.sleases6;
1505   struct arg_list *listdls6 = gstate.dleases, *tmp = NULL;
1506
1507   while(listdls6) {
1508     if (!memcmp(((dyn_lease6*)listdls6->arg)->duid, duid, duid_len)) {
1509       memcpy(nip6, ((dyn_lease6*)listdls6->arg)->lease_nip6, sizeof(nip6));
1510       if(tmp) tmp->next = listdls6->next;
1511       else gstate.dleases = listdls6->next;
1512       free(listdls6->arg);
1513       free(listdls6);
1514
1515       if(verifyip6_in_lease(nip6, duid, ia_type, iaid) < 0)
1516         memset(nip6, 0, sizeof(nip6));
1517       break;
1518     }
1519     tmp = listdls6;
1520     listdls6 = listdls6->next;
1521   }
1522
1523   if(!nip6[0] && !nip6[1] && !nip6[2] && !nip6[3]) {
1524     while(sls6) {
1525       if(!memcmp(sls6->duid, duid, 6)) {
1526         memcpy(nip6, sls6->nip6, sizeof(nip6));
1527         break;
1528       }
1529       sls6 = sls6->next;
1530     }
1531   }
1532
1533   if(!nip6[0] && !nip6[1] && !nip6[2] && !nip6[3]) {
1534     uint32_t tmpip6[4] = {0,};
1535     int i=3;
1536     memcpy(tmpip6, gconfig.start_ip6, sizeof(tmpip6));
1537     htonl6(gconfig.start_ip6, nip6);
1538     while(memcmp(tmpip6, gconfig.end_ip6, sizeof(tmpip6))<=0) {
1539       if(!verifyip6_in_lease(nip6, duid, ia_type, iaid)) break;
1540       ntohl6(nip6, tmpip6);
1541       while(i--) {
1542         if (tmpip6[i] == 0xffff) {
1543           tmpip6[i] = 0x0001;
1544         } else {
1545           ++tmpip6[i];
1546           break;
1547         }
1548       }
1549       htonl6(tmpip6, nip6);
1550     }
1551
1552     ntohl6(nip6, tmpip6);
1553     if (memcmp(tmpip6, gconfig.end_ip6, sizeof(tmpip6))>0) {
1554       memset(nip6, 0, sizeof(nip6));
1555       infomsg(infomode, "can't find free IP in IPv6 Pool.");
1556     }
1557   }
1558
1559   if(nip6[0] && nip6[1] && nip6[2] && nip6[3])
1560     addip6_to_lease(nip6, duid, ia_type, iaid, lifetime, 1);
1561   return nip6;
1562 }
1563
1564 static void read_leasefile(void)
1565 {
1566   uint32_t passed, ip;
1567   int32_t tmp_time;
1568   int64_t timestamp;
1569   dyn_lease *dls;
1570   int fd = open(gconfig.lease_file, O_RDONLY);
1571
1572   dls = xzalloc(sizeof(dyn_lease));
1573
1574   if (read(fd, &timestamp, sizeof(timestamp)) != sizeof(timestamp))
1575     goto lease_error_exit;
1576
1577   timestamp = SWAP_BE64(timestamp);
1578   passed = time(NULL) - timestamp;
1579   if ((uint64_t)passed > 12 * 60 * 60) goto lease_error_exit;
1580
1581   while (read(fd, dls, sizeof(dyn_lease)) == sizeof(dyn_lease)) {
1582     ip = ntohl(dls->lease_nip);
1583     if (ip >= gconfig.start_ip && ip <= gconfig.end_ip) {
1584       tmp_time = ntohl(dls->expires) - passed;
1585       if (tmp_time < 0) continue;
1586       addip_to_lease(dls->lease_nip, dls->lease_mac,
1587           (uint32_t*)&tmp_time, dls->hostname, 0);
1588     }
1589   }
1590 lease_error_exit:
1591   free(dls);
1592   close(fd);
1593 }
1594
1595 static void read_lease6file(void)
1596 {
1597   uint32_t passed, ip6[4];
1598   uint32_t tmp_time;
1599   int64_t timestamp;
1600   dyn_lease6 *dls6;
1601   int fd = open(gconfig.lease6_file, O_RDONLY);
1602
1603   dls6 = xzalloc(sizeof(dyn_lease6));
1604
1605   if (read(fd, &timestamp, sizeof(timestamp)) != sizeof(timestamp))
1606     goto lease6_error_exit;
1607
1608   timestamp = SWAP_BE64(timestamp);
1609   passed = time(NULL) - timestamp;
1610   if ((uint64_t)passed > 12 * 60 * 60) goto lease6_error_exit;
1611
1612   while (read(fd, dls6, sizeof(dyn_lease6)) == sizeof(dyn_lease6)) {
1613     ntohl6(dls6->lease_nip6, ip6);
1614     if (memcmp(ip6, gconfig.start_ip6, sizeof(ip6))<0 &&
1615         memcmp(ip6, gconfig.end_ip6, sizeof(ip6))>9) {
1616       tmp_time = ntohl(dls6->expires) - passed;
1617       if (tmp_time < 0U) continue;
1618       addip6_to_lease(dls6->lease_nip6, dls6->duid, dls6->ia_type, dls6->iaid,
1619           (uint32_t*)&tmp_time, 0);
1620     }
1621   }
1622
1623 lease6_error_exit:
1624   free(dls6);
1625   close(fd);
1626 }
1627
1628 void dhcpd_main(void)
1629 {
1630   struct timeval tv;
1631   int retval, i;
1632   uint8_t *optptr, msgtype = 0;
1633   uint16_t optlen = 0;
1634   uint32_t waited = 0, serverid = 0, requested_nip = 0;
1635   uint32_t requested_nip6[4] = {0,};
1636   uint8_t transactionid[3] = {0,};
1637   uint32_t reqested_lease = 0, ip_pool_size = 0;
1638   char *hstname = NULL;
1639   fd_set rfds;
1640
1641   infomode = LOG_CONSOLE;
1642   if (!(flag_chk(FLAG_f))) {
1643     daemon(0,0);
1644     infomode = LOG_SILENT;
1645   }
1646   if (flag_chk(FLAG_S)) {
1647         openlog("UDHCPD :", LOG_PID, LOG_DAEMON);
1648         infomode |= LOG_SYSTEM;
1649   }
1650   setlinebuf(stdout);
1651   //DHCPD_CONF_FILE
1652   parse_server_config((toys.optc==1)?toys.optargs[0]:"/etc/dhcpd.conf", keywords);
1653   infomsg(infomode, "toybox dhcpd started");
1654
1655   if (flag_chk(FLAG_6)){
1656     addr_version = AF_INET6;
1657     ntohl6(gconfig.start_ip6, gconfig.start_ip6);
1658     ntohl6(gconfig.end_ip6, gconfig.end_ip6);
1659     gconfig.t1 = ntohl(gconfig.t1);
1660     gconfig.t2 = ntohl(gconfig.t2);
1661     gconfig.pref_lifetime = ntohl(gconfig.pref_lifetime);
1662     gconfig.valid_lifetime = ntohl(gconfig.valid_lifetime);
1663     for(i=0;i<4;i++)
1664       ip_pool_size += (gconfig.end_ip6[i]-gconfig.start_ip6[i])<<((3-i)*8);
1665   } else {
1666     gconfig.start_ip = ntohl(gconfig.start_ip);
1667     gconfig.end_ip = ntohl(gconfig.end_ip);
1668     ip_pool_size = gconfig.end_ip - gconfig.start_ip + 1;
1669   }
1670
1671   if (gconfig.max_leases > ip_pool_size) {
1672     error_msg("max_leases=%u is too big, setting to %u",
1673         (unsigned) gconfig.max_leases, ip_pool_size);
1674     gconfig.max_leases = ip_pool_size;
1675   }
1676   write_pid(gconfig.pidfile);
1677   set_maxlease();
1678   read_leasefile();
1679   if(TT.iface) gconfig.interface = TT.iface;
1680   (addr_version==AF_INET6) ? read_lease6file() : read_leasefile();
1681
1682   if (get_interface(gconfig.interface, &gconfig.ifindex,
1683         (addr_version==AF_INET6)? gconfig.server_nip6 : &gconfig.server_nip,
1684         gconfig.server_mac)<0)
1685     perror_exit("Failed to get interface %s", gconfig.interface);
1686   setup_signal();
1687   if (addr_version==AF_INET6) {
1688     htonl6(gconfig.server_nip6, gconfig.server_nip6);
1689     open_listensock6();
1690   } else {
1691     gconfig.server_nip = htonl(gconfig.server_nip);
1692     open_listensock();
1693   }
1694
1695   fcntl(gstate.listensock, F_SETFD, FD_CLOEXEC);
1696
1697   for (;;) {
1698     uint32_t timestmp = time(NULL);
1699     FD_ZERO(&rfds);
1700     FD_SET(gstate.listensock, &rfds);
1701     FD_SET(sigfd.rd, &rfds);
1702     tv.tv_sec = gconfig.auto_time - waited;
1703     tv.tv_usec = 0;
1704     retval = 0;
1705     serverid = 0;
1706     msgtype = 0;
1707
1708     int maxfd = (sigfd.rd > gstate.listensock)? sigfd.rd : gstate.listensock;
1709     dbg("select waiting ....\n");
1710     retval = select(maxfd + 1, &rfds, NULL, NULL, (gconfig.auto_time?&tv:NULL));
1711     if (retval < 0) {
1712       if (errno == EINTR) {
1713         waited += (unsigned) time(NULL) - timestmp;
1714         continue;
1715       }
1716       dbg("Don't wait on Error in select\n");
1717       exit(0);
1718     }
1719     if (!retval) { // Timed out
1720       dbg("select wait Timed Out...\n");
1721       waited = 0;
1722       (addr_version==AF_INET6)? write_lease6file() : write_leasefile();
1723       if (get_interface(gconfig.interface, &gconfig.ifindex,
1724             (addr_version==AF_INET6)? gconfig.server_nip6 : &gconfig.server_nip,
1725             gconfig.server_mac)<0)
1726         perror_exit("Failed to get interface %s", gconfig.interface);
1727       if(addr_version == AF_INET6) {
1728         htonl6(gconfig.server_nip6, gconfig.server_nip6);
1729       } else gconfig.server_nip = htonl(gconfig.server_nip);
1730       continue;
1731     }
1732     if (FD_ISSET(sigfd.rd, &rfds)) { // Some Activity on RDFDs : is signal
1733       unsigned char sig;
1734       if (read(sigfd.rd, &sig, 1) != 1) {
1735         dbg("signal read failed.\n");
1736         continue;
1737       }
1738       switch (sig) {
1739         case SIGUSR1:
1740           infomsg(infomode, "Received SIGUSR1");
1741           (addr_version==AF_INET6)? write_lease6file() : write_leasefile();
1742           continue;
1743         case SIGTERM:
1744           infomsg(infomode, "received sigterm");
1745           (addr_version==AF_INET6)? write_lease6file() : write_leasefile();
1746           unlink(gconfig.pidfile);
1747           exit(0);
1748           break;
1749         default: break;
1750       }
1751     }
1752     if (FD_ISSET(gstate.listensock, &rfds)) { // Some Activity on RDFDs : is socke
1753       dbg("select listen sock read\n");
1754       if(addr_version==AF_INET6) {
1755         void *client_duid, *server_duid, *client_ia_na, *server_ia_na,
1756              *client_ia_pd, *server_ia_pd;
1757         uint8_t client_lla[6] = {0,};
1758         uint16_t client_duid_len = 0, server_duid_len = 0, server_ia_na_len = 0,
1759                  client_ia_na_len = 0, client_ia_pd_len = 0;
1760
1761         if(read_packet6() < 0) {
1762           open_listensock6();
1763           continue;
1764         }
1765         waited += time(NULL) - timestmp;
1766
1767         memcpy(&gstate.rqcode, &gstate.rcvd.rcvd_pkt6.msgtype, sizeof(uint8_t));
1768         memcpy(&transactionid, &gstate.rcvd.rcvd_pkt6.transaction_id,
1769             sizeof(transactionid));
1770
1771         if (!gstate.rqcode || gstate.rqcode < DHCP6SOLICIT ||
1772             gstate.rqcode > DHCP6RELAYREPLY) {
1773           dbg("no or bad message type option, ignoring packet.\n");
1774           continue;
1775         }
1776         if (!gstate.rcvd.rcvd_pkt6.transaction_id ||
1777             memcmp(gstate.rcvd.rcvd_pkt6.transaction_id, transactionid, 3)) {
1778           dbg("no or bad transaction id, ignoring packet.\n");
1779           continue;
1780         }
1781
1782         waited += time(NULL) - timestmp;
1783         switch (gstate.rqcode) {
1784           case DHCP6SOLICIT:
1785             dbg("Message Type: DHCP6SOLICIT\n");
1786             optptr = prepare_send_pkt6(DHCP6ADVERTISE);
1787             optlen = 0;
1788
1789             //TODO policy check
1790             //TODO Receive: ORO check (e.g. DNS)
1791
1792             //Receive: Identity Association for Non-temporary Address
1793             if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1794                   DHCP6_OPT_IA_NA, &client_ia_na_len, &client_ia_na)) {
1795               uint16_t ia_addr_len = sizeof(struct optval_ia_addr);
1796               void *ia_addr, *status_code;
1797               char *status_code_msg;
1798               uint16_t status_code_len = 0;
1799               server_ia_na_len = sizeof(struct optval_ia_na)-sizeof(uint8_t*);
1800
1801               //IA Address
1802               ia_addr = xzalloc(ia_addr_len);
1803               struct optval_ia_addr *ia_addr_p = (struct optval_ia_addr*)ia_addr;
1804               (*ia_addr_p).pref_lifetime = gconfig.pref_lifetime;
1805               (*ia_addr_p).valid_lifetime = gconfig.valid_lifetime;
1806               memcpy(&(*ia_addr_p).ipv6_addr,
1807                   getip6_from_pool(client_duid, client_duid_len,
1808                     DHCP6_OPT_IA_NA, (*(struct optval_ia_na*) client_ia_na).iaid,
1809                     &(*ia_addr_p).pref_lifetime), sizeof(uint32_t)*4);
1810               server_ia_na_len += (ia_addr_len+4);
1811
1812               //Status Code
1813               if(*(*ia_addr_p).ipv6_addr) {
1814                 status_code_msg = xstrdup("Assigned an address.");
1815                 status_code_len = strlen(status_code_msg)+1;
1816                 status_code = xzalloc(status_code_len);
1817                 struct optval_status_code *status_code_p =
1818                   (struct optval_status_code*)status_code;
1819                 (*status_code_p).status_code = htons(DHCP6_STATUS_SUCCESS);
1820                 memcpy(&(*status_code_p).status_msg, status_code_msg,
1821                     status_code_len);
1822                 server_ia_na_len += (status_code_len+4);
1823                 free(status_code_msg);
1824               } else {
1825                 status_code_msg = xstrdup("There's no available address.");
1826                 status_code_len = strlen(status_code_msg)+1;
1827                 status_code = xzalloc(status_code_len);
1828                 struct optval_status_code *status_code_p =
1829                   (struct optval_status_code*)status_code;
1830                 (*status_code_p).status_code = htons(DHCP6_STATUS_NOADDRSAVAIL);
1831                 memcpy(&(*status_code_p).status_msg, status_code_msg,
1832                     status_code_len);
1833                 server_ia_na_len += (status_code_len+4);
1834                 server_ia_na_len -= (ia_addr_len+4);
1835                 ia_addr_len = 0;
1836                 free(ia_addr);
1837                 free(status_code_msg);
1838                 //TODO send failed status code
1839                 break;
1840               }
1841
1842               //combine options
1843               server_ia_na = xzalloc(server_ia_na_len);
1844               struct optval_ia_na *ia_na_p = (struct optval_ia_na*)server_ia_na;
1845               (*ia_na_p).iaid = (*(struct optval_ia_na*)client_ia_na).iaid;
1846               (*ia_na_p).t1 = gconfig.t1;
1847               (*ia_na_p).t2 = gconfig.t2;
1848
1849               uint8_t* ia_na_optptr = &(*ia_na_p).optval;
1850               if(ia_addr_len) {
1851                 set_optval6(ia_na_optptr, DHCP6_OPT_IA_ADDR, ia_addr, ia_addr_len);
1852                 ia_na_optptr += (ia_addr_len + 4);
1853                 free(ia_addr);
1854               }
1855               if(status_code_len) {
1856                 set_optval6(ia_na_optptr, DHCP6_OPT_STATUS_CODE, status_code,
1857                     status_code_len);
1858                 ia_na_optptr += (status_code_len);
1859                 free(status_code);
1860               }
1861
1862               //Response: Identity Association for Non-temporary Address
1863               optptr = set_optval6(optptr, DHCP6_OPT_IA_NA, server_ia_na,
1864                   server_ia_na_len);
1865               optlen += (server_ia_na_len + 4);
1866               free(client_ia_na);free(server_ia_na);
1867             }
1868             //Receive: Identity Association for Prefix Delegation
1869             else if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1870                   DHCP6_OPT_IA_PD, &client_ia_pd_len, &client_ia_pd)) {
1871
1872               //TODO
1873               //Response: Identity Association for Prefix Delegation
1874             }
1875
1876             //Receive: Client Identifier (DUID)
1877             get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1878                 DHCP6_OPT_CLIENTID, &client_duid_len, &client_duid);
1879
1880             //DUID type: link-layer address plus time
1881             if(ntohs((*(struct optval_duid_llt*)client_duid).type) ==
1882                 DHCP6_DUID_LLT) {
1883               server_duid_len = 8+sizeof(gconfig.server_mac);
1884               server_duid = xzalloc(server_duid_len);
1885               struct optval_duid_llt *server_duid_p =
1886                 (struct optval_duid_llt*)server_duid;
1887               (*server_duid_p).type = htons(1);
1888               (*server_duid_p).hwtype = htons(1);
1889               (*server_duid_p).time = htonl((uint32_t)
1890                   (time(NULL) - 946684800) & 0xffffffff);
1891               memcpy(&(*server_duid_p).lladdr, gconfig.server_mac,
1892                   sizeof(gconfig.server_mac));
1893               memcpy(&client_lla, &(*(struct optval_duid_llt*)client_duid).lladdr,
1894                   sizeof(client_lla));
1895
1896               //Response: Server Identifier (DUID)
1897               optptr = set_optval6(optptr, DHCP6_OPT_SERVERID, server_duid,
1898                   server_duid_len);
1899               optlen += (server_duid_len + 4);
1900               //Response: Client Identifier
1901               optptr = set_optval6(optptr, DHCP6_OPT_CLIENTID, client_duid,
1902                   client_duid_len);
1903               optlen += (client_duid_len + 4);
1904               free(client_duid);free(server_duid);
1905             }
1906
1907             send_packet6(0, client_lla, optlen);
1908             write_lease6file();
1909             break;
1910           case DHCP6REQUEST:
1911             dbg("Message Type: DHCP6REQUEST\n");
1912             optptr = prepare_send_pkt6(DHCP6REPLY);
1913             optlen = 0;
1914
1915             //Receive: Client Identifier (DUID)
1916             get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1917                 DHCP6_OPT_CLIENTID, &client_duid_len, &client_duid);
1918             optptr = set_optval6(optptr, DHCP6_OPT_CLIENTID, client_duid,
1919                 client_duid_len);
1920             optlen += (client_duid_len + 4);
1921             memcpy(&client_lla, &(*(struct optval_duid_llt*)client_duid).lladdr,
1922                 sizeof(client_lla));
1923
1924             //Receive: Identity Association for Non-temporary Address
1925             if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1926                   DHCP6_OPT_IA_NA, &client_ia_na_len, &client_ia_na)) {
1927               uint16_t ia_addr_len = 0, status_code_len = 0;
1928               void *ia_addr, *status_code;
1929               uint16_t server_ia_na_len =
1930                 sizeof(struct optval_ia_na)-sizeof(uint8_t*);
1931               char *status_code_msg;
1932
1933               //Check IA Address
1934               get_optval6((uint8_t*)&(*(struct optval_ia_na*)client_ia_na).optval,
1935                   DHCP6_OPT_IA_ADDR, &ia_addr_len, &ia_addr);
1936               struct optval_ia_addr *ia_addr_p = (struct optval_ia_addr*)ia_addr;
1937               if(verifyip6_in_lease((*ia_addr_p).ipv6_addr, client_duid,
1938                     DHCP6_OPT_IA_NA, (*(struct optval_ia_na*)client_ia_na).iaid)
1939                   == -1) {
1940                 server_ia_na_len += (ia_addr_len + 4);
1941                 //Add Status Code
1942                 status_code_msg = xstrdup("Assigned an address.");
1943                 status_code_len = strlen(status_code_msg) + 1;
1944                 status_code = xzalloc(status_code_len);
1945                 struct optval_status_code *status_code_p =
1946                   (struct optval_status_code*)status_code;
1947                 (*status_code_p).status_code = htons(DHCP6_STATUS_SUCCESS);
1948                 memcpy(&(*status_code_p).status_msg, status_code_msg,
1949                     status_code_len);
1950                 server_ia_na_len += (status_code_len+4);
1951               } else {
1952                 //TODO send failed status code
1953                 break;
1954               }
1955
1956               //combine options
1957               server_ia_na = xzalloc(server_ia_na_len);
1958               struct optval_ia_na *ia_na_p = (struct optval_ia_na*)server_ia_na;
1959               (*ia_na_p).iaid = (*(struct optval_ia_na*)client_ia_na).iaid;
1960               (*ia_na_p).t1 = gconfig.t1;
1961               (*ia_na_p).t2 = gconfig.t2;
1962
1963               uint8_t* ia_na_optptr = &(*ia_na_p).optval;
1964               ia_na_optptr = set_optval6(ia_na_optptr, DHCP6_OPT_IA_ADDR,
1965                   ia_addr, ia_addr_len);
1966               free(ia_addr);
1967
1968               if(status_code_len) {
1969                 ia_na_optptr = set_optval6(ia_na_optptr, DHCP6_OPT_STATUS_CODE,
1970                     status_code, status_code_len);
1971                 free(status_code);
1972               }
1973
1974               //Response: Identity Association for Non-temporary Address
1975               //(Status Code added)
1976               optptr = set_optval6(optptr, DHCP6_OPT_IA_NA,
1977                   server_ia_na, server_ia_na_len);
1978               optlen += (server_ia_na_len + 4);
1979               free(client_ia_na);free(server_ia_na);
1980             }
1981
1982             //Receive: Server Identifier (DUID)
1983             get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
1984                 DHCP6_OPT_SERVERID, &server_duid_len, &server_duid);
1985             optptr = set_optval6(optptr, DHCP6_OPT_SERVERID,
1986                 server_duid, server_duid_len);
1987             optlen += (server_duid_len + 4);
1988
1989             free(client_duid); free(server_duid);
1990
1991             send_packet6(0, client_lla, optlen);
1992             write_lease6file();
1993             break;
1994           case DHCP6RENEW:  //TODO
1995           case DHCP6REBIND: //TODO
1996           case DHCP6RELEASE:
1997             dbg("Message Type: DHCP6RELEASE\n");
1998             optptr = prepare_send_pkt6(DHCP6REPLY);
1999             break;
2000           default:
2001             dbg("Message Type : %u\n", gstate.rqcode);
2002             break;
2003         }
2004
2005       } else {
2006         if(read_packet() < 0) {
2007           open_listensock();
2008           continue;
2009         }
2010         waited += time(NULL) - timestmp;
2011
2012         get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.options,
2013             DHCP_OPT_MESSAGE_TYPE, &gstate.rqcode);
2014         if (gstate.rqcode == 0 || gstate.rqcode < DHCPDISCOVER
2015             || gstate.rqcode > DHCPINFORM) {
2016           dbg("no or bad message type option, ignoring packet.\n");
2017           continue;
2018         }
2019         get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2020             DHCP_OPT_SERVER_ID, &serverid);
2021         if (serverid && (serverid != gconfig.server_nip)) {
2022           dbg("server ID doesn't match, ignoring packet.\n");
2023           continue;
2024         }
2025
2026         waited += time(NULL) - timestmp;
2027         switch (gstate.rqcode) {
2028           case DHCPDISCOVER:
2029             msgtype = DHCPOFFER;
2030             dbg("Message Type : DHCPDISCOVER\n");
2031             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2032                 DHCP_OPT_REQUESTED_IP, &requested_nip);
2033             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2034                 DHCP_OPT_HOST_NAME, &hstname);
2035             reqested_lease = gconfig.offer_time;
2036             get_reqparam(&gstate.rqopt);
2037             optptr = prepare_send_pkt();
2038             gstate.send.send_pkt.yiaddr = getip_from_pool(requested_nip,
2039                 gstate.rcvd.rcvd_pkt.chaddr, &reqested_lease, hstname);
2040             if(!gstate.send.send_pkt.yiaddr){
2041               msgtype = DHCPNAK;
2042               optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
2043               send_packet(1);
2044               break;
2045             }
2046             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2047                 DHCP_OPT_LEASE_TIME, &reqested_lease);
2048             reqested_lease = htonl(get_lease(reqested_lease + time(NULL)));
2049             optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
2050             optptr = set_optval(optptr, DHCP_OPT_SERVER_ID, &gconfig.server_nip, 4);
2051             optptr = set_optval(optptr, DHCP_OPT_LEASE_TIME, &reqested_lease, 4);
2052             optptr = set_reqparam(optptr, gstate.rqopt);
2053             send_packet(1);
2054             break;
2055           case DHCPREQUEST:
2056             msgtype = DHCPACK;
2057             dbg("Message Type : DHCPREQUEST\n");
2058             optptr = prepare_send_pkt();
2059             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2060                 DHCP_OPT_REQUESTED_IP, &requested_nip);
2061             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2062                 DHCP_OPT_LEASE_TIME, &reqested_lease);
2063             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2064                 DHCP_OPT_HOST_NAME, &hstname);
2065             gstate.send.send_pkt.yiaddr = getip_from_pool(requested_nip,
2066                 gstate.rcvd.rcvd_pkt.chaddr, &reqested_lease, hstname);
2067             if (!serverid) reqested_lease = gconfig.max_lease_sec;
2068             if (!gstate.send.send_pkt.yiaddr) {
2069               msgtype = DHCPNAK;
2070               optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
2071               send_packet(1);
2072               break;
2073             }
2074             get_reqparam(&gstate.rqopt);
2075             optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
2076             optptr = set_optval(optptr, DHCP_OPT_SERVER_ID, &gconfig.server_nip, 4);
2077             reqested_lease = htonl(reqested_lease);
2078             optptr = set_optval(optptr, DHCP_OPT_LEASE_TIME, &reqested_lease, 4);
2079             optptr = set_reqparam(optptr, gstate.rqopt);
2080             send_packet(1);
2081             write_leasefile();
2082             break;
2083           case DHCPDECLINE:// FALL THROUGH
2084           case DHCPRELEASE:
2085             dbg("Message Type : DHCPDECLINE or DHCPRELEASE \n");
2086             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2087                 DHCP_OPT_SERVER_ID, &serverid);
2088             if (serverid != gconfig.server_nip) break;
2089             get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
2090                 DHCP_OPT_REQUESTED_IP, &requested_nip);
2091             delip_from_lease(requested_nip, gstate.rcvd.rcvd_pkt.chaddr,
2092                 (gstate.rqcode==DHCPRELEASE)?0:gconfig.decline_time);
2093             break;
2094           default:
2095             dbg("Message Type : %u\n", gstate.rqcode);
2096             break;
2097         }
2098       }
2099     }
2100   }
2101 }