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 if( verify_packet(ses, p_in) < 0)
23 if(ses->state != PADO_CODE ){
24 poe_error(ses,"Unexpected packet: %P",p_in);
30 poe_dbglog (ses,"PADO received: %P", p_in);
33 memcpy(&ses->remote, &p_in->addr, sizeof(struct sockaddr_ll));
34 memcpy( &ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll));
36 ses->curr_pkt.hdr->code = PADR_CODE;
38 /* The HOST_UNIQ has been verified already... there's no "if" about this */
39 /* if(ses->filt->htag) */
40 copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_HOST_UNIQ));
42 if (ses->filt->ntag) {
43 ses->curr_pkt.tags[TAG_AC_NAME]=NULL;
45 // copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_NAME));
48 ses->curr_pkt.tags[TAG_SRV_NAME]=NULL;
50 copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_SRV_NAME));
52 copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_COOKIE));
53 copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_RELAY_SID));
55 ses->state = PADS_CODE;
59 send_disc(ses, &ses->curr_pkt);
60 (*p_out) = &ses->curr_pkt;
68 static int std_init_disc(struct session* ses,
69 struct pppoe_packet *p_in,
70 struct pppoe_packet **p_out){
72 memset(&ses->curr_pkt,0, sizeof(struct pppoe_packet));
75 /* Check if already connected */
76 if( ses->state != PADO_CODE ){
80 ses->curr_pkt.hdr = (struct pppoe_hdr*) ses->curr_pkt.buf;
81 ses->curr_pkt.hdr->ver = 1;
82 ses->curr_pkt.hdr->type = 1;
83 ses->curr_pkt.hdr->code = PADI_CODE;
86 memcpy( &ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll));
88 poe_info (ses,"Sending PADI");
90 poe_dbglog (ses,"Sending PADI");
92 ses->retransmits = 0 ;
95 ses->curr_pkt.tags[TAG_AC_NAME]=ses->filt->ntag;
96 poe_info(ses,"overriding AC name\n");
100 ses->curr_pkt.tags[TAG_SRV_NAME]=ses->filt->stag;
103 ses->curr_pkt.tags[TAG_HOST_UNIQ]=ses->filt->htag;
105 send_disc(ses, &ses->curr_pkt);
106 (*p_out)= &ses->curr_pkt;
111 static int std_rcv_pads(struct session* ses,
112 struct pppoe_packet *p_in,
113 struct pppoe_packet **p_out){
114 if( verify_packet(ses, p_in) < 0)
118 poe_dbglog (ses,"Got connection: %x",
119 ntohs(p_in->hdr->sid));
120 poe_info (ses,"Got connection: %x", ntohs(p_in->hdr->sid));
122 ses->sp.sa_family = AF_PPPOX;
123 ses->sp.sa_protocol = PX_PROTO_OE;
124 ses->sp.sa_addr.pppoe.sid = p_in->hdr->sid;
125 memcpy(ses->sp.sa_addr.pppoe.dev,ses->name, IFNAMSIZ);
126 memcpy(ses->sp.sa_addr.pppoe.remote, p_in->addr.sll_addr, ETH_ALEN);
132 static int std_rcv_padt(struct session* ses,
133 struct pppoe_packet *p_in,
134 struct pppoe_packet **p_out){
135 ses->state = PADO_CODE;
140 extern int disc_sock;
141 int client_init_ses (struct session *ses, char* devnam)
145 char dev[IFNAMSIZ+1];
149 /* do error checks here; session name etc are valid */
150 // poe_info (ses,"init_ses: creating socket");
152 /* Make socket if necessary */
155 disc_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
158 "Cannot create PF_PACKET socket for PPPoE discovery\n");
163 /* Check for long format */
164 retval =sscanf(devnam, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2,
165 addr+3, addr+4, addr+5,&sid,dev);
167 /* Verify the device name , construct ses->local */
168 retval = get_sockaddr_ll(devnam,&ses->local);
170 poe_fatal(ses, "client_init_ses: "
171 "Cannot create PF_PACKET socket for PPPoE discovery\n");
174 ses->state = PADO_CODE;
175 memcpy(&ses->remote, &ses->local, sizeof(struct sockaddr_ll) );
177 memset( ses->remote.sll_addr, 0xff, ETH_ALEN);
179 /* long form parsed */
181 /* Verify the device name , construct ses->local */
182 retval = get_sockaddr_ll(dev,&ses->local);
184 poe_fatal(ses,"client_init_ses(2): "
185 "Cannot create PF_PACKET socket for PPPoE discovery\n");
186 ses->state = PADS_CODE;
187 ses->sp.sa_family = AF_PPPOX;
188 ses->sp.sa_protocol = PX_PROTO_OE;
189 ses->sp.sa_addr.pppoe.sid = sid;
191 memcpy(&ses->remote, &ses->local, sizeof(struct sockaddr_ll) );
193 for(; i < ETH_ALEN ; ++i ){
194 ses->sp.sa_addr.pppoe.remote[i] = addr[i];
195 ses->remote.sll_addr[i]=addr[i];
197 memcpy(ses->sp.sa_addr.pppoe.dev, dev, IFNAMSIZ);
203 error("bad device name: %s",devnam);
206 retval = bind( disc_sock ,
207 (struct sockaddr*)&ses->local,
208 sizeof(struct sockaddr_ll));
212 error("bind to PF_PACKET socket failed: %m");
215 ses->fd = socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_OE);
218 poe_fatal(ses,"Failed to create PPPoE socket: %m");
222 ses->init_disc = std_init_disc;
223 ses->rcv_pado = std_rcv_pado;
224 ses->rcv_pads = std_rcv_pads;
225 ses->rcv_padt = std_rcv_padt;
227 /* this should be filter overridable */