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 |
* timeout -- don't wait more than timeout |
208 |
*%RETURNS: |
209 |
* -1: error |
210 |
* 0: timed out |
211 |
* 1: packet recived |
212 |
*%DESCRIPTION: |
213 |
* recive and filter junk packets |
214 |
***********************************************************************/ |
215 |
|
216 |
static int |
217 |
recvPacketForMe(PPPoEPacket *packet, int *len, PPPoEConnection *conn, int timeout) |
218 |
{ |
219 |
|
220 |
fd_set readable; |
221 |
int r; |
222 |
struct timeval tv; |
223 |
time_t start, now; |
224 |
int time_remain; |
225 |
|
226 |
start = time(&now); |
227 |
do { |
228 |
time(&now); |
229 |
time_remain = timeout - (int)difftime(now, start); |
230 |
if (time_remain > timeout) time_remain = timeout; |
231 |
|
232 |
if (time_remain <= 0) /* Timed out */ |
233 |
return 0; |
234 |
|
235 |
if (BPF_BUFFER_IS_EMPTY) { |
236 |
tv.tv_sec = time_remain; |
237 |
tv.tv_usec = 0; |
238 |
|
239 |
FD_ZERO(&readable); |
240 |
FD_SET(conn->discoverySocket, &readable); |
241 |
|
242 |
r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); |
243 |
if (r < 0) |
244 |
{ |
245 |
if (errno == EINTR) |
246 |
{ |
247 |
continue; /* interrupted, so retry */ |
248 |
}else /* select error */ |
249 |
{ |
250 |
error("pppoe: recvPacketForMe: select: %m"); |
251 |
return -1; |
252 |
} |
253 |
} |
254 |
|
255 |
if (r == 0) return 0; /* Timed out */ |
256 |
} |
257 |
|
258 |
/* Get the packet */ |
259 |
receivePacket(conn->discoverySocket, packet, len); |
260 |
|
261 |
/* Check length */ |
262 |
if (ntohs(packet->length) + HDR_SIZE > *len) { |
263 |
error("Bogus PPPoE length field (%u)", |
264 |
(unsigned int) ntohs(packet->length)); |
265 |
continue; |
266 |
} |
267 |
|
268 |
#ifdef USE_BPF |
269 |
/* If it's not a Discovery packet, loop again */ |
270 |
if (etherType(&packet) != Eth_PPPOE_Discovery) continue; |
271 |
#endif |
272 |
|
273 |
/* If it's not for us, loop again */ |
274 |
}while ( ! packetIsForMe(conn, packet)); |
275 |
|
276 |
return 1; |
277 |
} |
278 |
|
279 |
|
199 |
/*********************************************************************** |
280 |
/*********************************************************************** |
200 |
*%FUNCTION: sendPADI |
281 |
*%FUNCTION: sendPADI |
201 |
*%ARGUMENTS: |
282 |
*%ARGUMENTS: |
Lines 277-287
Link Here
|
277 |
void |
358 |
void |
278 |
waitForPADO(PPPoEConnection *conn, int timeout) |
359 |
waitForPADO(PPPoEConnection *conn, int timeout) |
279 |
{ |
360 |
{ |
280 |
fd_set readable; |
|
|
281 |
int r; |
361 |
int r; |
282 |
struct timeval tv; |
|
|
283 |
PPPoEPacket packet; |
362 |
PPPoEPacket packet; |
284 |
int len; |
363 |
int len; |
|
|
364 |
time_t start, now; |
365 |
int time_remain; |
285 |
|
366 |
|
286 |
struct PacketCriteria pc; |
367 |
struct PacketCriteria pc; |
287 |
pc.conn = conn; |
368 |
pc.conn = conn; |
Lines 291-332
Link Here
|
291 |
pc.seenServiceName = 0; |
372 |
pc.seenServiceName = 0; |
292 |
conn->error = 0; |
373 |
conn->error = 0; |
293 |
|
374 |
|
|
|
375 |
start = time(&now); |
294 |
do { |
376 |
do { |
295 |
if (BPF_BUFFER_IS_EMPTY) { |
377 |
time(&now); |
296 |
tv.tv_sec = timeout; |
378 |
time_remain = timeout - (int)difftime(now, start); |
297 |
tv.tv_usec = 0; |
379 |
if (time_remain > timeout) time_remain = timeout; |
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 |
|
380 |
|
323 |
#ifdef USE_BPF |
381 |
if (time_remain <= 0) return; /* Timed out */ |
324 |
/* If it's not a Discovery packet, loop again */ |
|
|
325 |
if (etherType(&packet) != Eth_PPPOE_Discovery) continue; |
326 |
#endif |
327 |
|
382 |
|
328 |
/* If it's not for us, loop again */ |
383 |
r = recvPacketForMe(&packet, &len, conn, time_remain); |
329 |
if (!packetIsForMe(conn, &packet)) continue; |
384 |
if (r<=0) return; /* Timed out or error */ |
330 |
|
385 |
|
331 |
if (packet.code == CODE_PADO) { |
386 |
if (packet.code == CODE_PADO) { |
332 |
if (NOT_UNICAST(packet.ethHdr.h_source)) { |
387 |
if (NOT_UNICAST(packet.ethHdr.h_source)) { |
Lines 447-498
Link Here
|
447 |
static void |
502 |
static void |
448 |
waitForPADS(PPPoEConnection *conn, int timeout) |
503 |
waitForPADS(PPPoEConnection *conn, int timeout) |
449 |
{ |
504 |
{ |
450 |
fd_set readable; |
|
|
451 |
int r; |
505 |
int r; |
452 |
struct timeval tv; |
|
|
453 |
PPPoEPacket packet; |
506 |
PPPoEPacket packet; |
454 |
int len; |
507 |
int len; |
|
|
508 |
time_t start, now; |
509 |
int time_remain; |
455 |
|
510 |
|
|
|
511 |
start = time(&now); |
456 |
conn->error = 0; |
512 |
conn->error = 0; |
457 |
do { |
513 |
do { |
458 |
if (BPF_BUFFER_IS_EMPTY) { |
514 |
time(&now); |
459 |
tv.tv_sec = timeout; |
515 |
time_remain = timeout - (int)difftime(now, start); |
460 |
tv.tv_usec = 0; |
516 |
if (time_remain > timeout) time_remain = timeout; |
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 |
|
517 |
|
491 |
/* If it's not from the AC, it's not for me */ |
518 |
if (time_remain <= 0) return; /* Timed out */ |
492 |
if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue; |
|
|
493 |
|
519 |
|
494 |
/* If it's not for us, loop again */ |
520 |
r = recvPacketForMe(&packet, &len, conn, time_remain); |
495 |
if (!packetIsForMe(conn, &packet)) continue; |
521 |
if (r<=0) return; /* Timed out or error */ |
496 |
|
522 |
|
497 |
/* Is it PADS? */ |
523 |
/* Is it PADS? */ |
498 |
if (packet.code == CODE_PADS) { |
524 |
if (packet.code == CODE_PADS) { |