1 /* dhcpd.c - DHCP server for dynamic network configuration. 2 * 3 * Copyright 2013 Madhur Verma <mad.flexi (at) gmail.com> 4 * Copyright 2013 Kyungwan Han <asura321 (at) gamil.com> 5 * Copyright 2015 Yeongdeok Suh <skyducks111 (at) 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. 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. 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 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 */ 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 */ 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. 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 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 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 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. 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 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. 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. 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 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 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 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. 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 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 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 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 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 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 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 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 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. 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. 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 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 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 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. 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. 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 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) 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. 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 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. 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. 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 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 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 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 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