1/*
2 * ppp 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: ppp.c,v 1.19 2009/12/02 20:07:37 Exp $
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <string.h>
25#include <sys/ioctl.h>
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
29#include <errno.h>
30#include <ctype.h>
31
32#include <bcmnvram.h>
33#include <shutils.h>
34#include <rc.h>
35
36#ifdef RTCONFIG_USB_MODEM
37#include <usb_info.h>
38#endif
39
40/*
41* parse ifname to retrieve unit #
42*/
43int
44ppp_ifunit(char *ifname)
45{
46	int unit;
47	char tmp[100], prefix[] = "wanXXXXXXXXXX_";
48
49	for (unit = WAN_UNIT_FIRST; unit < WAN_UNIT_MAX; unit++) {
50		snprintf(prefix, sizeof(prefix), "wan%d_", unit);
51		if (nvram_match(strcat_r(prefix, "pppoe_ifname", tmp), ifname))
52			return unit;
53	}
54
55	return -1;
56}
57
58int
59ppp_linkunit(char *linkname)
60{
61	if (strncmp(linkname, "wan", 3))
62		return -1;
63	if (!isdigit(linkname[3]))
64		return -1;
65	return atoi(&linkname[3]);
66}
67
68/*
69 * Called when link comes up
70 */
71int
72ipup_main(int argc, char **argv)
73{
74	FILE *fp;
75	char *wan_ifname = safe_getenv("IFNAME");
76	char *wan_linkname = safe_getenv("LINKNAME");
77	char tmp[100], prefix[] = "wanXXXXXXXXXX_";
78	char buf[256], *value;
79	int unit;
80
81	_dprintf("%s():: %s\n", __FUNCTION__, argv[0]);
82
83	/* Get unit from LINKNAME: ppp[UNIT] */
84	if ((unit = ppp_linkunit(wan_linkname)) < 0)
85		return 0;
86
87	_dprintf("%s: unit=%d ifname=%s\n", __FUNCTION__, unit, wan_ifname);
88	snprintf(prefix, sizeof(prefix), "wan%d_", unit);
89
90#ifdef DEBUG_RCTEST // Left for UI debug
91	int max_count = nvram_get_int("ppp_delay_sec");
92	int count;
93	if(max_count > 0){
94		for(count = 1; count <= max_count; ++count){
95			_dprintf("%s: unit=%d ifname=%s sleep %d seconds...\n", __FUNCTION__, unit, wan_ifname, count);
96			sleep(1);
97		}
98	}
99#endif
100
101	/* Stop triggering demand connection */
102	if (nvram_get_int(strcat_r(prefix, "pppoe_demand", tmp)))
103		nvram_set_int(strcat_r(prefix, "pppoe_demand", tmp), 1);
104
105#ifdef RTCONFIG_USB_MODEM
106	// wanX_ifname is used for device for USB Modem
107	if ((value = getenv("DEVICE")) &&
108	    (isSerialNode(value) || isACMNode(value))){
109		nvram_set(strcat_r(prefix, "ifname", tmp), value);
110		nvram_set(strcat_r(prefix, "proto", tmp), "pppoe");
111	}
112#endif
113
114	/* Touch connection file */
115	if (!(fp = fopen(strcat_r("/tmp/ppp/link.", wan_ifname, tmp), "a"))) {
116		perror(tmp);
117		return errno;
118	}
119	fclose(fp);
120
121	if ((value = getenv("IPLOCAL"))) {
122		if (nvram_invmatch(strcat_r(prefix, "ipaddr", tmp), value))
123			ifconfig(wan_ifname, IFUP, "0.0.0.0", NULL);
124		_ifconfig(wan_ifname, IFUP, value, "255.255.255.255", getenv("IPREMOTE"), 0);
125		nvram_set(strcat_r(prefix, "ipaddr", tmp), value);
126		nvram_set(strcat_r(prefix, "netmask", tmp), "255.255.255.255");
127	}
128
129	if ((value = getenv("IPREMOTE")))
130		nvram_set(strcat_r(prefix, "gateway", tmp), value);
131
132	strcpy(buf, "");
133	if ((value = getenv("DNS1")))
134		sprintf(buf, "%s", value);
135	if ((value = getenv("DNS2")))
136		sprintf(buf + strlen(buf), "%s%s", strlen(buf) ? " " : "", value);
137
138	/* empty DNS means they either were not requested or peer refused to send them.
139	 * for this case static DNS can be used, if they are configured */
140	if (strlen(buf) == 0 && !nvram_get_int(strcat_r(prefix, "dnsenable_x", tmp))) {
141		value = nvram_safe_get(strcat_r(prefix, "dns1_x", tmp));
142		if (*value && inet_addr_(value) != INADDR_ANY)
143			sprintf(buf, "%s", value);
144		value = nvram_safe_get(strcat_r(prefix, "dns2_x", tmp));
145		if (*value && inet_addr_(value) != INADDR_ANY)
146			sprintf(buf + strlen(buf), "%s%s", *buf ? " " : "", value);
147	}
148
149	nvram_set(strcat_r(prefix, "dns", tmp), buf);
150
151	wan_up(wan_ifname);
152
153	_dprintf("%s:: done\n", __FUNCTION__);
154	return 0;
155}
156
157/*
158 * Called when link goes down
159 */
160int
161ipdown_main(int argc, char **argv)
162{
163	char *wan_ifname = safe_getenv("IFNAME");
164	char *wan_linkname = safe_getenv("LINKNAME");
165	char tmp[100], prefix[] = "wanXXXXXXXXXX_";
166	int unit;
167
168	_dprintf("%s():: %s\n", __FUNCTION__, argv[0]);
169
170	/* Get unit from LINKNAME: ppp[UNIT] */
171	if ((unit = ppp_linkunit(wan_linkname)) < 0)
172		return 0;
173
174	_dprintf("%s: unit=%d ifname=%s\n", __FUNCTION__, unit, wan_ifname);
175	snprintf(prefix, sizeof(prefix), "wan%d_", unit);
176
177	wan_down(wan_ifname);
178
179	// override wan_state to get real reason
180	update_wan_state(prefix, WAN_STATE_STOPPED, pppstatus());
181
182	unlink(strcat_r("/tmp/ppp/link.", wan_ifname, tmp));
183
184	preset_wan_routes(wan_ifname);
185
186	_dprintf("%s:: done\n", __FUNCTION__);
187	return 0;
188}
189
190/*
191 * Called when interface comes up
192 */
193int
194ippreup_main(int argc, char **argv)
195{
196	char *wan_ifname = safe_getenv("IFNAME");
197	char *wan_linkname = safe_getenv("LINKNAME");
198	char tmp[100], prefix[] = "wanXXXXXXXXXX_";
199	int unit;
200
201	_dprintf("%s():: %s\n", __FUNCTION__, argv[0]);
202
203	/* Get unit from LINKNAME: ppp[UNIT] */
204	if ((unit = ppp_linkunit(wan_linkname)) < 0)
205		return 0;
206
207	_dprintf("%s: unit=%d ifname=%s\n", __FUNCTION__, unit, wan_ifname);
208	snprintf(prefix, sizeof(prefix), "wan%d_", unit);
209
210	/* Set wanX_pppoe_ifname to real interface name */
211	nvram_set(strcat_r(prefix, "pppoe_ifname", tmp), wan_ifname);
212
213	/* Start triggering demand connection */
214	if (nvram_get_int(strcat_r(prefix, "pppoe_demand", tmp)))
215		nvram_set_int(strcat_r(prefix, "pppoe_demand", tmp), 2);
216
217	_dprintf("%s:: done\n", __FUNCTION__);
218	return 0;
219}
220
221#ifdef RTCONFIG_IPV6
222int ip6up_main(int argc, char **argv)
223{
224	char *wan_ifname = safe_getenv("IFNAME");
225	char *wan_linkname = safe_getenv("LINKNAME");
226	char tmp[100], prefix[] = "wanXXXXXXXXXX_";
227	int unit;
228
229	if (!wan_ifname || strlen(wan_ifname) <= 0)
230		return 0;
231
232	/* Get unit from LINKNAME: ppp[UNIT] */
233	if ((unit = ppp_linkunit(wan_linkname)) < 0)
234		return 0;
235
236	_dprintf("%s: unit=%d ifname=%s\n", __FUNCTION__, unit, wan_ifname);
237	snprintf(prefix, sizeof(prefix), "wan%d_", unit);
238
239	/* share the same interface with pppoe ipv4 connection */
240	nvram_set(strcat_r(prefix, "pppoe_ifname", tmp), wan_ifname);
241
242	wan6_up(wan_ifname);
243
244	return 0;
245}
246
247int ip6down_main(int argc, char **argv)
248{
249	char *wan_ifname = safe_getenv("IFNAME");
250
251	wan6_down(wan_ifname);
252
253	return 0;
254}
255#endif	// IPV6
256
257/*
258 * Called when link closing with auth fail
259 */
260int
261authfail_main(int argc, char **argv)
262{
263	char *wan_ifname = safe_getenv("IFNAME");
264	char *wan_linkname = safe_getenv("LINKNAME");
265	char tmp[100], prefix[] = "wanXXXXXXXXXX_";
266	int unit;
267
268	_dprintf("%s():: %s\n", __FUNCTION__, argv[0]);
269
270	/* Get unit from LINKNAME: ppp[UNIT] */
271	if ((unit = ppp_linkunit(wan_linkname)) < 0)
272		return 0;
273
274	_dprintf("%s: unit=%d ifname=%s\n", __FUNCTION__, unit, wan_ifname);
275	snprintf(prefix, sizeof(prefix), "wan%d_", unit);
276
277	/* Stop triggering demand connection */
278	if (nvram_get_int(strcat_r(prefix, "pppoe_demand", tmp)))
279		nvram_set_int(strcat_r(prefix, "pppoe_demand", tmp), 1);
280
281	// override wan_state
282	update_wan_state(prefix, WAN_STATE_STOPPED, WAN_STOPPED_REASON_PPP_AUTH_FAIL);
283
284	_dprintf("%s:: done\n", __FUNCTION__);
285	return 0;
286}
287