3 Copyright 2003, CyberTAN Inc. All Rights Reserved
5 This is UNPUBLISHED PROPRIETARY SOURCE CODE of CyberTAN Inc.
6 the contents of this file may not be disclosed to third parties,
7 copied or duplicated in any form without the prior written
8 permission of CyberTAN Inc.
10 This software should be used as a reference only, and it not
11 intended for production use!
13 THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY
14 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN
15 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
16 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
21 Copyright 2005, Broadcom Corporation
24 THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
25 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
26 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
27 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
32 Modified for Tomato Firmware
33 Portions, Copyright (C) 2006-2009 Jonathan Zarate
39 #include <sys/sysinfo.h>
40 #include <sys/ioctl.h>
41 #include <arpa/inet.h>
43 static void expires(unsigned int seconds
)
49 sprintf(s
, "%u", (unsigned int)info
.uptime
+ seconds
);
50 f_write_string("/var/lib/misc/dhcpc.expires", s
, 0, 0);
54 // returns 1 if new/changed, 0 if not changed/no env
55 static int env2nv(char *env
, char *nv
)
58 if ((value
= getenv(env
)) != NULL
) {
59 if (!nvram_match(nv
, value
)) {
67 static int env2nv_gateway(const char *nv
)
74 if ((v
= getenv("router")) != NULL
) {
75 if ((b
= strdup(v
)) != NULL
) {
76 if ((v
= strchr(b
, ' ')) != NULL
) *v
= 0; // truncate multiple entries
77 if (!nvram_match((char *)nv
, b
)) {
84 else if ((v
= getenv("staticroutes")) != NULL
) {
85 if ((b
= strdup(v
)) == NULL
) return 0;
87 while ((g
= strsep(&v
, " ")) != NULL
) {
88 if (strcmp(g
, "0.0.0.0/0") == 0) {
89 if ((g
= strsep(&v
, " ")) && *g
) {
90 if (!nvram_match((char *)nv
, g
)) {
104 static const char renewing
[] = "/var/lib/misc/dhcpc.renewing";
106 static int deconfig(char *ifname
)
110 ifconfig(ifname
, IFUP
, "0.0.0.0", NULL
);
113 nvram_set("wan_ipaddr", "0.0.0.0");
114 nvram_set("wan_gateway", "0.0.0.0");
116 nvram_set("wan_lease", "0");
117 nvram_set("wan_routes1", "");
118 nvram_set("wan_routes2", "");
121 if (get_wan_proto() == WP_DHCP
) {
122 nvram_set("wan_netmask", "0.0.0.0");
123 nvram_set("wan_gateway_get", "0.0.0.0");
124 nvram_set("wan_get_dns", "");
127 // route_del(ifname, 0, NULL, NULL, NULL);
130 nvram_set("wan_6rd", "");
137 static int bound(char *ifname
, int renew
);
139 static int renew(char *ifname
)
142 int changed
= 0, routes_changed
= 0;
143 int wan_proto
= get_wan_proto();
149 if (env2nv("ip", "wan_ipaddr") ||
150 env2nv_gateway("wan_gateway") ||
151 (wan_proto
== WP_DHCP
&& env2nv("subnet", "wan_netmask"))) {
152 /* WAN IP or gateway changed, restart/reconfigure everything */
154 return bound(ifname
, 1);
157 if (wan_proto
== WP_DHCP
) {
158 changed
|= env2nv("domain", "wan_get_domain");
159 changed
|= env2nv("dns", "wan_get_dns");
162 nvram_set("wan_routes1_save", nvram_safe_get("wan_routes1"));
163 nvram_set("wan_routes2_save", nvram_safe_get("wan_routes2"));
165 /* Classless Static Routes (option 121) or MS Classless Static Routes (option 249) */
166 if (getenv("staticroutes"))
167 routes_changed
|= env2nv("staticroutes", "wan_routes1_save");
169 routes_changed
|= env2nv("msstaticroutes", "wan_routes1_save");
170 /* Static Routes (option 33) */
171 routes_changed
|= env2nv("routes", "wan_routes2_save");
173 changed
|= routes_changed
;
175 if ((a
= getenv("lease")) != NULL
) {
176 nvram_set("wan_lease", a
);
181 set_host_domain_name();
182 start_dnsmasq(); // (re)start
185 if (routes_changed
) {
186 do_wan_routes(ifname
, 0, 0);
187 nvram_set("wan_routes1", nvram_safe_get("wan_routes1_save"));
188 nvram_set("wan_routes2", nvram_safe_get("wan_routes2_save"));
189 do_wan_routes(ifname
, 0, 1);
191 nvram_unset("wan_routes1_save");
192 nvram_unset("wan_routes2_save");
194 TRACE_PT("wan_ipaddr=%s\n", nvram_safe_get("wan_ipaddr"));
195 TRACE_PT("wan_netmask=%s\n", nvram_safe_get("wan_netmask"));
196 TRACE_PT("wan_gateway=%s\n", nvram_safe_get("wan_gateway"));
197 TRACE_PT("wan_get_domain=%s\n", nvram_safe_get("wan_get_domain"));
198 TRACE_PT("wan_get_dns=%s\n", nvram_safe_get("wan_get_dns"));
199 TRACE_PT("wan_lease=%s\n", nvram_safe_get("wan_lease"));
200 TRACE_PT("wan_routes1=%s\n", nvram_safe_get("wan_routes1"));
201 TRACE_PT("wan_routes2=%s\n", nvram_safe_get("wan_routes2"));
206 static int bound(char *ifname
, int renew
)
213 int wan_proto
= get_wan_proto();
215 dns
= nvram_safe_get("wan_get_dns");
216 nvram_set("wan_routes1", "");
217 nvram_set("wan_routes2", "");
218 env2nv("ip", "wan_ipaddr");
219 env2nv_gateway("wan_gateway");
220 env2nv("dns", "wan_get_dns");
221 env2nv("domain", "wan_get_domain");
222 env2nv("lease", "wan_lease");
223 netmask
= getenv("subnet") ? : "255.255.255.255";
224 if (wan_proto
== WP_DHCP
) {
225 nvram_set("wan_netmask", netmask
);
226 nvram_set("wan_gateway_get", nvram_safe_get("wan_gateway"));
229 /* RFC3442: If the DHCP server returns both a Classless Static Routes option
230 * and a Router option, the DHCP client MUST ignore the Router option.
231 * Similarly, if the DHCP server returns both a Classless Static Routes
232 * option and a Static Routes option, the DHCP client MUST ignore the
233 * Static Routes option.
234 * Ref: http://www.faqs.org/rfcs/rfc3442.html
236 /* Classless Static Routes (option 121) */
237 if (!env2nv("staticroutes", "wan_routes1"))
238 /* or MS Classless Static Routes (option 249) */
239 env2nv("msstaticroutes", "wan_routes1");
240 /* Static Routes (option 33) */
241 env2nv("routes", "wan_routes2");
243 expires(atoi(safe_getenv("lease")));
246 env2nv("6rd", "wan_6rd");
249 TRACE_PT("wan_ipaddr=%s\n", nvram_safe_get("wan_ipaddr"));
250 TRACE_PT("wan_netmask=%s\n", netmask
);
251 TRACE_PT("wan_gateway=%s\n", nvram_safe_get("wan_gateway"));
252 TRACE_PT("wan_get_domain=%s\n", nvram_safe_get("wan_get_domain"));
253 TRACE_PT("wan_get_dns=%s\n", nvram_safe_get("wan_get_dns"));
254 TRACE_PT("wan_lease=%s\n", nvram_safe_get("wan_lease"));
255 TRACE_PT("wan_routes1=%s\n", nvram_safe_get("wan_routes1"));
256 TRACE_PT("wan_routes2=%s\n", nvram_safe_get("wan_routes2"));
258 TRACE_PT("wan_6rd=%s\n", nvram_safe_get("wan_6rd"));
261 ifconfig(ifname
, IFUP
, "0.0.0.0", NULL
);
262 ifconfig(ifname
, IFUP
, nvram_safe_get("wan_ipaddr"), netmask
);
264 if (wan_proto
!= WP_DHCP
) {
265 char *gw
= nvram_safe_get("wan_gateway");
267 preset_wan(ifname
, gw
, netmask
);
269 /* clear dns from the resolv.conf */
270 nvram_set("wan_get_dns", renew
? dns
: "");
282 start_wan_done(ifname
);
289 int dhcpc_event_main(int argc
, char **argv
)
293 if (!wait_action_idle(10)) return 1;
295 if ((argc
== 2) && (ifname
= getenv("interface")) != NULL
) {
296 TRACE_PT("event=%s\n", argv
[1]);
298 if (strcmp(argv
[1], "deconfig") == 0) return deconfig(ifname
);
299 if (strcmp(argv
[1], "bound") == 0) return bound(ifname
, 0);
300 if ((strcmp(argv
[1], "renew") == 0) || (strcmp(argv
[1], "update") == 0)) return renew(ifname
);
307 // -----------------------------------------------------------------------------
310 int dhcpc_release_main(int argc
, char **argv
)
314 if (!using_dhcpc()) return 1;
316 if (killall("udhcpc", SIGUSR2
) == 0) {
321 unlink("/var/lib/misc/wan.connecting");
327 int dhcpc_renew_main(int argc
, char **argv
)
333 if (!using_dhcpc()) return 1;
335 if ((pid
= pidof("udhcpc")) > 1) {
337 f_write(renewing
, NULL
, 0, 0, 0);
349 // -----------------------------------------------------------------------------
352 void start_dhcpc(void)
361 nvram_set("wan_get_dns", "");
362 f_write(renewing
, NULL
, 0, 0, 0);
364 ifname
= nvram_safe_get("wan_ifname");
365 proto
= get_wan_proto();
366 if (proto
== WP_DHCP
) {
367 nvram_set("wan_iface", ifname
);
370 #if 1 // REMOVEME after 1/1/2012
371 // temporary code for compatibility with old nvram variables
373 strcpy(cmd
, nvram_safe_get("dhcpc_custom"));
374 if (strstr(cmd
, "-V ") == NULL
) {
375 if ((p
= nvram_get("dhcpc_vendorclass")) && (*p
)) {
381 if (strstr(cmd
, "-r ") == NULL
) {
382 if ((p
= nvram_get("dhcpc_requestip")) && (*p
) && (strcmp(p
, "0.0.0.0") != 0)) {
389 nvram_set("dhcpc_custom", cmd
);
393 snprintf(cmd
, sizeof(cmd
),
394 "udhcpc -i %s -b -s dhcpc-event %s %s %s %s %s %s",
396 nvram_invmatch("wan_hostname", "") ? "-H" : "", nvram_safe_get("wan_hostname"),
397 nvram_get_int("dhcpc_minpkt") ? "-m" : "",
398 nvram_contains_word("log_events", "dhcpc") ? "-S" : "",
399 nvram_safe_get("dhcpc_custom"),
401 (get_ipv6_service() == IPV6_6RD_DHCP
) ? "-O 6rd" : ""
407 xstart("/bin/sh", "-c", cmd
);
412 void stop_dhcpc(void)
416 killall("dhcpc-event", SIGTERM
);
417 if (killall("udhcpc", SIGUSR2
) == 0) { // release
420 killall_tk("udhcpc");
426 // -----------------------------------------------------------------------------
430 int dhcp6c_state_main(int argc
, char **argv
)
432 char prefix
[INET6_ADDRSTRLEN
];
433 struct in6_addr addr
;
438 if (!wait_action_idle(10)) return 1;
440 nvram_set("ipv6_rtr_addr", getifaddr(nvram_safe_get("lan_ifname"), AF_INET6
, 0));
442 // extract prefix from configured IPv6 address
443 if (inet_pton(AF_INET6
, nvram_safe_get("ipv6_rtr_addr"), &addr
) > 0) {
444 r
= nvram_get_int("ipv6_prefix_length") ? : 64;
445 for (r
= 128 - r
, i
= 15; r
> 0; r
-= 8) {
447 addr
.s6_addr
[i
--] = 0;
449 addr
.s6_addr
[i
--] &= (0xff << r
);
451 inet_ntop(AF_INET6
, &addr
, prefix
, sizeof(prefix
));
452 nvram_set("ipv6_prefix", prefix
);
455 if (env2nv("new_domain_name_servers", "ipv6_get_dns")) {
459 // (re)start dnsmasq and httpd
463 TRACE_PT("ipv6_get_dns=%s\n", nvram_safe_get("ipv6_get_dns"));
468 void start_dhcp6c(void)
473 char *argv
[] = { "dhcp6c", "-T", "LL", NULL
, NULL
, NULL
};
478 // Check if turned on
479 if (get_ipv6_service() != IPV6_NATIVE_DHCP
) return;
481 prefix_len
= 64 - (nvram_get_int("ipv6_prefix_length") ? : 64);
484 wan6face
= nvram_safe_get("wan_iface");
486 nvram_set("ipv6_get_dns", "");
487 nvram_set("ipv6_rtr_addr", "");
488 nvram_set("ipv6_prefix", "");
490 // Create dhcp6c.conf
491 if ((f
= fopen("/etc/dhcp6c.conf", "w"))) {
495 " send rapid-commit;\n"
496 " request domain-name-servers;\n"
497 " script \"/sbin/dhcp6c-state\";\n"
500 " prefix-interface %s {\n"
505 "id-assoc na 0 { };\n",
507 nvram_safe_get("lan_ifname"),
513 if (nvram_get_int("debug_ipv6"))
515 argv
[argc
++] = wan6face
;
517 _eval(argv
, NULL
, 0, NULL
);
522 void stop_dhcp6c(void)
526 killall("dhcp6c-event", SIGTERM
);
527 killall_tk("dhcp6c");
532 #endif // TCONFIG_IPV6