Added modem driver (completely untested, currently no support for settings speed because modem API is missing).

Some minor changes.
Added TODO file to almost all modules.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5768 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald 2003-12-27 14:27:55 +00:00
parent 7abc3cd77b
commit 8dad9b1eb2
23 changed files with 1067 additions and 20 deletions

View File

@ -1,6 +1,7 @@
SubDir OBOS_TOP src add-ons kernel network ppp ;
SubInclude OBOS_TOP src add-ons kernel network ppp ipcp ;
SubInclude OBOS_TOP src add-ons kernel network ppp modem ;
SubInclude OBOS_TOP src add-ons kernel network ppp pap ;
SubInclude OBOS_TOP src add-ons kernel network ppp pppoe ;
SubInclude OBOS_TOP src add-ons kernel network ppp shared ;

View File

@ -0,0 +1,3 @@
- add CHAP
- add ISDN (CAPI)
- add PPP over TCP/IP (this is a virtual device that uses TCP/IP to connect to some other PPP server on the net)

View File

@ -12,7 +12,6 @@
#include <LockerHelper.h>
#include <cstring>
//#include <netinet/in.h>
#include <netinet/in_var.h>
#include <core_funcs.h>
#include <sys/sockio.h>
@ -192,12 +191,12 @@ IPCP::Send(struct mbuf *packet, uint16 protocolNumber = IPCP_PROTOCOL)
status_t
IPCP::Receive(struct mbuf *packet, uint16 protocolNumber)
{
if(protocolNumber == IP_PROTOCOL)
return ReceiveIPPacket(packet, protocolNumber);
if(!packet)
return B_ERROR;
if(protocolNumber == IP_PROTOCOL)
return ReceiveIPPacket(packet, protocolNumber);
if(protocolNumber != IPCP_PROTOCOL)
return PPP_UNHANDLED;
@ -257,9 +256,6 @@ IPCP::ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber)
if(protocolNumber != IP_PROTOCOL || State() != PPP_OPENED_STATE)
return PPP_UNHANDLED;
if(!packet)
return B_ERROR;
// TODO: add VJC support (the packet would be decoded here)
if (gProto[IPPROTO_IP] && gProto[IPPROTO_IP]->pr_input) {

View File

@ -0,0 +1,2 @@
- test server mode
- add VJC compression support

View File

@ -0,0 +1,121 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#include "ACFCHandler.h"
#include <KPPPConfigurePacket.h>
#define ACFC_TYPE 0x8
ACFCHandler::ACFCHandler(uint32 options, PPPInterface& interface)
: PPPOptionHandler("ACFC Handler", ACFC_TYPE, interface, NULL),
fOptions(options),
fLocalState(ACFC_DISABLED),
fPeerState(ACFC_DISABLED)
{
}
status_t
ACFCHandler::AddToRequest(PPPConfigurePacket& request)
{
// is ACFC not requested or was it rejected?
if(fLocalState == ACFC_REJECTED
|| (Options() & REQUEST_ACFC) == 0)
return B_OK;
// add ACFC request
ppp_configure_item item;
item.type = ACFC_TYPE;
item.length = 2;
return request.AddItem(&item) ? B_OK : B_ERROR;
}
status_t
ACFCHandler::ParseNak(const PPPConfigurePacket& nak)
{
// naks do not contain ACFC items
if(nak.ItemWithType(ACFC_TYPE))
return B_ERROR;
return B_OK;
}
status_t
ACFCHandler::ParseReject(const PPPConfigurePacket& reject)
{
if(reject.ItemWithType(ACFC_TYPE)) {
fLocalState = ACFC_REJECTED;
if(Options() & FORCE_ACFC_REQUEST)
return B_ERROR;
}
return B_OK;
}
status_t
ACFCHandler::ParseAck(const PPPConfigurePacket& ack)
{
if(ack.ItemWithType(ACFC_TYPE))
fLocalState = ACFC_ACCEPTED;
else {
fLocalState = ACFC_DISABLED;
if(Options() & FORCE_ACFC_REQUEST)
return B_ERROR;
}
return B_OK;
}
status_t
ACFCHandler::ParseRequest(const PPPConfigurePacket& request,
int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject)
{
if(!request.ItemWithType(ACFC_TYPE))
return B_OK;
if((Options() & ALLOW_ACFC) == 0) {
ppp_configure_item item;
item.type = ACFC_TYPE;
item.length = 2;
return reject.AddItem(&item) ? B_OK : B_ERROR;
}
return B_OK;
}
status_t
ACFCHandler::SendingAck(const PPPConfigurePacket& ack)
{
ppp_configure_item *item = ack.ItemWithType(ACFC_TYPE);
if(item && (Options() & ALLOW_ACFC) == 0)
return B_ERROR;
if(item)
fPeerState = ACFC_ACCEPTED;
else
fPeerState = ACFC_DISABLED;
return B_OK;
}
void
ACFCHandler::Reset()
{
fLocalState = fPeerState = ACFC_DISABLED;
}

View File

@ -0,0 +1,60 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#ifndef ACFC_HANDLER__H
#define ACFC_HANDLER__H
#include <KPPPOptionHandler.h>
// ACFC options
enum {
REQUEST_ACFC = 0x01,
// try to request ACFC (does not fail if not successful)
ALLOW_ACFC = 0x02,
// allow ACFC if other side requests it
FORCE_ACFC_REQUEST = 0x04,
// if ACFC request fails the connection attempt will terminate
};
enum acfc_state {
ACFC_DISABLED,
ACFC_ACCEPTED,
ACFC_REJECTED
// not used for peer state
};
class ACFCHandler : public PPPOptionHandler {
public:
ACFCHandler(uint32 options, PPPInterface& interface);
uint32 Options() const
{ return fOptions; }
acfc_state LocalState() const
{ return fLocalState; }
acfc_state PeerState() const
{ return fPeerState; }
virtual status_t AddToRequest(PPPConfigurePacket& request);
virtual status_t ParseNak(const PPPConfigurePacket& nak);
virtual status_t ParseReject(const PPPConfigurePacket& reject);
virtual status_t ParseAck(const PPPConfigurePacket& ack);
virtual status_t ParseRequest(const PPPConfigurePacket& request,
int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject);
virtual status_t SendingAck(const PPPConfigurePacket& ack);
virtual void Reset();
private:
uint32 fOptions;
acfc_state fLocalState, fPeerState;
};
#endif

View File

@ -0,0 +1,22 @@
SubDir OBOS_TOP src add-ons kernel network ppp modem ;
# for kernel_cpp.h and BLocker
UsePrivateHeaders net ;
UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(OBOS_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ;
UseHeaders [ FDirName $(OBOS_TOP) src add-ons kernel network ppp shared libkernelppp ] ;
R5KernelAddon modem : kernel network ppp :
modem.cpp
ModemDevice.cpp
ACFCHandler.cpp
;
LinkSharedOSLibs modem : libkernelppp.a ;
# Installation
OBOSInstall install-networking
: /boot/home/config/add-ons/kernel/network/ppp
: modem ;

View File

@ -0,0 +1,44 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#ifndef MODEM__H
#define MODEM__H
#include <SupportDefs.h>
#include <net/if.h>
#include <netinet/if_ether.h>
class ModemDevice;
#define CONTROL_ESCAPE 0x7d
#define FLAG_SEQUENCE 0x7e
#define ALL_STATIONS 0xff
#define UI 0x03
#define ESCAPE_DELAY 1000000
#define ESCAPE_SEQUENCE "+++"
#define AT_HANG_UP "ATH0"
#define MODEM_MTU 1502
#define PACKET_OVERHEAD 8
#define MODEM_TIMEOUT 3000000
// 3 seconds
#define MODEM_INTERFACE_KEY "interface"
#define MODEM_INIT_KEY "init"
#define MODEM_DIAL_KEY "dial"
extern struct core_module_info *core;
#if DEBUG
// defined in ModemDevice.cpp
void dump_packet(struct mbuf *packet);
#endif // DEBUG
#endif

View File

@ -0,0 +1,531 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#include <cstdio>
#include "ModemDevice.h"
#include "ACFCHandler.h"
#include "fcs.h"
#include <core_funcs.h>
#include <unistd.h>
// from libkernelppp
#include <settings_tools.h>
#include <LockerHelper.h>
#ifdef _KERNEL_MODE
#define spawn_thread spawn_kernel_thread
#define printf dprintf
#endif
#if DEBUG
static char sDigits[] = "0123456789ABCDEF";
void
dump_packet(struct mbuf *packet)
{
if(!packet)
return;
uint8 *data = mtod(packet, uint8*);
uint8 buffer[33];
uint8 bufferIndex = 0;
printf("Dumping packet;len=%ld;pkthdr.len=%d\n", packet->m_len,
packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : -1);
for(uint32 index = 0; index < packet->m_len; index++) {
buffer[bufferIndex++] = sDigits[data[index] >> 4];
buffer[bufferIndex++] = sDigits[data[index] & 0x0F];
if(bufferIndex == 32 || index == packet->m_len - 1) {
buffer[bufferIndex] = 0;
printf("%s\n", buffer);
bufferIndex = 0;
}
}
}
#endif
status_t
modem_put_line(int32 handle, const char *string, int32 length)
{
char line[128];
if(length > 126)
return -1;
sprintf(line, "%s\r", string);
return write(handle, line, length + 1);
}
status_t
modem_get_line(int32 handle, char *string, int32 length, const char *echo)
{
if(!string || length < 40)
return -1;
int32 result, position = 0;
while(position < length) {
result = read(handle, string + position, 1);
if(result < 0)
return -1;
else if(result == 1) {
if(string[position] == '\r') {
string[position] = 0;
if(!strcasecmp(string, echo)) {
position = 0;
continue;
}
return position;
}
position++;
}
}
return -1;
}
static
status_t
worker_thread(void *data)
{
ModemDevice *device = (ModemDevice*) data;
int32 handle = device->Handle();
uint8 buffer[MODEM_MTU];
// send init string
if(modem_put_line(handle, device->InitString(), strlen(device->InitString())) < 0
|| modem_get_line(handle, (char*) buffer, sizeof(buffer),
device->InitString()) < 0
|| strcmp((char*) buffer, "OK")) {
device->FailedDialing();
return B_ERROR;
}
// send dial string
if(modem_put_line(handle, device->DialString(), strlen(device->DialString())) < 0
|| modem_get_line(handle, (char*) buffer, sizeof(buffer),
device->DialString()) < 0
|| strncmp((char*) buffer, "CONNECT", 7)) {
device->FailedDialing();
return B_ERROR;
}
if(strlen((char*) buffer) > 8)
device->SetSpeed(atoi((char*) buffer + 8));
else
device->SetSpeed(19200);
// TODO: authenticate if needed
device->FinishedDialing();
// start decoding
int32 length = 0, position = 0;
bool inPacket = true, needsEscape = false;
while(true) {
// ignore data if buffer is full
if(position == MODEM_MTU)
position = 0;
length = read(handle, buffer + position, MODEM_MTU - position);
if(length < 0 || !device->IsUp()) {
device->ConnectionLost();
return B_ERROR;
}
// decode the packet
for(int32 index = 0; index < length; ) {
if(buffer[position] == FLAG_SEQUENCE) {
if(inPacket && position > 0)
device->DataReceived(buffer, position);
// DataReceived() will check FCS
length = length - index - 1;
// remaining data length
memmove(buffer, buffer + position + 1, length);
position = index = 0;
needsEscape = false;
inPacket = true;
continue;
}
if(buffer[position + index] < 0x20) {
++index;
continue;
}
if(needsEscape) {
buffer[position] = buffer[position + index] ^ 0x20;
++position;
needsEscape = false;
} else if(buffer[position + index] == CONTROL_ESCAPE) {
++index;
needsEscape = true;
} else {
buffer[position] = buffer[position + index];
++position;
}
}
}
}
ModemDevice::ModemDevice(PPPInterface& interface, driver_parameter *settings)
: PPPDevice("PPPoE", 0, interface, settings),
fInterfaceName(NULL),
fHandle(-1),
fWorkerThread(-1),
fOutputBytes(0),
fState(INITIAL)
{
#if DEBUG
printf("ModemDevice: Constructor\n");
if(!settings || !settings->parameters)
printf("ModemDevice::ctor: No settings!\n");
#endif
fACFC = new ACFCHandler(REQUEST_ACFC | ALLOW_ACFC, interface);
if(!interface.LCP().AddOptionHandler(fACFC)) {
fInitStatus = B_ERROR;
return;
}
interface.SetPFCOptions(PPP_REQUEST_PFC | PPP_ALLOW_PFC);
SetSpeed(19200);
SetMTU(MODEM_MTU);
// MTU size does not contain PPP header
fInterfaceName = get_parameter_value(MODEM_INTERFACE_KEY, settings);
fInitString = get_parameter_value(MODEM_INIT_KEY, settings);
fDialString = get_parameter_value(MODEM_DIAL_KEY, settings);
#if DEBUG
printf("ModemDevice::ctor: interfaceName: %s\n", interfaceName);
#endif
}
ModemDevice::~ModemDevice()
{
#if DEBUG
printf("ModemDevice: Destructor\n");
#endif
}
status_t
ModemDevice::InitCheck() const
{
if(fState != INITIAL && Handle() == -1)
return B_ERROR;
return InterfaceName() && PPPDevice::InitCheck() == B_OK ? B_OK : B_ERROR;
}
bool
ModemDevice::Up()
{
#if DEBUG
printf("ModemDevice: Up()\n");
#endif
if(InitCheck() != B_OK)
return false;
LockerHelper locker(fLock);
if(IsUp())
return true;
fState = INITIAL;
// reset state
// check if we are allowed to go up now (user intervention might disallow that)
if(!UpStarted()) {
CloseModem();
DownEvent();
return true;
// there was no error
}
OpenModem();
fState = DIALING;
if(fWorkerThread == -1) {
fWorkerThread = spawn_thread(worker_thread, "Modem: worker_thread",
B_NORMAL_PRIORITY, this);
resume_thread(fWorkerThread);
}
return true;
}
bool
ModemDevice::Down()
{
#if DEBUG
printf("ModemDevice: Down()\n");
#endif
if(InitCheck() != B_OK)
return false;
LockerHelper locker(fLock);
fState = TERMINATING;
if(!IsUp()) {
fState = INITIAL;
CloseModem();
DownEvent();
return true;
}
DownStarted();
// this tells StateMachine that DownEvent() does not mean we lost connection
// worker_thread will notice that we are terminating (IsUp() == false)
// ConnectionLost() will be called so we can terminate the connection there.
locker.UnlockNow();
int32 tmp;
wait_for_thread(fWorkerThread, &tmp);
DownEvent();
return true;
}
void
ModemDevice::SetSpeed(uint32 bps)
{
fInputTransferRate = bps / 8;
fOutputTransferRate = (fInputTransferRate * 60) / 100;
// 60% of input transfer rate
}
uint32
ModemDevice::InputTransferRate() const
{
return fInputTransferRate;
}
uint32
ModemDevice::OutputTransferRate() const
{
return fOutputTransferRate;
}
uint32
ModemDevice::CountOutputBytes() const
{
return fOutputBytes;
}
void
ModemDevice::OpenModem()
{
LockerHelper locker(fLock);
if(Handle() >= 0)
return;
char path[B_PATH_NAME_LENGTH];
sprintf(path, "/dev/modem/%s", InterfaceName());
fHandle = open(path, O_RDWR);
}
void
ModemDevice::CloseModem()
{
LockerHelper locker(fLock);
if(Handle() >= 0)
close(Handle());
fHandle = -1;
}
void
ModemDevice::FinishedDialing()
{
LockerHelper locker(fLock);
fOutputBytes = 0;
fState = OPENED;
UpEvent();
}
void
ModemDevice::FailedDialing()
{
LockerHelper locker(fLock);
fWorkerThread = -1;
fState = INITIAL;
CloseModem();
UpFailedEvent();
}
void
ModemDevice::ConnectionLost()
{
LockerHelper locker(fLock);
// switch to command mode and disconnect
fWorkerThread = -1;
fOutputBytes = 0;
snooze(ESCAPE_DELAY);
if(write(Handle(), ESCAPE_SEQUENCE, strlen(ESCAPE_SEQUENCE)) < 0)
return;
snooze(ESCAPE_DELAY);
modem_put_line(Handle(), AT_HANG_UP, strlen(AT_HANG_UP));
CloseModem();
}
status_t
ModemDevice::Send(struct mbuf *packet, uint16 protocolNumber = 0)
{
#if DEBUG
printf("ModemDevice: Send()\n");
dump_packet(packet);
#endif
if(!packet)
return B_ERROR;
else if(InitCheck() != B_OK || protocolNumber != 0) {
m_freem(packet);
return B_ERROR;
} else if(!IsUp()) {
m_freem(packet);
return PPP_NO_CONNECTION;
}
// we might need room for our header
if(fACFC->LocalState() != ACFC_ACCEPTED) {
M_PREPEND(packet, 2);
if(!packet)
return B_ERROR;
}
int32 position = 0, length;
if(packet->m_flags & M_PKTHDR)
length = packet->m_pkthdr.len;
else
length = packet->m_len;
// we need a contiguous chunk of memory
packet = m_pullup(packet, length);
if(!packet)
return B_ERROR;
uint8 buffer[2 * (MODEM_MTU + PACKET_OVERHEAD)], *data = mtod(packet, uint8*);
// add header
if(fACFC->LocalState() != ACFC_ACCEPTED) {
data[0] = ALL_STATIONS;
data[1] = UI;
}
// add FCS
uint16 fcs = 0xffff;
fcs = pppfcs16(fcs, data, length);
fcs ^= 0xffff;
data[length++] = fcs & 0x00ff;
data[length++] = (fcs & 0xff00) >> 8;
// encode packet
buffer[position++] = FLAG_SEQUENCE;
// mark beginning of packet
for(int32 index = 0; index < length; index++) {
if(data[index] < 0x20 || data[index] == FLAG_SEQUENCE
|| data[index] == CONTROL_ESCAPE) {
buffer[position++] = CONTROL_ESCAPE;
buffer[position++] = data[index] ^ 0x20;
} else
buffer[position++] = data[index];
}
buffer[position++] = FLAG_SEQUENCE;
// mark end of packet
m_freem(packet);
// send to modem
atomic_add((int32*) &fOutputBytes, position);
if(write(Handle(), buffer, position) < 0)
return PPP_NO_CONNECTION;
atomic_add((int32*) &fOutputBytes, -position);
return B_OK;
}
status_t
ModemDevice::DataReceived(uint8 *buffer, uint32 length)
{
// TODO: report corrupted packets to PPPInterface
if(length < 3)
return B_ERROR;
// check FCS
uint16 fcs = 0xffff;
fcs = pppfcs16(fcs, buffer, length - 2);
fcs ^= 0xffff;
if(buffer[length - 2] != fcs & 0x00ff || buffer[length - 1] != (fcs & 0xff00) >> 8)
return B_ERROR;
if(buffer[0] == ALL_STATIONS && buffer[1] == UI)
buffer += 2;
mbuf *packet = m_gethdr(MT_DATA);
packet->m_len = packet->m_pkthdr.len = length - 2;
uint8 *data = mtod(packet, uint8*);
memcpy(data, buffer, length - 2);
return Receive(packet);
}
status_t
ModemDevice::Receive(struct mbuf *packet, uint16 protocolNumber = 0)
{
// we do not need to lock because only the worker_thread calls this method
if(!packet)
return B_ERROR;
else if(InitCheck() != B_OK || !IsUp()) {
m_freem(packet);
return B_ERROR;
}
Interface().ReceiveFromDevice(packet);
}

View File

@ -0,0 +1,87 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#ifndef MODEM_DEVICE__H
#define MODEM_DEVICE__H
#include "Modem.h"
#include <KPPPDevice.h>
enum modem_state {
INITIAL,
// the same as IsDown() == true
TERMINATING,
DIALING,
OPENED
// the same as IsUp() == true
};
class ACFCHandler;
class ModemDevice : public PPPDevice {
public:
ModemDevice(PPPInterface& interface, driver_parameter *settings);
virtual ~ModemDevice();
const char *InterfaceName() const
{ return fInterfaceName; }
int32 Handle() const
{ return fHandle; }
// returns file handle for modem driver
const char *InitString() const
{ return fInitString; }
const char *DialString() const
{ return fDialString; }
virtual status_t InitCheck() const;
virtual bool Up();
virtual bool Down();
void SetSpeed(uint32 bps);
virtual uint32 InputTransferRate() const;
virtual uint32 OutputTransferRate() const;
// this is around 60% of the input transfer rate
virtual uint32 CountOutputBytes() const;
void OpenModem();
void CloseModem();
// notifications:
void FinishedDialing();
void FailedDialing();
void ConnectionLost();
virtual status_t Send(struct mbuf *packet, uint16 protocolNumber = 0);
status_t DataReceived(uint8 *buffer, uint32 length);
// this will put the data into an mbuf and call Receive()
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber = 0);
private:
const char *fInterfaceName, *fInitString, *fDialString;
int32 fHandle;
// file handle for modem driver
thread_id fWorkerThread;
uint32 fInputTransferRate, fOutputTransferRate;
uint32 fOutputBytes;
modem_state fState;
ACFCHandler *fACFC;
BLocker fLock;
};
#endif

View File

@ -0,0 +1,5 @@
- get escape character from S-Register 2 (default: +)
- get escape guard time from S-Register 12 (default: 1 second)
- add support for server mode
- add ACCM support (including ACCM option handler and encoding)
- add chat login authentication (like terminal login)

View File

@ -0,0 +1,62 @@
/*-----Lifted from RFC 1662,
PPP in HDLC-like Framing------------
http://www.faqs.org/rfcs/rfc1662.html
*/
/*
* u16 represents an unsigned 16-bit number. Adjust the typedef for
* your hardware.
*/
typedef uint16 u16;
/*
* FCS lookup table as calculated by the table generator.
*/
static u16 fcstab[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
#define PPPINITFCS16 0xffff /* Initial FCS value */
#define PPPGOODFCS16 0xf0b8 /* Good final FCS value */
/*
* Calculate a new fcs given the current fcs and the new data.
*/
u16 pppfcs16(u16 fcs, unsigned char *cp, int len)
{
while (len--)
fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];
return (fcs);
}

View File

@ -0,0 +1,97 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, Waldemar.Kornewald@web.de
//---------------------------------------------------------------------
#include <core_funcs.h>
#include <KernelExport.h>
#include <driver_settings.h>
#include <KPPPInterface.h>
#include <KPPPModule.h>
#include <LockerHelper.h>
#include "ModemDevice.h"
#ifdef _KERNEL_MODE
#define spawn_thread spawn_kernel_thread
#define printf dprintf
#else
#include <cstdio>
#endif
#define MODEM_MODULE_NAME "network/ppp/modem"
struct core_module_info *core = NULL;
status_t std_ops(int32 op, ...);
static
bool
add_to(PPPInterface& mainInterface, PPPInterface *subInterface,
driver_parameter *settings, ppp_module_key_type type)
{
if(mainInterface.Mode() != PPP_CLIENT_MODE || type != PPP_DEVICE_KEY_TYPE)
return B_ERROR;
ModemDevice *device;
bool success;
if(subInterface) {
device = new ModemDevice(*subInterface, settings);
success = subInterface->SetDevice(device);
} else {
device = new ModemDevice(mainInterface, settings);
success = mainInterface.SetDevice(device);
}
#if DEBUG
printf("Modem: add_to(): %s\n",
success && device && device->InitCheck() == B_OK ? "OK" : "ERROR");
#endif
return success && device && device->InitCheck() == B_OK;
}
static ppp_module_info modem_module = {
{
MODEM_MODULE_NAME,
0,
std_ops
},
NULL,
add_to
};
_EXPORT
status_t
std_ops(int32 op, ...)
{
switch(op) {
case B_MODULE_INIT:
if(get_module(NET_CORE_MODULE_NAME, (module_info**)&core) != B_OK)
return B_ERROR;
return B_OK;
case B_MODULE_UNINIT:
put_module(NET_CORE_MODULE_NAME);
break;
default:
return B_ERROR;
}
return B_OK;
}
_EXPORT
module_info *modules[] = {
(module_info*) &modem_module,
NULL
};

View File

@ -0,0 +1 @@
- test server mode

View File

@ -49,8 +49,10 @@ uint32 NewHostUniq();
void add_device(PPPoEDevice *device);
void remove_device(PPPoEDevice *device);
#if DEBUG
// defined in PPPoEDevice.cpp
void dump_packet(struct mbuf *packet);
#endif // DEBUG
#endif

View File

@ -68,6 +68,9 @@ PPPoEDevice::PPPoEDevice(PPPInterface& interface, driver_parameter *settings)
printf("PPPoEDevice::ctor: No settings!\n");
#endif
interface.SetPFCOptions(PPP_ALLOW_PFC);
// we do not want to fail just because the other side requests PFC
memset(fPeer, 0xFF, sizeof(fPeer));
SetMTU(1494);
// MTU size does not contain PPP header
@ -249,7 +252,7 @@ PPPoEDevice::Down()
EthernetIfnet()->output(EthernetIfnet(), packet, &destination, NULL);
DownEvent();
return false;
return true;
}
@ -284,16 +287,19 @@ PPPoEDevice::Send(struct mbuf *packet, uint16 protocolNumber = 0)
dump_packet(packet);
#endif
if(InitCheck() != B_OK || protocolNumber != 0) {
if(!packet)
return B_ERROR;
else if(InitCheck() != B_OK || protocolNumber != 0) {
m_freem(packet);
return B_ERROR;
} else if(!packet)
return B_ERROR;
}
LockerHelper locker(fLock);
if(!IsUp())
if(!IsUp()) {
m_freem(packet);
return PPP_NO_CONNECTION;
}
uint16 length = packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : packet->m_len;
@ -332,11 +338,12 @@ PPPoEDevice::Send(struct mbuf *packet, uint16 protocolNumber = 0)
status_t
PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber = 0)
{
if(InitCheck() != B_OK || IsDown()) {
if(!packet)
return B_ERROR;
else if(InitCheck() != B_OK || IsDown()) {
m_freem(packet);
return B_ERROR;
} else if(!packet)
return B_ERROR;
}
complete_pppoe_header *completeHeader = mtod(packet, complete_pppoe_header*);
if(!completeHeader) {

View File

@ -15,11 +15,11 @@
enum pppoe_state {
INITIAL,
// the same as IsDown()
// the same as IsDown() == true
PADI_SENT,
PADR_SENT,
OPENED
// the same as IsUp()
// the same as IsUp() == true
};

View File

@ -0,0 +1 @@
- add support for server mode

View File

@ -126,7 +126,7 @@ bool
add_to(PPPInterface& mainInterface, PPPInterface *subInterface,
driver_parameter *settings, ppp_module_key_type type)
{
if(type != PPP_DEVICE_KEY_TYPE)
if(mainInterface.Mode() != PPP_CLIENT_MODE || type != PPP_DEVICE_KEY_TYPE)
return B_ERROR;
PPPoEDevice *device;

View File

@ -45,6 +45,9 @@ PPPLayer::InitCheck() const
status_t
PPPLayer::SendToNext(struct mbuf *packet, uint16 protocolNumber) const
{
if(!packet)
return B_ERROR;
// Find the next possible handler for this packet.
// Normal protocols (Level() >= PPP_PROTOCOL_LEVEL) do not encapsulate anything.
if(Next()) {

View File

@ -0,0 +1,2 @@
- finish support for server mode
- add callback support

View File

@ -26,7 +26,7 @@ status_t
_PPPPFCHandler::AddToRequest(PPPConfigurePacket& request)
{
// is PFC not requested or was it rejected?
if(fLocalPFCState & PPP_PFC_REJECTED
if(fLocalPFCState == PPP_PFC_REJECTED
|| (Interface().PFCOptions() & PPP_REQUEST_PFC) == 0)
return B_OK;

View File

@ -146,7 +146,7 @@ class PPPInterface : public PPPLayer {
// the peer PFC state says if the peer accepted a request us
// i.e.: the peer might send PFC-compressed packets to us
bool UseLocalPFC() const
{ return LocalPFCState() & PPP_PFC_ACCEPTED; }
{ return LocalPFCState() == PPP_PFC_ACCEPTED; }
virtual bool Up();
// in server mode Up() listens for an incoming connection