CPU: Wrong CPU Load %.
[tomato.git] / release / src / router / ppp / pppd / plugins / pppoe / pppoe.c
blob3a418df4cdfe3db91f36dbc5682c604495169726
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.
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
32 #include "pppd.h"
33 #include "fsm.h"
34 #include "lcp.h"
35 #include "ipcp.h"
36 #include "ccp.h"
37 #include "pathnames.h"
39 const char pppd_version[] = VERSION;
41 #define _PATH_ETHOPT _ROOT_PATH "/etc/ppp/options."
43 #define PPPOE_MTU 1492
44 extern int kill_link;
45 static char *bad_options[] = {
46 "noaccomp",
47 "-ac",
48 "default-asyncmap",
49 "-am",
50 "asyncmap",
51 "-as",
52 "escape",
53 "multilink",
54 "receive-all",
55 "crtscts",
56 "-crtscts",
57 "nocrtscts",
58 "cdtrcts",
59 "nocdtrcts",
60 "xonxoff",
61 "modem",
62 "local",
63 "sync",
64 "deflate",
65 "nodeflate",
66 "vj",
67 "novj",
68 "nobsdcomp",
69 "bsdcomp",
70 "-bsdcomp",
71 NULL
74 bool pppoe_server=0;
75 char *pppoe_srv_name=NULL;
76 char *pppoe_ac_name=NULL;
77 char *hostuniq = NULL;
78 int retries = 0;
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,
86 devnam},
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},
97 { NULL }
102 struct session *ses = NULL;
103 static int connect_pppoe_ses(void)
105 int i,err=-1;
106 if( pppoe_server == 1 ){
107 srv_init_ses(ses,devnam);
108 }else{
109 client_init_ses(ses,devnam);
111 strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
113 err= session_connect ( ses );
115 if(err < 0){
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));
129 if( err < 0 ){
130 poe_fatal(ses,"Failed to connect PPPoE socket: %d %m",errno,errno);
131 return err;
133 /* Once the logging is fixed, print a message here indicating
134 connection parameters */
136 return ses->fd;
139 static void disconnect_pppoe_ses(void)
141 int ret;
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)
153 return 0;
156 static void init_device_pppoe(void)
158 struct filter *filt;
159 unsigned int size=0;
160 ses=(void *)malloc(sizeof(struct session));
161 if(!ses){
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 ");
168 poe_die (-1);
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)");
177 poe_die(-1);
179 ses->filt->ntag = make_filter_tag(PTT_AC_NAME,
180 strlen(pppoe_ac_name),
181 pppoe_ac_name);
183 if ( ses->filt->ntag== NULL) {
184 poe_error (ses,"failed to malloc for AC name");
185 poe_die(-1);
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)");
195 poe_die(-1);
197 ses->filt->stag = make_filter_tag(PTT_SRV_NAME,
198 strlen(pppoe_srv_name),
199 pppoe_srv_name);
200 if ( ses->filt->stag == NULL) {
201 poe_error (ses,"failed to malloc for service name");
202 poe_die(-1);
206 if (hostuniq) {
207 ses->filt->htag = make_filter_tag(PTT_HOST_UNIQ,
208 strlen(hostuniq),
209 hostuniq);
210 if ( ses->filt->htag == NULL) {
211 poe_error (ses,"failed to malloc for Uniq Host Id ");
212 poe_die(-1);
216 if (retries) {
217 ses->retries=retries;
220 memcpy( ses->name, devnam, IFNAMSIZ);
221 ses->opt_debug=1;
224 static void pppoe_extra_options()
226 int ret;
227 char buf[256];
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,
237 u_int32_t asyncmap,
238 int pcomp,
239 int accomp)
241 int sock;
242 struct ifreq ifr;
244 if (mtu > PPPOE_MTU)
245 warn("Couldn't increase MTU to %d", mtu);
246 sock = socket(AF_INET, SOCK_DGRAM, 0);
247 if (sock < 0)
248 fatal("Couldn't create IP socket: %m");
249 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
250 ifr.ifr_mtu = mtu;
251 if (ioctl(sock, SIOCSIFMTU, (caddr_t) &ifr) < 0)
252 fatal("ioctl(SIOCSIFMTU): %m");
253 (void) close (sock);
257 static void recv_config_pppoe(int mru,
258 u_int32_t asyncmap,
259 int pcomp,
260 int accomp)
262 if (mru > PPPOE_MTU)
263 error("Couldn't increase MRU to %d", mru);
266 static void set_xaccm_pppoe(int unit, ext_accm accm)
268 /* NOTHING */
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
276 * or die.
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)
285 int ret;
286 char dev[IFNAMSIZ+1];
287 int addr[ETH_ALEN];
288 int sid;
290 char **a;
291 ret =sscanf(cp, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2,
292 addr+3, addr+4, addr+5,&sid,dev);
293 if( ret != 8 ){
295 ret = get_sockaddr_ll(cp,NULL);
296 if (ret < 0)
297 fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
298 if (ret == 1)
299 strncpy(devnam, cp, sizeof(devnam));
300 }else{
301 /* long form parsed */
302 ret = get_sockaddr_ll(dev,NULL);
303 if (ret < 0)
304 fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
306 strncpy(devnam, cp, sizeof(devnam));
307 ret = 1;
311 if( ret == 1 && the_channel != &pppoe_channel ){
313 the_channel = &pppoe_channel;
316 char **a;
317 for (a = bad_options; *a != NULL; a++)
318 remove_option(*a);
320 modem = 0;
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;
340 init_device_pppoe();
342 return ret;
347 void plugin_init(void)
350 fatal("PPPoE plugin loading...");
353 #if _linux_
354 if (!ppp_available() && !new_style_driver)
355 fatal("Kernel doesn't support ppp_generic needed for PPPoE");
356 #else
357 fatal("No PPPoE support on this OS");
358 #endif
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,
368 check_options: NULL,
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,
375 close: NULL,
376 cleanup: NULL