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