1/*********************************************************************** 2* 3* pppoe.h 4* 5* Declaration of various PPPoE constants 6* 7* Copyright (C) 2000 Roaring Penguin Software Inc. 8* 9* This program may be distributed according to the terms of the GNU 10* General Public License, version 2 or (at your option) any later version. 11* 12* LIC: GPL 13* 14* $Id: pppoe.h,v 1.1.1.1 2008/10/15 03:30:51 james26_jang Exp $ 15* 16***********************************************************************/ 17 18#include "config.h" 19 20#if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H) 21#define _POSIX_SOURCE 1 /* For sigaction defines */ 22#endif 23 24#include <stdio.h> /* For FILE */ 25#include <sys/types.h> /* For pid_t */ 26 27/* How do we access raw Ethernet devices? */ 28#undef USE_LINUX_PACKET 29#undef USE_BPF 30 31#if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H) 32#define USE_LINUX_PACKET 1 33#elif defined(HAVE_SYS_DLPI_H) 34#define USE_DLPI 35#elif defined(HAVE_NET_BPF_H) 36#define USE_BPF 1 37#endif 38 39/* Sanity check */ 40#if !defined(USE_BPF) && !defined(USE_LINUX_PACKET) && !defined(USE_DLPI) 41#error Unknown method for accessing raw Ethernet frames 42#endif 43 44#ifdef HAVE_SYS_CDEFS_H 45#include <sys/cdefs.h> 46#endif 47 48#ifdef HAVE_SYS_SOCKET_H 49#include <sys/socket.h> 50#endif 51 52/* Ugly header files on some Linux boxes... */ 53#if defined(HAVE_LINUX_IF_H) 54#include <linux/if.h> 55#elif defined(HAVE_NET_IF_H) 56#include <net/if.h> 57#endif 58 59#ifdef HAVE_NET_IF_TYPES_H 60#include <net/if_types.h> 61#endif 62 63#ifdef HAVE_NET_IF_DL_H 64#include <net/if_dl.h> 65#endif 66 67/* I'm not sure why this is needed... I do not have OpenBSD */ 68#if defined(__OpenBSD__) 69#include <net/ppp_defs.h> 70#include <net/if_ppp.h> 71#endif 72 73#ifdef USE_BPF 74extern int bpfSize; 75struct PPPoEPacketStruct; 76void sessionDiscoveryPacket(struct PPPoEPacketStruct *packet); 77#define BPF_BUFFER_IS_EMPTY (bpfSize <= 0) 78#define BPF_BUFFER_HAS_DATA (bpfSize > 0) 79#define ethhdr ether_header 80#define h_dest ether_dhost 81#define h_source ether_shost 82#define h_proto ether_type 83#define ETH_DATA_LEN ETHERMTU 84#define ETH_ALEN ETHER_ADDR_LEN 85#else 86#undef USE_BPF 87#define BPF_BUFFER_IS_EMPTY 1 88#define BPF_BUFFER_HAS_DATA 0 89#endif 90 91#ifdef USE_DLPI 92#include <sys/ethernet.h> 93#define ethhdr ether_header 94#define ETH_DATA_LEN ETHERMTU 95#define ETH_ALEN ETHERADDRL 96#define h_dest ether_dhost.ether_addr_octet 97#define h_source ether_shost.ether_addr_octet 98#define h_proto ether_type 99 100/* cloned from dltest.h */ 101#define MAXDLBUF 8192 102#define MAXDLADDR 1024 103#define MAXWAIT 15 104#define OFFADDR(s, n) (u_char*)((char*)(s) + (int)(n)) 105#define CASERET(s) case s: return ("s") 106 107#endif 108 109/* Define various integer types -- assumes a char is 8 bits */ 110#if SIZEOF_UNSIGNED_SHORT == 2 111typedef unsigned short UINT16_t; 112#elif SIZEOF_UNSIGNED_INT == 2 113typedef unsigned int UINT16_t; 114#else 115#error Could not find a 16-bit integer type 116#endif 117 118#if SIZEOF_UNSIGNED_SHORT == 4 119typedef unsigned short UINT32_t; 120#elif SIZEOF_UNSIGNED_INT == 4 121typedef unsigned int UINT32_t; 122#elif SIZEOF_UNSIGNED_LONG == 4 123typedef unsigned long UINT32_t; 124#else 125#error Could not find a 16-bit integer type 126#endif 127 128#ifdef HAVE_LINUX_IF_ETHER_H 129#include <linux/if_ether.h> 130#endif 131 132#include <netinet/in.h> 133 134#ifdef HAVE_NETINET_IF_ETHER_H 135#include <sys/types.h> 136 137#ifdef HAVE_SYS_SOCKET_H 138#include <sys/socket.h> 139#endif 140#ifndef HAVE_SYS_DLPI_H 141#include <netinet/if_ether.h> 142#endif 143#endif 144 145 146 147/* Ethernet frame types according to RFC 2516 */ 148#define ETH_PPPOE_DISCOVERY 0x8863 149#define ETH_PPPOE_SESSION 0x8864 150 151/* But some brain-dead peers disobey the RFC, so frame types are variables */ 152extern UINT16_t Eth_PPPOE_Discovery; 153extern UINT16_t Eth_PPPOE_Session; 154 155/* PPPoE codes */ 156#define CODE_PADI 0x09 157#define CODE_PADO 0x07 158#define CODE_PADR 0x19 159#define CODE_PADS 0x65 160#define CODE_PADT 0xA7 161 162/* Extensions from draft-carrel-info-pppoe-ext-00 */ 163/* I do NOT like PADM or PADN, but they are here for completeness */ 164#define CODE_PADM 0xD3 165#define CODE_PADN 0xD4 166 167#define CODE_SESS 0x00 168 169/* PPPoE Tags */ 170#define TAG_END_OF_LIST 0x0000 171#define TAG_SERVICE_NAME 0x0101 172#define TAG_AC_NAME 0x0102 173#define TAG_HOST_UNIQ 0x0103 174#define TAG_AC_COOKIE 0x0104 175#define TAG_VENDOR_SPECIFIC 0x0105 176#define TAG_RELAY_SESSION_ID 0x0110 177#define TAG_SERVICE_NAME_ERROR 0x0201 178#define TAG_AC_SYSTEM_ERROR 0x0202 179#define TAG_GENERIC_ERROR 0x0203 180 181/* Extensions from draft-carrel-info-pppoe-ext-00 */ 182/* I do NOT like these tags one little bit */ 183#define TAG_HURL 0x111 184#define TAG_MOTM 0x112 185#define TAG_IP_ROUTE_ADD 0x121 186 187/* Discovery phase states */ 188#define STATE_SENT_PADI 0 189#define STATE_RECEIVED_PADO 1 190#define STATE_SENT_PADR 2 191#define STATE_SESSION 3 192#define STATE_TERMINATED 4 193 194/* How many PADI/PADS attempts? */ 195#define MAX_PADI_ATTEMPTS 3 196 197/* Initial timeout for PADO/PADS */ 198#define PADI_TIMEOUT 5 199 200/* States for scanning PPP frames */ 201#define STATE_WAITFOR_FRAME_ADDR 0 202#define STATE_DROP_PROTO 1 203#define STATE_BUILDING_PACKET 2 204 205/* Special PPP frame characters */ 206#define FRAME_ESC 0x7D 207#define FRAME_FLAG 0x7E 208#define FRAME_ADDR 0xFF 209#define FRAME_CTRL 0x03 210#define FRAME_ENC 0x20 211 212#define IPV4ALEN 4 213#define SMALLBUF 256 214 215/* A PPPoE Packet, including Ethernet headers */ 216typedef struct PPPoEPacketStruct { 217 struct ethhdr ethHdr; /* Ethernet header */ 218#ifdef PACK_BITFIELDS_REVERSED 219 unsigned int type:4; /* PPPoE Type (must be 1) */ 220 unsigned int ver:4; /* PPPoE Version (must be 1) */ 221#else 222 unsigned int ver:4; /* PPPoE Version (must be 1) */ 223 unsigned int type:4; /* PPPoE Type (must be 1) */ 224#endif 225 unsigned int code:8; /* PPPoE code */ 226 unsigned int session:16; /* PPPoE session */ 227 unsigned int length:16; /* Payload length */ 228 unsigned char payload[ETH_DATA_LEN]; /* A bit of room to spare */ 229} PPPoEPacket; 230 231/* Header size of a PPPoE packet */ 232#define PPPOE_OVERHEAD 6 /* type, code, session, length */ 233#define HDR_SIZE (sizeof(struct ethhdr) + PPPOE_OVERHEAD) 234#define MAX_PPPOE_PAYLOAD (ETH_DATA_LEN - PPPOE_OVERHEAD) 235#define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - 2) 236 237/* PPPoE Tag */ 238 239typedef struct PPPoETagStruct { 240 unsigned int type:16; /* tag type */ 241 unsigned int length:16; /* Length of payload */ 242 unsigned char payload[ETH_DATA_LEN]; /* A LOT of room to spare */ 243} PPPoETag; 244/* Header size of a PPPoE tag */ 245#define TAG_HDR_SIZE 4 246 247/* Chunk to read from stdin */ 248#define READ_CHUNK 4096 249 250/* Function passed to parsePacket */ 251typedef void ParseFunc(UINT16_t type, 252 UINT16_t len, 253 unsigned char *data, 254 void *extra); 255 256#define PPPINITFCS16 0xffff /* Initial FCS value */ 257 258/* Keep track of the state of a connection -- collect everything in 259 one spot */ 260 261typedef struct PPPoEConnectionStruct { 262 int discoveryState; /* Where we are in discovery */ 263 int discoverySocket; /* Raw socket for discovery frames */ 264 int sessionSocket; /* Raw socket for session frames */ 265 unsigned char myEth[ETH_ALEN]; /* My MAC address */ 266 unsigned char peerEth[ETH_ALEN]; /* Peer's MAC address */ 267 UINT16_t session; /* Session ID */ 268 char *ifName; /* Interface name */ 269 char *serviceName; /* Desired service name, if any */ 270 char *acName; /* Desired AC name, if any */ 271 int synchronous; /* Use synchronous PPP */ 272 int useHostUniq; /* Use Host-Uniq tag */ 273 int printACNames; /* Just print AC names */ 274 int skipDiscovery; /* Skip discovery */ 275 int noDiscoverySocket; /* Don't even open discovery socket */ 276 int killSession; /* Kill session and exit */ 277 FILE *debugFile; /* Debug file for dumping packets */ 278 int numPADOs; /* Number of PADO packets received */ 279 PPPoETag cookie; /* We have to send this if we get it */ 280 PPPoETag relayId; /* Ditto */ 281} PPPoEConnection; 282 283/* Structure used to determine acceptable PADO or PADS packet */ 284struct PacketCriteria { 285 PPPoEConnection *conn; 286 int acNameOK; 287 int serviceNameOK; 288 int seenACName; 289 int seenServiceName; 290}; 291 292/* Function Prototypes */ 293UINT16_t etherType(PPPoEPacket *packet); 294int openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr); 295int sendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size); 296int receivePacket(int sock, PPPoEPacket *pkt, int *size); 297void fatalSys(char const *str); 298void rp_fatal(char const *str); 299void printErr(char const *str); 300void sysErr(char const *str); 301void dumpPacket(FILE *fp, PPPoEPacket *packet, char const *dir); 302void dumpHex(FILE *fp, unsigned char const *buf, int len); 303int parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra); 304void parseLogErrs(UINT16_t typ, UINT16_t len, unsigned char *data, void *xtra); 305void syncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet); 306void asyncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet); 307void asyncReadFromEth(PPPoEConnection *conn, int sock, int clampMss); 308void syncReadFromEth(PPPoEConnection *conn, int sock, int clampMss); 309char *strDup(char const *str); 310void sendPADT(PPPoEConnection *conn, char const *msg); 311void sendPADTf(PPPoEConnection *conn, char const *fmt, ...); 312 313void sendSessionPacket(PPPoEConnection *conn, 314 PPPoEPacket *packet, int len); 315void initPPP(void); 316void clampMSS(PPPoEPacket *packet, char const *dir, int clampMss); 317UINT16_t computeTCPChecksum(unsigned char *ipHdr, unsigned char *tcpHdr); 318UINT16_t pppFCS16(UINT16_t fcs, unsigned char *cp, int len); 319void discovery(PPPoEConnection *conn); 320unsigned char *findTag(PPPoEPacket *packet, UINT16_t tagType, 321 PPPoETag *tag); 322 323#define SET_STRING(var, val) do { if (var) free(var); var = strDup(val); } while(0); 324 325#define CHECK_ROOM(cursor, start, len) \ 326do {\ 327 if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \ 328 syslog(LOG_ERR, "Would create too-long packet"); \ 329 return; \ 330 } \ 331} while(0) 332 333/* True if Ethernet address is broadcast or multicast */ 334#define NOT_UNICAST(e) ((e[0] & 0x01) != 0) 335#define BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) == 0xFF) 336#define NOT_BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) != 0xFF) 337