CPU: Wrong CPU Load %.
[tomato.git] / release / src / router / ppp / pppd / plugins / pppoe / pppoe_relay.c
blobcddf25771b83e348e0822c262cafa93ff1971955
1 /* PPPoE support library "libpppoe"
3 * Copyright 2000 Michal Ostrowski <mostrows@styx.uwaterloo.ca>,
4 * Jamal Hadi Salim <hadi@cyberus.ca>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include "pppoe.h"
14 static int relay_init_disc(struct session* ses,
15 struct pppoe_packet *p_in,
16 struct pppoe_packet **p_out){
18 ses->state = 0;
19 ses->retransmits = -1 ;
20 ses->retries = -1;
22 (*p_out) = NULL;
23 return 0;
26 static int pcid=0;
27 static int relay_rcv_padi(struct session* ses,
28 struct pppoe_packet *p_in,
29 struct pppoe_packet **p_out){
30 char tag_buf[32];
31 struct pppoe_con *newpc = NULL;
32 struct pppoe_tag *tag = (struct pppoe_tag *) tag_buf;
35 tag->tag_type = PTT_RELAY_SID;
36 tag->tag_len = htons(ETH_ALEN + sizeof(struct session *));
38 memcpy(tag->tag_data, p_in->addr.sll_addr, ETH_ALEN);
39 memcpy(tag->tag_data + ETH_ALEN, &ses, sizeof(struct session *));
41 if(! p_in->tags[TAG_RELAY_SID] ){
42 copy_tag(p_in, tag);
46 poe_dbglog(ses, "Recv'd PADI: %P",p_in);
47 poe_dbglog(ses, "Recv'd packet: %P",p_in);
48 newpc = get_con( ntohs(tag->tag_len), tag->tag_data );
49 if(!newpc){
51 newpc = (struct pppoe_con *) malloc(sizeof(struct pppoe_con));
52 memset(newpc , 0, sizeof(struct pppoe_con));
54 newpc->id = pcid++;
56 newpc->key_len = ntohs(p_in->tags[TAG_RELAY_SID]->tag_len);
57 memcpy(newpc->key, p_in->tags[TAG_RELAY_SID]->tag_data, newpc->key_len);
58 memcpy(newpc->client, p_in->addr.sll_addr, ETH_ALEN);
60 memcpy(newpc->server, MAC_BCAST_ADDR, ETH_ALEN);
62 store_con(newpc);
66 ++newpc->ref_count;
68 memset(p_in->addr.sll_addr, 0xff, ETH_ALEN);
70 p_in->addr.sll_ifindex = ses->remote.sll_ifindex;
72 send_disc(ses, p_in);
73 return 0;
76 static int relay_rcv_pkt(struct session* ses,
77 struct pppoe_packet *p_in,
78 struct pppoe_packet **p_out){
79 struct pppoe_con *pc;
80 char tag_buf[32];
81 struct pppoe_tag *tag = p_in->tags[TAG_RELAY_SID];
83 if( !tag ) return 0;
85 pc = get_con(ntohs(tag->tag_len),tag->tag_data);
87 if( !pc ) return 0;
89 poe_dbglog(ses, "Recv'd packet: %P",p_in);
91 if( memcmp(pc->client , p_in->addr.sll_addr , ETH_ALEN ) == 0 ){
93 memcpy(p_in->addr.sll_addr, pc->server, ETH_ALEN);
94 p_in->addr.sll_ifindex = ses->remote.sll_ifindex;
96 }else{
97 if( memcmp(pc->server, MAC_BCAST_ADDR, ETH_ALEN) == 0 ){
98 memcpy(pc->server, p_in->addr.sll_addr, ETH_ALEN);
100 }else if( memcmp(pc->server, p_in->addr.sll_addr, ETH_ALEN) !=0){
101 return 0;
104 memcpy(p_in->addr.sll_addr, pc->client, ETH_ALEN);
105 p_in->addr.sll_ifindex = ses->local.sll_ifindex;
111 send_disc(ses, p_in);
112 return 0;
115 static int relay_rcv_pads(struct session* ses,
116 struct pppoe_packet *p_in,
117 struct pppoe_packet **p_out){
119 struct pppoe_con *pc;
120 char tag_buf[32];
121 struct pppoe_tag *tag = p_in->tags[TAG_RELAY_SID];
122 struct sockaddr_pppox sp_cl= { AF_PPPOX, PX_PROTO_OE,
123 { p_in->hdr->sid, {0,},{0,}}};
125 struct sockaddr_pppox sp_sv= { AF_PPPOX, PX_PROTO_OE,
126 { p_in->hdr->sid, {0,},{0,}}};
128 int ret;
131 if( !tag ) return 0;
133 pc = get_con(ntohs(tag->tag_len),tag->tag_data);
135 if( !pc ) return 0;
138 if(!pc->connected){
140 pc->sv_sock = socket( AF_PPPOX, SOCK_DGRAM, PX_PROTO_OE);
141 if( pc->sv_sock < 0){
142 poe_fatal(ses,"Cannot open PPPoE socket: %i",errno);
145 pc->cl_sock = socket( AF_PPPOX, SOCK_DGRAM, PX_PROTO_OE);
146 if( pc->cl_sock < 0){
147 poe_fatal(ses,"Cannot open PPPoE socket: %i",errno);
150 memcpy( sp_sv.sa_addr.pppoe.dev, ses->fwd_name, IFNAMSIZ);
151 memcpy( sp_sv.sa_addr.pppoe.remote, pc->server, ETH_ALEN);
153 ret = connect( pc->sv_sock,
154 (struct sockaddr*)&sp_sv,
155 sizeof(struct sockaddr_pppox));
156 if( ret < 0){
157 poe_fatal(ses,"Cannot connect PPPoE socket: %i",errno);
160 memcpy( sp_cl.sa_addr.pppoe.dev, ses->name, IFNAMSIZ);
161 memcpy( sp_cl.sa_addr.pppoe.remote, pc->client, ETH_ALEN);
163 ret = connect( pc->cl_sock,
164 (struct sockaddr*)&sp_cl,
165 sizeof(struct sockaddr_pppox));
166 if( ret < 0){
167 poe_fatal(ses,"Cannot connect PPPoE socket: %i",errno);
171 ret = ioctl( pc->sv_sock, PPPOEIOCSFWD, &sp_cl);
172 if( ret < 0){
173 poe_fatal(ses,"Cannot set forwarding on PPPoE socket: %i",errno);
176 ret = ioctl( pc->cl_sock, PPPOEIOCSFWD, &sp_sv);
177 if( ret < 0){
178 poe_fatal(ses,"Cannot set forwarding on PPPoE socket: %i",errno);
181 pc->connected = 1;
184 poe_info(ses,"PPPoE relay for %E established to %E (sid=%04x)\n",
185 pc->client,pc->server, p_in->hdr->sid);
187 return relay_rcv_pkt(ses,p_in,p_out);
191 static int relay_rcv_padt(struct session* ses,
192 struct pppoe_packet *p_in,
193 struct pppoe_packet **p_out){
195 int ret;
196 struct pppoe_con *pc;
197 char tag_buf[32];
198 struct pppoe_tag *tag = p_in->tags[TAG_RELAY_SID];
200 if( !tag ) return 0;
202 pc = get_con(ntohs(tag->tag_len),tag->tag_data);
204 if( !pc ) return 0;
206 ret = relay_rcv_pkt(ses,p_in,p_out);
209 if(pc->cl_sock>0){
210 close(pc->cl_sock);
213 if(pc->sv_sock>0){
214 close(pc->sv_sock);
217 --pc->ref_count;
218 if( pc->ref_count == 0 ){
219 delete_con(pc->key_len, pc->key);
221 free(pc);
226 int relay_init_ses(struct session *ses, char* from, char* to)
228 int retval = client_init_ses(ses, from);
230 if(retval<0) return retval;
232 ses->fwd_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
233 if( ses->fwd_sock < 0 ) {
234 poe_fatal(ses,"Cannot create PF_PACKET socket for PPPoE forwarding\n");
237 /* Verify the device name , construct ses->local */
238 retval = get_sockaddr_ll(to, &ses->remote);
239 if (retval < 0)
240 poe_fatal(ses,"relay_init_ses:get_sockaddr_ll failed %m");
242 retval = bind( ses->fwd_sock ,
243 (struct sockaddr*)&ses->remote,
244 sizeof(struct sockaddr_ll));
246 if( retval < 0 ){
247 poe_fatal(ses,"bind to PF_PACKET socket failed: %m");
250 memcpy(ses->fwd_name, to, IFNAMSIZ);
251 memcpy(ses->name, from, IFNAMSIZ);
254 ses->init_disc = relay_init_disc;
255 ses->rcv_padi = relay_rcv_padi;
256 ses->rcv_pado = relay_rcv_pkt;
257 ses->rcv_padr = relay_rcv_pkt;
258 ses->rcv_pads = relay_rcv_pads;
259 ses->rcv_padt = relay_rcv_padt;