1/*
2 * pptpd.c
3 *
4 * Grabs any command line argument and processes any further options in
5 * the pptpd config file, before throwing over to pptpmanager.c.
6 *
7 * $Id: pptpd.c,v 1.18 2006/09/04 23:17:25 quozl Exp $
8 */
9
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#ifdef __linux__
15#define _GNU_SOURCE 1		/* strdup() prototype, broken arpa/inet.h */
16#endif
17
18#ifdef __svr4__
19#define __EXTENSIONS__ 1	/* strdup() prototype */
20#endif
21
22#ifdef __sgi__
23#define _XOPEN_SOURCE 500	/* strdup() prototype */
24#endif
25
26#include "our_syslog.h"
27#include "our_getopt.h"
28
29#include <fcntl.h>
30#include <netdb.h>
31#include <signal.h>
32#include <stdio.h>
33#include <string.h>
34#include <stdlib.h>
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39#include <sys/wait.h>
40#include <sys/stat.h>
41#include <unistd.h>
42
43#include "configfile.h"
44#include "defaults.h"
45#include "compat.h"
46#include "pptpmanager.h"
47
48#ifdef CONFIG_NETtel
49#include <linux/ledman.h>
50#endif
51
52/* command line arg variables */
53char *ppp_binary = NULL;
54char *pppdoptstr = NULL;
55char *speedstr = NULL;
56char *bindaddr = NULL;
57#ifdef BCRELAY
58char *bcrelay = NULL;
59#endif
60int pptp_debug = 0;
61int pptp_noipparam = 0;
62int pptp_logwtmp = 0;
63int pptp_delegate = 0;
64
65int pptp_stimeout = STIMEOUT_DEFAULT;
66
67int pptp_connections = CONNECTIONS_DEFAULT;
68
69/* Local prototypes */
70static void processIPStr(int type, char *ipstr);
71
72#ifndef HAVE_DAEMON
73static void my_daemon(int argc, char **argv);
74#endif
75
76static void log_pid(char *pid_file);
77static char *lookup(char *);
78
79#ifdef BCRELAY
80static void launch_bcrelay();
81static void launch_bcrelay_br0();
82static void launch_bcrelay_ppp();
83static pid_t bcrelayfork;
84#endif
85
86static void showusage(char *prog)
87{
88	printf("\npptpd v%s\n", VERSION);
89	printf("Usage: pptpd [options], where options are:\n\n");
90#ifdef BCRELAY
91	printf(" [-b] [--bcrelay if]       Use broadcast relay for broadcasts comming from.\n");
92	printf("                           the specified interface (default is eth1).\n");
93#endif
94	printf(" [-c] [--conf file]        Specifies the config file to read default\n");
95	printf("                           settings from (default is %s).\n", PPTPD_CONFIG_FILE_DEFAULT);
96	printf(" [-d] [--debug]            Turns on debugging (to syslog).\n");
97	printf(" [-e] [--ppp file]         Use alternate pppd binary, default %s.\n", PPP_BINARY);
98	printf(" [-f] [--fg]               Run in foreground.\n");
99	printf(" [-h] [--help]             Displays this help message.\n");
100	printf(" [-i] [--noipparam]        Suppress the passing of the client's IP address\n");
101	printf("                           to PPP, which is done by default otherwise.\n");
102	printf(" [-l] [--listen x.x.x.x]   Specifies IP of local interface to listen to.\n");
103#if !defined(BSDUSER_PPP)
104	printf(" [-o] [--option file]      Specifies the PPP options file to use\n");
105	printf("                           (default is /etc/ppp/options).\n");
106#endif
107	printf(" [-p] [--pidfile file]     Specifies the file to write the process ID to\n");
108	printf("                           (default is /var/run/pptpd.pid).\n");
109#if !defined(BSDUSER_PPP)
110	printf(" [-s] [--speed baud]       Specifies the baud speed for the PPP daemon\n");
111	printf("                           (default is 115200).\n");
112#endif
113	printf(" [-t] [--stimeout seconds] Specifies the timeout for the first packet. This is a DOS protection\n");
114	printf("                           (default is 10).\n");
115	printf(" [-v] [--version]          Displays the pptpd version number.\n");
116	printf(" [-w] [--logwtmp]          Update wtmp as users login.\n");
117	printf(" [-C] [--connections n]    Limit on number of connections.\n");
118	printf(" [-D] [--delegate]         Delegate IP allocation to pppd.\n");
119
120	printf("\n\nLogs and debugging go to syslog as DAEMON.");
121
122	printf("\n\nCommand line options will override any default settings and any settings\n");
123	printf("specified in the config file (default config file: %s).\n\n", PPTPD_CONFIG_FILE_DEFAULT);
124}
125
126
127static void showversion()
128{
129	printf("pptpd v%s\n", VERSION);
130}
131
132int main(int argc, char **argv)
133{
134	/* command line options */
135	int c;
136
137	/* function-local options */
138	int foreground = FALSE;
139	char *pid_file = NULL;
140
141	/* config file */
142	char *configFile = NULL;
143
144	/* config file parsing temp strings */
145	char tmp[MAX_CONFIG_STRING_SIZE], *tmpstr;
146
147	/* open a connection to the syslog daemon */
148	openlog("pptpd", LOG_PID, PPTP_FACILITY);
149
150	/* process command line options */
151	while (1) {
152		int option_index = 0;
153#ifdef BCRELAY
154		char *optstring = "b:c:de:fhil:o:p:s:t:vwC:D";
155#else
156		char *optstring = "c:de:fhil:o:p:s:t:vwC:D";
157#endif
158
159		static struct option long_options[] =
160		{
161#ifdef BCRELAY
162			{"bcrelay", 1, 0, 0},
163#endif
164			{"conf", 1, 0, 0},
165			{"debug", 0, 0, 0},
166			{"ppp", 1, 0, 0},
167			{"fg", 0, 0, 0},
168			{"help", 0, 0, 0},
169			{"noipparam", 0, 0, 0},
170			{"listen", 1, 0, 0},
171			{"option", 1, 0, 0},
172			{"pidfile", 1, 0, 0},
173			{"speed", 1, 0, 0},
174			{"stimeout", 1, 0, 0},
175			{"version", 0, 0, 0},
176			{"logwtmp", 0, 0, 0},
177			{"connections", 1, 0, 0},
178			{"delegate", 0, 0, 0},
179			{0, 0, 0, 0}
180		};
181
182		c = getopt_long(argc, argv, optstring, long_options, &option_index);
183		if (c == -1)
184			break;
185		/* convert long options to short form */
186		if (c == 0)
187#ifdef BCRELAY
188			c = "bcdefhilopstvwCD"[option_index];
189#else
190			c = "cdefhilopstvwCD"[option_index];
191#endif
192		switch (c) {
193#ifdef BCRELAY
194		case 'b': /* --bcrelay */
195			if (bcrelay) free(bcrelay);
196			bcrelay = strdup(optarg);
197			break;
198#endif
199
200		case 'l': /* --listen */
201			tmpstr = lookup(optarg);
202			if (!tmpstr) {
203				syslog(LOG_ERR, "MGR: Invalid listening address: %s!", optarg);
204				return 1;
205			}
206			if (bindaddr) free(bindaddr);
207			bindaddr = strdup(tmpstr);
208			break;
209
210		case 'h': /* --help */
211			showusage(argv[0]);
212			return 0;
213
214		case 'i': /* --noipparam */
215			pptp_noipparam = TRUE;
216			break;
217
218		case 'e': /* --ppp */
219			if (ppp_binary) free(ppp_binary);
220			ppp_binary = strdup(optarg);
221			break;
222
223		case 'd': /* --debug */
224			pptp_debug = TRUE;
225			break;
226
227		case 'f': /* --fg */
228			foreground = TRUE;
229			break;
230
231		case 'v': /* --version */
232			showversion();
233			return 0;
234
235		case 'w': /* --logwtmp */
236		        pptp_logwtmp = TRUE;
237			break;
238
239		case 'C': /* --connections */
240		        pptp_connections = atoi(optarg);
241			break;
242
243		case 'D': /* --delegate */
244		        pptp_delegate = TRUE;
245			break;
246
247		case 'o': /* --option */
248			if (pppdoptstr) free(pppdoptstr);
249			pppdoptstr = strdup(optarg);
250			break;
251
252		case 'p': /* --pidfile */
253			if (pid_file) free(pid_file);
254			pid_file = strdup(optarg);
255			break;
256
257		case 's': /* --speed */
258			if (speedstr) free(speedstr);
259			speedstr = strdup(optarg);
260			break;
261
262		case 't': /* --stimeout */
263			pptp_stimeout = atoi(optarg);
264			break;
265
266		case 'c': /* --conf */
267			{
268				FILE *f;
269				if (!(f = fopen(optarg, "r"))) {
270					syslog(LOG_ERR, "MGR: Config file not found!");
271					return 1;
272				}
273				fclose(f);
274				if(configFile) free(configFile);
275				configFile = strdup(optarg);
276				break;
277			}
278
279		default:
280			showusage(argv[0]);
281			return 1;
282		}
283	}
284
285	/* Now that we have all the command line args.. lets open the
286	 * conf file and add anything else (remembering not to override
287	 * anything since the command line has more privilages :-)
288	 */
289
290	if (!configFile)
291		configFile = strdup(PPTPD_CONFIG_FILE_DEFAULT);
292
293	if (read_config_file(configFile, CONNECTIONS_KEYWORD, tmp) > 0) {
294		pptp_connections = atoi(tmp);
295		if (pptp_connections <= 0)
296			pptp_connections = CONNECTIONS_DEFAULT;
297	}
298
299	slot_init(pptp_connections);
300
301	if (!pptp_debug && read_config_file(configFile, DEBUG_KEYWORD, tmp) > 0)
302		pptp_debug = TRUE;
303
304#ifdef BCRELAY
305	if (!bcrelay && read_config_file(configFile, BCRELAY_KEYWORD, tmp) > 0)
306		bcrelay = strdup(tmp);
307#endif
308
309	if (!pptp_stimeout && read_config_file(configFile, STIMEOUT_KEYWORD, tmp) > 0) {
310		pptp_stimeout = atoi(tmp);
311		if (pptp_stimeout <= 0)
312			pptp_stimeout = STIMEOUT_DEFAULT;
313	}
314
315	if (!pptp_noipparam && read_config_file(configFile, NOIPPARAM_KEYWORD, tmp) > 0) {
316		pptp_noipparam = TRUE;
317	}
318
319	if (!bindaddr && read_config_file(configFile, LISTEN_KEYWORD, tmp) > 0) {
320		tmpstr = lookup(tmp);
321		if(!tmpstr) {
322			syslog(LOG_ERR, "MGR: Invalid listening address: %s!", tmp);
323			return 1;
324		}
325		bindaddr = strdup(tmpstr);
326	}
327
328	if (!speedstr && read_config_file(configFile, SPEED_KEYWORD, tmp) > 0)
329		speedstr = strdup(tmp);
330
331	if (!pppdoptstr && read_config_file(configFile, PPPD_OPTION_KEYWORD, tmp) > 0) {
332		pppdoptstr = strdup(tmp);
333	}
334
335	if (!ppp_binary && read_config_file(configFile, PPP_BINARY_KEYWORD, tmp) > 0) {
336		ppp_binary = strdup(tmp);
337	}
338
339	if (!pptp_logwtmp && read_config_file(configFile, LOGWTMP_KEYWORD, tmp) > 0) {
340		pptp_logwtmp = TRUE;
341	}
342
343	if (!pptp_delegate && read_config_file(configFile, DELEGATE_KEYWORD, tmp) > 0) {
344		pptp_delegate = TRUE;
345	}
346
347	if (!pid_file)
348		pid_file = strdup((read_config_file(configFile, PIDFILE_KEYWORD,
349					tmp) > 0) ? tmp : PIDFILE_DEFAULT);
350
351	if (!pptp_delegate) {
352		/* NOTE: remote then local, reason can be seen at the end of processIPStr */
353
354		/* grab the remoteip string from the config file */
355		if (read_config_file(configFile, REMOTEIP_KEYWORD, tmp) <= 0) {
356			/* use "smart" defaults */
357			strlcpy(tmp, DEFAULT_REMOTE_IP_LIST, sizeof(tmp));
358		}
359		processIPStr(REMOTE, tmp);
360
361		/* grab the localip string from the config file */
362		if (read_config_file(configFile, LOCALIP_KEYWORD, tmp) <= 0) {
363			/* use "smart" defaults */
364			strlcpy(tmp, DEFAULT_LOCAL_IP_LIST, sizeof(tmp));
365		}
366		processIPStr(LOCAL, tmp);
367	}
368
369	free(configFile);
370
371	/* if not yet set, adopt default PPP binary path */
372	if (!ppp_binary) ppp_binary = strdup(PPP_BINARY);
373	/* check that the PPP binary is executable */
374	if (access(ppp_binary, X_OK) < 0) {
375		syslog(LOG_ERR, "MGR: PPP binary %s not executable",
376		       ppp_binary);
377		return 1;
378	}
379	/* check that the PPP options file is readable */
380	if (pppdoptstr && access(pppdoptstr, R_OK) < 0) {
381		syslog(LOG_ERR, "MGR: PPP options file %s not readable",
382		       pppdoptstr);
383		return 1;
384	}
385#ifdef BCRELAY
386	/* check that the bcrelay binary is executable */
387	if (bcrelay && access(BCRELAY_BIN, X_OK) < 0) {
388		syslog(LOG_ERR, "MGR: bcrelay binary %s not executable",
389		       BCRELAY_BIN);
390		return 1;
391	}
392#endif
393
394	if (!foreground) {
395#if HAVE_DAEMON
396		closelog();
397		freopen("/dev/null", "r", stdin);
398		daemon(0, 0);
399		/* returns to child only */
400		/* pid will have changed */
401		openlog("pptpd", LOG_PID, PPTP_FACILITY);
402#else	/* !HAVE_DAEMON */
403		my_daemon(argc, argv);
404		/* returns to child if !HAVE_FORK
405		 * never returns if HAVE_FORK (re-execs with -f)
406		 */
407#endif
408	}
409
410#ifdef BCRELAY
411      //Yau modified for dual way broadcast
412      if (strstr(bcrelay, "br0")) {
413             syslog(LOG_DEBUG, "CTRL: BCrelay incoming interface is %s", bcrelay);
414             /* Launch BCrelay  */
415#ifndef HAVE_FORK
416             switch(bcrelayfork = vfork()){
417#else
418             switch(bcrelayfork = fork()){
419#endif
420             case -1:        /* fork() error */
421                   syslog(LOG_ERR, "CTRL: Error forking to exec bcrelay");
422                   _exit(1);
423
424             case 0:         /* child */
425                   syslog(LOG_DEBUG, "CTRL (BCrelay Launcher): Launching BCrelay with pid %i", bcrelayfork);
426                   launch_bcrelay_br0();
427                   syslog(LOG_ERR, "CTRL (BCrelay Launcher): Failed to launch BCrelay.");
428                   _exit(1);
429             }
430         }
431         if (strstr(bcrelay, "ppp")) {
432             syslog(LOG_DEBUG, "CTRL: BCrelay incoming interface is %s", bcrelay);
433             /* Launch BCrelay  */
434#ifndef HAVE_FORK
435             switch(bcrelayfork = vfork()){
436#else
437             switch(bcrelayfork = fork()){
438#endif
439             case -1:        /* fork() error */
440                   syslog(LOG_ERR, "CTRL: Error forking to exec bcrelay");
441                   _exit(1);
442
443             case 0:         /* child */
444                   syslog(LOG_DEBUG, "CTRL (BCrelay Launcher): Launching BCrelay with pid %i", bcrelayfork);
445                   launch_bcrelay_ppp();
446                   syslog(LOG_ERR, "CTRL (BCrelay Launcher): Failed to launch BCrelay.");
447                   _exit(1);
448             }
449      } /* End bcrelay */
450#endif
451
452#ifdef CONFIG_NETtel
453	/* turn the NETtel VPN LED on */
454	ledman_cmd(LEDMAN_CMD_ON, LEDMAN_VPN);
455#endif
456	/* after we have our final pid... */
457	log_pid(pid_file);
458
459	/* manage connections until SIGTERM */
460	pptp_manager(argc, argv);
461
462#ifdef BCRELAY
463	if (bcrelayfork > 0) {
464		syslog(LOG_DEBUG, "CTRL: Closing child BCrelay with pid %i", bcrelayfork);
465		kill(bcrelayfork, SIGTERM);
466	}
467#endif
468
469	slot_free();
470	return 0;
471}
472
473static void log_pid(char *pid_file) {
474        FILE    *f;
475        pid_t   pid;
476
477        pid = getpid();
478        if ((f = fopen(pid_file, "w")) == NULL) {
479                syslog(LOG_ERR, "PPTPD: failed to open(%s), errno=%d\n",
480                        pid_file, errno);
481                return;
482        }
483        fprintf(f, "%d\n", pid);
484        fclose(f);
485}
486
487#ifndef HAVE_DAEMON
488static void my_daemon(int argc, char **argv)
489{
490#ifndef HAVE_FORK
491	/* need to use vfork - eg, uClinux */
492	char **new_argv;
493	int pid;
494	extern char **environ;
495	int fdr;
496
497	new_argv = malloc((argc + 2) * sizeof(char **));
498	fdr = open("/dev/null", O_RDONLY);
499	syslog(LOG_INFO, "MGR: Option parse OK, re-execing as daemon");
500	fflush(stderr);
501	if ((pid = vfork()) == 0) {
502		if (fdr != 0) { dup2(fdr, 0); close(fdr); }
503		SETSIDPGRP();
504		chdir("/");
505		umask(0);
506		memcpy(new_argv + 1, argv, (argc + 1) * sizeof(char **));
507		new_argv[0] = PPTPD_BIN;
508		new_argv[1] = "-f";
509		execve(PPTPD_BIN, new_argv, environ);
510		_exit(1);
511	} else if (pid > 0) {
512		exit(0);
513	} else {
514		syslog_perror("vfork");
515		exit(1);
516	}
517#else
518	int pid;
519
520	closelog();
521	if ((pid = fork()) < 0) {
522		syslog_perror("fork");
523		exit(1);
524	} else if (pid)
525		exit(0);
526	freopen("/dev/null", "r", stdin);
527	SETSIDPGRP();
528	chdir("/");
529	umask(0);
530	/* pid will have changed */
531	openlog("pptpd", LOG_PID, PPTP_FACILITY);
532#endif
533}
534#endif
535
536/* added for hostname/address lookup    -tmk
537 * returns NULL if not a valid hostname
538 */
539static char *lookup(char *hostname)
540{
541	struct hostent *ent;
542	struct in_addr hst_addr;
543
544	/* Try to parse IP directly */
545	if (inet_addr(hostname) != -1)
546		return hostname;
547
548	/* Else lookup hostname, return NULL if it fails */
549	if ((ent = gethostbyname(hostname)) == NULL)
550		return NULL;
551
552	/* That worked, print it back as a dotted quad. */
553	memcpy(&hst_addr.s_addr, ent->h_addr, ent->h_length);
554	return inet_ntoa(hst_addr);
555}
556
557#define DEBUG_IP_PARSER 1
558
559/* Return the address or NULL if not valid */
560static char *validip(char *hostname)
561{
562	/* Try to parse IP directly */
563	if (inet_addr(hostname) != -1)
564		return hostname;
565	else
566		return NULL;
567}
568
569/* Check if it's a valid IP range */
570static int isIpRange(char *str)
571{
572	int dashes = 0;
573	int dots = 0;
574
575#if DEBUG_IP_PARSER
576	syslog(LOG_DEBUG, "MGR: Checking if %s is a valid IP range", str);
577#endif
578	do {
579		if (*str == '-')
580			dashes++;
581		else if (*str == '.')
582			dots++;
583		else if (!strchr("0123456789", *str)) {
584#if DEBUG_IP_PARSER
585			syslog(LOG_DEBUG, "MGR: Not an IP range: character %c is not valid", *str);
586#endif
587			return 0;
588		}
589	} while (*++str);
590#if DEBUG_IP_PARSER
591	syslog(LOG_DEBUG, "MGR: Dashes = %d (wanted: 1), Dots = %d (wanted: 4)", dashes, dots);
592#endif
593	return (dashes == 1 && dots == 3);
594}
595
596/* process a type 0 (LOCAL) or type 1 (REMOTE) IP string */
597static void processIPStr(int type, char *ipstr)
598{
599	int pos;
600
601	char *tmpstr;
602	/* char tmpstr2[20]; xxx.xxx.xxx.xxx-xxx (largest we can get) */
603	char tmpstr2[128];	/* allow hostnames */
604	char *tmpstr3;
605	char tmpstr5[16];
606	char *tmpstr6;
607	char *tmpstr7;
608	int num;
609
610	char ipa[8];		/* xxx-xxx (largest we can get) */
611	char ipb[8];
612	char ipc[8];
613	char ipd[8];
614
615	char ip_pre[13];	/* xxx.xxx.xxx. (largest we can get) */
616	char ip_post[13];
617
618	char ipl[4];
619	char ipu[4];
620
621	int bail = FALSE;	/* so we know when to stop formatting the ip line */
622
623	int lower, upper, n;
624
625	num = 0;
626
627	while (!bail) {
628		if ((tmpstr = strchr(ipstr, ',')) == NULL) {
629			/* last (or only) entry reached */
630			strlcpy(tmpstr2, ipstr, sizeof(tmpstr2));
631			bail = TRUE;
632		} else {
633			pos = tmpstr - ipstr;
634			ipstr[pos] = '\0';
635			strlcpy(tmpstr2, ipstr, sizeof(tmpstr2));
636			ipstr = tmpstr + 1;
637		}
638
639#if DEBUG_IP_PARSER
640		syslog(LOG_DEBUG, "MGR: Parsing segment: %s", tmpstr2);
641#endif
642
643		if (!isIpRange(tmpstr2)) {
644			/* We got a normal IP
645			 * Check if the IP address is valid, use it if so
646			 */
647			if ((tmpstr7 = lookup(tmpstr2)) == NULL) {
648				syslog(LOG_ERR, "MGR: Bad IP address (%s) in config file!", tmpstr2);
649				exit(1);
650			}
651			if (num == pptp_connections) {
652				syslog(LOG_WARNING, "MGR: connections limit (%d) reached, extra IP addresses ignored", pptp_connections);
653				return;
654			}
655#if DEBUG_IP_PARSER
656			syslog(LOG_DEBUG, "MGR: Setting IP %d = %s", num, tmpstr7);
657#endif
658			if (type == LOCAL)
659				slot_set_local(num, tmpstr7);
660			else
661				slot_set_remote(num, tmpstr7);
662			num++;
663		} else {
664			/* Got a range;
665			 * eg. 192.168.0.234-238
666			 * or (thanx Kev! :-).. i thought i was finished :-)
667			 * 192.168-178.1.231
668			 */
669
670			/* lose the "."'s */
671			while ((tmpstr3 = strchr(tmpstr2, '.')) != NULL) {
672				pos = tmpstr3 - tmpstr2;
673				tmpstr2[pos] = ' ';
674			}
675
676			if ((tmpstr3 = strchr(tmpstr2, '-')) == NULL ||
677			    strchr(tmpstr3 + 1, '-') != NULL) {
678				syslog(LOG_ERR, "MGR: Confused in IP parse routines (multiple hyphens)");
679				continue;
680			}
681			/* should be left with "192 168 0 234-238"
682			 * or 192 168-178 1 231
683			 */
684
685			sscanf(tmpstr2, "%7s %7s %7s %7s", ipa, ipb, ipc, ipd);
686
687			if ((tmpstr6 = strchr(ipd, '-')) != NULL) {
688				pos = tmpstr6 - ipd;
689				ipd[pos] = ' ';
690				sscanf(ipd, "%3s %3s", ipl, ipu);
691#if DEBUG_IP_PARSER
692				syslog(LOG_DEBUG, "MGR: (lower upper) = (%s %s)", ipl, ipu);
693#endif
694				lower = atoi(ipl);
695				upper = atoi(ipu);
696#if DEBUG_IP_PARSER
697				syslog(LOG_DEBUG, "MGR: Range = %d to %d on 4th segment", lower, upper);
698#endif
699				sprintf(ip_pre, "%.3s.%.3s.%.3s.", ipa, ipb, ipc);
700				ip_post[0] = '\0';
701#if DEBUG_IP_PARSER
702				syslog(LOG_DEBUG, "MGR: Pre = %s Post = %s", ip_pre, ip_post);
703#endif
704			} else if ((tmpstr6 = strchr(ipc, '-')) != NULL) {
705				pos = tmpstr6 - ipc;
706				ipc[pos] = ' ';
707				sscanf(ipc, "%3s %3s", ipl, ipu);
708#if DEBUG_IP_PARSER
709				syslog(LOG_DEBUG, "MGR: (lower upper) = (%s %s)", ipl, ipu);
710#endif
711				lower = atoi(ipl);
712				upper = atoi(ipu);
713#if DEBUG_IP_PARSER
714				syslog(LOG_DEBUG, "MGR: Range = %d to %d on 3rd segment", lower, upper);
715#endif
716				sprintf(ip_pre, "%.3s.%.3s.", ipa, ipb);
717				sprintf(ip_post, ".%.3s", ipd);
718#if DEBUG_IP_PARSER
719				syslog(LOG_DEBUG, "MGR: Pre = %s Post = %s", ip_pre, ip_post);
720#endif
721			} else if ((tmpstr6 = strchr(ipb, '-')) != NULL) {
722				pos = tmpstr6 - ipb;
723				ipb[pos] = ' ';
724				sscanf(ipb, "%3s %3s", ipl, ipu);
725#if DEBUG_IP_PARSER
726				syslog(LOG_DEBUG, "MGR: (lower upper) = (%s %s)", ipl, ipu);
727#endif
728				lower = atoi(ipl);
729				upper = atoi(ipu);
730#if DEBUG_IP_PARSER
731				syslog(LOG_DEBUG, "MGR: Range = %d to %d on 2nd segment", lower, upper);
732#endif
733				sprintf(ip_pre, "%.3s.", ipa);
734				sprintf(ip_post, ".%.3s.%.3s", ipc, ipd);
735#if DEBUG_IP_PARSER
736				syslog(LOG_DEBUG, "MGR: Pre = %s Post = %s", ip_pre, ip_post);
737#endif
738			} else if ((tmpstr6 = strchr(ipa, '-')) != NULL) {
739				pos = tmpstr6 - ipa;
740				ipa[pos] = ' ';
741				sscanf(ipa, "%3s %3s", ipl, ipu);
742#if DEBUG_IP_PARSER
743				syslog(LOG_DEBUG, "MGR: (lower upper) = (%s %s)", ipl, ipu);
744#endif
745				lower = atoi(ipl);
746				upper = atoi(ipu);
747#if DEBUG_IP_PARSER
748				syslog(LOG_DEBUG, "MGR: Range = %d to %d on 1st segment", lower, upper);
749#endif
750				ip_pre[0] = '\0';
751				sprintf(ip_post, ".%.3s.%.3s.%.3s", ipb, ipc, ipd);
752#if DEBUG_IP_PARSER
753				syslog(LOG_DEBUG, "MGR: Pre = %s Post = %s", ip_pre, ip_post);
754#endif
755			} else {
756				syslog(LOG_ERR, "MGR: Confused in IP parse routines (lost hyphen)");
757				continue;
758			}
759
760			for (n = lower; n <= upper; n++) {
761				sprintf(tmpstr5, "%s%d%s", ip_pre, n, ip_post);
762				/* Check if the ip address is valid */
763				if ((tmpstr7 = validip(tmpstr5)) == NULL) {
764					syslog(LOG_ERR, "MGR: Bad IP address (%s) in config file!", tmpstr5);
765					exit(1);
766				}
767				if (num == pptp_connections) {
768					syslog(LOG_WARNING, "MGR: connections limit (%d) reached, extra IP addresses ignored", pptp_connections);
769					return;
770				}
771#if DEBUG_IP_PARSER
772				syslog(LOG_DEBUG, "MGR: Setting IP %d = %s", num, tmpstr7);
773#endif
774				if (type == LOCAL)
775					slot_set_local(num, tmpstr7);
776				else
777					slot_set_remote(num, tmpstr7);
778				num++;
779			}
780		}
781	}
782	if (num == 1 && type == LOCAL && pptp_connections > 1) {
783#if DEBUG_IP_PARSER
784		syslog(LOG_DEBUG, "MGR: Setting all %d local IPs to %s", pptp_connections, slot_get_local(0));
785#endif
786		for (n = 1; n < pptp_connections; n++)
787			slot_set_local(n, slot_get_local(0));
788	} else if (pptp_connections > num) {
789		syslog(LOG_INFO, "MGR: Maximum of %d connections reduced to %d, not enough IP addresses given",
790		       pptp_connections, num);
791		pptp_connections = num;
792	}
793}
794
795#ifdef BCRELAY
796/* launch_bcrelay
797 * Launches broadcast relay. Broadcast relay is responsible for relaying broadcasts to the clients
798 * retn: 0 on success, -1 on failure.
799 */
800static void launch_bcrelay() {
801  char *bcrelay_argv[8];
802  int an = 0;
803
804      if (strstr(bcrelay, "br0")) {
805           syslog(LOG_DEBUG, "MGR: BCrelay incoming interface is %s", bcrelay);
806           syslog(LOG_DEBUG, "MGR: BCrelay outgoing interface is regexp ppp[0-9].*");
807
808	   bcrelay_argv[an++] = BCRELAY_BIN;
809	   bcrelay_argv[an++] = "-i";
810	   bcrelay_argv[an++] = bcrelay;
811	   bcrelay_argv[an++] = "-o";
812	   bcrelay_argv[an++] = "ppp[0-9].*";
813           if (!pptp_debug) {
814	         bcrelay_argv[an++] = "-n";
815           }
816	   bcrelay_argv[an++] = NULL;
817
818           execvp(bcrelay_argv[0], bcrelay_argv);
819      }
820}
821
822//Yau add
823static void launch_bcrelay_br0() {
824  char *bcrelay_argv[8];
825  int an = 0;
826
827      if (strstr(bcrelay, "br0")) {
828           syslog(LOG_DEBUG, "MGR: BCrelay incoming interface is br0");
829           syslog(LOG_DEBUG, "MGR: BCrelay outgoing interface is regexp ppp[0-9].*");
830
831           bcrelay_argv[an++] = BCRELAY_BIN;
832           bcrelay_argv[an++] = "-i";
833           bcrelay_argv[an++] = "br0";
834           bcrelay_argv[an++] = "-o";
835           bcrelay_argv[an++] = "ppp[0-9].*";
836           if (!pptp_debug) {
837                 bcrelay_argv[an++] = "-n";
838           }
839           bcrelay_argv[an++] = NULL;
840
841           execvp(bcrelay_argv[0], bcrelay_argv);
842      }
843}
844
845static void launch_bcrelay_ppp() {
846  char *bcrelay_argv[8];
847  int an = 0;
848
849      if (strstr(bcrelay, "ppp")) {
850           syslog(LOG_DEBUG, "MGR: BCrelay incoming interface is regexp ppp[0-9].*");
851           syslog(LOG_DEBUG, "MGR: BCrelay outgoing interface is br0");
852
853           bcrelay_argv[an++] = BCRELAY_BIN;
854           bcrelay_argv[an++] = "-i";
855           bcrelay_argv[an++] = "ppp[0-9].*";
856           bcrelay_argv[an++] = "-o";
857           bcrelay_argv[an++] = "br0";
858           if (!pptp_debug) {
859                 bcrelay_argv[an++] = "-n";
860           }
861           bcrelay_argv[an++] = NULL;
862
863           execvp(bcrelay_argv[0], bcrelay_argv);
864      }
865
866}
867#endif
868