1/* PPPoE support library "libpppoe"
2 *
3 * Copyright 2000 Jamal Hadi Salim <hadi@cyberus.ca>
4 *
5 *  This program is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU General Public License
7 *  as published by the Free Software Foundation; either version
8 *  2 of the License, or (at your option) any later version.
9 */
10
11#include "pppoe.h"
12
13int detached=1;
14void
15sigproc (int src)
16{
17    int i;
18    fprintf (stderr,"Received signal %d", src);
19}
20
21void
22sigchild (int src)
23{
24    pid_t pid;
25    int status;
26    int i;
27    pid = waitpid (-1, &status, WNOHANG);
28
29    if (!detached)
30	fprintf (stderr,"Child received signal %d PID %d, status %d", src, pid, status);
31    if (pid < 1) {
32	return;
33    }
34}
35
36void
37print_help ()
38{
39
40    fprintf (stdout,"\npppoe version %d.%d build %d", VERSION_MAJOR, VERSION_MINOR,
41	     VERSION_DATE);
42    fprintf (stdout,"\nrecognized options are:");
43    fprintf (stdout,"\n -I <interface> : overrides the default interface of eth0");
44    fprintf (stdout,"\n -S : starts pppoed in server mode");
45    fprintf (stdout,"\n -R <num_retries>: forces pppoed to be restarted num_retries");
46    fprintf (stdout,"\n                   should the other end be detected to be dead.");
47    fprintf (stdout,"\n                   Needs lcp_echo. Read the INSTALL file instructions");
48    fprintf (stdout,"\n -F <filename> : specifies additional ppp options file");
49    fprintf (stdout,"\n -C <filename> : ppp options file in /etc/ppp/peers/");
50    fprintf (stdout,"\n -d <level> : sets debug level");
51    fprintf (stdout,"\n -D : prevents pppoed from detaching itself and running in the background");
52    fprintf (stdout,"\n -P <path to pppd> : selects a different pppd. Defaults to " _PATH_PPPD);
53    fprintf (stdout,"\n -A <AC name> to select a specific AC by name");
54    fprintf (stdout,"\n -E <AC service name> to select a specific AC service by name");
55    fprintf (stdout,"\n -G Do service discovery only");
56    fprintf (stdout,"\n -H Do service discovery and connection (no pppd)\n");
57}
58
59
60int
61get_args (int argc, char **argv,struct session *sess)
62{
63    struct filter *filt;
64    struct host_tag *tg;
65    int opt;
66
67
68    sess->opt_debug = 0;
69    DEB_DISC=0;
70    DEB_DISC2=0;
71    sess->log_to_fd = 1;
72    sess->np = 0;
73    sess->opt_daemonize = 0;
74
75    sess->log_to_fd = fileno (stdout);
76
77/* defaults to eth0 */
78    strcpy (sess->name, "eth0");
79
80
81    if ((sess->filt=malloc(sizeof(struct filter))) == NULL) {
82        poe_error (sess,"failed to malloc for Filter ");
83        poe_die (-1);
84    }
85
86    filt=sess->filt;  /* makes the code more readable */
87    memset(filt,0,sizeof(struct filter));
88
89    filt->num_restart=1;
90
91/* set default filters; move this to routine */
92    /* parse options */
93
94    while ((opt = getopt (argc, argv, "A:C:E:d:DR:I:F:L:V:P:SN:GH")) != -1)
95
96	switch (opt) {
97	case 'R':			/* sets number of retries */
98	    filt->num_restart = strtol (optarg, (char **) NULL, 10);
99	    filt->num_restart += 1;
100	    break;
101	case 'I':			/* sets interface */
102	    if (strlen (optarg) >= IFNAMSIZ) {
103		poe_error (sess,"interface name cannot exceed %d characters", IFNAMSIZ - 1);
104		return (-1);
105	    }
106	    strncpy (sess->name, optarg, strlen(optarg)+1);
107	    break;
108	case 'C':			/* name of the file in /etc/ppp/peers */
109	    if (NULL != filt->fname) {
110		poe_error (sess,"-F can not be used with -C");
111		return (-1);
112	    }
113	    if (strlen(optarg) > MAX_FNAME) {
114		poe_error (sess,"file name cannot exceed %d characters", MAX_FNAME - 1);
115		return (-1);
116	    }
117	    filt->fname=malloc(strlen(optarg));
118	    strncpy (filt->fname, optarg, strlen(optarg));
119	    filt->peermode=1;
120	    break;
121	case 'F':			/* sets the options file */
122	    if (NULL != filt->fname) {
123		poe_error (sess,"-F can not be used with -C");
124		return (-1);
125	    }
126
127	    if (strlen(optarg) > MAX_FNAME) {
128		poe_error (sess,"file name cannot exceed %d characters", MAX_FNAME - 1);
129		return (-1);
130	    }
131	    filt->fname=malloc(strlen(optarg)+1);
132	    strncpy (filt->fname, optarg, strlen(optarg)+1);
133
134	    poe_info (sess,"selected %s as filename\n",filt->fname);
135	    break;
136	case 'D':			/* don't daemonize */
137	    sess->opt_daemonize = 1;
138	    detached=0;
139	    break;
140	case 'd':			/* debug level */
141	    sess->opt_debug = strtol (optarg, (char **) NULL, 10);
142	    if (sess->opt_debug & 0x0002)
143		DEB_DISC=1;
144	    if (sess->opt_debug & 0x0004)
145		DEB_DISC2=1;
146	    break;
147	case 'P':			/* sets the pppd binary */
148	    if (strlen(optarg) > MAX_FNAME) {
149		poe_error (sess,"pppd binary cant exceed %d characters", MAX_FNAME - 1);
150		return (-1);
151	    }
152	    filt->pppd=malloc(strlen(optarg));
153	    strncpy (filt->pppd, optarg, strlen(optarg));
154	    break;
155	case 'H':
156	    sess->np = 2;
157	    break;
158	case 'G':
159	    sess->np = 1;
160	    break;
161	case 'V':			/* version */
162	    fprintf (stdout,"pppoe version %d.%d build %d", VERSION_MAJOR,
163		     VERSION_MINOR, VERSION_DATE);
164	    return (0);
165	case 'S':			/* server mode */
166	    sess->type = SESSION_SERVER;
167	    break;
168	case 'A':			/* AC override */
169	    poe_info (sess,"AC name override to %s", optarg);
170	    if (strlen (optarg) > 255) {
171		poe_error (sess," AC name too long
172			  (maximum allowed 256 chars)");
173		poe_die(-1);
174	    }
175	    if ((sess->filt->ntag= malloc (sizeof (struct pppoe_tag) +
176					   strlen (optarg)))== NULL) {
177		poe_error (sess,"failed to malloc for AC name");
178		poe_die(-1);
179	    }
180	    sess->filt->ntag->tag_len=htons(strlen(optarg));
181	    sess->filt->ntag->tag_type=PTT_AC_NAME;
182	    strcpy(sess->filt->ntag->tag_data,optarg);
183	    break;
184	case 'E':			/* AC service name override */
185	    poe_info (sess,"AC service name override to %s", optarg);
186	    if (strlen (optarg) > 255) {
187		poe_error (sess," Service name too long
188	          (maximum allowed 256 chars)");
189		poe_die(-1);
190	    }
191
192	    if ((filt->stag = malloc (strlen (optarg) + sizeof (struct pppoe_tag))) == NULL) {
193		poe_error (sess,"failed to malloc for service name: %m");
194		return (-1);
195	    }
196
197	    filt->stag->tag_len = htons (strlen (optarg));
198	    filt->stag->tag_type = PTT_SRV_NAME;
199	    strcpy ((char *) (filt->stag->tag_data), optarg);
200	    break;
201	default:
202	    poe_error (sess,"Unknown option '%c'", optopt);
203	    print_help ();
204	    return (-1);
205	}
206
207
208    return (1);
209
210}
211
212
213int main(int argc, char** argv){
214    int ret;
215    struct filter *filt;
216    struct session *ses = (struct session *)malloc(sizeof(struct session));
217    char buf[256];
218    ses=(void *)malloc(sizeof(struct session));
219
220    if(!ses){
221	return -1;
222    }
223    memset(ses,0,sizeof(struct session));
224
225
226
227    openlog ("pppoed", LOG_PID | LOG_NDELAY, LOG_PPPOE);
228    setlogmask (LOG_UPTO (ses->opt_debug ? LOG_DEBUG : LOG_INFO));
229
230
231    if ((get_args (argc,(char **) argv,ses)) <1)
232        poe_die(-1);
233
234    filt=ses->filt;  /* makes the code more readable */
235
236    if (!ses->np) {
237	poe_create_pidfile (ses);
238//	signal (SIGINT, &sigproc);
239//	signal (SIGTERM, &sigproc);
240	signal (SIGCHLD, &sigchild);
241    }
242
243    if(ses->type == SESSION_CLIENT){
244
245	poe_info(ses,"calling client_init_ses\n");
246	ret = client_init_ses(ses,ses->name);
247
248	if( ret < 0 ){
249	    return -1;
250	}
251
252	while (ses->filt->num_restart > 0)
253	{
254	    poe_info(ses,"Restart number %d ",ses->filt->num_restart);
255	    ppp_connect (ses);
256	    ses->filt->num_restart--;
257	}
258
259    }else if( ses->type == SESSION_SERVER ){
260
261	poe_info(ses,"calling srv_init_ses\n");
262	ret = srv_init_ses(ses,ses->name);
263
264	if( ret < 0 ){
265	    return -1;
266	}
267
268	ret = 1;
269	while(ret>=0)
270	    ret = ppp_connect(ses);
271
272    }
273
274
275
276
277    poe_info(ses,"ppp_connect came back! %d",ret);
278
279    exit(0);
280
281}
282