Lines 37-42
Link Here
|
37 |
#endif |
37 |
#endif |
38 |
|
38 |
|
39 |
#include <signal.h> |
39 |
#include <signal.h> |
|
|
40 |
#include <time.h> |
40 |
|
41 |
|
41 |
/********************************************************************** |
42 |
/********************************************************************** |
42 |
*%FUNCTION: parseForHostUniq |
43 |
*%FUNCTION: parseForHostUniq |
Lines 196-201
Link Here
|
196 |
} |
197 |
} |
197 |
} |
198 |
} |
198 |
|
199 |
|
|
|
200 |
|
201 |
/********************************************************************** |
202 |
*%FUNCTION: recvPacketForMe |
203 |
*%ARGUMENTS: |
204 |
* packet -- output parameter |
205 |
* len -- output parameter length |
206 |
* conn -- connection |
207 |
* start -- operation startup timestamp |
208 |
* timeout -- how long to wait (in seconds) |
209 |
*%RETURNS: |
210 |
* -1: error |
211 |
* 0: timed out |
212 |
* 1: packet received |
213 |
*%DESCRIPTION: |
214 |
* receive and filter junk packets |
215 |
***********************************************************************/ |
216 |
|
217 |
static int |
218 |
recvPacketForMe(PPPoEPacket *packet, int *len, PPPoEConnection *conn, time_t start, int timeout) |
219 |
{ |
220 |
|
221 |
fd_set readable; |
222 |
int r; |
223 |
struct timeval tv; |
224 |
time_t now; |
225 |
int time_remain; |
226 |
|
227 |
do { |
228 |
time(&now); |
229 |
time_remain = timeout - ((int)now - (int)start); |
230 |
if (time_remain <= 0) return 0; /* Timed out */ |
231 |
|
232 |
if (BPF_BUFFER_IS_EMPTY) { |
233 |
tv.tv_sec = time_remain; |
234 |
tv.tv_usec = 0; |
235 |
|
236 |
FD_ZERO(&readable); |
237 |
FD_SET(conn->discoverySocket, &readable); |
238 |
|
239 |
r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); |
240 |
if (r < 0) |
241 |
{ |
242 |
if (errno == EINTR) |
243 |
{ |
244 |
continue; /* interrupted, so retry */ |
245 |
}else /* select error */ |
246 |
{ |
247 |
error("pppoe: recvPacketForMe: select: %m"); |
248 |
return -1; |
249 |
} |
250 |
} |
251 |
|
252 |
if (r == 0) return 0; /* Timed out */ |
253 |
} |
254 |
|
255 |
/* Get the packet */ |
256 |
receivePacket(conn->discoverySocket, packet, len); |
257 |
|
258 |
/* Check length */ |
259 |
if (ntohs(packet->length) + HDR_SIZE > *len) { |
260 |
error("Bogus PPPoE length field (%u)", |
261 |
(unsigned int) ntohs(packet->length)); |
262 |
continue; |
263 |
} |
264 |
|
265 |
#ifdef USE_BPF |
266 |
/* If it's not a Discovery packet, loop again */ |
267 |
if (etherType(&packet) != Eth_PPPOE_Discovery) continue; |
268 |
#endif |
269 |
|
270 |
/* If it's not for us, loop again */ |
271 |
}while ( ! packetIsForMe(conn, packet)); |
272 |
|
273 |
return 1; |
274 |
} |
275 |
|
276 |
|
199 |
/*********************************************************************** |
277 |
/*********************************************************************** |
200 |
*%FUNCTION: sendPADI |
278 |
*%FUNCTION: sendPADI |
201 |
*%ARGUMENTS: |
279 |
*%ARGUMENTS: |
Lines 277-287
Link Here
|
277 |
void |
355 |
void |
278 |
waitForPADO(PPPoEConnection *conn, int timeout) |
356 |
waitForPADO(PPPoEConnection *conn, int timeout) |
279 |
{ |
357 |
{ |
280 |
fd_set readable; |
|
|
281 |
int r; |
358 |
int r; |
282 |
struct timeval tv; |
|
|
283 |
PPPoEPacket packet; |
359 |
PPPoEPacket packet; |
284 |
int len; |
360 |
int len; |
|
|
361 |
time_t start; |
285 |
|
362 |
|
286 |
struct PacketCriteria pc; |
363 |
struct PacketCriteria pc; |
287 |
pc.conn = conn; |
364 |
pc.conn = conn; |
Lines 291-332
Link Here
|
291 |
pc.seenServiceName = 0; |
368 |
pc.seenServiceName = 0; |
292 |
conn->error = 0; |
369 |
conn->error = 0; |
293 |
|
370 |
|
|
|
371 |
time(&start); |
294 |
do { |
372 |
do { |
295 |
if (BPF_BUFFER_IS_EMPTY) { |
373 |
r = recvPacketForMe(&packet, &len, conn, start, timeout); |
296 |
tv.tv_sec = timeout; |
374 |
if (r<=0) return; /* Timed out or error */ |
297 |
tv.tv_usec = 0; |
|
|
298 |
|
299 |
FD_ZERO(&readable); |
300 |
FD_SET(conn->discoverySocket, &readable); |
301 |
|
302 |
while(1) { |
303 |
r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); |
304 |
if (r >= 0 || errno != EINTR) break; |
305 |
} |
306 |
if (r < 0) { |
307 |
error("select (waitForPADO): %m"); |
308 |
return; |
309 |
} |
310 |
if (r == 0) return; /* Timed out */ |
311 |
} |
312 |
|
313 |
/* Get the packet */ |
314 |
receivePacket(conn->discoverySocket, &packet, &len); |
315 |
|
316 |
/* Check length */ |
317 |
if (ntohs(packet.length) + HDR_SIZE > len) { |
318 |
error("Bogus PPPoE length field (%u)", |
319 |
(unsigned int) ntohs(packet.length)); |
320 |
continue; |
321 |
} |
322 |
|
323 |
#ifdef USE_BPF |
324 |
/* If it's not a Discovery packet, loop again */ |
325 |
if (etherType(&packet) != Eth_PPPOE_Discovery) continue; |
326 |
#endif |
327 |
|
328 |
/* If it's not for us, loop again */ |
329 |
if (!packetIsForMe(conn, &packet)) continue; |
330 |
|
375 |
|
331 |
if (packet.code == CODE_PADO) { |
376 |
if (packet.code == CODE_PADO) { |
332 |
if (NOT_UNICAST(packet.ethHdr.h_source)) { |
377 |
if (NOT_UNICAST(packet.ethHdr.h_source)) { |
Lines 447-499
Link Here
|
447 |
static void |
492 |
static void |
448 |
waitForPADS(PPPoEConnection *conn, int timeout) |
493 |
waitForPADS(PPPoEConnection *conn, int timeout) |
449 |
{ |
494 |
{ |
450 |
fd_set readable; |
|
|
451 |
int r; |
495 |
int r; |
452 |
struct timeval tv; |
|
|
453 |
PPPoEPacket packet; |
496 |
PPPoEPacket packet; |
454 |
int len; |
497 |
int len; |
|
|
498 |
time_t start; |
455 |
|
499 |
|
|
|
500 |
time(&start); |
456 |
conn->error = 0; |
501 |
conn->error = 0; |
457 |
do { |
502 |
do { |
458 |
if (BPF_BUFFER_IS_EMPTY) { |
503 |
r = recvPacketForMe(&packet, &len, conn, start, timeout); |
459 |
tv.tv_sec = timeout; |
504 |
if (r<=0) return; /* Timed out or error */ |
460 |
tv.tv_usec = 0; |
|
|
461 |
|
462 |
FD_ZERO(&readable); |
463 |
FD_SET(conn->discoverySocket, &readable); |
464 |
|
465 |
while(1) { |
466 |
r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); |
467 |
if (r >= 0 || errno != EINTR) break; |
468 |
} |
469 |
if (r < 0) { |
470 |
error("select (waitForPADS): %m"); |
471 |
return; |
472 |
} |
473 |
if (r == 0) return; |
474 |
} |
475 |
|
476 |
/* Get the packet */ |
477 |
receivePacket(conn->discoverySocket, &packet, &len); |
478 |
|
479 |
/* Check length */ |
480 |
if (ntohs(packet.length) + HDR_SIZE > len) { |
481 |
error("Bogus PPPoE length field (%u)", |
482 |
(unsigned int) ntohs(packet.length)); |
483 |
continue; |
484 |
} |
485 |
|
486 |
#ifdef USE_BPF |
487 |
/* If it's not a Discovery packet, loop again */ |
488 |
if (etherType(&packet) != Eth_PPPOE_Discovery) continue; |
489 |
#endif |
490 |
|
505 |
|
491 |
/* If it's not from the AC, it's not for me */ |
506 |
/* If it's not from the AC, it's not for me */ |
492 |
if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue; |
507 |
if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue; |
493 |
|
508 |
|
494 |
/* If it's not for us, loop again */ |
|
|
495 |
if (!packetIsForMe(conn, &packet)) continue; |
496 |
|
497 |
/* Is it PADS? */ |
509 |
/* Is it PADS? */ |
498 |
if (packet.code == CODE_PADS) { |
510 |
if (packet.code == CODE_PADS) { |
499 |
/* Parse for goodies */ |
511 |
/* Parse for goodies */ |