1/* 2 * udhcpc scripts 3 * 4 * Copyright (C) 2009, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: udhcpc.c,v 1.27 2009/12/02 20:06:40 Exp $ 19 */ 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <sys/socket.h> 25#include <netinet/in.h> 26#include <arpa/inet.h> 27#include <errno.h> 28#include <time.h> 29#include <unistd.h> 30#include <net/ethernet.h> 31 32#include <bcmnvram.h> 33#include <shutils.h> 34#include <rc.h> 35 36/* Support for Domain Search List */ 37#undef DHCP_RFC3397 38 39/* returns: length of hex value 40 * dest size must be lagre enough to accept n bytes from 41 src in hex representation plus one \0 byte */ 42static int 43bin2hex(char *dest, size_t size, const void *src, size_t n) 44{ 45 unsigned char *sptr = (unsigned char *) src; 46 unsigned char *send = sptr + n; 47 char *dptr = dest; 48 49 while (sptr < send && size > 2) { 50 n = snprintf(dptr, size, "%02x", *sptr++); 51 dptr += n; 52 size -= n; 53 } 54 return dptr - dest; 55} 56 57#ifdef RTCONFIG_TR069 58/* returns: 59 * NULL on NULL value or alloc error 60 * binary representation of hex value on success 61 * if size if specified, returns actual size of parsed value 62 * note: value is alloced and needs to be free() */ 63static char * 64hex2bin(const char *value, size_t *size) 65{ 66 char buf[3], *src, *tmp; 67 unsigned char *dst, *ptr; 68 69 if (!(src = (char *) value) || 70 !(dst = calloc(1, strlen(src)/2 + 1))) 71 return NULL; 72 73 memset(buf, 0, sizeof(buf)); 74 for (ptr = dst; src[0] && src[1]; ptr++) { 75 buf[0] = *src++; 76 buf[1] = *src++; 77 *ptr = strtoul(buf, &tmp, 16); 78 if (tmp == buf || *tmp) 79 break; 80 } 81 if (size) 82 *size = ptr - dst; 83 84 return (char *) dst; 85} 86#endif 87 88/* set nvram to value 89 * returns: 90 * 0 if not changed 91 * 1 if new/changed/removed */ 92static int 93nvram_set_check(const char *name, const char *value) 94{ 95 char *nvalue = nvram_get(name); 96 97 if (nvalue == value || strcmp(nvalue ? : "", value ? : "") == 0) 98 return 0; 99 100 nvram_set(name, value); 101 return 1; 102} 103 104/* set nvram to env value 105 * returns: 106 * 0 if not changed 107 * 1 if new/changed/removed */ 108static int 109nvram_set_env(const char *name, const char *env) 110{ 111 char *evalue = getenv(env); 112 113 if (evalue) 114 evalue = trim_r(evalue); 115 116 return nvram_set_check(name, evalue); 117} 118 119struct viopt_hdr { 120 unsigned int entnum; 121 unsigned char len; 122 unsigned char data[0]; 123} __attribute__ ((__packed__)); 124 125struct opt_hdr { 126 unsigned char id; 127 unsigned char len; 128 unsigned char data[0]; 129} __attribute__ ((__packed__)); 130 131#ifdef RTCONFIG_TR069 132#ifdef RTCONFIG_TR181 133static struct viopt_hdr * 134viopt_get(const void *buf, size_t size, unsigned int entnum) 135{ 136 struct viopt_hdr *opt; 137 unsigned char *ptr = (unsigned char *) buf; 138 unsigned char *end = (unsigned char *) buf + size; 139 140 while (ptr + sizeof(*opt) <= end) { 141 opt = (struct viopt_hdr *) ptr; 142 if ((ptr += sizeof(*opt) + opt->len) > end) 143 break; 144 if (opt->entnum == entnum) 145 return opt; 146 } 147 148 return NULL; 149} 150#endif 151 152static struct opt_hdr * 153opt_get(const void *buf, size_t size, unsigned char id) 154{ 155 struct opt_hdr *opt; 156 unsigned char *ptr = (unsigned char *) buf; 157 unsigned char *end = (unsigned char *) buf + size; 158 159 while (ptr + sizeof(*opt) <= end) { 160 opt = (struct opt_hdr *) ptr; 161 if (opt->id == 0) { 162 ptr++; 163 continue; 164 } else if (opt->id == 255) 165 break; 166 if ((ptr += sizeof(*opt) + opt->len) > end) 167 break; 168 if (opt->id == id) 169 return opt; 170 } 171 172 return NULL; 173} 174 175static char 176*stropt(const struct opt_hdr *opt, char *buf) 177{ 178 strncpy(buf, (char *) opt->data, opt->len); 179 buf[opt->len] = '\0'; 180 return buf; 181} 182 183#ifdef RTCONFIG_TR181 184static int 185opt_add(const void *buf, size_t size, unsigned char id, void *data, unsigned char len) 186{ 187 struct opt_hdr *opt = (struct opt_hdr *) buf; 188 189 if (size >= sizeof(*opt) + len) { 190 opt->id = id; 191 opt->len = len; 192 memcpy(opt->data, data, len); 193 return sizeof(*opt) + len; 194 } 195 196 return 0; 197} 198#endif 199#endif 200 201struct duid { 202 uint16_t type; 203 uint16_t hwtype; 204 unsigned char ea[ETHER_ADDR_LEN]; 205} __attribute__ ((__packed__)); 206 207/* Generate DUID-LL */ 208int get_duid(struct duid *duid) 209{ 210 if (!duid || !ether_atoe(get_lan_hwaddr(), duid->ea)) 211 return 0; 212 213 duid->type = htons(3); /* DUID-LL */ 214 duid->hwtype = htons(1); /* Ethernet */ 215 216 return ETHER_ADDR_LEN; 217} 218 219static int 220expires(char *wan_ifname, unsigned int in) 221{ 222 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 223 int unit; 224 time_t now; 225 FILE *fp; 226 227 if ((unit = wan_prefix(wan_ifname, prefix)) < 0) 228 return -1; 229 if (wan_ifunit(wan_ifname) < 0) 230 snprintf(prefix, sizeof(prefix), "wan%d_x", unit); 231 232 nvram_set_int(strcat_r(prefix, "expires", tmp), (unsigned int) uptime() + in); 233 234 snprintf(tmp, sizeof(tmp), "/tmp/udhcpc%d.expires", unit); 235 if ((fp = fopen(tmp, "w")) == NULL) { 236 perror(tmp); 237 return errno; 238 } 239 time(&now); 240 fprintf(fp, "%d", (unsigned int) now + in); 241 fclose(fp); 242 243 return 0; 244} 245 246/* 247 * deconfig: This argument is used when udhcpc starts, and when a 248 * leases is lost. The script should put the interface in an up, but 249 * deconfigured state. 250*/ 251static int 252deconfig(int zcip) 253{ 254 char *wan_ifname = safe_getenv("interface"); 255 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 256 int unit = wan_ifunit(wan_ifname); 257 int end_wan_sbstate = WAN_STOPPED_REASON_DHCP_DECONFIG; 258 259 /* Figure out nvram variable name prefix for this i/f */ 260 if (wan_prefix(wan_ifname, prefix) < 0) 261 return -1; 262 if ((unit < 0) && 263 (nvram_match(strcat_r(prefix, "proto", tmp), "l2tp") || 264 nvram_match(strcat_r(prefix, "proto", tmp), "pptp"))) { 265 logmessage(zcip ? "zcip client" : "dhcp client", "skipping resetting IP address to 0.0.0.0"); 266 } else 267 ifconfig(wan_ifname, IFUP, "0.0.0.0", NULL); 268 269 expires(wan_ifname, 0); 270 wan_down(wan_ifname); 271 272#if (defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)) 273 if(nvram_get_int(strcat_r(prefix, "sbstate_t", tmp)) == WAN_STOPPED_REASON_DATALIMIT) 274 end_wan_sbstate = WAN_STOPPED_REASON_DATALIMIT; 275#endif 276 277 /* Skip physical VPN subinterface */ 278 if (!(unit < 0)) 279 update_wan_state(prefix, WAN_STATE_STOPPED, end_wan_sbstate); 280 281 _dprintf("udhcpc:: %s done\n", __FUNCTION__); 282 return 0; 283} 284 285/* 286 * bound: This argument is used when udhcpc moves from an unbound, to 287 * a bound state. All of the paramaters are set in enviromental 288 * variables, The script should configure the interface, and set any 289 * other relavent parameters (default gateway, dns server, etc). 290*/ 291static int 292bound(void) 293{ 294 char *wan_ifname = safe_getenv("interface"); 295 char *value, *gateway; 296 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 297 char wanprefix[sizeof("wanXXXXXXXXXX_")]; 298 int unit, ifunit; 299 int changed = 0; 300#ifdef RTCONFIG_TR069 301 size_t size = 0; 302#endif 303 304 /* Figure out nvram variable name prefix for this i/f */ 305 if ((ifunit = wan_prefix(wan_ifname, wanprefix)) < 0) 306 return -1; 307 if ((unit = wan_ifunit(wan_ifname)) < 0) 308 snprintf(prefix, sizeof(prefix), "wan%d_x", ifunit); 309 else snprintf(prefix, sizeof(prefix), "wan%d_", ifunit); 310 311 /* Stop zcip to avoid races */ 312 stop_zcip(ifunit); 313 314 changed += nvram_set_env(strcat_r(prefix, "ipaddr", tmp), "ip"); 315#if defined(RTCONFIG_USB_MODEM) && defined(RTCONFIG_INTERNAL_GOBI) 316 if (get_dualwan_by_unit(ifunit) == WANS_DUALWAN_IF_USB && 317 nvram_match("usb_modem_act_type", "gobi")) { 318 changed += nvram_set_check(strcat_r(prefix, "netmask", tmp), "255.255.255.255"); 319 if ((gateway = getenv("ip"))) 320 nvram_set(strcat_r(prefix, "gateway", tmp), trim_r(gateway)); 321 } else 322#endif 323{ 324 changed += nvram_set_env(strcat_r(prefix, "netmask", tmp), "subnet"); 325 if ((gateway = getenv("router"))) 326 nvram_set(strcat_r(prefix, "gateway", tmp), trim_r(gateway)); 327} 328 329 if (nvram_get_int(strcat_r(wanprefix, "dnsenable_x", tmp))) { 330 /* ex: android phone, the gateway is the DNS server. */ 331 if ((value = getenv("dns") ? : getenv("router"))) 332 nvram_set(strcat_r(prefix, "dns", tmp), trim_r(value)); 333#ifdef DHCP_RFC3397 334 if ((value = getenv("search")) && *value) { 335 char *domain, *result; 336 if ((domain = getenv("domain")) && *domain && 337 find_word(value, trim_r(domain)) == NULL) { 338 result = alloca(strlen(domain) + strlen(value) + 2); 339 sprintf(result, "%s %s", domain, value); 340 value = result; 341 } 342 nvram_set(strcat_r(prefix, "domain", tmp), trim_r(value)); 343 } else 344#endif 345 nvram_set_env(strcat_r(prefix, "domain", tmp), "domain"); 346 } 347 if ((value = getenv("wins"))) 348 nvram_set(strcat_r(prefix, "wins", tmp), trim_r(value)); 349 //if ((value = getenv("hostname"))) 350 // sethostname(value, strlen(value) + 1); 351 if ((value = getenv("lease"))) { 352 unsigned int lease = atoi(value); 353 nvram_set_int(strcat_r(prefix, "lease", tmp), lease); 354 expires(wan_ifname, lease); 355 } 356 357 /* classful static routes */ 358 nvram_set(strcat_r(prefix, "routes", tmp), getenv("routes")); 359 /* ms classless static routes */ 360 nvram_set(strcat_r(prefix, "routes_ms", tmp), getenv("msstaticroutes")); 361 /* rfc3442 classless static routes */ 362 nvram_set(strcat_r(prefix, "routes_rfc", tmp), getenv("staticroutes")); 363 364#ifdef RTCONFIG_IPV6 365 if ((value = getenv("ip6rd")) && 366 (get_ipv6_service() == IPV6_6RD && nvram_match(ipv6_nvname("ipv6_6rd_dhcp"), "1"))) { 367 char *ptr, *values[4]; 368 int i; 369 370 ptr = value = strdup(value); 371 for (i = 0; value && i < 4; i++) 372 values[i] = strsep(&value, " "); 373 if (i == 4) { 374 nvram_set(strcat_r(wanprefix, "6rd_ip4size", tmp), values[0]); 375 nvram_set(strcat_r(wanprefix, "6rd_prefixlen", tmp), values[1]); 376 nvram_set(strcat_r(wanprefix, "6rd_prefix", tmp), values[2]); 377 nvram_set(strcat_r(wanprefix, "6rd_router", tmp), values[3]); 378 } 379 free(ptr); 380 } 381#endif 382 383#ifdef RTCONFIG_TR069 384 if ((value = getenv("opt43")) && nvram_get_int("tr_discovery") && 385 (value = hex2bin(value, &size))) { 386 struct opt_hdr *opt; 387 char buf[256], *url = NULL; 388 if ((opt = opt_get(value, size, 1)) && 389 strstr(stropt(opt, buf), "://") > buf) 390 url = buf; 391 else if (strstr(value, "://") > value) 392 url = trim_r(value); 393 if (url && *url) { 394 nvram_set("tr_acs_url", url); 395 nvram_set_int("tr_enable", 1); 396 } 397 //if ((opt = opt_get(value, size, 1))) 398 // nvram_set(strcat_r(wanprefix, "tr_acs_url", tmp), stropt(opt, buf)); 399 //if ((opt = opt_get(value, size, 2))) 400 // nvram_set(strcat_r(wanprefix, "tr_pvgcode", tmp), stropt(opt, buf)); 401 free(value); 402 } 403#ifdef RTCONFIG_TR181 404 nvram_unset("vivso"); 405 if ((value = hex2bin(getenv("opt125"), &size))) { 406 struct viopt_hdr *viopt; 407 struct opt_hdr *oui, *serial, *class; 408 if ((viopt = viopt_get(value, size, htonl(3561))) && 409 (oui = opt_get(viopt->data, viopt->len, 4)) && 410 (serial = opt_get(viopt->data, viopt->len, 5))) { 411 char vivso[6 + 64 + 64 + 3]; 412 char *ptr = vivso; 413 char *end = ptr + sizeof(vivso); 414 ptr += snprintf(ptr, end - ptr, "%s,", stropt(oui, tmp)); 415 ptr += snprintf(ptr, end - ptr, "%s,", stropt(serial, tmp)); 416 if ((class = opt_get(viopt->data, viopt->len, 6))) 417 ptr += snprintf(ptr, end - ptr, "%s", stropt(class, tmp)); 418 nvram_set("vivso", vivso); 419 } 420 free(value); 421 } 422#endif 423#endif 424 425 // check if the ipaddr is safe to apply 426 // only handle one lan instance so far 427 // update_wan_state(prefix, WAN_STATE_STOPPED, WAN_STOPPED_REASON_INVALID_IPADDR) 428 if (inet_equal(nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)), nvram_safe_get(strcat_r(prefix, "netmask", tmp)), 429 nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask"))) { 430 update_wan_state(prefix, WAN_STATE_STOPPED, WAN_STOPPED_REASON_INVALID_IPADDR); 431 return 0; 432 } 433 434 /* Clean nat conntrack for this interface, 435 * but skip physical VPN subinterface for PPTP/L2TP */ 436 if (changed && !(unit < 0 && 437 (nvram_match(strcat_r(wanprefix, "proto", tmp), "l2tp") || 438 nvram_match(strcat_r(wanprefix, "proto", tmp), "pptp")))) 439 ifconfig(wan_ifname, IFUP, "0.0.0.0", NULL); 440 ifconfig(wan_ifname, IFUP, 441 nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)), 442 nvram_safe_get(strcat_r(prefix, "netmask", tmp))); 443 444 wan_up(wan_ifname); 445 446 logmessage("dhcp client", "bound %s via %s during %d seconds.", 447 nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)), 448 nvram_safe_get(strcat_r(prefix, "gateway", tmp)), 449 nvram_get_int(strcat_r(prefix, "lease", tmp)) 450 ); 451 452 _dprintf("udhcpc:: %s done\n", __FUNCTION__); 453 return 0; 454} 455 456/* 457 * renew: This argument is used when a DHCP lease is renewed. All of 458 * the paramaters are set in enviromental variables. This argument is 459 * used when the interface is already configured, so the IP address, 460 * will not change, however, the other DHCP paramaters, such as the 461 * default gateway, subnet mask, and dns server may change. 462 */ 463static int 464renew(void) 465{ 466 char *wan_ifname = safe_getenv("interface"); 467 char *value, *gateway; 468 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 469 char wanprefix[sizeof("wanXXXXXXXXXX_")]; 470 int unit, ifunit; 471 int changed = 0; 472 473 /* Figure out nvram variable name prefix for this i/f */ 474 if ((ifunit = wan_prefix(wan_ifname, wanprefix)) < 0) 475 return -1; 476 if ((unit = wan_ifunit(wan_ifname)) < 0) 477 snprintf(prefix, sizeof(prefix), "wan%d_x", ifunit); 478 else snprintf(prefix, sizeof(prefix), "wan%d_", ifunit); 479 480 if ((value = getenv("ip")) == NULL || 481 !nvram_match(strcat_r(prefix, "ipaddr", tmp), trim_r(value))) 482 return bound(); 483#if defined(RTCONFIG_USB_MODEM) && defined(RTCONFIG_INTERNAL_GOBI) 484 if (get_dualwan_by_unit(ifunit) == WANS_DUALWAN_IF_USB && 485 nvram_match("usb_modem_act_type", "gobi")) { 486 if (!nvram_match(strcat_r(prefix, "netmask", tmp), "255.255.255.255")) 487 return bound(); 488 if ((gateway = getenv("ip")) == NULL || 489 !nvram_match(strcat_r(prefix, "gateway", tmp), trim_r(gateway))) 490 return bound(); 491 } else 492#endif 493{ 494 if ((value = getenv("subnet")) == NULL || 495 !nvram_match(strcat_r(prefix, "netmask", tmp), trim_r(value))) 496 return bound(); 497 if ((gateway = getenv("router")) == NULL || 498 !nvram_match(strcat_r(prefix, "gateway", tmp), trim_r(gateway))) 499 return bound(); 500} 501 502 if (nvram_get_int(strcat_r(wanprefix, "dnsenable_x", tmp))) { 503 /* ex: android phone, the gateway is the DNS server. */ 504 if ((value = getenv("dns") ? : getenv("router"))) { 505 changed += !nvram_match(strcat_r(prefix, "dns", tmp), trim_r(value)); 506 nvram_set(strcat_r(prefix, "dns", tmp), trim_r(value)); 507 } 508#ifdef DHCP_RFC3397 509 if ((value = getenv("search")) && *value) { 510 char *domain, *result; 511 if ((domain = getenv("domain")) && *domain && 512 find_word(value, trim_r(domain)) == NULL) { 513 result = alloca(strlen(domain) + strlen(value) + 2); 514 sprintf(result, "%s %s", domain, value); 515 value = result; 516 } 517 changed += !nvram_match(strcat_r(prefix, "domain", tmp), trim_r(value)); 518 nvram_set(strcat_r(prefix, "domain", tmp), trim_r(value)); 519 } else 520#endif 521 changed += nvram_set_env(strcat_r(prefix, "domain", tmp), "domain"); 522 } 523 if ((value = getenv("wins"))) 524 nvram_set(strcat_r(prefix, "wins", tmp), trim_r(value)); 525 //if ((value = getenv("hostname"))) 526 // sethostname(value, strlen(value) + 1); 527 if ((value = getenv("lease"))) { 528 unsigned int lease = atoi(value); 529 nvram_set_int(strcat_r(prefix, "lease", tmp), lease); 530 expires(wan_ifname, lease); 531 } 532 533 /* Update actual DNS or delayed for DHCP+PPP */ 534 if (changed) 535 update_resolvconf(); 536 537 /* Update connected state and DNS for WEB UI, 538 * but skip physical VPN subinterface */ 539 if (changed && !(unit < 0)) 540 update_wan_state(wanprefix, WAN_STATE_CONNECTED, 0); 541 542 _dprintf("udhcpc:: %s done\n", __FUNCTION__); 543 return 0; 544} 545 546static int 547leasefail(void) 548{ 549 char *wan_ifname = safe_getenv("interface"); 550 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 551 char pid[sizeof("/var/run/zcipXXXXXXXXXX.pid")]; 552 int unit; 553 554 /* Figure out nvram variable name prefix for this i/f */ 555 if ((unit = wan_prefix(wan_ifname, prefix)) < 0) 556 return -1; 557 558 /* Start zcip for pppoe only */ 559 if (!nvram_match(strcat_r(prefix, "proto", tmp), "pppoe")) 560 return 0; 561 562 snprintf(pid, sizeof(pid), "/var/run/zcip%d.pid", unit); 563 if (kill_pidfile_s(pid, 0) == 0) 564 return 0; 565 566 return start_zcip(wan_ifname, unit, NULL); 567} 568 569int 570udhcpc_wan(int argc, char **argv) 571{ 572 _dprintf("%s:: %s\n", __FUNCTION__, argv[1] ? : ""); 573 if (!argv[1]) 574 return EINVAL; 575 else if (strstr(argv[1], "deconfig")) 576 return deconfig(0); 577 else if (strstr(argv[1], "bound")) 578 return bound(); 579 else if (strstr(argv[1], "renew")) 580 return renew(); 581 else if (strstr(argv[1], "leasefail")) 582 return leasefail(); 583/* else if (strstr(argv[1], "nak")) */ 584 585 return 0; 586} 587 588int 589start_udhcpc(char *wan_ifname, int unit, pid_t *ppid) 590{ 591 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 592 char pid[sizeof("/var/run/udhcpcXXXXXXXXXX.pid")]; 593 char clientid[sizeof("61:") + (32+32+1)*2]; 594#ifdef RTCONFIG_TR069 595 char vendorid[32+32+1+sizeof(",dslforum.org")]; 596#ifdef RTCONFIG_TR181 597 unsigned char optbuf[sizeof(struct viopt_hdr) + 128]; 598 unsigned char hwaddr[6]; 599 char vivopts[sizeof("125:") + sizeof(optbuf)*2]; 600#endif 601#endif 602 struct duid duid; 603 char *value; 604 char *dhcp_argv[] = { "/sbin/udhcpc", 605 "-i", wan_ifname, 606 "-p", (snprintf(pid, sizeof(pid), "/var/run/udhcpc%d.pid", unit), pid), 607 "-s", "/tmp/udhcpc", 608 NULL, /* -t2 */ 609 NULL, /* -T5 */ 610 NULL, /* -A120 */ 611 NULL, /* -b */ 612 NULL, NULL, /* -H wan_hostname */ 613 NULL, /* -Oroutes */ 614 NULL, /* -Ostaticroutes */ 615 NULL, /* -Omsstaticroutes */ 616#ifdef RTCONFIG_IPV6 617 NULL, /* -Oip6rd rfc */ 618 NULL, /* -Oip6rd comcast */ 619#endif 620 NULL, NULL, /* -x 61:wan_clientid */ 621 NULL, NULL, /* -V wan_vendorid */ 622#ifdef RTCONFIG_TR069 623 NULL, /* -O43 */ 624#ifdef RTCONFIG_TR181 625 NULL, NULL, /* -x 125:vivopts */ 626#endif 627#endif 628 NULL }; 629 int index = 7; /* first NULL */ 630 int len, dr_enable; 631 632 /* Use unit */ 633 snprintf(prefix, sizeof(prefix), "wan%d_", unit); 634 635 /* Stop zcip to avoid races */ 636 stop_zcip(unit); 637 638 /* Skip dhcp and start zcip for pppoe, if desired */ 639 if (nvram_match(strcat_r(prefix, "proto", tmp), "pppoe") && 640 nvram_match(strcat_r(prefix, "vpndhcp", tmp), "0")) 641 return start_zcip(wan_ifname, unit, ppid); 642 643 if (nvram_get_int("dhcpc_mode") == 0) { 644 /* 2 discover packets max (default 3 discover packets) */ 645 dhcp_argv[index++] = "-t2"; 646 /* 5 seconds between packets (default 3 seconds) */ 647 dhcp_argv[index++] = "-T5"; 648 /* Wait 160 seconds before trying again (default 20 seconds) */ 649 /* set to 160 to accomodate new timings enforced by Charter cable */ 650 dhcp_argv[index++] = "-A160"; 651 } 652 653 if (ppid == NULL) 654 dhcp_argv[index++] = "-b"; 655 656 value = nvram_safe_get(strcat_r(prefix, "hostname", tmp)); 657 if (*value && is_valid_hostname(value)) { 658 dhcp_argv[index++] = "-H"; 659 dhcp_argv[index++] = value; 660 } 661 662 /* 0: disable, 1: MS routes, 2: RFC routes, 3: Both */ 663 dr_enable = nvram_get_int("dr_enable_x"); 664 if (dr_enable != 0) { 665 dhcp_argv[index++] = "-O33"; /* routes */ 666 if (dr_enable & (1 << 0)) 667 dhcp_argv[index++] = "-O249"; /* "msstaticroutes" */ 668 if (dr_enable & (1 << 1)) 669 dhcp_argv[index++] = "-O121"; /* "staticroutes" */ 670 } 671 672#ifdef RTCONFIG_IPV6 673 if (get_ipv6_service() == IPV6_6RD && nvram_match(ipv6_nvname("ipv6_6rd_dhcp"), "1")) { 674 dhcp_argv[index++] = "-O212"; /* ip6rd rfc */ 675 dhcp_argv[index++] = "-O150"; /* ip6rd comcast */ 676 } 677#endif 678 679 /* Client ID */ 680 value = nvram_safe_get(strcat_r(prefix, "clientid", tmp)); 681 if (nvram_get_int(strcat_r(prefix, "clientid_type", tmp))) { 682 if (get_duid(&duid)) { 683 /* RFC4361 implementation, use WAN number as IAID. 684 * This also fits odhcp6c behavior for IA_NA for the WAN0 */ 685 unsigned long iaid = htonl(unit + 1); 686 len = snprintf(clientid, sizeof(clientid), "61:ff"); 687 len += bin2hex(clientid + len, sizeof(clientid) - len, &iaid, sizeof(iaid)); 688 bin2hex(clientid + len, sizeof(clientid) - len, &duid, sizeof(duid)); 689 dhcp_argv[index++] = "-x"; 690 dhcp_argv[index++] = clientid; 691 } 692 } else if (*value) { 693 len = snprintf(clientid, sizeof(clientid), "61:"); 694 bin2hex(clientid + len, sizeof(clientid) - len, value, strlen(value)); 695 dhcp_argv[index++] = "-x"; 696 dhcp_argv[index++] = clientid; 697 } 698 699 /* Vendor ID */ 700 value = nvram_safe_get(strcat_r(prefix, "vendorid", tmp)); 701#ifdef RTCONFIG_TR069 702 if (!nvram_invmatch("tr_acs_url", "")) 703 nvram_set_int("tr_discovery", 1); 704 if (nvram_get_int("tr_enable") && nvram_get_int("tr_discovery")) { 705 /* Add dslforum.org to VCI and request VSI */ 706 snprintf(vendorid, sizeof(vendorid) - sizeof(",dslforum.org") + 1, "%s", value); 707 len = strlen(vendorid); 708 snprintf(vendorid + len, sizeof(vendorid) - len, len ? ",%s" : "%s", "dslforum.org"); 709 value = vendorid; 710 dhcp_argv[index++] = "-O43"; 711 } 712#endif 713 if (*value) { 714 dhcp_argv[index++] = "-V"; 715 dhcp_argv[index++] = value; 716 } 717 718#ifdef RTCONFIG_TR069 719#ifdef RTCONFIG_TR181 720 if (ether_atoe(get_lan_hwaddr(), hwaddr)) { 721 struct viopt_hdr *viopt = (struct viopt_hdr *) optbuf; 722 unsigned char *ptr = viopt->data; 723 unsigned char *end = optbuf + sizeof(optbuf); 724 725 /* OUI */ 726 len = snprintf(tmp, sizeof(tmp), "%02X%02X%02X", hwaddr[0], hwaddr[1], hwaddr[2]); 727 ptr += opt_add(ptr, end - ptr, 1, tmp, len); 728 /* Serial */ 729 len = snprintf(tmp, sizeof(tmp), "%02X%02X%02X%02X%02X%02X", 730 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); 731 ptr += opt_add(ptr, end - ptr, 2, tmp, len); 732 /* Class */ 733 len = snprintf(tmp, sizeof(tmp), "%s", nvram_safe_get("productid")); 734 ptr += opt_add(ptr, end - ptr, 3, tmp, len); 735 736 viopt->entnum = htonl(3561); 737 viopt->len = ptr - viopt->data; 738 739 len = snprintf(vivopts, sizeof(vivopts), "125:"); 740 bin2hex(vivopts + len, sizeof(vivopts) - len, viopt, sizeof(*viopt) + viopt->len); 741 742 dhcp_argv[index++] = "-x"; 743 dhcp_argv[index++] = vivopts; 744 } 745#endif 746#endif 747 748 return _eval(dhcp_argv, NULL, 0, ppid); 749} 750 751void 752stop_udhcpc(int unit) 753{ 754 char pid[sizeof("/var/run/udhcpcXXXXXXXXXX.pid")]; 755 756 /* Stop zcip before udhcpc to avoid races */ 757 stop_zcip(unit); 758 759 /* Stop all instances */ 760 if (unit < 0) { 761 killall_tk("udhcpc"); 762 return; 763 } 764 765 /* Stop unit instance only */ 766 snprintf(pid, sizeof(pid), "/var/run/udhcpc%d.pid", unit); 767 if (kill_pidfile_s(pid, SIGUSR2) == 0) { 768 usleep(10000); 769 kill_pidfile_s(pid, SIGTERM); 770 } 771} 772 773/* 774 * config: This argument is used when zcip moves to configured state. 775 * All of the paramaters are set in enviromental variables, the script 776 * should configure the interface. 777*/ 778static int 779config(void) 780{ 781 char *wan_ifname = safe_getenv("interface"); 782 char *value; 783 char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")]; 784 char wanprefix[sizeof("wanXXXXXXXXXX_")]; 785 int unit, ifunit; 786 int changed = 0; 787 788 /* Figure out nvram variable name prefix for this i/f */ 789 if ((ifunit = wan_prefix(wan_ifname, wanprefix)) < 0) 790 return -1; 791 if ((unit = wan_ifunit(wan_ifname)) < 0) 792 snprintf(prefix, sizeof(prefix), "wan%d_x", ifunit); 793 else snprintf(prefix, sizeof(prefix), "wan%d_", ifunit); 794 795 if ((value = getenv("ip"))) { 796 changed = !nvram_match(strcat_r(prefix, "ipaddr", tmp), trim_r(value)); 797 nvram_set(strcat_r(prefix, "ipaddr", tmp), trim_r(value)); 798 } 799 nvram_set(strcat_r(prefix, "netmask", tmp), "255.255.0.0"); 800 nvram_set(strcat_r(prefix, "gateway", tmp), ""); 801 if (nvram_get_int(strcat_r(wanprefix, "dnsenable_x", tmp))) 802 nvram_set(strcat_r(prefix, "dns", tmp), ""); 803 nvram_unset(strcat_r(prefix, "wins", tmp)); 804 nvram_unset(strcat_r(prefix, "domain", tmp)); 805 nvram_unset(strcat_r(prefix, "lease", tmp)); 806 nvram_unset(strcat_r(prefix, "expires", tmp)); 807 808 nvram_unset(strcat_r(prefix, "routes", tmp)); 809 nvram_unset(strcat_r(prefix, "routes_ms", tmp)); 810 nvram_unset(strcat_r(prefix, "routes_rfc", tmp)); 811 812#ifdef RTCONFIG_TR069 813// nvram_unset(strcat_r(prefix, "tr_acs_url", tmp)); 814// nvram_unset(strcat_r(prefix, "tr_pvgcode", tmp)); 815#ifdef RTCONFIG_TR181 816 nvram_unset("vivso"); 817#endif 818#endif 819 /* Clean nat conntrack for this interface, 820 * but skip physical VPN subinterface for PPTP/L2TP */ 821 if (changed && !(unit < 0 && 822 (nvram_match(strcat_r(wanprefix, "proto", tmp), "l2tp") || 823 nvram_match(strcat_r(wanprefix, "proto", tmp), "pptp")))) 824 ifconfig(wan_ifname, IFUP, "0.0.0.0", NULL); 825 ifconfig(wan_ifname, IFUP, 826 nvram_safe_get(strcat_r(prefix, "ipaddr", tmp)), 827 nvram_safe_get(strcat_r(prefix, "netmask", tmp))); 828 829 wan_up(wan_ifname); 830 831 logmessage("zcip client", "configured %s", 832 nvram_safe_get(strcat_r(prefix, "ipaddr", tmp))); 833 834 _dprintf("zcip:: %s done\n", __FUNCTION__); 835 return 0; 836} 837 838int 839zcip_wan(int argc, char **argv) 840{ 841 _dprintf("%s:: %s\n", __FUNCTION__, argv[1] ? : ""); 842 if (!argv[1]) 843 return EINVAL; 844 else if (strstr(argv[1], "deconfig")) 845 return deconfig(1); 846 else if (strstr(argv[1], "config")) 847 return config(); 848/* else if (strstr(argv[1], "init")) */ 849 850 return 0; 851} 852 853int 854start_zcip(char *wan_ifname, int unit, pid_t *ppid) 855{ 856 char pid[sizeof("/var/run/zcipXXXXXXXXXX.pid")]; 857 char *zcip_argv[] = { "/sbin/zcip", 858 "-p", (snprintf(pid, sizeof(pid), "/var/run/zcip%d.pid", unit), pid), 859 wan_ifname, 860 "/tmp/zcip", 861 NULL }; 862 863 return _eval(zcip_argv, NULL, 0, ppid); 864} 865 866void 867stop_zcip(int unit) 868{ 869 char pid[sizeof("/var/run/zcipXXXXXXXXXX.pid")]; 870 871 /* Stop all instances */ 872 if (unit < 0) { 873 killall_tk("zcip"); 874 return; 875 } 876 877 /* Stop unit instance only */ 878 snprintf(pid, sizeof(pid), "/var/run/zcip%d.pid", unit); 879 kill_pidfile_s(pid, SIGTERM); 880} 881 882static int 883expires_lan(char *lan_ifname, unsigned int in) 884{ 885 time_t now; 886 FILE *fp; 887 char tmp[100]; 888 889 time(&now); 890 snprintf(tmp, sizeof(tmp), "/tmp/udhcpc-%s.expires", lan_ifname); 891 if (!(fp = fopen(tmp, "w"))) { 892 perror(tmp); 893 return errno; 894 } 895 fprintf(fp, "%d", (unsigned int) now + in); 896 fclose(fp); 897 return 0; 898} 899 900/* 901 * deconfig: This argument is used when udhcpc starts, and when a 902 * leases is lost. The script should put the interface in an up, but 903 * deconfigured state. 904*/ 905static int 906deconfig_lan(void) 907{ 908 char *lan_ifname = safe_getenv("interface"); 909 910 //ifconfig(lan_ifname, IFUP, "0.0.0.0", NULL); 911_dprintf("%s: IFUP.\n", __FUNCTION__); 912#ifdef RTCONFIG_DHCP_OVERRIDE 913 if (nvram_get_int("sw_mode") == SW_MODE_AP) 914 ; 915 else 916#endif 917 if(nvram_match("lan_proto", "static")) 918 ifconfig(lan_ifname, IFUP | IFF_ALLMULTI, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask")); 919 else 920 ifconfig(lan_ifname, IFUP | IFF_ALLMULTI, nvram_default_get("lan_ipaddr"), nvram_default_get("lan_netmask")); 921 922 expires_lan(lan_ifname, 0); 923 924 lan_down(lan_ifname); 925 926 _dprintf("done\n"); 927 return 0; 928} 929 930/* 931 * bound: This argument is used when udhcpc moves from an unbound, to 932 * a bound state. All of the paramaters are set in enviromental 933 * variables, The script should configure the interface, and set any 934 * other relavent parameters (default gateway, dns server, etc). 935*/ 936static int 937bound_lan(void) 938{ 939 char *lan_ifname = safe_getenv("interface"); 940 char *value; 941#if defined(RTCONFIG_TR069) && defined(RTCONFIG_TR181) 942 char tmp[100]; 943 int size; 944#endif 945 946 if ((value = getenv("ip"))) { 947 /* restart httpd after lan_ipaddr udpating through lan dhcp client */ 948 if (!nvram_match("lan_ipaddr", trim_r(value))) { 949 stop_httpd(); 950 start_httpd(); 951 } 952 nvram_set("lan_ipaddr", trim_r(value)); 953 } 954 if ((value = getenv("subnet"))) 955 nvram_set("lan_netmask", trim_r(value)); 956 if ((value = getenv("router"))) 957 nvram_set("lan_gateway", trim_r(value)); 958 if ((value = getenv("lease"))) { 959 nvram_set("lan_lease", trim_r(value)); 960 expires_lan(lan_ifname, atoi(value)); 961 } 962 if (nvram_get_int("lan_dnsenable_x") && (value = getenv("dns"))) 963 nvram_set("lan_dns", trim_r(value)); 964 965#if defined(RTCONFIG_TR069) && defined(RTCONFIG_TR181) 966 nvram_unset("vivso"); 967 if ((value = hex2bin(getenv("opt125"), &size))) { 968 struct viopt_hdr *viopt; 969 struct opt_hdr *oui, *serial, *class; 970 if ((viopt = viopt_get(value, size, htonl(3561))) && 971 (oui = opt_get(viopt->data, viopt->len, 4)) && 972 (serial = opt_get(viopt->data, viopt->len, 5))) { 973 char vivso[6 + 64 + 64 + 3]; 974 char *ptr = vivso; 975 char *end = ptr + sizeof(vivso); 976 ptr += snprintf(ptr, end - ptr, "%s,", stropt(oui, tmp)); 977 ptr += snprintf(ptr, end - ptr, "%s,", stropt(serial, tmp)); 978 if ((class = opt_get(viopt->data, viopt->len, 6))) 979 ptr += snprintf(ptr, end - ptr, "%s", stropt(class, tmp)); 980 nvram_set("vivso", vivso); 981 } 982 free(value); 983 } 984#endif 985 986_dprintf("%s: IFUP.\n", __FUNCTION__); 987#ifdef RTCONFIG_WIRELESSREPEATER 988 if(nvram_get_int("sw_mode") == SW_MODE_REPEATER && nvram_get_int("wlc_mode") == 0){ 989 update_lan_state(LAN_STATE_CONNECTED, 0); 990 _dprintf("done\n"); 991 return 0; 992 } 993#endif 994 995#ifdef RTCONFIG_DHCP_OVERRIDE 996 if (nvram_get_int("sw_mode") == SW_MODE_AP && nvram_match("dnsqmode", "2")) { 997 nvram_set("dnsqmode", "1"); 998 restart_dnsmasq(1); 999 } 1000#endif 1001 1002 ifconfig(lan_ifname, IFUP | IFF_ALLMULTI, nvram_safe_get("lan_ipaddr"), 1003 nvram_safe_get("lan_netmask")); 1004 1005 lan_up(lan_ifname); 1006 1007 _dprintf("done\n"); 1008 return 0; 1009} 1010 1011/* 1012 * renew: This argument is used when a DHCP lease is renewed. All of 1013 * the paramaters are set in enviromental variables. This argument is 1014 * used when the interface is already configured, so the IP address, 1015 * will not change, however, the other DHCP paramaters, such as the 1016 * default gateway, subnet mask, and dns server may change. 1017 */ 1018static int 1019renew_lan(void) 1020{ 1021 bound_lan(); 1022 1023 _dprintf("done\n"); 1024 return 0; 1025} 1026 1027/* dhcp client script entry for LAN (AP) */ 1028int 1029udhcpc_lan(int argc, char **argv) 1030{ 1031 _dprintf("%s:: %s\n", __FUNCTION__, argv[1] ? : ""); 1032 if (!argv[1]) 1033 return EINVAL; 1034 else if (strstr(argv[1], "deconfig")) 1035 return deconfig_lan(); 1036 else if (strstr(argv[1], "bound")) 1037 return bound_lan(); 1038 else if (strstr(argv[1], "renew")) 1039 return renew_lan(); 1040/* else if (strstr(argv[1], "leasefail")) */ 1041/* else if (strstr(argv[1], "nak")) */ 1042 1043 return EINVAL; 1044} 1045 1046// ----------------------------------------------------------------------------- 1047 1048#ifdef RTCONFIG_IPV6 1049static int 1050deconfig6(char *wan_ifname) 1051{ 1052 char *lan_ifname = nvram_safe_get("lan_ifname"); 1053 1054 if (nvram_invmatch(ipv6_nvname("ipv6_wan_addr"), "")) { 1055 eval("ip", "-6", "addr", "del", nvram_safe_get(ipv6_nvname("ipv6_wan_addr")), "dev", wan_ifname); 1056 nvram_set(ipv6_nvname("ipv6_wan_addr"), ""); 1057 } 1058 1059 if (get_ipv6_service() == IPV6_NATIVE_DHCP && 1060 nvram_get_int(ipv6_nvname("ipv6_dhcp_pd"))) { 1061 if (nvram_invmatch(ipv6_nvname("ipv6_prefix"), "") || 1062 nvram_get_int(ipv6_nvname("ipv6_prefix_length")) != 0) { 1063 eval("ip", "-6", "addr", "flush", "scope", "global", "dev", lan_ifname); 1064 nvram_set(ipv6_nvname("ipv6_rtr_addr"), ""); 1065 nvram_set(ipv6_nvname("ipv6_prefix"), ""); 1066 nvram_set(ipv6_nvname("ipv6_prefix_length"), ""); 1067 } 1068 } 1069 1070 if (nvram_invmatch(ipv6_nvname("ipv6_get_dns"), "") || 1071 nvram_invmatch(ipv6_nvname("ipv6_get_domain"), "")) { 1072 nvram_set(ipv6_nvname("ipv6_get_dns"), ""); 1073 nvram_set(ipv6_nvname("ipv6_get_domain"), ""); 1074 if (nvram_get_int(ipv6_nvname("ipv6_dnsenable"))) 1075 update_resolvconf(); 1076#ifdef RTCONFIG_6RELAYD 1077 if (get_ipv6_service() == IPV6_PASSTHROUGH) 1078 stop_6relayd(); 1079#endif 1080 } 1081 1082 return 0; 1083} 1084 1085static int 1086bound6(char *wan_ifname, int bound) 1087{ 1088 char *lan_ifname = nvram_safe_get("lan_ifname"); 1089 struct in6_addr range; 1090 char addr[INET6_ADDRSTRLEN + 1], *value; 1091 char tmp[100], *next; 1092 int wanaddr_changed, prefix_changed, dns_changed; 1093 int size, start, end, intval; 1094 1095 value = safe_getenv("RA_HOPLIMIT"); 1096 if (*value && (intval = atoi(value))) 1097 ipv6_sysconf(wan_ifname, "hop_limit", intval); 1098 1099 value = safe_getenv("RA_MTU"); 1100 if (*value && (intval = atoi(value)) && intval < ifconfig_mtu(wan_ifname, 0)) { 1101 ipv6_sysconf(wan_ifname, "mtu", intval); 1102 ipv6_sysconf(lan_ifname, "mtu", intval); 1103 } else if ((intval = ipv6_getconf(wan_ifname, "mtu"))) 1104 ipv6_sysconf(lan_ifname, "mtu", intval); 1105 1106 value = safe_getenv("ADDRESSES"); 1107 if (*value) { 1108 foreach(tmp, value, next) { 1109 char *ptr = tmp; 1110 value = strsep(&ptr,","); 1111 break; /* only first address at the moment */ 1112 } 1113 } 1114 wanaddr_changed = !nvram_match(ipv6_nvname("ipv6_wan_addr"), value); 1115 if (wanaddr_changed) { 1116 if (nvram_invmatch(ipv6_nvname("ipv6_wan_addr"), "")) 1117 eval("ip", "-6", "addr", "del", nvram_safe_get(ipv6_nvname("ipv6_wan_addr")), "dev", wan_ifname); 1118 nvram_set(ipv6_nvname("ipv6_wan_addr"), value); 1119 } 1120 if (*value) 1121 eval("ip", "-6", "addr", "add", value, "dev", wan_ifname); 1122 1123 prefix_changed = 0; 1124 if (get_ipv6_service() == IPV6_NATIVE_DHCP && 1125 nvram_get_int(ipv6_nvname("ipv6_dhcp_pd"))) { 1126 value = safe_getenv("PREFIXES"); 1127 if (*value) { 1128 foreach(tmp, value, next) { 1129 char *ptr = tmp; 1130 value = strsep(&ptr,","); 1131 break; /* only first prefix at the moment */ 1132 } 1133 } 1134 if (sscanf(value, "%[^/]/%d", addr, &size) != 2) 1135 goto skip; 1136 1137 prefix_changed = (!nvram_match(ipv6_nvname("ipv6_prefix"), addr) || 1138 nvram_get_int(ipv6_nvname("ipv6_prefix_length")) != size); 1139 if (prefix_changed) { 1140 eval("ip", "-6", "addr", "flush", "scope", "global", "dev", lan_ifname); 1141 nvram_set(ipv6_nvname("ipv6_rtr_addr"), ""); 1142 nvram_set(ipv6_nvname("ipv6_prefix"), addr); 1143 nvram_set_int(ipv6_nvname("ipv6_prefix_length"), size); 1144 } 1145 if (*addr) 1146 add_ip6_lanaddr(); 1147 1148 if (prefix_changed && nvram_get_int(ipv6_nvname("ipv6_autoconf_type"))) { 1149 /* TODO: rework WEB UI to specify ranges without prefix 1150 * TODO: add size checking, now range takes all of 16 bit */ 1151 start = (inet_pton(AF_INET6, nvram_safe_get(ipv6_nvname("ipv6_dhcp_start")), &range) > 0) ? 1152 ntohs(range.s6_addr16[7]) : 0x1000; 1153 end = (inet_pton(AF_INET6, nvram_safe_get(ipv6_nvname("ipv6_dhcp_end")), &range) > 0) ? 1154 ntohs(range.s6_addr16[7]) : 0x2000; 1155 1156 value = nvram_safe_get(ipv6_nvname("ipv6_prefix")); 1157 inet_pton(AF_INET6, *value ? value : "::", &range); 1158 1159 range.s6_addr16[7] = (start < end) ? htons(start) : htons(end); 1160 inet_ntop(AF_INET6, &range, addr, sizeof(addr)); 1161 nvram_set(ipv6_nvname("ipv6_dhcp_start"), addr); 1162 range.s6_addr16[7] = (start < end) ? htons(end) : htons(start); 1163 inet_ntop(AF_INET6, &range, addr, sizeof(addr)); 1164 nvram_set(ipv6_nvname("ipv6_dhcp_end"), addr); 1165 } 1166 } 1167skip: 1168 1169 if (*safe_getenv("RDNSS")) { 1170 dns_changed = nvram_set_env(ipv6_nvname("ipv6_get_dns"), "RDNSS"); 1171 dns_changed += nvram_set_env(ipv6_nvname("ipv6_get_domain"), "DOMAINS"); 1172 } else { 1173 dns_changed = nvram_set_env(ipv6_nvname("ipv6_get_dns"), "RA_DNS"); 1174 dns_changed += nvram_set_env(ipv6_nvname("ipv6_get_domain"), "RA_DOMAINS"); 1175 } 1176 if (dns_changed && nvram_get_int(ipv6_nvname("ipv6_dnsenable"))) 1177 update_resolvconf(); 1178 1179#ifdef RTCONFIG_6RELAYD 1180 if (dns_changed && get_ipv6_service() == IPV6_PASSTHROUGH) 1181 start_6relayd(); 1182#endif 1183 1184 if (bound == 1 || wanaddr_changed || prefix_changed) { 1185 char *address = nvram_safe_get(ipv6_nvname("ipv6_wan_addr")); 1186 char *prefix = nvram_safe_get(ipv6_nvname("ipv6_prefix")); 1187 1188 if (*prefix) { 1189 snprintf(addr, sizeof(addr), "%s/%d", prefix, nvram_get_int(ipv6_nvname("ipv6_prefix_length"))); 1190 prefix = addr; 1191 } 1192 logmessage("dhcp6 client", "%s %s%s%s%s%s", 1193 bound ? "bound" : "informed", 1194 *address ? "address " : "", address, *address ? ", " : "", 1195 *prefix ? "prefix " : "", prefix); 1196 } 1197 1198 return 0; 1199} 1200 1201static int 1202ra_updated6(char *wan_ifname) 1203{ 1204 char *lan_ifname = nvram_safe_get("lan_ifname"); 1205 char *value; 1206 int dns_changed, intval; 1207 1208 value = safe_getenv("RA_HOPLIMIT"); 1209 if (*value && (intval = atoi(value))) 1210 ipv6_sysconf(wan_ifname, "hop_limit", intval); 1211 1212 value = safe_getenv("RA_MTU"); 1213 if (*value && (intval = atoi(value)) && intval < ifconfig_mtu(wan_ifname, 0)) { 1214 ipv6_sysconf(wan_ifname, "mtu", intval); 1215 ipv6_sysconf(lan_ifname, "mtu", intval); 1216 } 1217 1218 if (*safe_getenv("RDNSS")) { 1219 dns_changed = nvram_set_env(ipv6_nvname("ipv6_get_dns"), "RDNSS"); 1220 dns_changed += nvram_set_env(ipv6_nvname("ipv6_get_domain"), "DOMAINS"); 1221 } else { 1222 dns_changed = nvram_set_env(ipv6_nvname("ipv6_get_dns"), "RA_DNS"); 1223 dns_changed += nvram_set_env(ipv6_nvname("ipv6_get_domain"), "RA_DOMAINS"); 1224 } 1225 if (dns_changed && nvram_get_int(ipv6_nvname("ipv6_dnsenable"))) 1226 update_resolvconf(); 1227 1228#ifdef RTCONFIG_6RELAYD 1229 if (dns_changed && get_ipv6_service() == IPV6_PASSTHROUGH) 1230 start_6relayd(); 1231#endif 1232 1233 return 0; 1234} 1235 1236int dhcp6c_wan(int argc, char **argv) 1237{ 1238 if (!argv[1] || !argv[2]) 1239 return EINVAL; 1240 else if (strcmp(argv[2], "started") == 0 || 1241 strcmp(argv[2], "stopped") == 0 || 1242 strcmp(argv[2], "unbound") == 0) 1243 return deconfig6(argv[1]); 1244 else if (strcmp(argv[2], "bound") == 0) 1245 return bound6(argv[1], 1); 1246 else if (strcmp(argv[2], "updated") == 0 || 1247 strcmp(argv[2], "rebound") == 0) 1248 return bound6(argv[1], 2); 1249 else if (strcmp(argv[2], "informed") == 0) 1250 return bound6(argv[1], 0); 1251 else if (strcmp(argv[2], "ra-updated") == 0) 1252 return ra_updated6(argv[2]); 1253 1254 return 0; 1255} 1256 1257int 1258start_dhcp6c(void) 1259{ 1260 char *wan_ifname = (char *) get_wan6face(); 1261 char *dhcp6c_argv[] = { "odhcp6c", 1262#ifndef RTCONFIG_BCMARM 1263 "-f", 1264#else 1265 "-df", 1266#endif 1267 "-R", 1268 "-s", "/tmp/dhcp6c", 1269 "-N", "try", 1270 NULL, NULL, /* -c duid */ 1271 NULL, NULL, /* -FP len:iaidhex */ 1272 NULL, NULL, /* -rdns -rdomain */ 1273 NULL, NULL, /* -rsolmaxrt -r infmaxrt */ 1274 NULL, /* -v */ 1275 NULL, /* interface */ 1276 NULL }; 1277 int index = 7; 1278 struct duid duid; 1279 char duid_arg[sizeof(duid)*2+1]; 1280 char prefix_arg[sizeof("128:xxxxxxxx")]; 1281 int i; 1282#ifndef RTCONFIG_BCMARM 1283 pid_t pid; 1284#endif 1285 1286 /* Check if enabled */ 1287 if (get_ipv6_service() != IPV6_NATIVE_DHCP 1288#ifdef RTCONFIG_6RELAYD 1289 && get_ipv6_service() != IPV6_PASSTHROUGH 1290#endif 1291 ) 1292 return 0; 1293 1294 if (!wan_ifname || *wan_ifname == '\0') 1295 return -1; 1296 1297#ifdef RTCONFIG_6RELAYD 1298 stop_6relayd(); 1299#endif 1300 stop_dhcp6c(); 1301 1302 if (get_duid(&duid)) { 1303 bin2hex(duid_arg, sizeof(duid_arg), &duid, sizeof(duid)); 1304 dhcp6c_argv[index++] = "-c"; 1305 dhcp6c_argv[index++] = duid_arg; 1306 } 1307 1308 if (get_ipv6_service() == IPV6_NATIVE_DHCP && 1309 nvram_get_int(ipv6_nvname("ipv6_dhcp_pd"))) { 1310 /* Generate IA_PD IAID from the last 7 digits of WAN MAC */ 1311 unsigned long iaid = ether_atoe(nvram_safe_get("wan0_hwaddr"), duid.ea) ? 1312 ((unsigned long)(duid.ea[3] & 0x0f) << 16) | 1313 ((unsigned long)(duid.ea[4]) << 8) | 1314 ((unsigned long)(duid.ea[5])) : 1; 1315 i = 64 - (nvram_get_int(ipv6_nvname("ipv6_prefix_length")) ? : 64); 1316 if (i < 0) 1317 i = 0; 1318 snprintf(prefix_arg, sizeof(prefix_arg), "%d:%lx", i, iaid); 1319 dhcp6c_argv[index++] = "-FP"; 1320 dhcp6c_argv[index++] = prefix_arg; 1321 } 1322 1323 if (nvram_get_int(ipv6_nvname("ipv6_dnsenable")) 1324#ifdef RTCONFIG_6RELAYD 1325 || get_ipv6_service() == IPV6_PASSTHROUGH 1326#endif 1327 ) { 1328 dhcp6c_argv[index++] = "-r23"; /* dns */ 1329 dhcp6c_argv[index++] = "-r24"; /* domain */ 1330 } 1331 dhcp6c_argv[index++] = "-r82"; /* sol_max_rt */ 1332 dhcp6c_argv[index++] = "-r83"; /* inf_max_rt */ 1333 1334 if (nvram_get_int("ipv6_debug")) 1335 dhcp6c_argv[index++] = "-v"; 1336 1337 dhcp6c_argv[index++] = wan_ifname; 1338 1339#ifndef RTCONFIG_BCMARM 1340 return _eval(dhcp6c_argv, NULL, 0, &pid); 1341#else 1342 return _eval(dhcp6c_argv, NULL, 0, NULL); 1343#endif 1344} 1345 1346void stop_dhcp6c(void) 1347{ 1348 killall_tk("odhcp6c"); 1349} 1350#endif // RTCONFIG_IPV6 1351