X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fplugins%2Fpppoe%2Fpppoe.h;h=82ae01d2d0ce4e3aa0d5f9a7c6b6a14a7f05b14a;hb=a352af45cf46af5de0c2b2377f0ca8e33776ad6c;hp=4490cc9ddc31b4c57d814275f12672666cb3912c;hpb=cdbb124cea5feeb4468ad3f2e5b5d17de583da6d;p=ppp.git diff --git a/pppd/plugins/pppoe/pppoe.h b/pppd/plugins/pppoe/pppoe.h index 4490cc9..82ae01d 100644 --- a/pppd/plugins/pppoe/pppoe.h +++ b/pppd/plugins/pppoe/pppoe.h @@ -1,273 +1,328 @@ -/* PPPoE support library "libpppoe" - * - * Copyright 2000 Michal Ostrowski , - * Jamal Hadi Salim - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef PPPOE_H -#define PPPOE_H 1 -#include /* stdio */ -#include /* strtoul(), realloc() */ -#include /* STDIN_FILENO,exec */ -#include /* memcpy() */ -#include /* errno */ -#include -#include -#include -#include -#include - -#include /* socket types */ -#include -#include -#include -#include -#include /* ioctl() */ -#include -#include /* socket() */ -#include /* ifreq struct */ -#include -#include - -#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 -#include -//#include -#else -#include -#include -#include +/*********************************************************************** +* +* pppoe.h +* +* Declaration of various PPPoE constants +* +* Copyright (C) 2000 Roaring Penguin Software Inc. +* +* This program may be distributed according to the terms of the GNU +* General Public License, version 2 or (at your option) any later version. +* +* $Id: pppoe.h,v 1.4 2008/06/15 04:35:50 paulus Exp $ +* +***********************************************************************/ + +#include "config.h" + +#include /* For FILE */ +#include /* For pid_t */ +#include +#include + +#include "pppd/pppd.h" /* For error */ + +/* How do we access raw Ethernet devices? */ +#undef USE_LINUX_PACKET +#undef USE_BPF + +#if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H) +#define USE_LINUX_PACKET 1 +#elif defined(HAVE_SYS_DLPI_H) +#define USE_DLPI +#elif defined(HAVE_NET_BPF_H) +#define USE_BPF 1 #endif - -#include - -/* - jamal: we really have to change this - to make it compatible to the 2.2 and - 2.3 kernel -*/ - -#include - - -#define CONNECTED 1 -#define DISCONNECTED 0 - -#ifndef _PATH_PPPD -#define _PATH_PPPD "/usr/sbin/pppd" +/* Sanity check */ +#if !defined(USE_BPF) && !defined(USE_LINUX_PACKET) && !defined(USE_DLPI) +#error Unknown method for accessing raw Ethernet frames #endif -#ifndef LOG_PPPOE -#define LOG_PPPOE LOG_DAEMON +#ifdef HAVE_SYS_SOCKET_H +#include #endif +/* This has to be included before Linux 4.8's linux/in.h + * gets dragged in. */ +#include -#define VERSION_MAJOR 0 -#define VERSION_MINOR 4 -#define VERSION_DATE 991120 - -/* Bigger than the biggest ethernet packet we'll ever see, in bytes */ -#define MAX_PACKET 2000 - -/* references: RFC 2516 */ -/* ETHER_TYPE fields for PPPoE */ - -#define ETH_P_PPPOE_DISC 0x8863 /* discovery stage */ -#define ETH_P_PPPOE_SESS 0x8864 - -/* ethernet broadcast address */ -#define MAC_BCAST_ADDR "\xff\xff\xff\xff\xff\xff" - -/* Format for parsing long device-name */ -#define _STR(x) #x -#define FMTSTRING(size) "%x:%x:%x:%x:%x:%x/%x/%" _STR(size) "s" +/* Ugly header files on some Linux boxes... */ +#if defined(HAVE_LINUX_IF_H) +#include +#elif defined(HAVE_NET_IF_H) +#include +#endif -/* maximum payload length */ -#define MAX_PAYLOAD 1484 +#ifdef HAVE_NET_IF_TYPES_H +#include +#endif +#define BPF_BUFFER_IS_EMPTY 1 +#define BPF_BUFFER_HAS_DATA 0 +/* Define various integer types -- assumes a char is 8 bits */ +#if SIZEOF_UNSIGNED_SHORT == 2 +typedef unsigned short UINT16_t; +#elif SIZEOF_UNSIGNED_INT == 2 +typedef unsigned int UINT16_t; +#else +#error Could not find a 16-bit integer type +#endif -/* PPPoE tag types */ -#define MAX_TAGS 11 +#if SIZEOF_UNSIGNED_SHORT == 4 +typedef unsigned short UINT32_t; +#elif SIZEOF_UNSIGNED_INT == 4 +typedef unsigned int UINT32_t; +#elif SIZEOF_UNSIGNED_LONG == 4 +typedef unsigned long UINT32_t; +#else +#error Could not find a 32-bit integer type +#endif +#ifdef HAVE_LINUX_IF_ETHER_H +#include +#else -/* PPPoE packet; includes Ethernet headers and such */ -struct pppoe_packet{ - struct sockaddr_ll addr; - struct pppoe_tag *tags[MAX_TAGS]; - struct pppoe_hdr *hdr; - char buf[MAX_PAYLOAD]; /* buffer in which tags are held */ -}; -/* Defines meaning of each "tags" element */ - -#define TAG_SRV_NAME 0 -#define TAG_AC_NAME 1 -#define TAG_HOST_UNIQ 2 -#define TAG_AC_COOKIE 3 -#define TAG_VENDOR 4 -#define TAG_RELAY_SID 5 -#define TAG_SRV_ERR 6 -#define TAG_SYS_ERR 7 -#define TAG_GEN_ERR 8 -#define TAG_EOL 9 - -static int tag_map[] = { PTT_SRV_NAME, - PTT_AC_NAME, - PTT_HOST_UNIQ, - PTT_AC_COOKIE, - PTT_VENDOR, - PTT_RELAY_SID, - PTT_SRV_ERR, - PTT_SYS_ERR, - PTT_GEN_ERR, - PTT_EOL -}; +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifndef HAVE_SYS_DLPI_H +#include +#endif +#endif +#endif -/* Debug flags */ -int DEB_DISC,DEB_DISC2; -/* - #define DEB_DISC (opt_debug & 0x0002) - #define DEB_DISC2 (opt_debug & 0x0004) -*/ -#define MAX_FNAME 256 - - -struct session; - -/* return <0 --> fatal error; abor - return =0 --> ok, proceed - return >0 --> ok, qui -*/ -typedef int (*packet_cb_t)(struct session* ses, - struct pppoe_packet *p_in, - struct pppoe_packet **p_out); - -/* various override filter tags */ -struct filter { - struct pppoe_tag *stag; /* service name tag override */ - struct pppoe_tag *ntag; /*AC name override */ - struct pppoe_tag *htag; /* hostuniq override */ - int num_restart; - int peermode; - char *fname; - char *pppd; -} __attribute__ ((packed)); - - -struct pppoe_tag *make_filter_tag(short type, short length, char* data); - -/* Session type definitions */ -#define SESSION_CLIENT 0 -#define SESSION_SERVER 1 -#define SESSION_RELAY 2 - -struct session { - - /* Administrative */ - int type; - int opt_debug; - int detached; - int np; - int log_to_fd; - int ifindex; /* index of device */ - char name[IFNAMSIZ]; /*dev name */ - struct pppoe_packet curr_pkt; - - packet_cb_t init_disc; - packet_cb_t rcv_pado; - packet_cb_t rcv_padi; - packet_cb_t rcv_pads; - packet_cb_t rcv_padr; - packet_cb_t rcv_padt; - packet_cb_t timeout; - - - /* Generic */ - struct filter *filt; - struct sockaddr_ll local; - struct sockaddr_ll remote; - struct sockaddr_pppox sp; - int fd; /* fd of PPPoE socket */ - - - /* For client */ - int retransmits; /* Number of retransmission performed - if < 0 , retransmissions disabled */ - int retries; - int state; - int opt_daemonize; - - /* For server */ - int fork; - - /* For forwarding */ - int fwd_sock; - char fwd_name[IFNAMSIZ]; /* Name of device to forward to */ -} __attribute__ ((packed)); - -/* - retransmit retries for the PADR and PADI packets - during discovery -*/ -int PADR_ret; -int PADI_ret; - -int log_to_fd; -int ctrl_fd; -int opt_debug; -int opt_daemonize; - - -/* Structure for keeping track of connection relays */ -struct pppoe_con{ - struct pppoe_con *next; - int id; - int connected; - int cl_sock; - int sv_sock; - int ref_count; - char client[ETH_ALEN]; - char server[ETH_ALEN]; - char key_len; - char key[32]; +/* Ethernet frame types according to RFC 2516 */ +#define ETH_PPPOE_DISCOVERY 0x8863 +#define ETH_PPPOE_SESSION 0x8864 + +/* But some brain-dead peers disobey the RFC, so frame types are variables */ +extern UINT16_t Eth_PPPOE_Discovery; +extern UINT16_t Eth_PPPOE_Session; + +/* PPPoE codes */ +#define CODE_PADI 0x09 +#define CODE_PADO 0x07 +#define CODE_PADR 0x19 +#define CODE_PADS 0x65 +#define CODE_PADT 0xA7 + +/* Extensions from draft-carrel-info-pppoe-ext-00 */ +/* I do NOT like PADM or PADN, but they are here for completeness */ +#define CODE_PADM 0xD3 +#define CODE_PADN 0xD4 + +#define CODE_SESS 0x00 + +/* PPPoE Tags */ +#define TAG_END_OF_LIST 0x0000 +#define TAG_SERVICE_NAME 0x0101 +#define TAG_AC_NAME 0x0102 +#define TAG_HOST_UNIQ 0x0103 +#define TAG_AC_COOKIE 0x0104 +#define TAG_VENDOR_SPECIFIC 0x0105 +#define TAG_RELAY_SESSION_ID 0x0110 +#define TAG_PPP_MAX_PAYLOAD 0x0120 +#define TAG_SERVICE_NAME_ERROR 0x0201 +#define TAG_AC_SYSTEM_ERROR 0x0202 +#define TAG_GENERIC_ERROR 0x0203 + +/* Extensions from draft-carrel-info-pppoe-ext-00 */ +/* I do NOT like these tags one little bit */ +#define TAG_HURL 0x111 +#define TAG_MOTM 0x112 +#define TAG_IP_ROUTE_ADD 0x121 + +/* Discovery phase states */ +#define STATE_SENT_PADI 0 +#define STATE_RECEIVED_PADO 1 +#define STATE_SENT_PADR 2 +#define STATE_SESSION 3 +#define STATE_TERMINATED 4 + +/* How many PADI/PADS attempts? */ +#define MAX_PADI_ATTEMPTS 3 + +/* Initial timeout for PADO/PADS */ +#define PADI_TIMEOUT 5 + +/* States for scanning PPP frames */ +#define STATE_WAITFOR_FRAME_ADDR 0 +#define STATE_DROP_PROTO 1 +#define STATE_BUILDING_PACKET 2 + +/* Special PPP frame characters */ +#define FRAME_ESC 0x7D +#define FRAME_FLAG 0x7E +#define FRAME_ADDR 0xFF +#define FRAME_CTRL 0x03 +#define FRAME_ENC 0x20 + +#define IPV4ALEN 4 +#define SMALLBUF 256 + +/* There are other fixed-size buffers preventing + this from being increased to 16110. The buffer + sizes would need to be properly de-coupled from + the default MRU. For now, getting up to 1500 is + enough. */ +#define ETH_JUMBO_LEN 1508 + +/* A PPPoE Packet, including Ethernet headers */ +typedef struct PPPoEPacketStruct { + struct ethhdr ethHdr; /* Ethernet header */ + unsigned int vertype:8; /* PPPoE Version and Type (must both be 1) */ + unsigned int code:8; /* PPPoE code */ + unsigned int session:16; /* PPPoE session */ + unsigned int length:16; /* Payload length */ + unsigned char payload[ETH_JUMBO_LEN]; /* A bit of room to spare */ +} PPPoEPacket; + +#define PPPOE_VER(vt) ((vt) >> 4) +#define PPPOE_TYPE(vt) ((vt) & 0xf) +#define PPPOE_VER_TYPE(v, t) (((v) << 4) | (t)) + +/* Header size of a PPPoE packet */ +#define PPPOE_OVERHEAD 6 /* type, code, session, length */ +#define HDR_SIZE (sizeof(struct ethhdr) + PPPOE_OVERHEAD) +#define MAX_PPPOE_PAYLOAD (ETH_JUMBO_LEN - PPPOE_OVERHEAD) +#define PPP_OVERHEAD 2 /* protocol */ +#define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - PPP_OVERHEAD) +#define TOTAL_OVERHEAD (PPPOE_OVERHEAD + PPP_OVERHEAD) +#define ETH_PPPOE_MTU (ETH_DATA_LEN - TOTAL_OVERHEAD) + +/* PPPoE Tag */ + +typedef struct PPPoETagStruct { + unsigned int type:16; /* tag type */ + unsigned int length:16; /* Length of payload */ + unsigned char payload[ETH_JUMBO_LEN]; /* A LOT of room to spare */ +} PPPoETag; +/* Header size of a PPPoE tag */ +#define TAG_HDR_SIZE 4 + +/* Chunk to read from stdin */ +#define READ_CHUNK 4096 + +/* Function passed to parsePacket */ +typedef void ParseFunc(UINT16_t type, + UINT16_t len, + unsigned char *data, + void *extra); + +#define PPPINITFCS16 0xffff /* Initial FCS value */ + +/* Keep track of the state of a connection -- collect everything in + one spot */ + +typedef struct PPPoEConnectionStruct { + int discoveryState; /* Where we are in discovery */ + int discoverySocket; /* Raw socket for discovery frames */ + int sessionSocket; /* Raw socket for session frames */ + unsigned char myEth[ETH_ALEN]; /* My MAC address */ + unsigned char peerEth[ETH_ALEN]; /* Peer's MAC address */ + unsigned char req_peer_mac[ETH_ALEN]; /* required peer MAC address */ + unsigned char req_peer; /* require mac addr to match req_peer_mac */ + UINT16_t session; /* Session ID */ + char *ifName; /* Interface name */ + char *serviceName; /* Desired service name, if any */ + char *acName; /* Desired AC name, if any */ + int synchronous; /* Use synchronous PPP */ + PPPoETag hostUniq; /* Use Host-Uniq tag */ + FILE *debugFile; /* Debug file for dumping packets */ + int numPADOs; /* Number of PADO packets received */ + PPPoETag cookie; /* We have to send this if we get it */ + PPPoETag relayId; /* Ditto */ + int error; /* Error packet received */ + int debug; /* Set to log packets sent and received */ + int discoveryTimeout; /* Timeout for discovery packets */ + int discoveryAttempts; /* Number of discovery attempts */ + int seenMaxPayload; + int mtu; /* Stored MTU */ + int mru; /* Stored MRU */ +} PPPoEConnection; + +/* Structure used to determine acceptable PADO or PADS packet */ +struct PacketCriteria { + PPPoEConnection *conn; + int acNameOK; + int serviceNameOK; + int seenACName; + int seenServiceName; }; -/* Functions exported from utils.c. */ - -/* Functions exported from pppoehash.c */ -struct pppoe_con *get_con(int len, char *key); -int store_con(struct pppoe_con *pc); -struct pppoe_con *delete_con(unsigned long len, char *key); - -/* exported by lib.c */ - -extern int init_lib(); - -extern int get_sockaddr_ll(const char *devnam,struct sockaddr_ll* sll); - -extern int client_init_ses (struct session *ses, char* devnam); -extern int relay_init_ses(struct session *ses, char* from, char* to); -extern int srv_init_ses(struct session *ses, char* from); -extern int session_connect(struct session *ses); -extern int session_disconnect(struct session*ses); - -extern int verify_packet( struct session *ses, struct pppoe_packet *p); - -extern void copy_tag(struct pppoe_packet *dest, struct pppoe_tag *pt); -extern struct pppoe_tag *get_tag(struct pppoe_hdr *ph, u_int16_t idx); -extern int send_disc(struct session *ses, struct pppoe_packet *p); - - -extern int add_client(char *addr); - -/* Make connections (including spawning pppd) as server/client */ -extern ppp_connect(struct session *ses); - - -#endif +/* Function Prototypes */ +UINT16_t etherType(PPPoEPacket *packet); +int openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr); +int sendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size); +int receivePacket(int sock, PPPoEPacket *pkt, int *size); +void fatalSys(char const *str); +void dumpPacket(FILE *fp, PPPoEPacket *packet, char const *dir); +void dumpHex(FILE *fp, unsigned char const *buf, int len); +int parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra); +void parseLogErrs(UINT16_t typ, UINT16_t len, unsigned char *data, void *xtra); +void syncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet); +void asyncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet); +void asyncReadFromEth(PPPoEConnection *conn, int sock, int clampMss); +void syncReadFromEth(PPPoEConnection *conn, int sock, int clampMss); +char *strDup(char const *str); +void sendPADT(PPPoEConnection *conn, char const *msg); +void sendSessionPacket(PPPoEConnection *conn, + PPPoEPacket *packet, int len); +void initPPP(void); +void clampMSS(PPPoEPacket *packet, char const *dir, int clampMss); +UINT16_t computeTCPChecksum(unsigned char *ipHdr, unsigned char *tcpHdr); +UINT16_t pppFCS16(UINT16_t fcs, unsigned char *cp, int len); +void discovery(PPPoEConnection *conn); +unsigned char *findTag(PPPoEPacket *packet, UINT16_t tagType, + PPPoETag *tag); + +extern int pppoe_verbose; +void pppoe_printpkt(PPPoEPacket *packet, + void (*printer)(void *, char *, ...), void *arg); +void pppoe_log_packet(const char *prefix, PPPoEPacket *packet); + +static inline int parseHostUniq(const char *uniq, PPPoETag *tag) +{ + unsigned i, len = strlen(uniq); + +#define hex(x) \ + (((x) <= '9') ? ((x) - '0') : \ + (((x) <= 'F') ? ((x) - 'A' + 10) : \ + ((x) - 'a' + 10))) + + if (!len || len % 2 || len / 2 > sizeof(tag->payload)) + return 0; + + for (i = 0; i < len; i += 2) { + if (!isxdigit(uniq[i]) || !isxdigit(uniq[i+1])) + return 0; + + tag->payload[i / 2] = (char)(hex(uniq[i]) << 4 | hex(uniq[i+1])); + } + +#undef hex + + tag->type = htons(TAG_HOST_UNIQ); + tag->length = htons(len / 2); + return 1; +} + +#define SET_STRING(var, val) do { if (var) free(var); var = strDup(val); } while(0); + +#define CHECK_ROOM(cursor, start, len) \ +do {\ + if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \ + error("Would create too-long packet"); \ + return; \ + } \ +} while(0) + +/* True if Ethernet address is broadcast or multicast */ +#define NOT_UNICAST(e) ((e[0] & 0x01) != 0) +#define BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) == 0xFF) +#define NOT_BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) != 0xFF)