]> git.ozlabs.org Git - ppp.git/blob - pppd/plugins/pppoe/pppoe.c
Correct utmp handling - Robert Davidson <puttputt@iaccess.ws>
[ppp.git] / pppd / plugins / pppoe / pppoe.c
1 /* pppoe.c - pppd plugin to implement PPPoE protocol.
2  *
3  * Copyright 2000 Michal Ostrowski <mostrows@styx.uwaterloo.ca>,
4  *                Jamal Hadi Salim <hadi@cyberus.ca>
5  * Borrows heavily from the PPPoATM plugin by Mitchell Blank Jr.,
6  * which is based in part on work from Jens Axboe and Paul Mackerras.
7  *
8  *  This program is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU General Public License
10  *  as published by the Free Software Foundation; either version
11  *  2 of the License, or (at your option) any later version.
12  */
13
14 #include <string.h>
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <unistd.h>
19 #include <errno.h>
20 #include <sys/stat.h>
21 #include "pppoe.h"
22 #if _linux_
23 extern int new_style_driver;    /* From sys-linux.c */
24 #include <linux/ppp_defs.h>
25 #include <linux/if_pppox.h>
26 #include <linux/if_ppp.h>
27 #else
28 #error this module meant for use with linux only at this time
29 #endif
30
31
32 #include "pppd.h"
33 #include "fsm.h"
34 #include "lcp.h"
35 #include "ipcp.h"
36 #include "ccp.h"
37 #include "pathnames.h"
38 #define _PATH_ETHOPT         _ROOT_PATH "/etc/ppp/options."
39
40 #define PPPOE_MTU       1492
41 extern int kill_link;
42 static char *bad_options[] = {
43     "noaccomp",
44     "-ac",
45     "default-asyncmap",
46     "-am",
47     "asyncmap",
48     "-as",
49     "escape",
50     "multilink",
51     "receive-all",
52     "crtscts",
53     "-crtscts",
54     "nocrtscts",
55     "cdtrcts",
56     "nocdtrcts",
57     "xonxoff",
58     "modem",
59     "local",
60     "sync",
61     "deflate",
62     "nodeflate",
63     "vj",
64     "novj",
65     "nobsdcomp",
66     "bsdcomp",
67     "-bsdcomp",
68     NULL
69 };
70
71 bool    pppoe_server=0;
72 char    *pppoe_srv_name=NULL;
73 char    *pppoe_ac_name=NULL;
74 char    *hostuniq = NULL;
75 int     retries = 0;
76
77 int setdevname_pppoe(const char *cp);
78
79 static option_t pppoe_options[] = {
80         { "device name", o_wild, (void *) &setdevname_pppoe,
81           "Serial port device name",
82           OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG  | OPT_A2STRVAL | OPT_STATIC,
83           devnam},
84         { "pppoe_srv_name", o_string, &pppoe_srv_name,
85           "PPPoE service name"},
86         { "pppoe_ac_name", o_string, &pppoe_ac_name,
87           "PPPoE access concentrator name"},
88         { "pppoe_hostuniq", o_string, &hostuniq,
89           "PPPoE client uniq hostid "},
90         { "pppoe_retransmit", o_int, &retries,
91           "PPPoE client number of retransmit tries"},
92         { "pppoe_server", o_bool, &pppoe_server,
93           "PPPoE listen for incoming requests",1},
94         { NULL }
95 };
96
97
98
99 struct session *ses = NULL;
100 static int connect_pppoe_ses(void)
101 {
102     int i,err=-1;
103     if( pppoe_server == 1 ){
104         srv_init_ses(ses,devnam);
105     }else{
106         client_init_ses(ses,devnam);
107     }
108 #if 0
109     ses->np=1;  /* jamal debug the discovery portion */
110 #endif
111     strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
112
113     err= session_connect ( ses );
114
115     if(err < 0){
116         poe_fatal(ses,"Failed to negotiate PPPoE connection: %d %m",errno,errno);
117     }
118
119
120     poe_info(ses,"Connecting PPPoE socket: %E %04x %s %p",
121              ses->sp.sa_addr.pppoe.remote,
122              ses->sp.sa_addr.pppoe.sid,
123              ses->sp.sa_addr.pppoe.dev,ses);
124
125     err = connect(ses->fd, (struct sockaddr*)&ses->sp,
126                   sizeof(struct sockaddr_pppox));
127
128
129     if( err < 0 ){
130         poe_fatal(ses,"Failed to connect PPPoE socket: %d %m",errno,errno);
131         return err;
132     }
133 #if 0
134     if (ses->np)
135         fatal("discovery complete\n");
136 #endif
137     /* Once the logging is fixed, print a message here indicating
138        connection parameters */
139
140     return ses->fd;
141 }
142
143 static void disconnect_pppoe_ses(void)
144 {
145     int ret;
146     warn("Doing disconnect");
147     session_disconnect(ses);
148     ses->sp.sa_addr.pppoe.sid = 0;
149     ret = connect(ses->fd, (struct sockaddr*)&ses->sp,
150             sizeof(struct sockaddr_pppox));
151
152 }
153
154
155 static int setspeed_pppoe(const char *cp)
156 {
157     return 0;
158 }
159
160 static void init_device_pppoe(void)
161 {
162     struct filter *filt;
163     unsigned int size=0;
164     ses=(void *)malloc(sizeof(struct session));
165     if(!ses){
166         fatal("No memory for new PPPoE session");
167     }
168     memset(ses,0,sizeof(struct session));
169
170     if ((ses->filt=malloc(sizeof(struct filter))) == NULL) {
171         poe_error (ses,"failed to malloc for Filter ");
172         poe_die (-1);
173     }
174
175     filt=ses->filt;  /* makes the code more readable */
176     memset(filt,0,sizeof(struct filter));
177
178     if (pppoe_ac_name !=NULL) {
179         if (strlen (pppoe_ac_name) > 255) {
180             poe_error (ses," AC name too long (maximum allowed 256 chars)");
181             poe_die(-1);
182         }
183         ses->filt->ntag = make_filter_tag(PTT_AC_NAME,
184                                           strlen(pppoe_ac_name),
185                                           pppoe_ac_name);
186
187         if ( ses->filt->ntag== NULL) {
188             poe_error (ses,"failed to malloc for AC name");
189             poe_die(-1);
190         }
191
192     }
193
194
195     if (pppoe_srv_name !=NULL) {
196         if (strlen (pppoe_srv_name) > 255) {
197             poe_error (ses," Service name too long
198                         (maximum allowed 256 chars)");
199             poe_die(-1);
200         }
201         ses->filt->stag = make_filter_tag(PTT_SRV_NAME,
202                                           strlen(pppoe_srv_name),
203                                           pppoe_srv_name);
204         if ( ses->filt->stag == NULL) {
205             poe_error (ses,"failed to malloc for service name");
206             poe_die(-1);
207         }
208     }
209
210     if (hostuniq) {
211         ses->filt->htag = make_filter_tag(PTT_HOST_UNIQ,
212                                           strlen(hostuniq),
213                                           hostuniq);
214         if ( ses->filt->htag == NULL) {
215             poe_error (ses,"failed to malloc for Uniq Host Id ");
216             poe_die(-1);
217         }
218     }
219
220     if (retries) {
221         ses->retries=retries;
222     }
223
224     memcpy( ses->name, devnam, IFNAMSIZ);
225     ses->opt_debug=1;
226 }
227
228 static void pppoe_extra_options()
229 {
230     int ret;
231     char buf[256];
232     snprintf(buf, 256, _PATH_ETHOPT "%s",devnam);
233     if(!options_from_file(buf, 0, 0, 1))
234         exit(EXIT_OPTION_ERROR);
235
236 }
237
238
239
240 static void send_config_pppoe(int mtu,
241                               u_int32_t asyncmap,
242                               int pcomp,
243                               int accomp)
244 {
245     int sock;
246     struct ifreq ifr;
247
248     if (mtu > PPPOE_MTU) {
249         warn("Not increasing MTU to %d, max is %d", mtu, PPPOE_MTU);
250         return;
251     }
252 }
253
254
255 static void recv_config_pppoe(int mru,
256                               u_int32_t asyncmap,
257                               int pcomp,
258                               int accomp)
259 {
260     if (mru > PPPOE_MTU)
261         error("Not increasing MRU to %d, max is %d", mru, PPPOE_MTU);
262 }
263
264 static void set_xaccm_pppoe(int unit, ext_accm accm)
265 {
266     /* NOTHING */
267 }
268
269
270
271 struct channel pppoe_channel;
272 /* Check is cp is a valid ethernet device
273  * return either 1 if "cp" is a reasonable thing to name a device
274  * or die.
275  * Note that we don't actually open the device at this point
276  * We do need to fill in:
277  *   devnam: a string representation of the device
278  */
279
280 int (*old_setdevname_hook)(const char* cp) = NULL;
281 int setdevname_pppoe(const char *cp)
282 {
283     int ret;
284     char dev[IFNAMSIZ+1];
285     int addr[ETH_ALEN];
286     int sid;
287
288     char **a;
289     ret =sscanf(cp, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2,
290                 addr+3, addr+4, addr+5,&sid,dev);
291     if( ret != 8 ){
292
293         ret = get_sockaddr_ll(cp,NULL);
294         if (ret < 0)
295             fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
296         if (ret == 1)
297             strncpy(devnam, cp, sizeof(devnam));
298     }else{
299         /* long form parsed */
300         ret = get_sockaddr_ll(dev,NULL);
301         if (ret < 0)
302             fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
303
304         strncpy(devnam, cp, sizeof(devnam));
305         ret = 1;
306     }
307
308
309     if( ret == 1 && the_channel != &pppoe_channel ){
310
311         the_channel = &pppoe_channel;
312
313         lcp_allowoptions[0].neg_accompression = 0;
314         lcp_wantoptions[0].neg_accompression = 0;
315
316         lcp_allowoptions[0].neg_asyncmap = 0;
317         lcp_wantoptions[0].neg_asyncmap = 0;
318
319         lcp_allowoptions[0].neg_pcompression = 0;
320         lcp_wantoptions[0].neg_pcompression = 0;
321
322         ccp_allowoptions[0].deflate = 0 ;
323         ccp_wantoptions[0].deflate = 0 ;
324
325         ipcp_allowoptions[0].neg_vj=0;
326         ipcp_wantoptions[0].neg_vj=0;
327
328         ccp_allowoptions[0].bsd_compress = 0;
329         ccp_wantoptions[0].bsd_compress = 0;
330
331         init_device_pppoe();
332     }
333     return ret;
334 }
335
336
337
338 void plugin_init(void)
339 {
340 /*
341   fatal("PPPoE plugin loading...");
342 */
343
344 #if _linux_
345     if (!ppp_available() && !new_style_driver)
346         fatal("Kernel doesn't support ppp_generic needed for PPPoE");
347 #else
348     fatal("No PPPoE support on this OS");
349 #endif
350     add_options(pppoe_options);
351
352
353     info("PPPoE Plugin Initialized");
354 }
355
356 struct channel pppoe_channel = {
357     options: pppoe_options,
358     process_extra_options: &pppoe_extra_options,
359     check_options: NULL,
360     connect: &connect_pppoe_ses,
361     disconnect: &disconnect_pppoe_ses,
362     establish_ppp: &generic_establish_ppp,
363     disestablish_ppp: &generic_disestablish_ppp,
364     send_config: &send_config_pppoe,
365     recv_config: &recv_config_pppoe,
366     close: NULL,
367     cleanup: NULL
368 };
369