1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 *
17 * Copyright 2004, ASUSTeK Inc.
18 * All Rights Reserved.
19 *
20 * THIS SOFTWARE IS OFFERED "AS IS", AND ASUS GRANTS NO WARRANTIES OF ANY
21 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
22 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
23 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
24 *
25 */
26#include "rc.h"
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <errno.h>
31#include <string.h>
32#include <unistd.h>
33
34#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2)
35#define JFFS_TR_FOLDER		"/jffs/tr"
36#endif
37#define TR_FOLDER			"/tmp/tr"
38#define DEFAULT_TR_XML		"/usr/tr/tr.xml"
39#define TR_XML_FILE			"tr.xml"
40#define TR_XML_BAK_FILE		"tr.xml.bak"
41#define TR_XML_TAR_FILE			"tr.xml.tz"
42#define TR_XML_BAK_TAR_FILE		"tr.xml.bak.tz"
43#define DHCPC_LEASE_LIST	"/tmp/dhcpc_lease_list"
44#define TR_CONFIG_FILE		TR_FOLDER"/tr.conf"
45#define TR_LOG_FILE			TR_FOLDER"/tr.log"
46#define CA_CERT_FILE		TR_FOLDER"/ca.pem"
47#define CLIENT_CERT_FILE	TR_FOLDER"/client.crt"
48#define CLIENT_KEY_FILE		TR_FOLDER"/client.key"
49//#define IPDRDOC_FOLDER		TR_FOLDER"/IPDRDoc"
50
51int generate_tr_config()
52{
53	FILE *fp;
54
55	/* Generate tr configuration file */
56	if (!(fp = fopen(TR_CONFIG_FILE, "w"))) {
57		perror(TR_CONFIG_FILE);
58		return -1;
59	}
60
61	fprintf(fp, "#TCPAddress = 0.0.0.0\n");
62	fprintf(fp, "TCPAddress = :: #or IPv6_Addr\n");
63	fprintf(fp, "TCPChallenge = Basic\n");
64	fprintf(fp, "TCPNotifyInterval = 0\n");
65	fprintf(fp, "UDPAddress = 0.0.0.0\n");
66	fprintf(fp, "UDPPort = 7547\n");
67	fprintf(fp, "UDPNotifyInterval = 20\n");
68	fprintf(fp, "#CLIAddress = 0.0.0.0\n");
69	fprintf(fp, "CLIAddress = ::\n");
70	fprintf(fp, "CLIPort = 1234\n");
71	fprintf(fp, "CLITimeout = 10\n");
72	fprintf(fp, "CLIDocRoot = /usr/tr/doc/html\n");
73	fprintf(fp, "CLIIndex = index.html\n");
74	fprintf(fp, "MaxListener = 3\n");
75	fprintf(fp, "CACert = %s\n", CA_CERT_FILE);
76	fprintf(fp, "ClientCert = %s\n", CLIENT_CERT_FILE);
77	fprintf(fp, "ClientKey = %s\n", CLIENT_KEY_FILE);
78	fprintf(fp, "SSLPassword= password\n");
79	fprintf(fp, "Init = tr.xml\n");
80	//fprintf(fp, "#At the moment, all statis inform parameter MUST be constant value parameter\n");
81#ifdef RTCONFIG_TR181
82	fprintf(fp, "InformParameter = Device.DeviceInfo.SpecVersion\n");
83	fprintf(fp, "InformParameter = Device.DeviceInfo.HardwareVersion\n");
84	fprintf(fp, "InformParameter = Device.DeviceInfo.SoftwareVersion\n");
85	fprintf(fp, "InformParameter = Device.DeviceInfo.ProvisioningCode\n");
86	fprintf(fp, "InformParameter = Device.ManagementServer.ConnectionRequestURL\n");
87	fprintf(fp, "InformParameter = Device.ManagementServer.ParameterKey\n");
88	//fprintf(fp, "#InformParameter = Device.WANDevice.1.WANConnectionDevice.1.WANPPPConnection.1.ExternalIPAddress\n");
89#else	/* TR098 */
90	fprintf(fp, "InformParameter = InternetGatewayDevice.DeviceSummary\n");
91	fprintf(fp, "InformParameter = InternetGatewayDevice.DeviceInfo.SpecVersion\n");
92	fprintf(fp, "InformParameter = InternetGatewayDevice.DeviceInfo.HardwareVersion\n");
93	fprintf(fp, "InformParameter = InternetGatewayDevice.DeviceInfo.SoftwareVersion\n");
94	fprintf(fp, "InformParameter = InternetGatewayDevice.DeviceInfo.ProvisioningCode\n");
95	fprintf(fp, "InformParameter = InternetGatewayDevice.ManagementServer.ConnectionRequestURL\n");
96	fprintf(fp, "InformParameter = InternetGatewayDevice.ManagementServer.ParameterKey\n");
97	//fprintf(fp, "#InformParameter = InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANPPPConnection.1.ExternalIPAddress\n");
98#endif
99	fprintf(fp, "LogFileName = %s\n", TR_LOG_FILE);
100	fprintf(fp, "LogAutoRotate = true\n");
101	fprintf(fp, "LogBackup = 5\n");
102	fprintf(fp, "LogLevel = DEBUG\n");
103	if(nvram_get_int("TR_debug") == 1)
104		fprintf(fp, "LogMode = BOTH\n");
105	else
106		fprintf(fp, "LogMode = NONE\n");
107	fprintf(fp, "LogLimit = 1MB\n");
108	fprintf(fp, "TaskQueueLenLimit = 64\n");
109	fprintf(fp, "Upload = 1:1 Vendor Configuration File:/tmp/Settings_%s.CFG\n", nvram_safe_get("productid"));
110	fprintf(fp, "Upload = 0:2 Vendor Log File:/tmp/syslog.log\n");
111	//fprintf(fp, "Upload = 0:X 00256D 3GPP Performance File:pm.xml\n");
112	fprintf(fp, "Download = 1 Firmware Upgrade Image:/tmp/firmware.trx\n");
113	fprintf(fp, "Download = 2 Web Content:web.html\n");
114	fprintf(fp, "Download = 3 Vendor Configuration File:/tmp/settings_u.prf\n");
115#ifdef RTCONFIG_SFEXPRESS
116	fprintf(fp, "Download = 4 Openvpn Client1 File:/tmp/openvpn_file\n");
117	fprintf(fp, "Download = 5 Openvpn Client2 File:/tmp/openvpn_file\n");
118	fprintf(fp, "Download = 6 Openvpn Client3 File:/tmp/openvpn_file\n");
119#endif
120	//fprintf(fp, "Download = 4 Tone File:tone.file\n");
121	//fprintf(fp, "Download = 5 Ringer File:ringer.file\n");
122	//fprintf(fp, "Download = X Worksys DUInstallDownload: duin.pkg\n");
123	//fprintf(fp, "Download = X Worksys DUUpdateDownload: duup.pkg\n");
124	//fprintf(fp, "Download = X 00256D 3GPP Configuration File:cm.xml\n");
125	fprintf(fp, "TrustTargetFileName = false\n");
126	fprintf(fp, "CheckIdleInterval = 2\n");
127	fprintf(fp, "DownloadRetryInterval = 5\n");
128	fprintf(fp, "DownloadMaxRetries = 3\n");
129#if 0
130	fprintf(fp, "#CustomedEvent = 1:X 123456 Event1\n");
131	fprintf(fp, "CustomedEvent = 1: X 00256D 3GPP Reprovision Required: SecGW\n");
132	fprintf(fp, "CustomedEvent = 2: X 00256D 3GPP Reprovision Required: FAPGW\n");
133#endif
134	fprintf(fp, "SessionTimeout = 10\n");
135	fprintf(fp, "Expect100Continue = false\n");
136	fprintf(fp, "HTTPChunk = true\n");
137	fprintf(fp, "KAISpan=5\n");
138	fprintf(fp, "StunRepeat = 2\n");
139#if 0
140	fprintf(fp, "WIBRepeat = 5\n");
141	fprintf(fp, "WIBSpan = 5\n");
142	fprintf(fp, "WIBReInterval = 10\n");
143	fprintf(fp, "ResponseStatus1 = Device.DeviceInfo.SoftwareVersion\n");
144	fprintf(fp, "ResponseStatus1 = Device.MultiInstanceSample\n");
145#endif
146	//fprintf(fp, "IPDRDoc = %s\n", IPDRDOC_FOLDER);
147
148	fclose(fp);
149
150	return 0;
151}
152
153int check_xml_file_version(char *def_file, char *run_file)
154{
155	FILE *fp_def, *fp_run;
156	int res = 0;
157	char buf[128];
158	char def_ver_info[16] = "", run_ver_info[16] = "";
159	char *p;
160
161	/* get version info from the xml file of default */
162	if ((fp_def = fopen(def_file, "r")) == NULL) {
163		_dprintf("*** can't open file(%s)\n", def_file);
164		return res;
165	}
166
167	memset(buf, 0, sizeof(buf));
168	while(fgets(buf, sizeof(buf), fp_def) != NULL) {
169#ifdef RTCONFIG_TR181
170		if(strstr(buf, "'Device'")) {
171#else	/* TR098 */
172		if(strstr(buf, "'InternetGatewayDevice'")) {
173#endif
174			if((p =strstr(buf, "arg="))) {
175				sscanf(p, "arg='%[^']", def_ver_info);
176				//logmessage("TR-069 agent", "def_ver_info: %s, len: %d", def_ver_info, strlen(def_ver_info));
177				break;
178			}
179		}
180	}
181	fclose(fp_def);
182
183	/* get version info from the xml file of runtime */
184	if ((fp_run = fopen(run_file, "r")) == NULL) {
185		_dprintf("*** can't open file(%s)\n", run_file);
186		return res;
187	}
188
189	memset(buf, 0, sizeof(buf));
190	while(fgets(buf, sizeof(buf), fp_run) != NULL) {
191#ifdef RTCONFIG_TR181
192		if(strstr(buf, "'Device'")) {
193#else	/* TR098 */
194		if(strstr(buf, "'InternetGatewayDevice'")) {
195#endif
196			if((p =strstr(buf, "arg="))) {
197				sscanf(p, "arg='%[^']", run_ver_info);
198				//logmessage("TR-069 agent", "def_ver_info: %s, len: %d", run_ver_info, strlen(run_ver_info));
199				break;
200			}
201		}
202	}
203	fclose(fp_run);
204
205	//logmessage("TR-069 agent", "def_ver_info: %s, run_ver_info: %s", def_ver_info, run_ver_info);
206
207	if (!strcmp(def_ver_info, run_ver_info)) {
208		res = 1;
209		logmessage("TR-069 agent", "version match");
210	}
211	else
212		logmessage("TR-069 agent", "version dismatch");
213
214	return res;
215}
216
217char *convert_cert(const char *name, char *buf)
218{
219	char *value;
220	int len, i;
221
222	value = nvram_safe_get(name);
223
224	len = strlen(value);
225
226	for (i=0; (i < len); i++) {
227		if (value[i] == '>')
228			buf[i] = '\n';
229		else
230			buf[i] = value[i];
231	}
232
233	buf[i] = '\0';
234
235	return buf;
236}
237
238void save_cert_from_nvram()
239{
240	char buf[3000];
241	FILE *fp = NULL;
242
243	/* write ca cert from nvram */
244	if (check_if_file_exist(CA_CERT_FILE))
245		unlink(CA_CERT_FILE);
246
247	if(!nvram_is_empty("tr_ca_cert")) {
248		fp = fopen(CA_CERT_FILE, "w");
249		chmod(CA_CERT_FILE, S_IRUSR|S_IWUSR);
250		fprintf(fp, "%s", convert_cert("tr_ca_cert", buf));
251		fclose(fp);
252	}
253
254	/* write client cert from nvram */
255	if (check_if_file_exist(CLIENT_CERT_FILE))
256		unlink(CLIENT_CERT_FILE);
257
258	if(!nvram_is_empty("tr_client_cert")) {
259		fp = fopen(CLIENT_CERT_FILE, "w");
260		chmod(CLIENT_CERT_FILE, S_IRUSR|S_IWUSR);
261		fprintf(fp, "%s", convert_cert("tr_client_cert", buf));
262		fclose(fp);
263	}
264
265	/* write client key from nvram */
266	if (check_if_file_exist(CLIENT_KEY_FILE))
267		unlink(CLIENT_KEY_FILE);
268
269	if(!nvram_is_empty("tr_client_key")) {
270		fp = fopen(CLIENT_KEY_FILE, "w");
271		chmod(CLIENT_KEY_FILE, S_IRUSR|S_IWUSR);
272		fprintf(fp, "%s", convert_cert("tr_client_key", buf));
273		fclose(fp);
274	}
275}
276
277void
278stop_tr(void)
279{
280	killall_tk("tr069");
281}
282
283int
284start_tr(void)
285{
286	char *tr_argv[] = { "/sbin/tr069", "-d", TR_FOLDER, NULL};
287	char tr_xml_path[64];
288	pid_t pid;
289	int ret;
290
291	if (!nvram_match("tr_enable", "1") || nvram_match("tr_acs_url", "")) {
292		return 0;
293	}
294
295	if (getpid() != 1) {
296		notify_rc_after_wait("start_tr");
297		return 0;
298	}
299
300	/* Shut down previous instance if any */
301	stop_tr();
302
303	/* Check tr folder whether exists or not */
304	if (!check_if_dir_exist(TR_FOLDER))
305		mkdir(TR_FOLDER, 0744);
306
307#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2)
308	/* Check tr folder on jffs whether exists or not */
309	if (!check_if_dir_exist(JFFS_TR_FOLDER))
310		mkdir(JFFS_TR_FOLDER, 0744);
311
312	/* copy /jffs/tr/tr.xml to /tmp/tr and then delete it */
313	if (check_if_file_exist(JFFS_TR_FOLDER"/"TR_XML_FILE)) {
314		eval("cp", JFFS_TR_FOLDER"/"TR_XML_FILE, TR_FOLDER);
315		unlink(JFFS_TR_FOLDER"/"TR_XML_FILE);
316	}
317
318	/* copy /jffs/tr/tr.xml.bak to /tmp/tr and then delete it */
319	if (check_if_file_exist(JFFS_TR_FOLDER"/"TR_XML_BAK_FILE)) {
320		eval("cp", JFFS_TR_FOLDER"/"TR_XML_BAK_FILE, TR_FOLDER);
321		unlink(JFFS_TR_FOLDER"/"TR_XML_BAK_FILE);
322	}
323
324	/* untar /jffs/tr/tr.xml.tz to /tmp/tr */
325	if (check_if_file_exist(JFFS_TR_FOLDER"/"TR_XML_TAR_FILE))
326		eval("tar", "-zxf", JFFS_TR_FOLDER"/"TR_XML_TAR_FILE);
327
328	/* untar /jffs/tr/tr.xml.bak.tz to /tmp/tr */
329	if (check_if_file_exist(JFFS_TR_FOLDER"/"TR_XML_BAK_TAR_FILE))
330		eval("tar", "-zxf", JFFS_TR_FOLDER"/"TR_XML_BAK_TAR_FILE);
331#endif
332
333	/* Check IPDRDoc folder whether exists or not */
334	//if (!check_if_dir_exist(IPDRDOC_FOLDER));
335	//	mkdir(IPDRDOC_FOLDER, 0744);
336
337	/* Check tr.xml whether exists or not */
338	sprintf(tr_xml_path, "%s/%s", TR_FOLDER, TR_XML_FILE);
339	if (!check_if_file_exist(tr_xml_path))
340		eval("cp", DEFAULT_TR_XML, tr_xml_path);
341	else
342	{
343		if (!check_xml_file_version(DEFAULT_TR_XML, tr_xml_path))
344			eval("cp", DEFAULT_TR_XML, tr_xml_path);
345	}
346
347	/* Generate tr configuration file */
348	ret = generate_tr_config();
349	if (ret < 0)
350		return ret;
351
352	/* write cert and key to file */
353	save_cert_from_nvram();
354
355	/* Execute tr agent */
356	ret = _eval(tr_argv, NULL, 0, &pid);
357
358	if (pids("tr069"))
359		logmessage("TR-069 agent", "daemon is started");
360
361	return ret;
362}
363
364int check_udhcpc_lease_exist(char *check_str)
365{
366	FILE *fp;
367	char buf[128];
368	int res = 0;
369
370	if (!(fp = fopen(DHCPC_LEASE_LIST, "r")))
371		return 0;
372
373	while(fgets(buf, sizeof(buf), fp) != NULL) {
374		if(strstr(buf, check_str) != NULL)
375			res = 1;
376	}
377
378	fclose(fp);
379
380	return res;
381}
382
383int
384dhcpc_lease_main(int argc, char **argv)
385{
386	char *oui = safe_getenv("DNSMASQ_CPEWAN_OUI");
387	char *serial = safe_getenv("DNSMASQ_CPEWAN_SERIAL");
388	char *class = safe_getenv("DNSMASQ_CPEWAN_CLASS");
389	int hn_exist = 1;
390
391	if(argc != 5 && argc != 4)
392		return -1;
393
394	if(argc == 4)
395		hn_exist = 0;
396	else if(argc == 5)
397		hn_exist = 1;
398	else
399		return -1;
400
401	_dprintf("%s():: %s, %s, %s, %s\n", __FUNCTION__, argv[1], argv[2], argv[3], hn_exist ? argv[4]: "No hostname");
402
403//	if((oui && *oui) && (serial && *serial)) {
404	if(!pids("tr069")) {	/* write the info of manageable device into the file */
405		if(!strcmp(argv[1], "add") || !strcmp(argv[1], "old")) {
406			if((oui && *oui) && (serial && *serial)) {
407				char check_str[128];
408
409				snprintf(check_str, sizeof(check_str), "%s,%s,%s,%s", oui, serial, class, argv[2]);
410
411				if(!check_udhcpc_lease_exist(check_str)) {
412					FILE *fp;
413
414					if (!(fp = fopen(DHCPC_LEASE_LIST, "a")))
415						return -1;
416
417					/* write oui, serial, class */
418					_dprintf("%s():: %s %s %s %s\n", __FUNCTION__, argv[1], oui, serial, class);
419					fprintf(fp, "%s,%s,%s,%s\n", oui, serial, class, argv[2]);
420
421					fclose(fp);
422				}
423			}
424		}
425	}
426	else	/* send the info of manageable device to tr069 agent */
427	{
428		char cmd[256];
429		char cmdhost[256];
430
431		memset(cmd, 0 ,sizeof(cmd));
432		memset(cmdhost, 0 ,sizeof(cmdhost));
433
434		if(!strcmp(argv[1], "add") || !strcmp(argv[1], "old")) {
435			snprintf(cmdhost, sizeof(cmdhost), "/sbin/sendtocli http://127.0.0.1:1234/hostshost/device \"action=add&ipaddr=%s&hostname=%s\"", argv[3], hn_exist ? argv[4] : "");
436
437
438			if((oui && *oui) && (serial && *serial)) {
439				char check_str[128];
440
441				snprintf(check_str, sizeof(check_str), "%s,%s,%s,%s", oui, serial, class, argv[2]);
442
443				if(!check_udhcpc_lease_exist(check_str)) {
444					FILE *fp;
445
446					if (!(fp = fopen(DHCPC_LEASE_LIST, "a")))
447						return -1;
448
449					/* write oui, serial, class */
450					_dprintf("%s():: %s %s %s %s\n", __FUNCTION__, argv[1], oui, serial, class);
451					fprintf(fp, "%s,%s,%s,%s\n", oui, serial, class, argv[2]);
452
453					fclose(fp);
454				}
455
456				_dprintf("%s():: %s %s %s %s\n", __FUNCTION__, oui, serial, class, argv[2]);
457				snprintf(cmd, sizeof(cmd), "/sbin/sendtocli http://127.0.0.1:1234/manageable/device \"action=add&oui=%s&serial=%s&class=%s\"", oui, serial, class);
458			}
459		}
460		else if(!strcmp(argv[1], "del")) {
461			snprintf(cmdhost, sizeof(cmdhost), "/sbin/sendtocli http://127.0.0.1:1234/hostshost/device \"action=del&ipaddr=%s&hostname=%s\"", argv[3], hn_exist ? argv[4] : "");
462
463			FILE *fp;
464			char buf[128];
465			char *oui_str = NULL, *serial_str = NULL, *class_str = NULL, *hwaddr_str = NULL;
466
467			if (!(fp = fopen(DHCPC_LEASE_LIST, "r")))
468				return -1;
469
470			while(fgets(buf, sizeof(buf), fp) != NULL) {
471				if(strstr(buf, argv[2]) != NULL) {
472					if ((vstrsep(buf, ",", &oui_str, &serial_str, &class_str, &hwaddr_str) != 4))
473						continue;
474					_dprintf("%s():: oui: %s, serial: %s, class: %s, hwaddr: %s\n", oui_str, serial_str, class_str, hwaddr_str);
475					snprintf(cmd, sizeof(cmd), "/sbin/sendtocli http://127.0.0.1:1234/manageable/device \"action=del&oui=%s&serial=%s&class=%s\"", oui_str, serial_str, class_str);
476					break;
477				}
478			}
479
480			fclose(fp);
481		}
482
483		if(strlen(cmd)) {
484			_dprintf("%s():: %s\n", __FUNCTION__, cmd);
485			system(cmd);
486		}
487
488	}
489
490	_dprintf("%s:: done\n", __FUNCTION__);
491	return 0;
492}
493