18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* discovery.c
48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Perform PPPoE discovery
68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Copyright (C) 1999 by Roaring Penguin Software Inc.
88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic char const RCSID[] =
128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project"$Id: discovery.c,v 1.3 2004/11/04 10:07:37 paulus Exp $";
138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "pppoe.h"
158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_SYSLOG_H
178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <syslog.h>
188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <string.h>
218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdlib.h>
228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <errno.h>
238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_SYS_TIME_H
258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/time.h>
268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_SYS_UIO_H
298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/uio.h>
308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_UNISTD_H
338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <unistd.h>
348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_LINUX_PACKET
378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/ioctl.h>
388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <fcntl.h>
398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <signal.h>
428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: parseForHostUniq
458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- tag type
478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* len -- tag length
488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* data -- tag data.
498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* extra -- user-supplied pointer.  This is assumed to be a pointer to int.
508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* If a HostUnique tag is found which matches our PID, sets *extra to 1.
548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectparseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data,
578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		 void *extra)
588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int *val = (int *) extra;
608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (type == TAG_HOST_UNIQ && len == sizeof(pid_t)) {
618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	pid_t tmp;
628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(&tmp, data, len);
638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (tmp == getpid()) {
648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    *val = 1;
658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: packetIsForMe
718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* conn -- PPPoE connection info
738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* packet -- a received PPPoE packet
748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* 1 if packet is for this PPPoE daemon; 0 otherwise.
768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* If we are using the Host-Unique tag, verifies that packet contains
788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* our unique identifier.
798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint
818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectpacketIsForMe(PPPoEConnection *conn, PPPoEPacket *packet)
828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int forMe = 0;
848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* If packet is not directed to our MAC address, forget it */
868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (memcmp(packet->ethHdr.h_dest, conn->myEth, ETH_ALEN)) return 0;
878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* If we're not using the Host-Unique tag, then accept the packet */
898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!conn->useHostUniq) return 1;
908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    parsePacket(packet, parseForHostUniq, &forMe);
928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return forMe;
938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: parsePADOTags
978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- tag type
998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* len -- tag length
1008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* data -- tag data
1018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* extra -- extra user data.  Should point to a PacketCriteria structure
1028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*          which gets filled in according to selected AC name and service
1038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*          name.
1048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
1058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
1068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
1078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Picks interesting tags out of a PADO packet
1088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
1098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
1108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectparsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data,
1118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	      void *extra)
1128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct PacketCriteria *pc = (struct PacketCriteria *) extra;
1148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoEConnection *conn = pc->conn;
1158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int i;
1168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    switch(type) {
1188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_AC_NAME:
1198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	pc->seenACName = 1;
1208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->printACNames) {
1218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("Access-Concentrator: %.*s\n", (int) len, data);
1228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->acName && len == strlen(conn->acName) &&
1248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    !strncmp((char *) data, conn->acName, len)) {
1258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    pc->acNameOK = 1;
1268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
1288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_SERVICE_NAME:
1298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	pc->seenServiceName = 1;
1308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->printACNames && len > 0) {
1318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("       Service-Name: %.*s\n", (int) len, data);
1328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->serviceName && len == strlen(conn->serviceName) &&
1348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    !strncmp((char *) data, conn->serviceName, len)) {
1358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    pc->serviceNameOK = 1;
1368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
1388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_AC_COOKIE:
1398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->printACNames) {
1408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("Got a cookie:");
1418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    /* Print first 20 bytes of cookie */
1428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    for (i=0; i<len && i < 20; i++) {
1438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printf(" %02x", (unsigned) data[i]);
1448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
1458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (i < len) printf("...");
1468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("\n");
1478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->cookie.type = htons(type);
1498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->cookie.length = htons(len);
1508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(conn->cookie.payload, data, len);
1518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
1528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_RELAY_SESSION_ID:
1538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->printACNames) {
1548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("Got a Relay-ID:");
1558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    /* Print first 20 bytes of relay ID */
1568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    for (i=0; i<len && i < 20; i++) {
1578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printf(" %02x", (unsigned) data[i]);
1588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
1598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (i < len) printf("...");
1608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("\n");
1618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->relayId.type = htons(type);
1638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->relayId.length = htons(len);
1648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(conn->relayId.payload, data, len);
1658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
1668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_SERVICE_NAME_ERROR:
1678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->printACNames) {
1688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("Got a Service-Name-Error tag: %.*s\n", (int) len, data);
1698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	} else {
1708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    syslog(LOG_ERR, "PADO: Service-Name-Error: %.*s", (int) len, data);
1718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    exit(1);
1728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
1748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_AC_SYSTEM_ERROR:
1758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->printACNames) {
1768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("Got a System-Error tag: %.*s\n", (int) len, data);
1778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	} else {
1788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    syslog(LOG_ERR, "PADO: System-Error: %.*s", (int) len, data);
1798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    exit(1);
1808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
1828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_GENERIC_ERROR:
1838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->printACNames) {
1848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    printf("Got a Generic-Error tag: %.*s\n", (int) len, data);
1858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	} else {
1868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    syslog(LOG_ERR, "PADO: Generic-Error: %.*s", (int) len, data);
1878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    exit(1);
1888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
1908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
1948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: parsePADSTags
1958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
1968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- tag type
1978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* len -- tag length
1988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* data -- tag data
1998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* extra -- extra user data (pointer to PPPoEConnection structure)
2008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
2018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
2028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
2038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Picks interesting tags out of a PADS packet
2048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
2058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
2068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectparsePADSTags(UINT16_t type, UINT16_t len, unsigned char *data,
2078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	      void *extra)
2088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoEConnection *conn = (PPPoEConnection *) extra;
2108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    switch(type) {
2118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_SERVICE_NAME:
2128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_DEBUG, "PADS: Service-Name: '%.*s'", (int) len, data);
2138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
2148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_SERVICE_NAME_ERROR:
2158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "PADS: Service-Name-Error: %.*s", (int) len, data);
2168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(stderr, "PADS: Service-Name-Error: %.*s\n", (int) len, data);
2178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	exit(1);
2188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_AC_SYSTEM_ERROR:
2198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "PADS: System-Error: %.*s", (int) len, data);
2208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(stderr, "PADS: System-Error: %.*s\n", (int) len, data);
2218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	exit(1);
2228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_GENERIC_ERROR:
2238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "PADS: Generic-Error: %.*s", (int) len, data);
2248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(stderr, "PADS: Generic-Error: %.*s\n", (int) len, data);
2258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	exit(1);
2268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_RELAY_SESSION_ID:
2278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->relayId.type = htons(type);
2288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->relayId.length = htons(len);
2298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(conn->relayId.payload, data, len);
2308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
2318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
2338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
2358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: sendPADI
2368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
2378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* conn -- PPPoEConnection structure
2388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
2398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
2408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
2418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Sends a PADI packet
2428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
2438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
2448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectsendPADI(PPPoEConnection *conn)
2458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoEPacket packet;
2478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *cursor = packet.payload;
2488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoETag *svc = (PPPoETag *) (&packet.payload);
2498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t namelen = 0;
2508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t plen;
2518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->serviceName) {
2538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	namelen = (UINT16_t) strlen(conn->serviceName);
2548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    plen = TAG_HDR_SIZE + namelen;
2568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    CHECK_ROOM(cursor, packet.payload, plen);
2578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Set destination to Ethernet broadcast address */
2598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memset(packet.ethHdr.h_dest, 0xFF, ETH_ALEN);
2608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN);
2618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);
2638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.ver = 1;
2648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.type = 1;
2658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.code = CODE_PADI;
2668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.session = 0;
2678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    svc->type = TAG_SERVICE_NAME;
2698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    svc->length = htons(namelen);
2708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    CHECK_ROOM(cursor, packet.payload, namelen+TAG_HDR_SIZE);
2718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->serviceName) {
2738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(svc->payload, conn->serviceName, strlen(conn->serviceName));
2748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    cursor += namelen + TAG_HDR_SIZE;
2768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* If we're using Host-Uniq, copy it over */
2788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->useHostUniq) {
2798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	PPPoETag hostUniq;
2808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	pid_t pid = getpid();
2818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	hostUniq.type = htons(TAG_HOST_UNIQ);
2828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	hostUniq.length = htons(sizeof(pid));
2838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(hostUniq.payload, &pid, sizeof(pid));
2848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	CHECK_ROOM(cursor, packet.payload, sizeof(pid) + TAG_HDR_SIZE);
2858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE);
2868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cursor += sizeof(pid) + TAG_HDR_SIZE;
2878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	plen += sizeof(pid) + TAG_HDR_SIZE;
2888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.length = htons(plen);
2918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
2938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->debugFile) {
2948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	dumpPacket(conn->debugFile, &packet, "SENT");
2958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(conn->debugFile, "\n");
2968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fflush(conn->debugFile);
2978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
2998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
3018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: waitForPADO
3028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
3038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* conn -- PPPoEConnection structure
3048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* timeout -- how long to wait (in seconds)
3058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
3068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
3078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
3088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Waits for a PADO packet and copies useful information
3098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
3108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
3118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectwaitForPADO(PPPoEConnection *conn, int timeout)
3128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
3138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    fd_set readable;
3148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int r;
3158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct timeval tv;
3168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoEPacket packet;
3178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int len;
3188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct PacketCriteria pc;
3208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pc.conn          = conn;
3218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pc.acNameOK      = (conn->acName)      ? 0 : 1;
3228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pc.serviceNameOK = (conn->serviceName) ? 0 : 1;
3238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pc.seenACName    = 0;
3248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pc.seenServiceName = 0;
3258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    do {
3278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (BPF_BUFFER_IS_EMPTY) {
3288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    tv.tv_sec = timeout;
3298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    tv.tv_usec = 0;
3308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    FD_ZERO(&readable);
3328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    FD_SET(conn->discoverySocket, &readable);
3338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    while(1) {
3358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
3368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (r >= 0 || errno != EINTR) break;
3378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (r < 0) {
3398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fatalSys("select (waitForPADO)");
3408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (r == 0) return;        /* Timed out */
3428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Get the packet */
3458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	receivePacket(conn->discoverySocket, &packet, &len);
3468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Check length */
3488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ntohs(packet.length) + HDR_SIZE > len) {
3498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    syslog(LOG_ERR, "Bogus PPPoE length field (%u)",
3508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   (unsigned int) ntohs(packet.length));
3518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    continue;
3528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_BPF
3558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* If it's not a Discovery packet, loop again */
3568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (etherType(&packet) != Eth_PPPOE_Discovery) continue;
3578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
3588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->debugFile) {
3608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    dumpPacket(conn->debugFile, &packet, "RCVD");
3618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    fprintf(conn->debugFile, "\n");
3628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    fflush(conn->debugFile);
3638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* If it's not for us, loop again */
3658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (!packetIsForMe(conn, &packet)) continue;
3668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (packet.code == CODE_PADO) {
3688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (NOT_UNICAST(packet.ethHdr.h_source)) {
3698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printErr("Ignoring PADO packet from non-unicast MAC address");
3708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		continue;
3718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    parsePacket(&packet, parsePADOTags, &pc);
3738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (!pc.seenACName) {
3748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printErr("Ignoring PADO packet with no AC-Name tag");
3758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		continue;
3768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (!pc.seenServiceName) {
3788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printErr("Ignoring PADO packet with no Service-Name tag");
3798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		continue;
3808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    conn->numPADOs++;
3828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (conn->printACNames) {
3838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		printf("--------------------------------------------------\n");
3848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (pc.acNameOK && pc.serviceNameOK) {
3868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN);
3878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (conn->printACNames) {
3888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    printf("AC-Ethernet-Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
3898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   (unsigned) conn->peerEth[0],
3908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   (unsigned) conn->peerEth[1],
3918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   (unsigned) conn->peerEth[2],
3928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   (unsigned) conn->peerEth[3],
3938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   (unsigned) conn->peerEth[4],
3948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   (unsigned) conn->peerEth[5]);
3958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    continue;
3968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
3978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		conn->discoveryState = STATE_RECEIVED_PADO;
3988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		break;
3998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
4008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } while (conn->discoveryState != STATE_RECEIVED_PADO);
4028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
4038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
4058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: sendPADR
4068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
4078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* conn -- PPPoE connection structur
4088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
4098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
4108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
4118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Sends a PADR packet
4128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
4138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
4148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectsendPADR(PPPoEConnection *conn)
4158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
4168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoEPacket packet;
4178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoETag *svc = (PPPoETag *) packet.payload;
4188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *cursor = packet.payload;
4198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t namelen = 0;
4218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t plen;
4228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->serviceName) {
4248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	namelen = (UINT16_t) strlen(conn->serviceName);
4258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    plen = TAG_HDR_SIZE + namelen;
4278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    CHECK_ROOM(cursor, packet.payload, plen);
4288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN);
4308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN);
4318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);
4338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.ver = 1;
4348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.type = 1;
4358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.code = CODE_PADR;
4368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.session = 0;
4378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    svc->type = TAG_SERVICE_NAME;
4398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    svc->length = htons(namelen);
4408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->serviceName) {
4418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(svc->payload, conn->serviceName, namelen);
4428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    cursor += namelen + TAG_HDR_SIZE;
4448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* If we're using Host-Uniq, copy it over */
4468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->useHostUniq) {
4478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	PPPoETag hostUniq;
4488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	pid_t pid = getpid();
4498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	hostUniq.type = htons(TAG_HOST_UNIQ);
4508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	hostUniq.length = htons(sizeof(pid));
4518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(hostUniq.payload, &pid, sizeof(pid));
4528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	CHECK_ROOM(cursor, packet.payload, sizeof(pid)+TAG_HDR_SIZE);
4538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE);
4548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cursor += sizeof(pid) + TAG_HDR_SIZE;
4558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	plen += sizeof(pid) + TAG_HDR_SIZE;
4568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Copy cookie and relay-ID if needed */
4598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->cookie.type) {
4608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	CHECK_ROOM(cursor, packet.payload,
4618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   ntohs(conn->cookie.length) + TAG_HDR_SIZE);
4628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE);
4638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
4648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
4658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->relayId.type) {
4688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	CHECK_ROOM(cursor, packet.payload,
4698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   ntohs(conn->relayId.length) + TAG_HDR_SIZE);
4708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE);
4718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
4728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
4738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.length = htons(plen);
4768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
4778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->debugFile) {
4788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	dumpPacket(conn->debugFile, &packet, "SENT");
4798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(conn->debugFile, "\n");
4808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fflush(conn->debugFile);
4818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
4838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
4858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: waitForPADS
4868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
4878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* conn -- PPPoE connection info
4888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* timeout -- how long to wait (in seconds)
4898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
4908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
4918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
4928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Waits for a PADS packet and copies useful information
4938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
4948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
4958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectwaitForPADS(PPPoEConnection *conn, int timeout)
4968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
4978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    fd_set readable;
4988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int r;
4998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    struct timeval tv;
5008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoEPacket packet;
5018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int len;
5028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    do {
5048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (BPF_BUFFER_IS_EMPTY) {
5058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    tv.tv_sec = timeout;
5068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    tv.tv_usec = 0;
5078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    FD_ZERO(&readable);
5098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    FD_SET(conn->discoverySocket, &readable);
5108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    while(1) {
5128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);
5138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (r >= 0 || errno != EINTR) break;
5148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
5158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (r < 0) {
5168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fatalSys("select (waitForPADS)");
5178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
5188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (r == 0) return;
5198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Get the packet */
5228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	receivePacket(conn->discoverySocket, &packet, &len);
5238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Check length */
5258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (ntohs(packet.length) + HDR_SIZE > len) {
5268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    syslog(LOG_ERR, "Bogus PPPoE length field (%u)",
5278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   (unsigned int) ntohs(packet.length));
5288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    continue;
5298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef USE_BPF
5328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* If it's not a Discovery packet, loop again */
5338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (etherType(&packet) != Eth_PPPOE_Discovery) continue;
5348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
5358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->debugFile) {
5368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    dumpPacket(conn->debugFile, &packet, "RCVD");
5378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    fprintf(conn->debugFile, "\n");
5388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    fflush(conn->debugFile);
5398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* If it's not from the AC, it's not for me */
5428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue;
5438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* If it's not for us, loop again */
5458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (!packetIsForMe(conn, &packet)) continue;
5468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Is it PADS?  */
5488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (packet.code == CODE_PADS) {
5498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    /* Parse for goodies */
5508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    parsePacket(&packet, parsePADSTags, conn);
5518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    conn->discoveryState = STATE_SESSION;
5528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
5538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } while (conn->discoveryState != STATE_SESSION);
5558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Don't bother with ntohs; we'll just end up converting it back... */
5578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    conn->session = packet.session;
5588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    syslog(LOG_INFO, "PPP session is %d", (int) ntohs(conn->session));
5608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* RFC 2516 says session id MUST NOT be zero or 0xFFFF */
5628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ntohs(conn->session) == 0 || ntohs(conn->session) == 0xFFFF) {
5638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Access concentrator used a session value of %x -- the AC is violating RFC 2516", (unsigned int) ntohs(conn->session));
5648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
5668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
5688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: discovery
5698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
5708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* conn -- PPPoE connection info structure
5718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
5728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
5738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
5748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Performs the PPPoE discovery phase
5758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
5768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
5778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectdiscovery(PPPoEConnection *conn)
5788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
5798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int padiAttempts = 0;
5808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int padrAttempts = 0;
5818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int timeout = PADI_TIMEOUT;
5828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Skip discovery and don't open discovery socket? */
5848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->skipDiscovery && conn->noDiscoverySocket) {
5858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->discoveryState = STATE_SESSION;
5868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
5878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    conn->discoverySocket =
5908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);
5918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Skip discovery? */
5938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->skipDiscovery) {
5948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->discoveryState = STATE_SESSION;
5958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
5968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    do {
5998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	padiAttempts++;
6008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (padiAttempts > MAX_PADI_ATTEMPTS) {
6018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    warn("Timeout waiting for PADO packets");
6028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    close(conn->discoverySocket);
6038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    conn->discoverySocket = -1;
6048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return;
6058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
6068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sendPADI(conn);
6078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->discoveryState = STATE_SENT_PADI;
6088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	waitForPADO(conn, timeout);
6098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* If we're just probing for access concentrators, don't do
6118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	   exponential backoff.  This reduces the time for an unsuccessful
6128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	   probe to 15 seconds. */
6138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (!conn->printACNames) {
6148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    timeout *= 2;
6158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
6168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (conn->printACNames && conn->numPADOs) {
6178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
6188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
6198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } while (conn->discoveryState == STATE_SENT_PADI);
6208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* If we're only printing access concentrator names, we're done */
6228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->printACNames) {
6238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	die(0);
6248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
6258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    timeout = PADI_TIMEOUT;
6278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    do {
6288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	padrAttempts++;
6298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (padrAttempts > MAX_PADI_ATTEMPTS) {
6308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    warn("Timeout waiting for PADS packets");
6318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    close(conn->discoverySocket);
6328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    conn->discoverySocket = -1;
6338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return;
6348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
6358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sendPADR(conn);
6368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	conn->discoveryState = STATE_SENT_PADR;
6378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	waitForPADS(conn, timeout);
6388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	timeout *= 2;
6398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } while (conn->discoveryState == STATE_SENT_PADR);
6408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
6418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* We're done. */
6428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    conn->discoveryState = STATE_SESSION;
6438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return;
6448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
6458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
646