⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pppoe.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
字号:
/*
 *   PPPoE (PPP-over-Ethernet) for Watt-32. Refer RFC-2516 for spec.
 *
 *   Version
 *
 *   0.5 : Aug 07, 2001 : G. Vanem - created
 *   0.6 : Aug 08, 2001 : Added extensions from
                          draft-carrel-info-pppoe-ext-00.txt
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "wattcp.h"
#include "misc.h"
#include "strings.h"
#include "pcconfig.h"
#include "pcdbug.h"
#include "pcqueue.h"
#include "pctcp.h"
#include "pcsed.h"
#include "pcpkt.h"
#include "pppoe.h"

#if defined(USE_PPPOE)
#include <netinet/in.h>
#include <net/ppp_defs.h>

enum States {
     StateDiscovery = 1,
     StateSession
   };

static void (*prev_hook) (const char*, const char*) = NULL;

static mac_address macAddr;   /* AC's MAC address */
static WORD        session;
static BOOL        got_PADO;
static BOOL        got_PADS;
static BOOL        got_PADT;
static enum States state;

static struct {
         int   enable;
         int   timeout;
         int   retries;
         char *serviceName;
       } cfg = { 0, 5, 3, NULL };

static int  pppoe_send (int code);
static int  pppoe_wait (int code);

static void pppoe_config (const char *name, const char *value)
{
  static struct config_table pppoe_cfg[] = {
                { "ENABLE",      ARG_ATOI,   (void*)&cfg.enable      },
                { "TIMEOUT",     ARG_ATOI,   (void*)&cfg.timeout     },
                { "RETRIES",     ARG_ATOI,   (void*)&cfg.retries     },
                { "SERVICENAME", ARG_STRDUP, (void*)&cfg.serviceName },
                { NULL }
              };
  if (!parse_config_table(&pppoe_cfg[0], "PPPOE.", name, value) && prev_hook)
     (*prev_hook) (name, value);
}

/*
 * Set config-parser hook and initial values
 */
void pppoe_init (void)
{
  prev_hook = usr_init;
  usr_init  = pppoe_config;
  state = StateDiscovery;
  got_PADO = got_PADS = got_PADT = FALSE;
  memset (&macAddr, 0xFF, sizeof(macAddr)); /* start with broadcast */
}

/*
 * Initialise PPPoE by going through Discovery state and
 * enter Session state
 */
int pppoe_discovery (void)
{
  int loop;

  if (!cfg.enable)
     return (1);

  for (loop = 1; loop <= cfg.retries; loop++)
  {
    if (!pppoe_send(PPPOE_CODE_PADI))  /* send Init packet */
       return (0);

    if (pppoe_wait(PPPOE_CODE_PADO))   /* wait for Offer */
       break;
  }
  if (loop > cfg.retries)
     return (0);

  for (loop = 1; loop <= cfg.retries; loop++)
  {
    if (!pppoe_send(PPPOE_CODE_PADR))  /* send Request */
       return (0);

    if (pppoe_wait(PPPOE_CODE_PADS))   /* wait for Session-confirm */
       break;
  }
  if (loop > cfg.retries)
     return (0);

  state = StateSession;
  return (1);
}

/*
 * Close down PPPoE by sending PADT
 */
void pppoe_exit (void)
{
  if (!cfg.enable || state != StateSession)
     return;

  pppoe_send (PPPOE_CODE_PADT);
  session = 0;
  state = 0;
  memset (&macAddr, 0xFF, sizeof(macAddr));
}

/*
 * pppoe_handler() - handle incoming PPPoE packets
 */
int pppoe_handler (struct pppoe_Packet *pkt)
{
  WORD proto, code;

  if (pkt->head.type != 1 || pkt->head.ver != 1)
     return (0);

  proto = pkt->head.proto;
  code  = pkt->head.code;

  if (proto == PPPOE_SESS_TYPE && state == StateSession)
  {
    if (code == PPPOE_CODE_SESS && pkt->head.session == session &&
        !memcmp(pkt->head.source, &macAddr, sizeof(macAddr)))
    {
      int   len = intel16 (pkt->head.length);
      BYTE *ppp = &pkt->data[0] - 2; /* overwrite pkt->head.length */

      PPP_ADDRESS (ppp) = PPP_ALLSTATIONS;
      PPP_CONTROL (ppp) = PPP_UI;
   // ppp_input (ppp, len);
    }
  }
  else if (proto == PPPOE_DISC_TYPE && state == StateDiscovery)
  {
    if (code == PPPOE_CODE_PADO)
    {
      got_PADO = TRUE;
      memcpy (&macAddr, &pkt->head.source, sizeof(macAddr));
    }
    else if (code == PPPOE_CODE_PADT && pkt->head.session == session)
    {
      got_PADT = TRUE;
      outsnl ("PPPoE: session terminated");
    }
    else if (code == PPPOE_CODE_PADS)
    {
      got_PADS = TRUE;
      session = pkt->head.session;
    }
  }
  return (1);
}

/*
 * Return true if we have a session
 */
BOOL pppoe_is_up (void)
{
  return (session != 0 && state == StateSession && !got_PADT);
}

/*
 * Build a PADx packet
 */
static int build_pad (struct pppoe_Packet *pkt, WORD code)
{
  BYTE *tags = &pkt->data[0];
  int   len  = 0;

  pkt->head.ver     = 1;
  pkt->head.type    = 1;
  pkt->head.code    = code;
  pkt->head.session = session;

  if (code == PPPOE_CODE_PADI || code == PPPOE_CODE_PADR)
  {
    len = PPPOE_TAG_HDR_SIZE;
    *(WORD*) tags = PPPOE_TAG_SERVICE_NAME;
    if (cfg.serviceName)
    {
      int slen = strlen (cfg.serviceName);
      len += slen;
      memcpy (tags, cfg.serviceName, slen);
      *(WORD*) (tags+2) = intel16 (slen);
    }
    else
      *(WORD*) (tags+2) = 0;  /* No service-selection */
  }
  pkt->head.length = intel16 (len);
  return (len + PPPOE_HDR_SIZE);
}

/*
 * Build and send a PADx (PPPoE Active Discovery) packet as
 * link-layer broadcast or unicast
 */
static int pppoe_send (int code)
{
  void         *eth = _eth_formatpacket (&macAddr[0], PPPOE_DISC_TYPE);
  pppoe_Packet *pkt = (struct pppoe_Packet*) MAC_HDR (eth);
  int           len = build_pad (pkt, code);

#if defined(USE_DEBUG)
  if (_dbugxmit)
    (*_dbugxmit) (NULL, eth, __FILE__, __LINE__);
  if (debug_on)
  {
    outs ("PPPOE: sending code 0x");
    outhex (code);
  }
#endif
  return _eth_send (len);
}

/*
 * Loop waiting for timeout or PAD response
 */
static int pppoe_wait (int wait_code)
{
  DWORD timer = set_timeout (1000 * cfg.timeout);

  while (1)
  {
    tcp_tick (NULL);

    if (chk_timeout(timer))
       return (0);

    if ((wait_code == PPPOE_CODE_PADO && got_PADO) ||
        (wait_code == PPPOE_CODE_PADS && got_PADS))
    {
      if (debug_on)
      {
        outs ("PPPoE: got code 0x");
        outhex (wait_code);
      }
      return (1);
    }
  }
  return (0);
}

#endif /* (USE_PPPOE) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -