CPU: Wrong CPU Load %.
[tomato.git] / release / src / router / ppp / pppoecd / pppoe.c
blob9fd12c0f021950707696538d1e55a7011a11be6c
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 #include <linux/ppp_defs.h>
24 #include <linux/if_pppox.h>
25 #include <linux/if_ppp.h>
26 #else
27 #error this module meant for use with linux only at this time
28 #endif
31 #include <pppd.h>
32 #include <fsm.h>
33 #include <lcp.h>
34 #include <ipcp.h>
35 #include <ccp.h>
36 #include <pathnames.h>
38 const char pppd_version[] = VERSION;
40 #define _PATH_ETHOPT _ROOT_PATH "/etc/ppp/options."
42 #define PPPOE_MTU 1492
43 extern int kill_link;
45 bool pppoe_server=0;
46 char *pppoe_srv_name=NULL;
47 char *pppoe_ac_name=NULL;
48 char *hostuniq = NULL;
49 int retries = 0;
51 int setdevname_pppoe(const char *cp);
53 struct session *ses = NULL;
54 static int connect_pppoe_ses(void)
56 int err;
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);
64 if (err < 0) {
65 poe_error(ses,"Failed to negotiate PPPoE connection: %d %m",errno,errno);
66 return err;
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);
79 if (err < 0) {
80 poe_error(ses,"Failed to connect PPPoE socket: %d %m",errno,errno);
81 return err;
84 /* Once the logging is fixed, print a message here indicating
85 connection parameters */
87 return ses->fd;
90 static void disconnect_pppoe_ses(void)
92 int ret;
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)
102 struct filter *filt;
103 ses=(void *)malloc(sizeof(struct session));
104 if(!ses){
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 ");
111 poe_die (-1);
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)");
120 poe_die(-1);
122 ses->filt->ntag = make_filter_tag(PTT_AC_NAME,
123 strlen(pppoe_ac_name),
124 pppoe_ac_name);
126 if ( ses->filt->ntag== NULL) {
127 poe_error (ses,"failed to malloc for AC name");
128 poe_die(-1);
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)");
137 poe_die(-1);
139 ses->filt->stag = make_filter_tag(PTT_SRV_NAME,
140 strlen(pppoe_srv_name),
141 pppoe_srv_name);
142 if ( ses->filt->stag == NULL) {
143 poe_error (ses,"failed to malloc for service name");
144 poe_die(-1);
148 if (hostuniq) {
149 ses->filt->htag = make_filter_tag(PTT_HOST_UNIQ,
150 strlen(hostuniq),
151 hostuniq);
152 if ( ses->filt->htag == NULL) {
153 poe_error (ses,"failed to malloc for Uniq Host Id ");
154 poe_die(-1);
158 if (retries) {
159 ses->retries=retries;
162 memcpy( ses->name, devnam, IFNAMSIZ);
163 ses->opt_debug=1;
164 ses->fd = -1;
167 static void send_config_pppoe(int mtu,
168 u_int32_t asyncmap,
169 int pcomp,
170 int accomp)
172 int sock;
173 struct ifreq ifr;
175 if (mtu > PPPOE_MTU) {
176 warn("Couldn't increase MTU to %d", mtu);
177 mtu = PPPOE_MTU;
179 sock = socket(AF_INET, SOCK_DGRAM, 0);
180 if (sock < 0)
181 fatal("Couldn't create IP socket: %m");
182 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
183 ifr.ifr_mtu = mtu;
184 if (ioctl(sock, SIOCSIFMTU, (caddr_t) &ifr) < 0)
185 fatal("ioctl(SIOCSIFMTU): %m");
186 (void) close (sock);
190 static void recv_config_pppoe(int mru,
191 u_int32_t asyncmap,
192 int pcomp,
193 int accomp)
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
202 * or die.
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)
211 int ret;
212 char dev[IFNAMSIZ+1];
213 int addr[ETH_ALEN];
214 int sid;
215 option_t *opt;
217 ret =sscanf(cp, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2,
218 addr+3, addr+4, addr+5,&sid,dev);
219 if( ret != 8 ){
221 ret = get_sockaddr_ll(cp,NULL);
222 if (ret < 0)
223 fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
224 if (ret == 1)
225 strncpy(devnam, cp, sizeof(devnam));
226 }else{
227 /* long form parsed */
228 ret = get_sockaddr_ll(dev,NULL);
229 if (ret < 0)
230 fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
232 strncpy(devnam, cp, sizeof(devnam));
233 ret = 1;
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;
262 break;
266 #ifdef CCP_SUPPORT
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;
272 #endif
274 init_device_pppoe();
276 return ret;
279 struct channel pppoe_channel = {
280 options: NULL,
281 process_extra_options: NULL,
282 check_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,
289 close: NULL,
290 cleanup: NULL