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 #include <linux/ppp_defs.h>
24 #include <linux/if_pppox.h>
25 #include <linux/if_ppp.h>
27 #error this module meant for use with linux only at this time
36 #include <pathnames.h>
38 const char pppd_version
[] = VERSION
;
40 #define _PATH_ETHOPT _ROOT_PATH "/etc/ppp/options."
42 #define PPPOE_MTU 1492
46 char *pppoe_srv_name
=NULL
;
47 char *pppoe_ac_name
=NULL
;
48 char *hostuniq
= NULL
;
51 int setdevname_pppoe(const char *cp
);
53 struct session
*ses
= NULL
;
54 static int connect_pppoe_ses(void)
58 client_init_ses(ses
, devnam
);
60 strlcpy(ppp_devnam
, devnam
, sizeof(ppp_devnam
));
62 err
= session_connect(ses
);
63 LOGX_DEBUG("%s: session_connect()=%d", __FUNCTION__
, err
);
65 poe_error(ses
,"Failed to negotiate PPPoE connection: %d %m",errno
,errno
);
70 poe_info(ses
,"Connecting PPPoE socket: %E %04x %s %p",
71 ses
->sp
.sa_addr
.pppoe
.remote
,
72 ses
->sp
.sa_addr
.pppoe
.sid
,
73 ses
->sp
.sa_addr
.pppoe
.dev
,ses
);
75 err
= connect(ses
->fd
, (struct sockaddr
*)&ses
->sp
,
76 sizeof(struct sockaddr_pppox
));
77 LOGX_DEBUG("%s: connect()=%d", __FUNCTION__
, err
);
80 poe_error(ses
,"Failed to connect PPPoE socket: %d %m",errno
,errno
);
84 /* Once the logging is fixed, print a message here indicating
85 connection parameters */
90 static void disconnect_pppoe_ses(void)
93 warn("Doing disconnect");
94 session_disconnect(ses
);
95 ses
->sp
.sa_addr
.pppoe
.sid
= 0;
96 ret
= connect(ses
->fd
, (struct sockaddr
*)&ses
->sp
,
97 sizeof(struct sockaddr_pppox
));
100 static void init_device_pppoe(void)
103 ses
=(void *)malloc(sizeof(struct session
));
105 fatal("No memory for new PPPoE session");
107 memset(ses
,0,sizeof(struct session
));
109 if ((ses
->filt
=malloc(sizeof(struct filter
))) == NULL
) {
110 poe_error (ses
,"failed to malloc for Filter ");
114 filt
=ses
->filt
; /* makes the code more readable */
115 memset(filt
,0,sizeof(struct filter
));
117 if (pppoe_ac_name
!=NULL
) {
118 if (strlen (pppoe_ac_name
) > 255) {
119 poe_error (ses
," AC name too long (maximum allowed 256 chars)");
122 ses
->filt
->ntag
= make_filter_tag(PTT_AC_NAME
,
123 strlen(pppoe_ac_name
),
126 if ( ses
->filt
->ntag
== NULL
) {
127 poe_error (ses
,"failed to malloc for AC name");
134 if (pppoe_srv_name
!=NULL
) {
135 if (strlen (pppoe_srv_name
) > 255) {
136 poe_error (ses
," Service name too long (maximum allowed 256 chars)");
139 ses
->filt
->stag
= make_filter_tag(PTT_SRV_NAME
,
140 strlen(pppoe_srv_name
),
142 if ( ses
->filt
->stag
== NULL
) {
143 poe_error (ses
,"failed to malloc for service name");
149 ses
->filt
->htag
= make_filter_tag(PTT_HOST_UNIQ
,
152 if ( ses
->filt
->htag
== NULL
) {
153 poe_error (ses
,"failed to malloc for Uniq Host Id ");
159 ses
->retries
=retries
;
162 memcpy( ses
->name
, devnam
, IFNAMSIZ
);
167 static void send_config_pppoe(int mtu
,
175 if (mtu
> PPPOE_MTU
) {
176 warn("Couldn't increase MTU to %d", mtu
);
179 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
181 fatal("Couldn't create IP socket: %m");
182 strlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
184 if (ioctl(sock
, SIOCSIFMTU
, (caddr_t
) &ifr
) < 0)
185 fatal("ioctl(SIOCSIFMTU): %m");
190 static void recv_config_pppoe(int mru
,
195 // if (mru > PPPOE_MTU)
196 // error("Couldn't increase MRU to %d", mru);
199 struct channel pppoe_channel
;
200 /* Check is cp is a valid ethernet device
201 * return either 1 if "cp" is a reasonable thing to name a device
203 * Note that we don't actually open the device at this point
204 * We do need to fill in:
205 * devnam: a string representation of the device
208 int (*old_setdevname_hook
)(const char* cp
) = NULL
;
209 int setdevname_pppoe(const char *cp
)
212 char dev
[IFNAMSIZ
+1];
217 ret
=sscanf(cp
, FMTSTRING(IFNAMSIZ
),addr
, addr
+1, addr
+2,
218 addr
+3, addr
+4, addr
+5,&sid
,dev
);
221 ret
= get_sockaddr_ll(cp
,NULL
);
223 fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
225 strncpy(devnam
, cp
, sizeof(devnam
));
227 /* long form parsed */
228 ret
= get_sockaddr_ll(dev
,NULL
);
230 fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
232 strncpy(devnam
, cp
, sizeof(devnam
));
236 info("PPPoE: Use %s for PPPoE discovery\n", devnam
);
238 if( ret
== 1 && the_channel
!= &pppoe_channel
){
240 the_channel
= &pppoe_channel
;
242 lcp_allowoptions
[0].neg_accompression
= 0;
243 lcp_wantoptions
[0].neg_accompression
= 0;
245 lcp_allowoptions
[0].neg_asyncmap
= 0;
246 lcp_wantoptions
[0].neg_asyncmap
= 0;
248 lcp_allowoptions
[0].neg_pcompression
= 0;
249 lcp_wantoptions
[0].neg_pcompression
= 0;
251 ipcp_allowoptions
[0].neg_vj
=0;
252 ipcp_wantoptions
[0].neg_vj
=0;
254 ipcp_allowoptions
[0].default_route
=1;
256 /* remove for add -R parameter set default route. by tallest.*/
257 //ipcp_wantoptions[0].default_route=0;
259 for (opt
= ipcp_protent
.options
; opt
->name
!= NULL
; ++opt
) {
260 if (!strncmp(opt
->name
, "usepeerdns", 10)) {
261 *(bool *)(opt
->addr
) = 1;
267 ccp_allowoptions
[0].deflate
= 0 ;
268 ccp_wantoptions
[0].deflate
= 0 ;
270 ccp_allowoptions
[0].bsd_compress
= 0;
271 ccp_wantoptions
[0].bsd_compress
= 0;
279 struct channel pppoe_channel
= {
281 process_extra_options
: NULL
,
283 connect
: &connect_pppoe_ses
,
284 disconnect
: &disconnect_pppoe_ses
,
285 establish_ppp
: &generic_establish_ppp
,
286 disestablish_ppp
: &generic_disestablish_ppp
,
287 send_config
: &send_config_pppoe
,
288 recv_config
: &recv_config_pppoe
,