1 /* pppoe.c - pppd plugin to implement PPPoE protocol.
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.
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.
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
17 #include <sys/socket.h>
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>
28 #error this module meant for use with linux only at this time
37 #include "pathnames.h"
39 const char pppd_version
[] = VERSION
;
41 #define _PATH_ETHOPT _ROOT_PATH "/etc/ppp/options."
43 #define PPPOE_MTU 1492
45 static char *bad_options
[] = {
75 char *pppoe_srv_name
=NULL
;
76 char *pppoe_ac_name
=NULL
;
77 char *hostuniq
= NULL
;
80 int setdevname_pppoe(const char *cp
);
82 static option_t pppoe_options
[] = {
83 { "device name", o_wild
, (void *) &setdevname_pppoe
,
84 "Serial port device name",
85 OPT_DEVNAM
| OPT_PRIVFIX
| OPT_NOARG
| OPT_A2STRVAL
| OPT_STATIC
,
87 { "pppoe_srv_name", o_string
, &pppoe_srv_name
,
88 "PPPoE service name"},
89 { "pppoe_ac_name", o_string
, &pppoe_ac_name
,
90 "PPPoE access concentrator name"},
91 { "pppoe_hostuniq", o_string
, &hostuniq
,
92 "PPPoE client uniq hostid "},
93 { "pppoe_retransmit", o_int
, &retries
,
94 "PPPoE client number of retransmit tries"},
95 { "pppoe_server", o_bool
, &pppoe_server
,
96 "PPPoE listen for incoming requests",1},
102 struct session
*ses
= NULL
;
103 static int connect_pppoe_ses(void)
106 if( pppoe_server
== 1 ){
107 srv_init_ses(ses
,devnam
);
109 client_init_ses(ses
,devnam
);
111 strlcpy(ppp_devnam
, devnam
, sizeof(ppp_devnam
));
113 err
= session_connect ( ses
);
116 poe_fatal(ses
,"Failed to negotiate PPPoE connection: %d %m",errno
,errno
);
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
);
125 err
= connect(ses
->fd
, (struct sockaddr
*)&ses
->sp
,
126 sizeof(struct sockaddr_pppox
));
130 poe_fatal(ses
,"Failed to connect PPPoE socket: %d %m",errno
,errno
);
133 /* Once the logging is fixed, print a message here indicating
134 connection parameters */
139 static void disconnect_pppoe_ses(void)
142 warn("Doing disconnect");
143 session_disconnect(ses
);
144 ses
->sp
.sa_addr
.pppoe
.sid
= 0;
145 ret
= connect(ses
->fd
, (struct sockaddr
*)&ses
->sp
,
146 sizeof(struct sockaddr_pppox
));
151 static int setspeed_pppoe(const char *cp
)
156 static void init_device_pppoe(void)
160 ses
=(void *)malloc(sizeof(struct session
));
162 fatal("No memory for new PPPoE session");
164 memset(ses
,0,sizeof(struct session
));
166 if ((ses
->filt
=malloc(sizeof(struct filter
))) == NULL
) {
167 poe_error (ses
,"failed to malloc for Filter ");
171 filt
=ses
->filt
; /* makes the code more readable */
172 memset(filt
,0,sizeof(struct filter
));
174 if (pppoe_ac_name
!=NULL
) {
175 if (strlen (pppoe_ac_name
) > 255) {
176 poe_error (ses
," AC name too long (maximum allowed 256 chars)");
179 ses
->filt
->ntag
= make_filter_tag(PTT_AC_NAME
,
180 strlen(pppoe_ac_name
),
183 if ( ses
->filt
->ntag
== NULL
) {
184 poe_error (ses
,"failed to malloc for AC name");
191 if (pppoe_srv_name
!=NULL
) {
192 if (strlen (pppoe_srv_name
) > 255) {
193 poe_error (ses
," Service name too long
194 (maximum allowed 256 chars)");
197 ses
->filt
->stag
= make_filter_tag(PTT_SRV_NAME
,
198 strlen(pppoe_srv_name
),
200 if ( ses
->filt
->stag
== NULL
) {
201 poe_error (ses
,"failed to malloc for service name");
207 ses
->filt
->htag
= make_filter_tag(PTT_HOST_UNIQ
,
210 if ( ses
->filt
->htag
== NULL
) {
211 poe_error (ses
,"failed to malloc for Uniq Host Id ");
217 ses
->retries
=retries
;
220 memcpy( ses
->name
, devnam
, IFNAMSIZ
);
224 static void pppoe_extra_options()
228 snprintf(buf
, 256, _PATH_ETHOPT
"%s",devnam
);
229 if(!options_from_file(buf
, 0, 0, 1))
230 exit(EXIT_OPTION_ERROR
);
236 static void send_config_pppoe(int mtu
,
245 warn("Couldn't increase MTU to %d", mtu
);
246 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
248 fatal("Couldn't create IP socket: %m");
249 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
251 if (ioctl(sock
, SIOCSIFMTU
, (caddr_t
) &ifr
) < 0)
252 fatal("ioctl(SIOCSIFMTU): %m");
257 static void recv_config_pppoe(int mru
,
263 error("Couldn't increase MRU to %d", mru
);
266 static void set_xaccm_pppoe(int unit
, ext_accm accm
)
273 struct channel pppoe_channel
;
274 /* Check is cp is a valid ethernet device
275 * return either 1 if "cp" is a reasonable thing to name a device
277 * Note that we don't actually open the device at this point
278 * We do need to fill in:
279 * devnam: a string representation of the device
282 int (*old_setdevname_hook
)(const char* cp
) = NULL
;
283 int setdevname_pppoe(const char *cp
)
286 char dev
[IFNAMSIZ
+1];
291 ret
=sscanf(cp
, FMTSTRING(IFNAMSIZ
),addr
, addr
+1, addr
+2,
292 addr
+3, addr
+4, addr
+5,&sid
,dev
);
295 ret
= get_sockaddr_ll(cp
,NULL
);
297 fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
299 strncpy(devnam
, cp
, sizeof(devnam
));
301 /* long form parsed */
302 ret
= get_sockaddr_ll(dev
,NULL
);
304 fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
306 strncpy(devnam
, cp
, sizeof(devnam
));
311 if( ret
== 1 && the_channel
!= &pppoe_channel
){
313 the_channel
= &pppoe_channel
;
317 for (a
= bad_options
; *a
!= NULL
; a
++)
322 lcp_allowoptions
[0].neg_accompression
= 0;
323 lcp_wantoptions
[0].neg_accompression
= 0;
325 lcp_allowoptions
[0].neg_asyncmap
= 0;
326 lcp_wantoptions
[0].neg_asyncmap
= 0;
328 lcp_allowoptions
[0].neg_pcompression
= 0;
329 lcp_wantoptions
[0].neg_pcompression
= 0;
331 ccp_allowoptions
[0].deflate
= 0 ;
332 ccp_wantoptions
[0].deflate
= 0 ;
334 ipcp_allowoptions
[0].neg_vj
=0;
335 ipcp_wantoptions
[0].neg_vj
=0;
337 ccp_allowoptions
[0].bsd_compress
= 0;
338 ccp_wantoptions
[0].bsd_compress
= 0;
347 void plugin_init(void)
350 fatal("PPPoE plugin loading...");
354 if (!ppp_available() && !new_style_driver
)
355 fatal("Kernel doesn't support ppp_generic needed for PPPoE");
357 fatal("No PPPoE support on this OS");
359 add_options(pppoe_options
);
362 info("PPPoE Plugin Initialized");
365 struct channel pppoe_channel
= {
366 options
: pppoe_options
,
367 process_extra_options
: &pppoe_extra_options
,
369 connect
: &connect_pppoe_ses
,
370 disconnect
: &disconnect_pppoe_ses
,
371 establish_ppp
: &generic_establish_ppp
,
372 disestablish_ppp
: &generic_disestablish_ppp
,
373 send_config
: &send_config_pppoe
,
374 recv_config
: &recv_config_pppoe
,