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);
133 static int bound(char *ifname
, int renew
);
135 static int renew(char *ifname
)
138 int changed
= 0, routes_changed
= 0;
139 int wan_proto
= get_wan_proto();
145 if (env2nv("ip", "wan_ipaddr") ||
146 env2nv_gateway("wan_gateway") ||
147 (wan_proto
== WP_DHCP
&& env2nv("subnet", "wan_netmask"))) {
148 /* WAN IP or gateway changed, restart/reconfigure everything */
150 return bound(ifname
, 1);
153 if (wan_proto
== WP_DHCP
) {
154 changed
|= env2nv("domain", "wan_get_domain");
155 changed
|= env2nv("dns", "wan_get_dns");
158 nvram_set("wan_routes1_save", nvram_safe_get("wan_routes1"));
159 nvram_set("wan_routes2_save", nvram_safe_get("wan_routes2"));
161 /* Classless Static Routes (option 121) or MS Classless Static Routes (option 249) */
162 if (getenv("staticroutes"))
163 routes_changed
|= env2nv("staticroutes", "wan_routes1_save");
165 routes_changed
|= env2nv("msstaticroutes", "wan_routes1_save");
166 /* Static Routes (option 33) */
167 routes_changed
|= env2nv("routes", "wan_routes2_save");
169 changed
|= routes_changed
;
171 if ((a
= getenv("lease")) != NULL
) {
172 nvram_set("wan_lease", a
);
177 set_host_domain_name();
178 start_dnsmasq(); // (re)start
181 if (routes_changed
) {
182 do_wan_routes(ifname
, 0, 0);
183 nvram_set("wan_routes1", nvram_safe_get("wan_routes1_save"));
184 nvram_set("wan_routes2", nvram_safe_get("wan_routes2_save"));
185 do_wan_routes(ifname
, 0, 1);
187 nvram_unset("wan_routes1_save");
188 nvram_unset("wan_routes2_save");
190 TRACE_PT("wan_ipaddr=%s\n", nvram_safe_get("wan_ipaddr"));
191 TRACE_PT("wan_netmask=%s\n", nvram_safe_get("wan_netmask"));
192 TRACE_PT("wan_gateway=%s\n", nvram_safe_get("wan_gateway"));
193 TRACE_PT("wan_get_domain=%s\n", nvram_safe_get("wan_get_domain"));
194 TRACE_PT("wan_get_dns=%s\n", nvram_safe_get("wan_get_dns"));
195 TRACE_PT("wan_lease=%s\n", nvram_safe_get("wan_lease"));
196 TRACE_PT("wan_routes1=%s\n", nvram_safe_get("wan_routes1"));
197 TRACE_PT("wan_routes2=%s\n", nvram_safe_get("wan_routes2"));
202 static int bound(char *ifname
, int renew
)
209 int wan_proto
= get_wan_proto();
211 dns
= nvram_safe_get("wan_get_dns");
212 nvram_set("wan_routes1", "");
213 nvram_set("wan_routes2", "");
214 env2nv("ip", "wan_ipaddr");
215 env2nv_gateway("wan_gateway");
216 env2nv("dns", "wan_get_dns");
217 env2nv("domain", "wan_get_domain");
218 env2nv("lease", "wan_lease");
219 netmask
= getenv("subnet") ? : "255.255.255.255";
220 if (wan_proto
== WP_DHCP
) {
221 nvram_set("wan_netmask", netmask
);
222 nvram_set("wan_gateway_get", nvram_safe_get("wan_gateway"));
225 /* RFC3442: If the DHCP server returns both a Classless Static Routes option
226 * and a Router option, the DHCP client MUST ignore the Router option.
227 * Similarly, if the DHCP server returns both a Classless Static Routes
228 * option and a Static Routes option, the DHCP client MUST ignore the
229 * Static Routes option.
230 * Ref: http://www.faqs.org/rfcs/rfc3442.html
232 /* Classless Static Routes (option 121) */
233 if (!env2nv("staticroutes", "wan_routes1"))
234 /* or MS Classless Static Routes (option 249) */
235 env2nv("msstaticroutes", "wan_routes1");
236 /* Static Routes (option 33) */
237 env2nv("routes", "wan_routes2");
239 expires(atoi(safe_getenv("lease")));
241 TRACE_PT("wan_ipaddr=%s\n", nvram_safe_get("wan_ipaddr"));
242 TRACE_PT("wan_netmask=%s\n", netmask
);
243 TRACE_PT("wan_gateway=%s\n", nvram_safe_get("wan_gateway"));
244 TRACE_PT("wan_get_domain=%s\n", nvram_safe_get("wan_get_domain"));
245 TRACE_PT("wan_get_dns=%s\n", nvram_safe_get("wan_get_dns"));
246 TRACE_PT("wan_lease=%s\n", nvram_safe_get("wan_lease"));
247 TRACE_PT("wan_routes1=%s\n", nvram_safe_get("wan_routes1"));
248 TRACE_PT("wan_routes2=%s\n", nvram_safe_get("wan_routes2"));
250 ifconfig(ifname
, IFUP
, "0.0.0.0", NULL
);
251 ifconfig(ifname
, IFUP
, nvram_safe_get("wan_ipaddr"), netmask
);
253 if (wan_proto
!= WP_DHCP
) {
254 char *gw
= nvram_safe_get("wan_gateway");
256 preset_wan(ifname
, gw
, netmask
);
258 /* clear dns from the resolv.conf */
259 nvram_set("wan_get_dns", renew
? dns
: "");
271 start_wan_done(ifname
);
278 int dhcpc_event_main(int argc
, char **argv
)
282 if (!wait_action_idle(10)) return 1;
284 if ((argc
== 2) && (ifname
= getenv("interface")) != NULL
) {
285 TRACE_PT("event=%s\n", argv
[1]);
287 if (strcmp(argv
[1], "deconfig") == 0) return deconfig(ifname
);
288 if (strcmp(argv
[1], "bound") == 0) return bound(ifname
, 0);
289 if ((strcmp(argv
[1], "renew") == 0) || (strcmp(argv
[1], "update") == 0)) return renew(ifname
);
296 // -----------------------------------------------------------------------------
299 int dhcpc_release_main(int argc
, char **argv
)
303 if (!using_dhcpc()) return 1;
305 if (killall("udhcpc", SIGUSR2
) == 0) {
310 unlink("/var/lib/misc/wan.connecting");
316 int dhcpc_renew_main(int argc
, char **argv
)
322 if (!using_dhcpc()) return 1;
324 if ((pid
= pidof("udhcpc")) > 1) {
326 f_write(renewing
, NULL
, 0, 0, 0);
338 // -----------------------------------------------------------------------------
341 void start_dhcpc(void)
350 nvram_set("wan_get_dns", "");
351 f_write(renewing
, NULL
, 0, 0, 0);
353 ifname
= nvram_safe_get("wan_ifname");
354 proto
= get_wan_proto();
355 if (proto
== WP_DHCP
) {
356 nvram_set("wan_iface", ifname
);
359 #if 1 // REMOVEME after 1/1/2012
360 // temporary code for compatibility with old nvram variables
362 strcpy(cmd
, nvram_safe_get("dhcpc_custom"));
363 if (strstr(cmd
, "-V ") == NULL
) {
364 if ((p
= nvram_get("dhcpc_vendorclass")) && (*p
)) {
370 if (strstr(cmd
, "-r ") == NULL
) {
371 if ((p
= nvram_get("dhcpc_requestip")) && (*p
) && (strcmp(p
, "0.0.0.0") != 0)) {
378 nvram_set("dhcpc_custom", cmd
);
382 snprintf(cmd
, sizeof(cmd
),
383 "udhcpc -i %s -b -s dhcpc-event %s %s %s %s %s",
385 nvram_invmatch("wan_hostname", "") ? "-H" : "", nvram_safe_get("wan_hostname"),
386 nvram_get_int("dhcpc_minpkt") ? "-m" : "",
387 nvram_contains_word("log_events", "dhcpc") ? "-S" : "",
388 nvram_safe_get("dhcpc_custom"));
390 xstart("/bin/sh", "-c", cmd
);
395 void stop_dhcpc(void)
399 killall("dhcpc-event", SIGTERM
);
400 if (killall("udhcpc", SIGUSR2
) == 0) { // release
403 killall_tk("udhcpc");
409 // -----------------------------------------------------------------------------
413 int dhcp6c_state_main(int argc
, char **argv
)
415 char prefix
[INET6_ADDRSTRLEN
];
416 struct in6_addr addr
;
421 if (!wait_action_idle(10)) return 1;
423 nvram_set("ipv6_rtr_addr", getifaddr(nvram_safe_get("lan_ifname"), AF_INET6
));
425 // extract prefix from configured IPv6 address
426 if (inet_pton(AF_INET6
, nvram_safe_get("ipv6_rtr_addr"), &addr
) > 0) {
427 r
= nvram_get_int("ipv6_prefix_length") ? : 64;
428 for (r
= 128 - r
, i
= 15; r
> 0; r
-= 8) {
430 addr
.s6_addr
[i
--] = 0;
432 addr
.s6_addr
[i
--] &= (0xff << r
);
434 inet_ntop(AF_INET6
, &addr
, prefix
, sizeof(prefix
));
435 nvram_set("ipv6_prefix", prefix
);
438 if (env2nv("new_domain_name_servers", "ipv6_get_dns")) {
440 start_dnsmasq(); // (re)start
443 // notify radvd of possible change
444 killall("radvd", SIGHUP
);
446 TRACE_PT("ipv6_get_dns=%s\n", nvram_safe_get("ipv6_get_dns"));
451 void start_dhcp6c(void)
456 char *argv
[] = { "dhcp6c", NULL
, NULL
, NULL
};
461 // Check if turned on
462 if (get_ipv6_service() != IPV6_NATIVE_DHCP
) return;
464 prefix_len
= 64 - (nvram_get_int("ipv6_prefix_length") ? : 64);
467 wan6face
= nvram_safe_get("wan_iface");
469 nvram_set("ipv6_get_dns", "");
470 nvram_set("ipv6_rtr_addr", "");
471 nvram_set("ipv6_prefix", "");
473 // Create dhcp6c.conf
474 if ((f
= fopen("/etc/dhcp6c.conf", "w"))) {
478 " send rapid-commit;\n"
479 " request domain-name-servers;\n"
480 " script \"/sbin/dhcp6c-state\";\n"
483 " prefix-interface lo {\n"
487 " prefix-interface %s {\n"
494 nvram_safe_get("lan_ifname"),
500 if (nvram_get_int("debug_ipv6"))
502 argv
[argc
++] = wan6face
;
504 _eval(argv
, NULL
, 0, NULL
);
509 void stop_dhcp6c(void)
513 killall("dhcp6c-event", SIGTERM
);
514 killall_tk("dhcp6c");
519 #endif // TCONFIG_IPV6