Correct utmp handling - Robert Davidson <puttputt@iaccess.ws>
[ppp.git] / pppd / plugins / pppoe / pppoe_client.c
1 /* PPPoE support library "libpppoe"
2  *
3  * Copyright 2000 Michal Ostrowski <mostrows@styx.uwaterloo.ca>,
4  *                Jamal Hadi Salim <hadi@cyberus.ca>
5  *
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.
10  */
11
12 #include "pppoe.h"
13
14
15
16 static int std_rcv_pado(struct session* ses,
17                         struct pppoe_packet *p_in,
18                         struct pppoe_packet **p_out){
19     
20     if( verify_packet(ses, p_in) < 0)
21         return -1;
22     
23     if(ses->state != PADO_CODE ){
24         poe_error(ses,"Unexpected packet: %P",p_in);
25         return 0;
26     }
27     
28     
29     if (DEB_DISC2) {
30         poe_dbglog (ses,"PADO received: %P", p_in);
31     }
32     
33     memcpy(&ses->remote, &p_in->addr, sizeof(struct sockaddr_ll));
34     memcpy( &ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll));
35     
36     ses->curr_pkt.hdr->code = PADR_CODE;
37     
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));  
41     
42     if (ses->filt->ntag) {
43         ses->curr_pkt.tags[TAG_AC_NAME]=NULL;
44     }
45 //    copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_AC_NAME));
46     
47     if(ses->filt->stag) {
48         ses->curr_pkt.tags[TAG_SRV_NAME]=NULL;
49     }
50     copy_tag(&ses->curr_pkt,get_tag(p_in->hdr,PTT_SRV_NAME));
51     
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));
54     
55     ses->state = PADS_CODE;
56     
57     ses->retransmits = 0;
58     
59     send_disc(ses, &ses->curr_pkt);
60     (*p_out) = &ses->curr_pkt;
61     
62     if (ses->np)
63         return 1;
64     
65     return 0;
66 }
67
68 static int std_init_disc(struct session* ses,
69                          struct pppoe_packet *p_in,
70                          struct pppoe_packet **p_out){
71     
72     memset(&ses->curr_pkt,0, sizeof(struct pppoe_packet));
73
74     
75     /* Check if already connected */
76     if( ses->state != PADO_CODE ){
77         return 1;
78     }
79     
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;
84     
85     
86     memcpy( &ses->curr_pkt.addr, &ses->remote , sizeof(struct sockaddr_ll));
87     
88     poe_info (ses,"Sending PADI");
89     if (DEB_DISC)
90         poe_dbglog (ses,"Sending PADI");
91     
92     ses->retransmits = 0 ;
93     
94     if(ses->filt->ntag) {
95         ses->curr_pkt.tags[TAG_AC_NAME]=ses->filt->ntag;
96         poe_info(ses,"overriding AC name\n");
97     }
98     
99     if(ses->filt->stag)
100         ses->curr_pkt.tags[TAG_SRV_NAME]=ses->filt->stag;
101     
102     if(ses->filt->htag)
103         ses->curr_pkt.tags[TAG_HOST_UNIQ]=ses->filt->htag;
104     
105     send_disc(ses, &ses->curr_pkt);
106     (*p_out)= &ses->curr_pkt;
107     return 0;
108 }
109
110
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)
115         return -1;
116     
117     if (DEB_DISC)
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));
121     
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);
127     
128     
129     return 1;
130 }
131
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;
136     return 0;
137 }
138
139
140 extern int disc_sock;
141 int client_init_ses (struct session *ses, char* devnam)
142 {
143     int i=0;
144     int retval;
145     char dev[IFNAMSIZ+1];
146     int addr[ETH_ALEN];
147     int sid;
148     
149     /* do error checks here; session name etc are valid */
150 //    poe_info (ses,"init_ses: creating socket");
151     
152     /* Make socket if necessary */
153     if( disc_sock < 0 ){
154         
155         disc_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
156         if( disc_sock < 0 ){
157             poe_fatal(ses,
158                       "Cannot create PF_PACKET socket for PPPoE discovery\n");
159         }
160         
161     }
162     
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);
166     if( retval != 8 ){
167         /* Verify the device name , construct ses->local */
168         retval = get_sockaddr_ll(devnam,&ses->local);
169         if (retval < 0)
170             poe_fatal(ses, "client_init_ses: "
171                       "Cannot create PF_PACKET socket for PPPoE discovery\n");
172         
173         
174         ses->state = PADO_CODE;
175         memcpy(&ses->remote, &ses->local, sizeof(struct sockaddr_ll) );
176         
177         memset( ses->remote.sll_addr, 0xff, ETH_ALEN);
178     }else{
179         /* long form parsed */
180
181         /* Verify the device name , construct ses->local */
182         retval = get_sockaddr_ll(dev,&ses->local);
183         if (retval < 0)
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;
190         
191         memcpy(&ses->remote, &ses->local, sizeof(struct sockaddr_ll) );
192         
193         for(; i < ETH_ALEN ; ++i ){
194             ses->sp.sa_addr.pppoe.remote[i] = addr[i];
195             ses->remote.sll_addr[i]=addr[i];
196         }
197         memcpy(ses->sp.sa_addr.pppoe.dev, dev, IFNAMSIZ);
198         
199         
200         
201     }
202     if( retval < 0 )
203         error("bad device name: %s",devnam);
204     
205     
206     retval = bind( disc_sock ,
207                    (struct sockaddr*)&ses->local,
208                    sizeof(struct sockaddr_ll));
209     
210     
211     if( retval < 0 ){
212         error("bind to PF_PACKET socket failed: %m");
213     }
214     
215     ses->fd = socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_OE);
216     if(ses->fd < 0)
217     {
218         poe_fatal(ses,"Failed to create PPPoE socket: %m");
219     }
220     
221     
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;
226     
227     /* this should be filter overridable */
228     ses->retries = 10;
229     
230     return ses->fd;
231 }
232