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.
16 static int std_rcv_pado(struct session
* ses
,
17 struct pppoe_packet
*p_in
,
18 struct pppoe_packet
**p_out
){
20 struct pppoe_tag
*ac_name
, *srv_name
;
21 char ac
[1024], srv
[1024];
23 if(ses
->state
!= PADO_CODE
){
24 poe_error(ses
,"Unexpected packet: %P",p_in
);
28 if( verify_packet(ses
, p_in
) < 0)
31 LOGX_INFO("Received PADO.");
34 poe_dbglog (ses
,"PADO received: %P", p_in
);
36 memcpy(&ses
->remote
, &p_in
->addr
, sizeof(struct sockaddr_ll
));
37 memcpy(&ses
->curr_pkt
.addr
, &ses
->remote
, sizeof(struct sockaddr_ll
));
39 ses
->curr_pkt
.hdr
->code
= PADR_CODE
;
41 /* The HOST_UNIQ has been verified already... there's no "if" about this */
42 /* if(ses->filt->htag) */
43 copy_tag(&ses
->curr_pkt
,get_tag(p_in
->hdr
,PTT_HOST_UNIQ
));
45 if (ses
->filt
->ntag
) {
46 ses
->curr_pkt
.tags
[TAG_AC_NAME
]=NULL
;
49 ac_name
= get_tag(p_in
->hdr
,PTT_AC_NAME
);
50 srv_name
= get_tag(p_in
->hdr
,PTT_SRV_NAME
);
52 memset(ac
, 0, sizeof(ac
));
53 memset(srv
, 0, sizeof(srv
));
55 strncpy(ac
, ac_name
->tag_data
, ntohs(ac_name
->tag_len
));
56 strncpy(srv
, srv_name
->tag_data
, ntohs(srv_name
->tag_len
));
58 script_setenv("AC_NAME", ac
, 1);
59 script_setenv("SRV_NAME", srv
, 1);
62 ses
->curr_pkt
.tags
[TAG_SRV_NAME
]=NULL
;
64 copy_tag(&ses
->curr_pkt
,get_tag(p_in
->hdr
,PTT_SRV_NAME
));
66 copy_tag(&ses
->curr_pkt
,get_tag(p_in
->hdr
,PTT_AC_COOKIE
));
67 copy_tag(&ses
->curr_pkt
,get_tag(p_in
->hdr
,PTT_RELAY_SID
));
69 ses
->state
= PADS_CODE
;
73 LOGX_INFO("Sending PADR.");
75 send_disc(ses
, &ses
->curr_pkt
);
76 (*p_out
) = &ses
->curr_pkt
;
84 static int std_init_disc(struct session
* ses
,
85 struct pppoe_packet
*p_in
,
86 struct pppoe_packet
**p_out
){
88 /* Check if already connected */
89 if( ses
->state
!= PADO_CODE
){
93 memset(&ses
->curr_pkt
,0, sizeof(struct pppoe_packet
));
95 ses
->curr_pkt
.hdr
= (struct pppoe_hdr
*) ses
->curr_pkt
.buf
;
96 ses
->curr_pkt
.hdr
->ver
= 1;
97 ses
->curr_pkt
.hdr
->type
= 1;
98 ses
->curr_pkt
.hdr
->code
= PADI_CODE
;
101 memcpy( &ses
->curr_pkt
.addr
, &ses
->remote
, sizeof(struct sockaddr_ll
));
103 LOGX_INFO("Sending PADI.");
105 ses
->retransmits
= 0 ;
107 if(ses
->filt
->ntag
) {
108 ses
->curr_pkt
.tags
[TAG_AC_NAME
]=ses
->filt
->ntag
;
109 poe_info(ses
,"overriding AC name\n");
113 ses
->curr_pkt
.tags
[TAG_SRV_NAME
]=ses
->filt
->stag
;
116 ses
->curr_pkt
.tags
[TAG_HOST_UNIQ
]=ses
->filt
->htag
;
118 ses
->retransmits
= 0 ;
120 send_disc(ses
, &ses
->curr_pkt
);
121 (*p_out
)= &ses
->curr_pkt
;
127 static int std_rcv_pads(struct session
* ses
,
128 struct pppoe_packet
*p_in
,
129 struct pppoe_packet
**p_out
){
130 if(ses
->state
!= PADS_CODE
){
131 poe_error(ses
,"Unexpected packet: %P",p_in
);
135 if( verify_packet(ses
, p_in
) < 0)
138 ses
->sp
.sa_family
= AF_PPPOX
;
139 ses
->sp
.sa_protocol
= PX_PROTO_OE
;
140 ses
->sp
.sa_addr
.pppoe
.sid
= p_in
->hdr
->sid
;
141 memcpy(ses
->sp
.sa_addr
.pppoe
.dev
,ses
->name
, IFNAMSIZ
);
142 memcpy(ses
->sp
.sa_addr
.pppoe
.remote
, p_in
->addr
.sll_addr
, ETH_ALEN
);
145 poe_dbglog (ses
,"Got connection: %x %s <--->%E",
146 ses
->sp
.sa_addr
.pppoe
.sid
,
147 ses
->sp
.sa_addr
.pppoe
.dev
, ses
->sp
.sa_addr
.pppoe
.remote
);
149 LOGX_INFO("Received PADS. SID: 0x%04X", ses
->sp
.sa_addr
.pppoe
.sid
);
153 static int std_rcv_padt(struct session
* ses
,
154 struct pppoe_packet
*p_in
,
155 struct pppoe_packet
**p_out
){
157 LOGX_INFO("Received PADT.");
158 ses
->state
= PADO_CODE
;
163 extern int disc_sock
;
165 int client_init_ses (struct session
*ses
, char* devnam
)
169 char dev
[IFNAMSIZ
+1];
173 /* Make socket if necessary */
175 disc_sock
= socket(PF_PACKET
, SOCK_DGRAM
, 0);
177 poe_fatal(ses
, "Cannot create PF_PACKET socket for PPPoE discovery\n");
181 /* Check for long format */
182 retval
=sscanf(devnam
, FMTSTRING(IFNAMSIZ
),addr
, addr
+1, addr
+2,
183 addr
+3, addr
+4, addr
+5,&sid
,dev
);
185 /* Verify the device name , construct ses->local */
186 retval
= get_sockaddr_ll(devnam
,&ses
->local
);
188 poe_fatal(ses
, "client_init_ses: "
189 "Cannot create PF_PACKET socket for PPPoE discovery\n");
192 ses
->state
= PADO_CODE
;
193 memcpy(&ses
->remote
, &ses
->local
, sizeof(struct sockaddr_ll
) );
195 memset( ses
->remote
.sll_addr
, 0xff, ETH_ALEN
);
197 /* long form parsed */
199 /* Verify the device name , construct ses->local */
200 retval
= get_sockaddr_ll(dev
,&ses
->local
);
202 poe_fatal(ses
,"client_init_ses(2): "
203 "Cannot create PF_PACKET socket for PPPoE discovery\n");
204 ses
->state
= PADS_CODE
;
205 ses
->sp
.sa_family
= AF_PPPOX
;
206 ses
->sp
.sa_protocol
= PX_PROTO_OE
;
207 ses
->sp
.sa_addr
.pppoe
.sid
= sid
;
209 memcpy(&ses
->remote
, &ses
->local
, sizeof(struct sockaddr_ll
) );
211 for(; i
< ETH_ALEN
; ++i
){
212 ses
->sp
.sa_addr
.pppoe
.remote
[i
] = addr
[i
];
213 ses
->remote
.sll_addr
[i
]=addr
[i
];
215 memcpy(ses
->sp
.sa_addr
.pppoe
.dev
, dev
, IFNAMSIZ
);
221 error("bad device name: %s",devnam
);
225 poe_dbglog (ses
,"Local ETH %E", ses
->local
.sll_addr
);
228 retval
= bind( disc_sock
,
229 (struct sockaddr
*)&ses
->local
,
230 sizeof(struct sockaddr_ll
));
234 error("bind to PF_PACKET socket failed: %m");
237 /* Make socket if necessary */
239 ses
->fd
= socket(AF_PPPOX
,SOCK_STREAM
,PX_PROTO_OE
);
242 poe_fatal(ses
,"Failed to create PPPoE socket: %m");
247 ses
->init_disc
= std_init_disc
;
248 ses
->rcv_pado
= std_rcv_pado
;
249 ses
->rcv_pads
= std_rcv_pads
;
250 ses
->rcv_padt
= std_rcv_padt
;
252 /* this should be filter overridable */
253 ses
->retries
= retry_num
;