18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* 28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Perform PPPoE discovery 38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * 48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Copyright (C) 2000-2001 by Roaring Penguin Software Inc. 58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Copyright (C) 2004 Marco d'Itri <md@linux.it> 68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * 78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * This program may be distributed according to the terms of the GNU 88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * General Public License, version 2 or (at your option) any later version. 98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * 108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */ 118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdio.h> 138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdlib.h> 148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <unistd.h> 158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <errno.h> 168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <string.h> 178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "pppoe.h" 198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 201286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_UNISTD_H 211286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <unistd.h> 221286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 241286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_NETPACKET_PACKET_H 251286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <netpacket/packet.h> 261286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#elif defined(HAVE_LINUX_IF_PACKET_H) 271286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <linux/if_packet.h> 281286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 291286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 301286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_NET_ETHERNET_H 311286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <net/ethernet.h> 321286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 331286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 341286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_ASM_TYPES_H 351286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <asm/types.h> 361286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 371286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 381286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_SYS_IOCTL_H 391286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <sys/ioctl.h> 401286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 411286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 421286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <errno.h> 431286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <stdlib.h> 441286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <string.h> 451286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 461286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_NET_IF_ARP_H 471286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#include <net/if_arp.h> 481286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 491286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchar *xstrdup(const char *s); 518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid usage(void); 528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid die(int status) 548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project exit(status); 568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 581286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/* Initialize frame types to RFC 2516 values. Some broken peers apparently 591286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley use different frame types... sigh... */ 601286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 611286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyUINT16_t Eth_PPPOE_Discovery = ETH_PPPOE_DISCOVERY; 621286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyUINT16_t Eth_PPPOE_Session = ETH_PPPOE_SESSION; 631286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 641286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/********************************************************************** 651286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: etherType 661286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 671286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* packet -- a received PPPoE packet 681286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 691286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* ethernet packet type (see /usr/include/net/ethertypes.h) 701286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 711286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Checks the ethernet packet header to determine its type. 721286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* We should only be receveing DISCOVERY and SESSION types if the BPF 731286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* is set up correctly. Logs an error if an unexpected type is received. 741286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Note that the ethernet type names come from "pppoe.h" and the packet 751286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* packet structure names use the LINUX dialect to maintain consistency 761286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* with the rest of this file. See the BSD section of "pppoe.h" for 771286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* translations of the data structure names. 781286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 791286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyUINT16_t 801286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyetherType(PPPoEPacket *packet) 811286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 821286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley UINT16_t type = (UINT16_t) ntohs(packet->ethHdr.h_proto); 831286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (type != Eth_PPPOE_Discovery && type != Eth_PPPOE_Session) { 841286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Invalid ether type 0x%x\n", type); 851286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 861286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return type; 871286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 881286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 891286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/********************************************************************** 901286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: openInterface 911286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 921286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* ifname -- name of interface 931286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* type -- Ethernet frame type 941286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* hwaddr -- if non-NULL, set to the hardware address 951286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 961286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* A raw socket for talking to the Ethernet card. Exits on error. 971286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 981286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Opens a raw Ethernet socket 991286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 1001286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyint 1011286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyopenInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr) 1021286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 1031286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int optval=1; 1041286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int fd; 1051286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley struct ifreq ifr; 1061286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int domain, stype; 1071286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1081286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_STRUCT_SOCKADDR_LL 1091286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley struct sockaddr_ll sa; 1101286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#else 1111286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley struct sockaddr sa; 1121286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 1131286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1141286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memset(&sa, 0, sizeof(sa)); 1151286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1161286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_STRUCT_SOCKADDR_LL 1171286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley domain = PF_PACKET; 1181286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley stype = SOCK_RAW; 1191286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#else 1201286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley domain = PF_INET; 1211286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley stype = SOCK_PACKET; 1221286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 1231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1241286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if ((fd = socket(domain, stype, htons(type))) < 0) { 1251286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Give a more helpful message for the common error case */ 1261286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (errno == EPERM) { 1271286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley rp_fatal("Cannot create raw socket -- pppoe must be run as root."); 1281286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1291286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fatalSys("socket"); 1301286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1311286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1321286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) { 1331286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fatalSys("setsockopt"); 1341286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1351286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1361286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Fill in hardware address */ 1371286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (hwaddr) { 1381286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1391286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { 1401286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fatalSys("ioctl(SIOCGIFHWADDR)"); 1411286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1421286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 1431286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef ARPHRD_ETHER 1441286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { 1451286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley char buffer[256]; 1461286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sprintf(buffer, "Interface %.16s is not Ethernet", ifname); 1471286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley rp_fatal(buffer); 1481286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1491286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 1501286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (NOT_UNICAST(hwaddr)) { 1511286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley char buffer[256]; 1521286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sprintf(buffer, 1531286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley "Interface %.16s has broadcast/multicast MAC address??", 1541286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley ifname); 1551286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley rp_fatal(buffer); 1561286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1571286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1581286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1591286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Sanity check on MTU */ 1601286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1611286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) { 1621286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fatalSys("ioctl(SIOCGIFMTU)"); 1631286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1641286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (ifr.ifr_mtu < ETH_DATA_LEN) { 1651286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Interface %.16s has MTU of %d -- should be %d.\n", 1661286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley ifname, ifr.ifr_mtu, ETH_DATA_LEN); 1671286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "You may have serious connection problems.\n"); 1681286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1691286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1701286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef HAVE_STRUCT_SOCKADDR_LL 1711286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Get interface index */ 1721286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sa.sll_family = AF_PACKET; 1731286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sa.sll_protocol = htons(type); 1741286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1751286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1761286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { 1771286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fatalSys("ioctl(SIOCFIGINDEX): Could not get interface index"); 1781286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1791286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sa.sll_ifindex = ifr.ifr_ifindex; 1801286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1811286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#else 1821286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley strcpy(sa.sa_data, ifname); 1831286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 1841286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1851286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* We're only interested in packets on specified interface */ 1861286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 1871286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fatalSys("bind"); 1881286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 1891286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1901286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return fd; 1911286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 1921286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1931286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 1941286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/*********************************************************************** 1951286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: sendPacket 1961286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 1971286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* sock -- socket to send to 1981286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* pkt -- the packet to transmit 1991286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* size -- size of packet (in bytes) 2001286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 2011286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* 0 on success; -1 on failure 2021286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 2031286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Transmits a packet 2041286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 2051286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyint 2061286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleysendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size) 2071286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 2081286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#if defined(HAVE_STRUCT_SOCKADDR_LL) 2091286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (send(sock, pkt, size, 0) < 0) { 2101286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sysErr("send (sendPacket)"); 2111286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return -1; 2121286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2131286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#else 2141286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley struct sockaddr sa; 2151286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 2161286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (!conn) { 2171286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley rp_fatal("relay and server not supported on Linux 2.0 kernels"); 2181286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2191286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley strcpy(sa.sa_data, conn->ifName); 2201286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (sendto(sock, pkt, size, 0, &sa, sizeof(sa)) < 0) { 2211286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sysErr("sendto (sendPacket)"); 2221286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return -1; 2231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2241286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 2251286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return 0; 2261286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 2271286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 2281286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/*********************************************************************** 2291286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: receivePacket 2301286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 2311286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* sock -- socket to read from 2321286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* pkt -- place to store the received packet 2331286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* size -- set to size of packet in bytes 2341286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 2351286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* >= 0 if all OK; < 0 if error 2361286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 2371286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Receives a packet 2381286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 2391286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyint 2401286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyreceivePacket(int sock, PPPoEPacket *pkt, int *size) 2411286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 2421286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) { 2431286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sysErr("recv (receivePacket)"); 2441286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return -1; 2451286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2461286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return 0; 2471286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 2481286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 2491286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/********************************************************************** 2501286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: parsePacket 2511286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 2521286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* packet -- the PPPoE discovery packet to parse 2531286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* func -- function called for each tag in the packet 2541286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* extra -- an opaque data pointer supplied to parsing function 2551286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 2561286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* 0 if everything went well; -1 if there was an error 2571286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 2581286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Parses a PPPoE discovery packet, calling "func" for each tag in the packet. 2591286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* "func" is passed the additional argument "extra". 2601286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 2611286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyint 2621286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyparsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra) 2631286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 2641286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley UINT16_t len = ntohs(packet->length); 2651286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley unsigned char *curTag; 2661286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley UINT16_t tagType, tagLen; 2671286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 2681286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (PPPOE_VER(packet->vertype) != 1) { 2691286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Invalid PPPoE version (%d)\n", 2701286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley PPPOE_VER(packet->vertype)); 2711286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return -1; 2721286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2731286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (PPPOE_TYPE(packet->vertype) != 1) { 2741286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Invalid PPPoE type (%d)\n", 2751286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley PPPOE_TYPE(packet->vertype)); 2761286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return -1; 2771286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2781286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 2791286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Do some sanity checks on packet */ 2801286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (len > ETH_JUMBO_LEN - PPPOE_OVERHEAD) { /* 6-byte overhead for PPPoE header */ 2811286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Invalid PPPoE packet length (%u)\n", len); 2821286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return -1; 2831286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2841286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 2851286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Step through the tags */ 2861286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley curTag = packet->payload; 2871286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley while(curTag - packet->payload < len) { 2881286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Alignment is not guaranteed, so do this by hand... */ 2891286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley tagType = (curTag[0] << 8) + curTag[1]; 2901286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley tagLen = (curTag[2] << 8) + curTag[3]; 2911286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (tagType == TAG_END_OF_LIST) { 2921286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return 0; 2931286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2941286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) { 2951286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Invalid PPPoE tag length (%u)\n", tagLen); 2961286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return -1; 2971286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 2981286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra); 2991286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley curTag = curTag + TAG_HDR_SIZE + tagLen; 3001286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 3011286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return 0; 3021286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 3031286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 3041286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/********************************************************************** 3051286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: parseForHostUniq 3061286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 3071286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* type -- tag type 3081286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* len -- tag length 3091286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* data -- tag data. 3101286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* extra -- user-supplied pointer. This is assumed to be a pointer to int. 3111286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 3121286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Nothing 3131286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 3141286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* If a HostUnique tag is found which matches our PID, sets *extra to 1. 3151286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 3161286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyvoid 3171286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyparseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data, 3181286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley void *extra) 3191286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 3201286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int *val = (int *) extra; 3211286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (type == TAG_HOST_UNIQ && len == sizeof(pid_t)) { 3221286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pid_t tmp; 3231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(&tmp, data, len); 3241286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (tmp == getpid()) { 3251286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley *val = 1; 3261286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 3271286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 3281286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 3291286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 3301286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/********************************************************************** 3311286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: packetIsForMe 3321286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 3331286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* conn -- PPPoE connection info 3341286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* packet -- a received PPPoE packet 3351286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 3361286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* 1 if packet is for this PPPoE daemon; 0 otherwise. 3371286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 3381286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* If we are using the Host-Unique tag, verifies that packet contains 3391286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* our unique identifier. 3401286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 3411286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyint 3421286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleypacketIsForMe(PPPoEConnection *conn, PPPoEPacket *packet) 3431286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 3441286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int forMe = 0; 3451286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 3461286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* If packet is not directed to our MAC address, forget it */ 3471286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (memcmp(packet->ethHdr.h_dest, conn->myEth, ETH_ALEN)) return 0; 3481286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 3491286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* If we're not using the Host-Unique tag, then accept the packet */ 3501286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (!conn->useHostUniq) return 1; 3511286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 3521286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley parsePacket(packet, parseForHostUniq, &forMe); 3531286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return forMe; 3541286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 3551286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 3561286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/********************************************************************** 3571286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: parsePADOTags 3581286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 3591286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* type -- tag type 3601286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* len -- tag length 3611286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* data -- tag data 3621286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* extra -- extra user data. Should point to a PacketCriteria structure 3631286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* which gets filled in according to selected AC name and service 3641286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* name. 3651286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 3661286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Nothing 3671286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 3681286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Picks interesting tags out of a PADO packet 3691286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 3701286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyvoid 3711286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleyparsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data, 3721286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley void *extra) 3731286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 3741286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley struct PacketCriteria *pc = (struct PacketCriteria *) extra; 3751286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley PPPoEConnection *conn = pc->conn; 3761286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int i; 3771286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 3781286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley switch(type) { 3791286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley case TAG_AC_NAME: 3801286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc->seenACName = 1; 3811286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("Access-Concentrator: %.*s\n", (int) len, data); 3821286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->acName && len == strlen(conn->acName) && 3831286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley !strncmp((char *) data, conn->acName, len)) { 3841286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc->acNameOK = 1; 3851286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 3861286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley break; 3871286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley case TAG_SERVICE_NAME: 3881286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc->seenServiceName = 1; 3891286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (len > 0) { 3901286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf(" Service-Name: %.*s\n", (int) len, data); 3911286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 3921286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->serviceName && len == strlen(conn->serviceName) && 3931286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley !strncmp((char *) data, conn->serviceName, len)) { 3941286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc->serviceNameOK = 1; 3951286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 3961286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley break; 3971286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley case TAG_AC_COOKIE: 3981286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("Got a cookie:"); 3991286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Print first 20 bytes of cookie */ 4001286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley for (i=0; i<len && i < 20; i++) { 4011286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf(" %02x", (unsigned) data[i]); 4021286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 4031286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (i < len) printf("..."); 4041286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("\n"); 4051286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->cookie.type = htons(type); 4061286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->cookie.length = htons(len); 4071286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(conn->cookie.payload, data, len); 4081286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley break; 4091286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley case TAG_RELAY_SESSION_ID: 4101286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("Got a Relay-ID:"); 4111286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Print first 20 bytes of relay ID */ 4121286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley for (i=0; i<len && i < 20; i++) { 4131286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf(" %02x", (unsigned) data[i]); 4141286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 4151286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (i < len) printf("..."); 4161286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("\n"); 4171286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->relayId.type = htons(type); 4181286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->relayId.length = htons(len); 4191286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(conn->relayId.payload, data, len); 4201286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley break; 4211286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley case TAG_SERVICE_NAME_ERROR: 4221286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("Got a Service-Name-Error tag: %.*s\n", (int) len, data); 4231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley break; 4241286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley case TAG_AC_SYSTEM_ERROR: 4251286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("Got a System-Error tag: %.*s\n", (int) len, data); 4261286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley break; 4271286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley case TAG_GENERIC_ERROR: 4281286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("Got a Generic-Error tag: %.*s\n", (int) len, data); 4291286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley break; 4301286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 4311286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 4321286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4331286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/*********************************************************************** 4341286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: sendPADI 4351286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 4361286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* conn -- PPPoEConnection structure 4371286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 4381286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Nothing 4391286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 4401286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Sends a PADI packet 4411286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 4421286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyvoid 4431286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleysendPADI(PPPoEConnection *conn) 4441286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 4451286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley PPPoEPacket packet; 4461286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley unsigned char *cursor = packet.payload; 4471286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley PPPoETag *svc = (PPPoETag *) (&packet.payload); 4481286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley UINT16_t namelen = 0; 4491286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley UINT16_t plen; 4501286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4511286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->serviceName) { 4521286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley namelen = (UINT16_t) strlen(conn->serviceName); 4531286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 4541286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley plen = TAG_HDR_SIZE + namelen; 4551286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley CHECK_ROOM(cursor, packet.payload, plen); 4561286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4571286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Set destination to Ethernet broadcast address */ 4581286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memset(packet.ethHdr.h_dest, 0xFF, ETH_ALEN); 4591286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); 4601286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4611286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); 4621286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley packet.vertype = PPPOE_VER_TYPE(1, 1); 4631286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley packet.code = CODE_PADI; 4641286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley packet.session = 0; 4651286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4661286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley svc->type = TAG_SERVICE_NAME; 4671286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley svc->length = htons(namelen); 4681286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley CHECK_ROOM(cursor, packet.payload, namelen+TAG_HDR_SIZE); 4691286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4701286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->serviceName) { 4711286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(svc->payload, conn->serviceName, strlen(conn->serviceName)); 4721286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 4731286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley cursor += namelen + TAG_HDR_SIZE; 4741286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4751286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* If we're using Host-Uniq, copy it over */ 4761286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->useHostUniq) { 4771286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley PPPoETag hostUniq; 4781286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pid_t pid = getpid(); 4791286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley hostUniq.type = htons(TAG_HOST_UNIQ); 4801286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley hostUniq.length = htons(sizeof(pid)); 4811286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(hostUniq.payload, &pid, sizeof(pid)); 4821286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley CHECK_ROOM(cursor, packet.payload, sizeof(pid) + TAG_HDR_SIZE); 4831286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE); 4841286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley cursor += sizeof(pid) + TAG_HDR_SIZE; 4851286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley plen += sizeof(pid) + TAG_HDR_SIZE; 4861286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 4871286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4881286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley packet.length = htons(plen); 4891286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4901286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); 4911286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->debugFile) { 4921286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley dumpPacket(conn->debugFile, &packet, "SENT"); 4931286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(conn->debugFile, "\n"); 4941286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fflush(conn->debugFile); 4951286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 4961286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 4971286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 4981286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/********************************************************************** 4991286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: waitForPADO 5001286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 5011286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* conn -- PPPoEConnection structure 5021286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* timeout -- how long to wait (in seconds) 5031286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 5041286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Nothing 5051286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 5061286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Waits for a PADO packet and copies useful information 5071286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 5081286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyvoid 5091286c078a4b93695b3812e8c7fe7918c28ea18b4Adam LangleywaitForPADO(PPPoEConnection *conn, int timeout) 5101286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 5111286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fd_set readable; 5121286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int r; 5131286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley struct timeval tv; 5141286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley PPPoEPacket packet; 5151286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int len; 5161286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5171286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley struct PacketCriteria pc; 5181286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc.conn = conn; 5191286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc.acNameOK = (conn->acName) ? 0 : 1; 5201286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc.serviceNameOK = (conn->serviceName) ? 0 : 1; 5211286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc.seenACName = 0; 5221286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley pc.seenServiceName = 0; 5231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->error = 0; 5241286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5251286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley do { 5261286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (BPF_BUFFER_IS_EMPTY) { 5271286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley tv.tv_sec = timeout; 5281286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley tv.tv_usec = 0; 5291286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5301286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley FD_ZERO(&readable); 5311286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley FD_SET(conn->discoverySocket, &readable); 5321286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5331286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley while(1) { 5341286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); 5351286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (r >= 0 || errno != EINTR) break; 5361286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5371286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (r < 0) { 5381286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley perror("select (waitForPADO)"); 5391286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return; 5401286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5411286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (r == 0) return; /* Timed out */ 5421286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5431286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5441286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Get the packet */ 5451286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley receivePacket(conn->discoverySocket, &packet, &len); 5461286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5471286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* Check length */ 5481286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (ntohs(packet.length) + HDR_SIZE > len) { 5491286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Bogus PPPoE length field (%u)\n", 5501286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley (unsigned int) ntohs(packet.length)); 5511286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley continue; 5521286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5531286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5541286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#ifdef USE_BPF 5551286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* If it's not a Discovery packet, loop again */ 5561286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (etherType(&packet) != Eth_PPPOE_Discovery) continue; 5571286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley#endif 5581286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5591286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->debugFile) { 5601286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley dumpPacket(conn->debugFile, &packet, "RCVD"); 5611286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(conn->debugFile, "\n"); 5621286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fflush(conn->debugFile); 5631286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5641286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley /* If it's not for us, loop again */ 5651286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (!packetIsForMe(conn, &packet)) continue; 5661286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 5671286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (packet.code == CODE_PADO) { 5681286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (BROADCAST(packet.ethHdr.h_source)) { 5691286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Ignoring PADO packet from broadcast MAC address\n"); 5701286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley continue; 5711286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5721286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley parsePacket(&packet, parsePADOTags, &pc); 5731286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->error) 5741286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return; 5751286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (!pc.seenACName) { 5761286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Ignoring PADO packet with no AC-Name tag\n"); 5771286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley continue; 5781286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5791286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (!pc.seenServiceName) { 5801286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Ignoring PADO packet with no Service-Name tag\n"); 5811286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley continue; 5821286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5831286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->numPADOs++; 5841286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("--------------------------------------------------\n"); 5851286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (pc.acNameOK && pc.serviceNameOK) { 5861286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN); 5871286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (conn->printACNames) { 5881286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley printf("AC-Ethernet-Address: %02x:%02x:%02x:%02x:%02x:%02x\n", 5891286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley (unsigned) conn->peerEth[0], 5901286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley (unsigned) conn->peerEth[1], 5911286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley (unsigned) conn->peerEth[2], 5921286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley (unsigned) conn->peerEth[3], 5931286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley (unsigned) conn->peerEth[4], 5941286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley (unsigned) conn->peerEth[5]); 5951286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley continue; 5961286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 5971286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->discoveryState = STATE_RECEIVED_PADO; 5981286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley break; 5991286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 6001286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 6011286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } while (conn->discoveryState != STATE_RECEIVED_PADO); 6021286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 6031286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 6041286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley/********************************************************************** 6051286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%FUNCTION: discovery 6061286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%ARGUMENTS: 6071286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* conn -- PPPoE connection info structure 6081286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%RETURNS: 6091286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Nothing 6101286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley*%DESCRIPTION: 6111286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley* Performs the PPPoE discovery phase 6121286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley***********************************************************************/ 6131286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleyvoid 6141286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langleydiscovery(PPPoEConnection *conn) 6151286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley{ 6161286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int padiAttempts = 0; 6171286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley int timeout = PADI_TIMEOUT; 6181286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 6191286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->discoverySocket = 6201286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth); 6211286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 6221286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley do { 6231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley padiAttempts++; 6241286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley if (padiAttempts > MAX_PADI_ATTEMPTS) { 6251286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "Timeout waiting for PADO packets\n"); 6261286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley close(conn->discoverySocket); 6271286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->discoverySocket = -1; 6281286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley return; 6291286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } 6301286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley sendPADI(conn); 6311286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley conn->discoveryState = STATE_SENT_PADI; 6321286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley waitForPADO(conn, timeout); 6331286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley } while (!conn->numPADOs); 6341286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley} 6351286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley 6368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint main(int argc, char *argv[]) 6378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 6388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project int opt; 6398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project PPPoEConnection *conn; 6408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 6418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn = malloc(sizeof(PPPoEConnection)); 6428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (!conn) 6438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project fatalSys("malloc"); 6448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 6458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project memset(conn, 0, sizeof(PPPoEConnection)); 6468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 6478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project while ((opt = getopt(argc, argv, "I:D:VUAS:C:h")) > 0) { 6488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project switch(opt) { 6498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project case 'S': 6508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->serviceName = xstrdup(optarg); 6518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project break; 6528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project case 'C': 6538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->acName = xstrdup(optarg); 6548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project break; 6558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project case 'U': 6568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->useHostUniq = 1; 6578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project break; 6588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project case 'D': 6598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->debugFile = fopen(optarg, "w"); 6608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (!conn->debugFile) { 6618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project fprintf(stderr, "Could not open %s: %s\n", 6628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project optarg, strerror(errno)); 6638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project exit(1); 6648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 6651286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(conn->debugFile, "pppoe-discovery %s\n", RP_VERSION); 6668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project break; 6678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project case 'I': 6688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->ifName = xstrdup(optarg); 6698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project break; 6708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project case 'A': 6718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project /* this is the default */ 6728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project break; 6738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project case 'V': 6748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project case 'h': 6758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project usage(); 6768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project exit(0); 6778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project default: 6788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project usage(); 6798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project exit(1); 6808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 6818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project } 6828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 6838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project /* default interface name */ 6848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (!conn->ifName) 6858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->ifName = strdup("eth0"); 6868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 6878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->discoverySocket = -1; 6888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->sessionSocket = -1; 6898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project conn->printACNames = 1; 6908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 6918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project discovery(conn); 6928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project exit(0); 6938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 6948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 6958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid rp_fatal(char const *str) 6968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 6971286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "%s\n", str); 6988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project exit(1); 6998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 7008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 7018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid fatalSys(char const *str) 7028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 7031286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley perror(str); 7048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project exit(1); 7058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 7068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 7078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid sysErr(char const *str) 7088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 7098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project rp_fatal(str); 7108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 7118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 7128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchar *xstrdup(const char *s) 7138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 7148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project register char *ret = strdup(s); 7158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project if (!ret) 7168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project sysErr("strdup"); 7178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project return ret; 7188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 7198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project 7208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid usage(void) 7218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{ 7228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project fprintf(stderr, "Usage: pppoe-discovery [options]\n"); 7231286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley fprintf(stderr, "\nVersion " RP_VERSION "\n"); 7248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project} 725