18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* common.c
48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Implementation of user-space PPPoE redirector for Linux.
68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Common functions used by PPPoE client and server
88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Copyright (C) 2000 by Roaring Penguin Software Inc.
108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* This program may be distributed according to the terms of the GNU
128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* General Public License, version 2 or (at your option) any later version.
138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic char const RCSID[] =
178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project"$Id: common.c,v 1.2 2004/01/13 04:03:58 paulus Exp $";
188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "pppoe.h"
208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_SYSLOG_H
228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <syslog.h>
238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <string.h>
268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <errno.h>
278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdlib.h>
288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef HAVE_UNISTD_H
308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <unistd.h>
318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: parsePacket
358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* packet -- the PPPoE discovery packet to parse
378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* func -- function called for each tag in the packet
388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* extra -- an opaque data pointer supplied to parsing function
398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* 0 if everything went well; -1 if there was an error
418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Parses a PPPoE discovery packet, calling "func" for each tag in the packet.
438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* "func" is passed the additional argument "extra".
448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint
468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectparsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra)
478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t len = ntohs(packet->length);
498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *curTag;
508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t tagType, tagLen;
518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (packet->ver != 1) {
538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Invalid PPPoE version (%d)", (int) packet->ver);
548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return -1;
558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (packet->type != 1) {
578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Invalid PPPoE type (%d)", (int) packet->type);
588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return -1;
598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Do some sanity checks on packet */
628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len);
648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return -1;
658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Step through the tags */
688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    curTag = packet->payload;
698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    while(curTag - packet->payload < len) {
708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Alignment is not guaranteed, so do this by hand... */
718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	tagType = (((UINT16_t) curTag[0]) << 8) +
728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    (UINT16_t) curTag[1];
738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	tagLen = (((UINT16_t) curTag[2]) << 8) +
748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    (UINT16_t) curTag[3];
758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (tagType == TAG_END_OF_LIST) {
768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return 0;
778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen);
808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return -1;
818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra);
838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	curTag = curTag + TAG_HDR_SIZE + tagLen;
848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return 0;
868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: findTag
908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* packet -- the PPPoE discovery packet to parse
928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- the type of the tag to look for
938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* tag -- will be filled in with tag contents
948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* A pointer to the tag if one of the specified type is found; NULL
968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* otherwise.
978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Looks for a specific tag type.
998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
1008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectunsigned char *
1018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectfindTag(PPPoEPacket *packet, UINT16_t type, PPPoETag *tag)
1028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t len = ntohs(packet->length);
1048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *curTag;
1058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t tagType, tagLen;
1068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (packet->ver != 1) {
1088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Invalid PPPoE version (%d)", (int) packet->ver);
1098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return NULL;
1108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (packet->type != 1) {
1128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Invalid PPPoE type (%d)", (int) packet->type);
1138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return NULL;
1148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Do some sanity checks on packet */
1178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
1188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len);
1198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return NULL;
1208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Step through the tags */
1238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    curTag = packet->payload;
1248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    while(curTag - packet->payload < len) {
1258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Alignment is not guaranteed, so do this by hand... */
1268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	tagType = (((UINT16_t) curTag[0]) << 8) +
1278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    (UINT16_t) curTag[1];
1288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	tagLen = (((UINT16_t) curTag[2]) << 8) +
1298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    (UINT16_t) curTag[3];
1308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (tagType == TAG_END_OF_LIST) {
1318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return NULL;
1328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
1348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen);
1358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return NULL;
1368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (tagType == type) {
1388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    memcpy(tag, curTag, tagLen + TAG_HDR_SIZE);
1398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return curTag;
1408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	curTag = curTag + TAG_HDR_SIZE + tagLen;
1428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return NULL;
1448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
1478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: printErr
1488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
1498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* str -- error message
1508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
1518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
1528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
1538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Prints a message to stderr and syslog.
1548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
1558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
1568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectprintErr(char const *str)
1578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    fprintf(stderr, "pppoe: %s\n", str);
1598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    syslog(LOG_ERR, "%s", str);
1608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
1648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: strDup
1658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
1668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* str -- string to copy
1678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
1688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* A malloc'd copy of str.  Exits if malloc fails.
1698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
1708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchar *
1718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectstrDup(char const *str)
1728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    char *copy = malloc(strlen(str)+1);
1748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!copy) {
1758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rp_fatal("strdup failed");
1768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    strcpy(copy, str);
1788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return copy;
1798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef PPPOE_STANDALONE
1828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
1838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: computeTCPChecksum
1848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
1858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* ipHdr -- pointer to IP header
1868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* tcpHdr -- pointer to TCP header
1878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
1888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* The computed TCP checksum
1898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
1908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectUINT16_t
1918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectcomputeTCPChecksum(unsigned char *ipHdr, unsigned char *tcpHdr)
1928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT32_t sum = 0;
1948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t count = ipHdr[2] * 256 + ipHdr[3];
1958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *addr = tcpHdr;
1968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char pseudoHeader[12];
1978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Count number of bytes in TCP header and data */
1998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    count -= (ipHdr[0] & 0x0F) * 4;
2008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(pseudoHeader, ipHdr+12, 8);
2028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pseudoHeader[8] = 0;
2038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pseudoHeader[9] = ipHdr[9];
2048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pseudoHeader[10] = (count >> 8) & 0xFF;
2058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pseudoHeader[11] = (count & 0xFF);
2068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Checksum the pseudo-header */
2088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sum += * (UINT16_t *) pseudoHeader;
2098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sum += * ((UINT16_t *) (pseudoHeader+2));
2108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sum += * ((UINT16_t *) (pseudoHeader+4));
2118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sum += * ((UINT16_t *) (pseudoHeader+6));
2128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sum += * ((UINT16_t *) (pseudoHeader+8));
2138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sum += * ((UINT16_t *) (pseudoHeader+10));
2148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Checksum the TCP header and data */
2168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    while (count > 1) {
2178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sum += * (UINT16_t *) addr;
2188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	addr += 2;
2198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	count -= 2;
2208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (count > 0) {
2228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sum += *addr;
2238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    while(sum >> 16) {
2268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sum = (sum & 0xffff) + (sum >> 16);
2278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return (UINT16_t) (~sum & 0xFFFF);
2298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
2308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
2328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: clampMSS
2338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
2348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* packet -- PPPoE session packet
2358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* dir -- either "incoming" or "outgoing"
2368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* clampMss -- clamp value
2378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
2388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
2398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
2408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Clamps MSS option if TCP SYN flag is set.
2418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
2428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
2438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectclampMSS(PPPoEPacket *packet, char const *dir, int clampMss)
2448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
2458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *tcpHdr;
2468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *ipHdr;
2478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *opt;
2488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *endHdr;
2498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *mssopt = NULL;
2508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t csum;
2518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int len, minlen;
2538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* check PPP protocol type */
2558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (packet->payload[0] & 0x01) {
2568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /* 8 bit protocol type */
2578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /* Is it IPv4? */
2598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (packet->payload[0] != 0x21) {
2608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project            /* Nope, ignore it */
2618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project            return;
2628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        }
2638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ipHdr = packet->payload + 1;
2658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	minlen = 41;
2668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } else {
2678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /* 16 bit protocol type */
2688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        /* Is it IPv4? */
2708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        if (packet->payload[0] != 0x00 ||
2718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project            packet->payload[1] != 0x21) {
2728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project            /* Nope, ignore it */
2738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project            return;
2748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        }
2758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project        ipHdr = packet->payload + 2;
2778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	minlen = 42;
2788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Is it too short? */
2818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    len = (int) ntohs(packet->length);
2828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (len < minlen) {
2838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* 20 byte IP header; 20 byte TCP header; at least 1 or 2 byte PPP protocol */
2848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
2858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Verify once more that it's IPv4 */
2888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((ipHdr[0] & 0xF0) != 0x40) {
2898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
2908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Is it a fragment that's not at the beginning of the packet? */
2938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((ipHdr[6] & 0x1F) || ipHdr[7]) {
2948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Yup, don't touch! */
2958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
2968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
2978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Is it TCP? */
2988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (ipHdr[9] != 0x06) {
2998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
3008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Get start of TCP header */
3038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    tcpHdr = ipHdr + (ipHdr[0] & 0x0F) * 4;
3048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Is SYN set? */
3068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!(tcpHdr[13] & 0x02)) {
3078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
3088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Compute and verify TCP checksum -- do not touch a packet with a bad
3118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project       checksum */
3128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    csum = computeTCPChecksum(ipHdr, tcpHdr);
3138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (csum) {
3148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "Bad TCP checksum %x", (unsigned int) csum);
3158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Upper layers will drop it */
3178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
3188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Look for existing MSS option */
3218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    endHdr = tcpHdr + ((tcpHdr[12] & 0xF0) >> 2);
3228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    opt = tcpHdr + 20;
3238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    while (opt < endHdr) {
3248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (!*opt) break;	/* End of options */
3258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	switch(*opt) {
3268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case 1:
3278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    opt++;
3288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
3298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	case 2:
3318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (opt[1] != 4) {
3328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/* Something fishy about MSS option length. */
3338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		syslog(LOG_ERR,
3348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       "Bogus length for MSS option (%u) from %u.%u.%u.%u",
3358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) opt[1],
3368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) ipHdr[12],
3378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) ipHdr[13],
3388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) ipHdr[14],
3398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) ipHdr[15]);
3408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
3418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    mssopt = opt;
3438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
3448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	default:
3458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (opt[1] < 2) {
3468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/* Someone's trying to attack us? */
3478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		syslog(LOG_ERR,
3488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       "Bogus TCP option length (%u) from %u.%u.%u.%u",
3498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) opt[1],
3508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) ipHdr[12],
3518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) ipHdr[13],
3528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) ipHdr[14],
3538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       (unsigned int) ipHdr[15]);
3548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
3558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
3568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    opt += (opt[1]);
3578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
3588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Found existing MSS option? */
3608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (mssopt) break;
3618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* If MSS exists and it's low enough, do nothing */
3648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (mssopt) {
3658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned mss = mssopt[2] * 256 + mssopt[3];
3668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (mss <= clampMss) {
3678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return;
3688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	mssopt[2] = (((unsigned) clampMss) >> 8) & 0xFF;
3718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	mssopt[3] = ((unsigned) clampMss) & 0xFF;
3728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } else {
3738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* No MSS option.  Don't add one; we'll have to use 536. */
3748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
3758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
3768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Recompute TCP checksum */
3788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    tcpHdr[16] = 0;
3798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    tcpHdr[17] = 0;
3808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    csum = computeTCPChecksum(ipHdr, tcpHdr);
3818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    (* (UINT16_t *) (tcpHdr+16)) = csum;
3828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
3838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif /* PPPOE_STANDALONE */
3848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/***********************************************************************
3868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: sendPADT
3878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
3888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* conn -- PPPoE connection
3898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* msg -- if non-NULL, extra error message to include in PADT packet.
3908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
3918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
3928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
3938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Sends a PADT packet
3948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
3958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
3968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectsendPADT(PPPoEConnection *conn, char const *msg)
3978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
3988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    PPPoEPacket packet;
3998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char *cursor = packet.payload;
4008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT16_t plen = 0;
4028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Do nothing if no session established yet */
4048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!conn->session) return;
4058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Do nothing if no discovery socket */
4078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->discoverySocket < 0) return;
4088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN);
4108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN);
4118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);
4138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.ver = 1;
4148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.type = 1;
4158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.code = CODE_PADT;
4168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.session = conn->session;
4178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Reset Session to zero so there is no possibility of
4198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project       recursive calls to this function by any signal handler */
4208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    conn->session = 0;
4218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* If we're using Host-Uniq, copy it over */
4238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->useHostUniq) {
4248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	PPPoETag hostUniq;
4258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	pid_t pid = getpid();
4268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	hostUniq.type = htons(TAG_HOST_UNIQ);
4278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	hostUniq.length = htons(sizeof(pid));
4288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(hostUniq.payload, &pid, sizeof(pid));
4298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE);
4308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cursor += sizeof(pid) + TAG_HDR_SIZE;
4318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	plen += sizeof(pid) + TAG_HDR_SIZE;
4328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Copy error message */
4358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (msg) {
4368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	PPPoETag err;
4378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	size_t elen = strlen(msg);
4388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	err.type = htons(TAG_GENERIC_ERROR);
4398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	err.length = htons(elen);
4408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	strcpy(err.payload, msg);
4418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(cursor, &err, elen + TAG_HDR_SIZE);
4428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cursor += elen + TAG_HDR_SIZE;
4438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	plen += elen + TAG_HDR_SIZE;
4448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* Copy cookie and relay-ID if needed */
4478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->cookie.type) {
4488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	CHECK_ROOM(cursor, packet.payload,
4498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   ntohs(conn->cookie.length) + TAG_HDR_SIZE);
4508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE);
4518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
4528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
4538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->relayId.type) {
4568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	CHECK_ROOM(cursor, packet.payload,
4578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   ntohs(conn->relayId.length) + TAG_HDR_SIZE);
4588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE);
4598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
4608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
4618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    packet.length = htons(plen);
4648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
4658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (conn->debugFile) {
4668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	dumpPacket(conn->debugFile, &packet, "SENT");
4678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(conn->debugFile, "\n");
4688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fflush(conn->debugFile);
4698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
4708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    syslog(LOG_INFO,"Sent PADT");
4718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
4728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/**********************************************************************
4748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%FUNCTION: parseLogErrs
4758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%ARGUMENTS:
4768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* type -- tag type
4778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* len -- tag length
4788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* data -- tag data
4798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* extra -- extra user data
4808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%RETURNS:
4818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Nothing
4828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*%DESCRIPTION:
4838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Picks error tags out of a packet and logs them.
4848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project***********************************************************************/
4858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
4868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source ProjectparseLogErrs(UINT16_t type, UINT16_t len, unsigned char *data,
4878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	     void *extra)
4888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
4898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    switch(type) {
4908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_SERVICE_NAME_ERROR:
4918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "PADT: Service-Name-Error: %.*s", (int) len, data);
4928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(stderr, "PADT: Service-Name-Error: %.*s\n", (int) len, data);
4938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
4948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_AC_SYSTEM_ERROR:
4958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "PADT: System-Error: %.*s", (int) len, data);
4968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(stderr, "PADT: System-Error: %.*s\n", (int) len, data);
4978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
4988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    case TAG_GENERIC_ERROR:
4998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	syslog(LOG_ERR, "PADT: Generic-Error: %.*s", (int) len, data);
5008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fprintf(stderr, "PADT: Generic-Error: %.*s\n", (int) len, data);
5018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	break;
5028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
5038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
5048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
505