Some small changes and fixes.

Most important:
Finished IPCP and PAP modules.
Both of them are untested at the moment.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5442 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald
2003-11-22 12:28:32 +00:00
parent 5e427b6a85
commit ca43389a75
19 changed files with 2487 additions and 48 deletions
@@ -200,7 +200,10 @@ PPPManager::Output(ifnet *ifp, struct mbuf *buf, struct sockaddr *dst,
if(!protocol->IsEnabled() || protocol->AddressFamily() != dst->sa_family)
continue;
result = protocol->Send(buf, protocol->ProtocolNumber());
if(protocol->Flags() & PPP_INCLUDES_NCP)
result = protocol->Send(buf, protocol->ProtocolNumber() & 0x7FFF);
else
result = protocol->Send(buf, protocol->ProtocolNumber());
if(result == PPP_UNHANDLED)
continue;
+2
View File
@@ -1,4 +1,6 @@
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 pap ;
SubInclude OBOS_TOP src add-ons kernel network ppp pppoe ;
SubInclude OBOS_TOP src add-ons kernel network ppp shared ;
@@ -0,0 +1,24 @@
SubDir OBOS_TOP src add-ons kernel network ppp ipcp ;
# 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 ipcp : kernel network ppp :
ipcp.cpp
Protocol.cpp
inet_addr.c
;
SEARCH on [ FGristFiles inet_addr.c ] = [ FDirName $(OBOS_TOP) src kits network libnet ] ;
LinkSharedOSLibs ipcp : libkernelppp.a ;
# Installation
OBOSInstall install-networking
: /boot/home/config/add-ons/kernel/network/ppp
: ipcp ;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,136 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, [email protected]
//---------------------------------------------------------------------
#ifndef PROTOCOL__H
#define PROTOCOL__H
#include <driver_settings.h>
#include <KPPPProtocol.h>
#include <Locker.h>
#include <arpa/inet.h>
#define IPCP_PROTOCOL 0x8021
#define IP_PROTOCOL 0x0021
typedef struct ip_item {
uint8 type;
uint8 length;
in_addr_t address;
} ip_item;
enum ipcp_configure_item_codes {
IPCP_ADDRESSES = 1,
IPCP_COMPRESSION_PROTOCOL = 2,
IPCP_ADDRESS = 3,
IPCP_PRIMARY_DNS = 129,
IPCP_SECONDARY_DNS = 131
};
typedef struct ipcp_requests {
// let peer suggest value if ours equals 0.0.0.0
in_addr_t address;
in_addr_t netmask;
// if equal 0.0.0.0 it will be chosen automatically
in_addr_t primaryDNS;
in_addr_t secondaryDNS;
} ipcp_requests;
// the values that were negotiated
typedef struct ipcp_configuration {
in_addr_t address;
in_addr_t primaryDNS;
in_addr_t secondaryDNS;
} ipcp_configuration;
extern struct protosw *proto[];
// defined in ipcp.cpp
class IPCP : public PPPProtocol {
public:
IPCP(PPPInterface& interface, driver_parameter *settings);
virtual ~IPCP();
ppp_state State() const
{ return fState; }
virtual bool Up();
virtual bool Down();
virtual status_t Send(struct mbuf *packet,
uint16 protocolNumber = IPCP_PROTOCOL);
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber);
status_t ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber);
virtual void Pulse();
private:
bool ParseSideRequests(driver_parameter *requests, ppp_side side);
void UpdateAddresses();
// for state machine
void NewState(ppp_state next);
uint8 NextID();
// return the next id for IPCP packets
// events
void TOGoodEvent();
void TOBadEvent();
void RCREvent(struct mbuf *packet);
void RCRGoodEvent(struct mbuf *packet);
void RCRBadEvent(struct mbuf *nak, struct mbuf *reject);
void RCAEvent(struct mbuf *packet);
void RCNEvent(struct mbuf *packet);
void RTREvent(struct mbuf *packet);
void RTAEvent(struct mbuf *packet);
void RUCEvent(struct mbuf *packet);
void RXJBadEvent(struct mbuf *packet);
// actions
void IllegalEvent(ppp_event event);
void ReportUpFailedEvent();
void ReportUpEvent();
void ReportDownEvent();
void InitializeRestartCount();
void ZeroRestartCount();
bool SendConfigureRequest();
bool SendConfigureAck(struct mbuf *packet);
bool SendConfigureNak(struct mbuf *packet);
bool SendTerminateRequest();
bool SendTerminateAck(struct mbuf *request = NULL);
bool SendCodeReject(struct mbuf *packet);
private:
ipcp_configuration fLocalConfiguration, fPeerConfiguration;
ipcp_requests fLocalRequests, fPeerRequests;
// used for local requests
bool fRequestPrimaryDNS, fRequestSecondaryDNS;
// for state machine
ppp_state fState;
vint32 fID;
// counters and timers
int32 fMaxRequest, fMaxTerminate, fMaxNak;
int32 fRequestCounter, fTerminateCounter, fNakCounter;
uint8 fRequestID, fTerminateID;
// the ID we used for the last configure/terminate request
bigtime_t fNextTimeout;
BLocker fLock;
};
#endif
@@ -0,0 +1,114 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, [email protected]
//---------------------------------------------------------------------
#include <core_funcs.h>
#include <KernelExport.h>
#include <driver_settings.h>
#include <KPPPInterface.h>
#include <KPPPModule.h>
#include <LockerHelper.h>
#include "Protocol.h"
#ifdef _KERNEL_MODE
#define spawn_thread spawn_kernel_thread
#define printf dprintf
#else
#include <cstdio>
#endif
#define IPCP_MODULE_NAME "network/ppp/ipcp"
struct protosw *proto[IPPROTO_MAX];
struct core_module_info *core = NULL;
status_t std_ops(int32 op, ...);
static BLocker lock;
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// TODO: Remove isascii() (needed for inet_aton()) when our kernel is finished!
// isascii() is not defined in the R5 kernel, thus we must define it here:
extern "C"
int
isascii(char c)
{
return c & ~0x7f == 0; // If c is a 7 bit value.
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
static
bool
add_to(PPPInterface& mainInterface, PPPInterface *subInterface,
driver_parameter *settings, ppp_module_key_type type)
{
if(type != PPP_PROTOCOL_KEY_TYPE)
return B_ERROR;
IPCP *ipcp;
bool success;
if(subInterface) {
ipcp = new IPCP(*subInterface, settings);
success = subInterface->AddProtocol(ipcp);
} else {
ipcp = new IPCP(mainInterface, settings);
success = mainInterface.AddProtocol(ipcp);
}
#if DEBUG
printf("IPCP: add_to(): %s\n",
success && ipcp && ipcp->InitCheck() == B_OK ? "OK" : "ERROR");
#endif
return success && ipcp && ipcp->InitCheck() == B_OK;
}
static ppp_module_info ipcp_module = {
{
IPCP_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;
memset(proto, 0, sizeof(struct protosw*) * IPPROTO_MAX);
add_protosw(proto, NET_LAYER1);
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*) &ipcp_module,
NULL
};
@@ -0,0 +1,21 @@
SubDir OBOS_TOP src add-ons kernel network ppp pap ;
# 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 pap : kernel network ppp :
pap.cpp
Protocol.cpp
;
LinkSharedOSLibs pap : libkernelppp.a ;
# Installation
OBOSInstall install-networking
: /boot/home/config/add-ons/kernel/network/ppp
: pap ;
@@ -0,0 +1,608 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, [email protected]
//---------------------------------------------------------------------
#include "Protocol.h"
#include <KPPPConfigurePacket.h>
#include <KPPPInterface.h>
#include <LockerHelper.h>
#include <cstring>
#include <netinet/in.h>
#include <core_funcs.h>
#include <sys/sockio.h>
#ifdef _KERNEL_MODE
#define spawn_thread spawn_kernel_thread
#define printf dprintf
#elif DEBUG
#include <cstdio>
#endif
#define PAP_TIMEOUT 3000000
// 3 seconds
// PAPHandler
#define AUTHENTICATION_TYPE 0x3
#define AUTHENTICATOR_TYPE_STRING "Authenticator"
typedef struct authentication_item {
uint8 type;
uint8 length;
uint16 protocolNumber;
} authentication_item;
PAPHandler::PAPHandler(PAP& owner, PPPInterface& interface)
: PPPOptionHandler("PAP", AUTHENTICATION_TYPE, interface, NULL),
fOwner(owner)
{
}
status_t
PAPHandler::AddToRequest(PPPConfigurePacket& request)
{
// only local authenticators send requests to peer
if(Owner().Side() != PPP_PEER_SIDE)
return B_OK;
authentication_item item;
item.type = AUTHENTICATION_TYPE;
item.length = sizeof(item);
item.protocolNumber = htons(PAP_PROTOCOL);
request.AddItem((ppp_configure_item*) &item);
return B_OK;
}
status_t
PAPHandler::ParseNak(const PPPConfigurePacket& nak)
{
return B_OK;
}
status_t
PAPHandler::ParseReject(const PPPConfigurePacket& reject)
{
return B_OK;
}
status_t
PAPHandler::ParseAck(const PPPConfigurePacket& ack)
{
return B_OK;
}
status_t
PAPHandler::ParseRequest(const PPPConfigurePacket& request,
int32 index, PPPConfigurePacket& nak, PPPConfigurePacket& reject)
{
// only local authenticators handle requests from peer
if(Owner().Side() != PPP_LOCAL_SIDE)
return B_OK;
// we merely check if the values are correct
authentication_item *item = (authentication_item*) request.ItemAt(index);
if(item->type != AUTHENTICATION_TYPE
|| item->length != 4 || ntohs(item->protocolNumber) != PAP_PROTOCOL)
return B_ERROR;
return B_OK;
}
status_t
PAPHandler::SendingAck(const PPPConfigurePacket& ack)
{
return B_OK;
}
void
PAPHandler::Reset()
{
}
// PAP
PAP::PAP(PPPInterface& interface, driver_parameter *settings)
: PPPProtocol("PAP", PPP_AUTHENTICATION_PHASE, PAP_PROTOCOL, PPP_PROTOCOL_LEVEL,
AF_INET, 0, interface, settings, PPP_NO_FLAGS,
AUTHENTICATOR_TYPE_STRING, new PAPHandler(*this, interface)),
fState(INITIAL),
fID(system_time() & 0xFF),
fMaxRequest(3),
fRequestID(0),
fNextTimeout(0)
{
fUser[0] = fPassword[0] = 0;
ParseSettings(settings);
}
PAP::~PAP()
{
}
status_t
PAP::InitCheck() const
{
if(Side() != PPP_LOCAL_SIDE && Side() != PPP_PEER_SIDE)
return B_ERROR;
return PPPProtocol::InitCheck();
}
bool
PAP::Up()
{
#if DEBUG
printf("PAP: Up() state=%d\n", State());
#endif
LockerHelper locker(fLock);
switch(State()) {
case INITIAL:
if(Side() == PPP_LOCAL_SIDE) {
NewState(REQ_SENT);
InitializeRestartCount();
locker.UnlockNow();
SendRequest();
} else if(Side() == PPP_PEER_SIDE) {
NewState(WAITING_FOR_REQ);
InitializeRestartCount();
fNextTimeout = system_time() + PAP_TIMEOUT;
} else {
UpFailedEvent();
return false;
}
break;
default:
;
}
return true;
}
bool
PAP::Down()
{
#if DEBUG
printf("PAP: Down() state=%d\n", State());
#endif
LockerHelper locker(fLock);
switch(Interface().Phase()) {
case PPP_DOWN_PHASE:
// interface finished terminating
case PPP_ESTABLISHED_PHASE:
// terminate this NCP individually (block until we finished terminating)
NewState(INITIAL);
locker.UnlockNow();
DownEvent();
break;
/* case PPP_TERMINATION_PHASE:
// interface is terminating
break;
case PPP_ESTABLISHMENT_PHASE:
// interface is reconfiguring
break;
*/
default:
;
}
return true;
}
status_t
PAP::Send(struct mbuf *packet, uint16 protocolNumber)
{
// we do not encapsulate PAP packets
m_freem(packet);
return B_ERROR;
}
status_t
PAP::Receive(struct mbuf *packet, uint16 protocolNumber)
{
if(!packet)
return B_ERROR;
if(protocolNumber != PAP_PROTOCOL)
return PPP_UNHANDLED;
ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*);
// check if the packet is meant for us:
// only peer authenticators handle requests
if(data->code == PPP_CONFIGURE_REQUEST && Side() != PPP_PEER_SIDE)
return PPP_UNHANDLED;
// only local authenticators handle acks and naks
if((data->code == PPP_CONFIGURE_ACK || data->code == PPP_CONFIGURE_NAK)
&& Side() != PPP_LOCAL_SIDE)
return PPP_UNHANDLED;
// remove padding
int32 length = packet->m_len;
if(packet->m_flags & M_PKTHDR)
length = packet->m_pkthdr.len;
length -= ntohs(data->length);
if(length)
m_adj(packet, -length);
if(ntohs(data->length) < 4)
return B_ERROR;
// packet is freed by event methods
// code values are the same as for LCP (but very reduced)
switch(data->code) {
case PPP_CONFIGURE_REQUEST:
RREvent(packet);
break;
case PPP_CONFIGURE_ACK:
RAEvent(packet);
break;
case PPP_CONFIGURE_NAK:
RNEvent(packet);
break;
default:
return PPP_UNHANDLED;
}
return B_OK;
}
void
PAP::Pulse()
{
LockerHelper locker(fLock);
if(fNextTimeout == 0 || fNextTimeout > system_time())
return;
fNextTimeout = 0;
locker.UnlockNow();
switch(State()) {
case REQ_SENT:
case WAITING_FOR_REQ:
if(fRequestCounter <= 0)
TOBadEvent();
else
TOGoodEvent();
break;
default:
;
}
}
bool
PAP::ParseSettings(driver_parameter *requests)
{
memset(fUser, 0, sizeof(fUser));
memset(fPassword, 0, sizeof(fPassword));
// The following values are allowed:
// "User"
// "Password"
for(int32 index = 0; index < requests->parameter_count; index++) {
if(requests->parameters[index].value_count == 0)
continue;
// ignore user and password if too long (255 chars at max)
if(!strcasecmp(requests->parameters[index].name, "User")
&& strlen(requests->parameters[index].values[0]) < sizeof(fUser))
strcpy(fUser, requests->parameters[index].values[0]);
else if(!strcasecmp(requests->parameters[index].name, "Password")
&& strlen(requests->parameters[index].values[0]) < sizeof(fPassword))
strcpy(fPassword, requests->parameters[index].values[0]);
}
return true;
}
uint8
PAP::NextID()
{
return (uint8) atomic_add(&fID, 1);
}
void
PAP::NewState(pap_state next)
{
#if DEBUG
printf("PAP: NewState(%d) state=%d\n", next, State());
#endif
// state changes
if(State() == INITIAL && next != State()) {
if(Side() == PPP_LOCAL_SIDE)
Interface().StateMachine().LocalAuthenticationRequested();
else if(Side() == PPP_PEER_SIDE)
Interface().StateMachine().PeerAuthenticationRequested();
UpStarted();
} else if(State() == ACCEPTED && next != State())
DownStarted();
// maybe we do not need the timer anymore
if(next == INITIAL || next == ACCEPTED)
fNextTimeout = 0;
fState = next;
}
void
PAP::TOGoodEvent()
{
#if DEBUG
printf("PAP: TOGoodEvent() state=%d\n", State());
#endif
LockerHelper locker(fLock);
switch(State()) {
case REQ_SENT:
locker.UnlockNow();
SendRequest();
break;
case WAITING_FOR_REQ:
fNextTimeout = system_time() + PAP_TIMEOUT;
break;
default:
;
}
}
void
PAP::TOBadEvent()
{
#if DEBUG
printf("PAP: TOBadEvent() state=%d\n", State());
#endif
LockerHelper locker(fLock);
switch(State()) {
case REQ_SENT:
case WAITING_FOR_REQ:
NewState(INITIAL);
locker.UnlockNow();
UpFailedEvent();
break;
default:
;
}
}
void
PAP::RREvent(struct mbuf *packet)
{
#if DEBUG
printf("PAP: RREvent() state=%d\n", State());
#endif
LockerHelper locker(fLock);
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
int32 length = ntohs(request->length);
uint8 *data = request->data;
uint8 *userLength = data;
uint8 *passwordLength = data + 1 + data[0];
// make sure the length values are all okay
if(6 + *userLength + *passwordLength > length) {
m_freem(packet);
return;
}
char *user = (char*) userLength + 1, *password = (char*) passwordLength + 1;
if(*userLength == strlen(fUser) && *passwordLength == strlen(fPassword)
&& !strncmp(user, fUser, *userLength)
&& !strncmp(password, fPassword, *passwordLength)) {
NewState(ACCEPTED);
locker.UnlockNow();
Interface().StateMachine().PeerAuthenticationAccepted(user);
UpEvent();
SendAck(packet);
} else {
NewState(INITIAL);
locker.UnlockNow();
Interface().StateMachine().PeerAuthenticationDenied(user);
UpFailedEvent();
SendNak(packet);
}
}
void
PAP::RAEvent(struct mbuf *packet)
{
#if DEBUG
printf("PAP: RAEvent() state=%d\n", State());
#endif
LockerHelper locker(fLock);
if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) {
// this packet is not a reply to our request
// TODO: log this event
m_freem(packet);
return;
}
switch(State()) {
case REQ_SENT:
NewState(ACCEPTED);
locker.UnlockNow();
Interface().StateMachine().LocalAuthenticationAccepted(fUser);
UpEvent();
break;
default:
;
}
m_freem(packet);
}
void
PAP::RNEvent(struct mbuf *packet)
{
#if DEBUG
printf("PAP: RNEvent() state=%d\n", State());
#endif
LockerHelper locker(fLock);
if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) {
// this packet is not a reply to our request
// TODO: log this event
m_freem(packet);
return;
}
switch(State()) {
case REQ_SENT:
NewState(INITIAL);
locker.UnlockNow();
Interface().StateMachine().LocalAuthenticationDenied(fUser);
UpFailedEvent();
break;
default:
;
}
m_freem(packet);
}
void
PAP::InitializeRestartCount()
{
fRequestCounter = fMaxRequest;
}
bool
PAP::SendRequest()
{
#if DEBUG
printf("PAP: SendRequest() state=%d\n", State());
#endif
LockerHelper locker(fLock);
--fRequestCounter;
fNextTimeout = system_time() + PAP_TIMEOUT;
locker.UnlockNow();
struct mbuf *packet = m_gethdr(MT_DATA);
if(!packet)
return false;
packet->m_pkthdr.len = packet->m_len = 6 + strlen(fUser) + strlen(fPassword);
// reserve some space for overhead (we are lazy and reserve too much)
packet->m_data += Interface().PacketOverhead();
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
request->code = PPP_CONFIGURE_REQUEST;
request->id = fRequestID = NextID();
request->length = htons(packet->m_len);
uint8 *data = request->data;
data[0] = strlen(fUser);
memcpy(data + 1, fUser, strlen(fUser));
data[1 + data[0]] = strlen(fPassword);
memcpy(data + 2 + data[0], fUser, strlen(fUser));
return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
}
bool
PAP::SendAck(struct mbuf *packet)
{
#if DEBUG
printf("PAP: SendAck() state=%d\n", State());
#endif
if(!packet)
return false;
ppp_lcp_packet *ack = mtod(packet, ppp_lcp_packet*);
ack->code = PPP_CONFIGURE_ACK;
packet->m_len = 5;
if(packet->m_flags & M_PKTHDR)
packet->m_pkthdr.len = 5;
ack->length = htons(packet->m_len);
ack->data[0] = 0;
return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
}
bool
PAP::SendNak(struct mbuf *packet)
{
#if DEBUG
printf("PAP: SendNak() state=%d\n", State());
#endif
if(!packet)
return false;
ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*);
nak->code = PPP_CONFIGURE_NAK;
packet->m_len = 5;
if(packet->m_flags & M_PKTHDR)
packet->m_pkthdr.len = 5;
nak->length = htons(packet->m_len);
nak->data[0] = 0;
return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
}
@@ -0,0 +1,114 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, [email protected]
//---------------------------------------------------------------------
#ifndef PROTOCOL__H
#define PROTOCOL__H
#include <driver_settings.h>
#include <KPPPOptionHandler.h>
#include <KPPPProtocol.h>
#include <Locker.h>
#include <arpa/inet.h>
#define PAP_PROTOCOL 0xC023
enum pap_state {
INITIAL,
REQ_SENT,
WAITING_FOR_REQ,
ACCEPTED
};
class PAP;
class PAPHandler : public PPPOptionHandler {
public:
PAPHandler(PAP& owner, PPPInterface& interface);
PAP& Owner() const
{ return fOwner; }
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:
PAP& fOwner;
};
class PAP : public PPPProtocol {
public:
PAP(PPPInterface& interface, driver_parameter *settings);
virtual ~PAP();
virtual status_t InitCheck() const;
pap_state State() const
{ return fState; }
virtual bool Up();
virtual bool Down();
virtual status_t Send(struct mbuf *packet, uint16 protocolNumber);
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber);
virtual void Pulse();
private:
bool ParseSettings(driver_parameter *settings);
// for state machine
void NewState(pap_state next);
uint8 NextID();
// return the next id for PAP packets
// events
void TOGoodEvent();
void TOBadEvent();
void RREvent(struct mbuf *packet);
void RAEvent(struct mbuf *packet);
void RNEvent(struct mbuf *packet);
// actions
void ReportUpFailedEvent();
void ReportUpEvent();
void ReportDownEvent();
void InitializeRestartCount();
bool SendRequest();
bool SendAck(struct mbuf *packet);
bool SendNak(struct mbuf *packet);
private:
char fUser[256], fPassword[256];
// for state machine
pap_state fState;
vint32 fID;
// counters and timers
int32 fMaxRequest;
int32 fRequestCounter;
uint8 fRequestID;
// the ID we used for the last configure/terminate request
bigtime_t fNextTimeout;
BLocker fLock;
};
#endif
@@ -0,0 +1,97 @@
//----------------------------------------------------------------------
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
// Copyright (c) 2003 Waldemar Kornewald, [email protected]
//---------------------------------------------------------------------
#include <core_funcs.h>
#include <KernelExport.h>
#include <driver_settings.h>
#include <KPPPInterface.h>
#include <KPPPModule.h>
#include <LockerHelper.h>
#include "Protocol.h"
#ifdef _KERNEL_MODE
#define spawn_thread spawn_kernel_thread
#define printf dprintf
#else
#include <cstdio>
#endif
#define PAP_MODULE_NAME "network/ppp/pap"
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(type != PPP_AUTHENTICATOR_KEY_TYPE)
return B_ERROR;
PAP *pap;
bool success;
if(subInterface) {
pap = new PAP(*subInterface, settings);
success = subInterface->AddProtocol(pap);
} else {
pap = new PAP(mainInterface, settings);
success = mainInterface.AddProtocol(pap);
}
#if DEBUG
printf("IPCP: add_to(): %s\n",
success && pap && pap->InitCheck() == B_OK ? "OK" : "ERROR");
#endif
return success && pap && pap->InitCheck() == B_OK;
}
static ppp_module_info pap_module = {
{
PAP_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*) &pap_module,
NULL
};
@@ -172,7 +172,8 @@ std_ops(int32 op, ...)
if(get_module(NET_CORE_MODULE_NAME, (module_info**)&core) != B_OK)
return B_ERROR;
if(get_module(NET_ETHERNET_MODULE_NAME, (module_info**)&ethernet) != B_OK) {
if(get_module(NET_ETHERNET_MODULE_NAME,
(module_info**) &ethernet) != B_OK) {
put_module(NET_CORE_MODULE_NAME);
return B_ERROR;
}
@@ -5,10 +5,6 @@ UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(OBOS_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ;
# for kernel_cpp.cpp/h and BLocker
SEARCH_SOURCE += [ FDirName $(OBOS_TOP) src kernel core util ] ;
SEARCH_SOURCE += [ FDirName $(OBOS_TOP) src kernel core disk_device_manager ] ;
R5KernelStaticLibrary kernelppp :
kernel_cpp.cpp
@@ -32,3 +28,6 @@ R5KernelStaticLibrary kernelppp :
_KPPPAuthenticationHandler.cpp
_KPPPPFCHandler.cpp
;
SEARCH on [ FGristFiles kernel_cpp.cpp ] = [ FDirName $(OBOS_TOP) src kernel core util ] ;
SEARCH on [ FGristFiles Locker.cpp ] = [ FDirName $(OBOS_TOP) src kernel core disk_device_manager ] ;
@@ -312,6 +312,18 @@ PPPInterface::SetMRU(uint32 MRU)
}
uint32
PPPInterface::PacketOverhead() const
{
uint32 overhead = fHeaderLength + 2;
if(Device())
overhead += Device()->Overhead();
return overhead;
}
status_t
PPPInterface::Control(uint32 op, void *data, size_t length)
{
@@ -1177,7 +1189,7 @@ PPPInterface::Send(struct mbuf *packet, uint16 protocolNumber)
// make sure that protocol is allowed to send and everything is up
if(!Device()->IsUp() || !protocol || !protocol->IsEnabled()
|| !IsProtocolAllowed(*protocol)){
|| !IsProtocolAllowed(*protocol)) {
m_freem(packet);
return B_ERROR;
}
@@ -1248,6 +1260,7 @@ PPPInterface::Receive(struct mbuf *packet, uint16 protocolNumber)
// Find handler and let it parse the packet.
// The handler does need not be up because if we are a server
// the handler might be upped by this packet.
// If authenticating we only allow authentication phase protocols.
PPPProtocol *protocol = ProtocolFor(protocolNumber);
for(; protocol;
protocol = protocol->NextProtocol() ?
@@ -202,7 +202,7 @@ PPPLCP::Down()
status_t
PPPLCP::Send(struct mbuf *packet, uint16 protocolNumber)
PPPLCP::Send(struct mbuf *packet, uint16 protocolNumber = PPP_LCP_PROTOCOL)
{
if(Target())
return Target()->Send(packet, PPP_LCP_PROTOCOL);
@@ -226,9 +226,6 @@ PPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber)
int32 length = packet->m_len;
if(packet->m_flags & M_PKTHDR)
length = packet->m_pkthdr.len;
#if DEBUG
printf("LCP::Recv: len=%ld;datalen=%d\n", length, ntohs(data->length));
#endif
length -= ntohs(data->length);
if(length)
m_adj(packet, -length);
@@ -32,8 +32,8 @@
PPPStateMachine::PPPStateMachine(PPPInterface& interface)
: fInterface(interface),
fLCP(interface.LCP()),
fPhase(PPP_DOWN_PHASE),
fState(PPP_INITIAL_STATE),
fPhase(PPP_DOWN_PHASE),
fID(system_time() & 0xFF),
fMagicNumber(0),
fLocalAuthenticationStatus(PPP_NOT_AUTHENTICATED),
@@ -143,6 +143,7 @@ PPPStateMachine::Reconfigure()
NewState(PPP_REQ_SENT_STATE);
NewPhase(PPP_ESTABLISHMENT_PHASE);
// indicates to handlers that we are reconfiguring
DownProtocols();
ResetLCPHandlers();
@@ -726,8 +727,10 @@ PPPStateMachine::OpenEvent()
LockerHelper locker(fLock);
// reset all handlers
DownProtocols();
ResetLCPHandlers();
if(Phase() != PPP_ESTABLISHED_PHASE) {
DownProtocols();
ResetLCPHandlers();
}
switch(State()) {
case PPP_INITIAL_STATE:
@@ -960,7 +963,6 @@ PPPStateMachine::RCRGoodEvent(struct mbuf *packet)
break;
case PPP_OPENED_STATE:
// tld,scr,sca/8
NewState(PPP_ACK_SENT_STATE);
NewPhase(PPP_ESTABLISHMENT_PHASE);
// indicates to handlers that we are reconfiguring
@@ -1492,7 +1494,6 @@ PPPStateMachine::TimerEvent()
default:
;
}
}
@@ -1572,11 +1573,13 @@ PPPStateMachine::RCREvent(struct mbuf *packet)
}
}
if(nak.CountItems() > 0)
if(nak.CountItems() > 0) {
RCRBadEvent(nak.ToMbuf(Interface().MRU(), LCP().AdditionalOverhead()), NULL);
else if(reject.CountItems() > 0)
m_freem(packet);
} else if(reject.CountItems() > 0) {
RCRBadEvent(NULL, reject.ToMbuf(Interface().MRU(), LCP().AdditionalOverhead()));
else
m_freem(packet);
} else
RCRGoodEvent(packet);
}
@@ -1732,9 +1735,6 @@ PPPStateMachine::InitializeRestartCount()
fRequestCounter = fMaxRequest;
fTerminateCounter = fMaxTerminate;
fNakCounter = fMaxNak;
LockerHelper locker(fLock);
fNextTimeout = system_time() + PPP_STATE_MACHINE_TIMEOUT;
}
@@ -1744,9 +1744,6 @@ PPPStateMachine::ZeroRestartCount()
fRequestCounter = 0;
fTerminateCounter = 0;
fNakCounter = 0;
LockerHelper locker(fLock);
fNextTimeout = system_time() + PPP_STATE_MACHINE_TIMEOUT;
}
@@ -1884,9 +1881,9 @@ PPPStateMachine::SendTerminateAck(struct mbuf *request = NULL)
ack = mtod(reply, ppp_lcp_packet*);
ack->id = NextID();
}
} else
ack = mtod(reply, ppp_lcp_packet*);
ack = mtod(reply, ppp_lcp_packet*);
ack->code = PPP_TERMINATE_ACK;
ack->length = htons(4);
@@ -1915,15 +1912,14 @@ PPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocolNumber, uint
M_PREPEND(packet, length);
// add some space for the header
int32 adjust = 0;
// adjust packet size by this value if packet is too big
// adjust packet if too big
int32 adjust = Interface().MRU();
if(packet->m_flags & M_PKTHDR) {
if((uint32) packet->m_pkthdr.len > Interface().MRU())
adjust = Interface().MRU() - packet->m_pkthdr.len;
} else if(packet->m_len > Interface().MRU())
adjust = Interface().MRU() - packet->m_len;
adjust -= packet->m_pkthdr.len;
} else
adjust -= packet->m_len;
if(adjust != 0)
if(adjust < 0)
m_adj(packet, adjust);
ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*);
@@ -1994,6 +1990,9 @@ PPPStateMachine::BringProtocolsUp()
uint32
PPPStateMachine::BringPhaseUp()
{
// Servers do not need to bring all protocols up.
// The client specifies which protocols he wants to go up.
LockerHelper locker(fLock);
// check for phase change
@@ -2004,14 +2003,23 @@ PPPStateMachine::BringPhaseUp()
PPPProtocol *protocol = Interface().FirstProtocol();
for(; protocol; protocol = protocol->NextProtocol()) {
if(protocol->IsEnabled() && protocol->ActivationPhase() == Phase()) {
if(protocol->IsUpRequested()) {
if(protocol->IsGoingUp() && Interface().Mode() == PPP_CLIENT_MODE)
++count;
else if(protocol->IsDown() && protocol->IsUpRequested()) {
if(Interface().Mode() == PPP_CLIENT_MODE)
++count;
protocol->Up();
} else if(protocol->IsGoingUp())
++count;
}
}
}
// We only wait until authentication is complete.
if(Interface().Mode() == PPP_SERVER_MODE
&& (LocalAuthenticationStatus() == PPP_AUTHENTICATING
|| PeerAuthenticationStatus() == PPP_AUTHENTICATING))
++count;
return count;
}
@@ -19,7 +19,7 @@ typedef struct mru_item {
uint8 type;
uint8 length;
uint16 MRU;
};
} mru_item;
status_t ParseRequestedItem(mru_item *item, PPPInterface& interface);
@@ -88,6 +88,8 @@ class PPPInterface : public PPPLayer {
uint32 InterfaceMTU() const
{ return fInterfaceMTU; }
// this is the MRU including protocol overhead
uint32 PacketOverhead() const;
// including device and encapsulator headers
virtual status_t Control(uint32 op, void *data, size_t length);
@@ -56,7 +56,10 @@ class PPPStateMachine {
bool SendEchoRequest();
bool SendDiscardRequest();
// public events
// public events:
// NOTE: Local/PeerAuthenticationAccepted/Denied MUST be called before
// Up(Failed)/DownEvent in order to allow changing the configuration of
// the next phase's protocols before they are brought up.
void LocalAuthenticationRequested();
void LocalAuthenticationAccepted(const char *name);
void LocalAuthenticationDenied(const char *name);
@@ -143,8 +146,8 @@ class PPPStateMachine {
PPPInterface& fInterface;
PPPLCP& fLCP;
ppp_phase fPhase;
ppp_state fState;
ppp_phase fPhase;
vint32 fID;
uint32 fMagicNumber;
@@ -153,14 +156,14 @@ class PPPStateMachine {
fPeerAuthenticationStatus;
char *fLocalAuthenticationName, *fPeerAuthenticationName;
BLocker fLock;
// counters and timers
int32 fMaxRequest, fMaxTerminate, fMaxNak;
int32 fRequestCounter, fTerminateCounter, fNakCounter;
uint8 fRequestID, fTerminateID, fEchoID;
// the ID we used for the last configure/terminate/echo request
bigtime_t fNextTimeout;
BLocker fLock;
};
@@ -92,13 +92,9 @@ enum {
PPP_ALWAYS_ALLOWED = 0x01,
// protocol may send/receive in Phase() >= PPP_ESTABLISHMENT_PHASE,
// but only LCP is allowed in State() != PPP_OPENED_STATE!
PPP_NEEDS_DOWN = 0x02,
// protocol needs a Down() in addition to a Reset() to
// terminate the connection properly (losing the connection
// still results in a Reset() only)
PPP_NOT_IMPORTANT = 0x04,
PPP_NOT_IMPORTANT = 0x02,
// if this protocol fails to go up we do not disconnect
PPP_INCLUDES_NCP = 0x08
PPP_INCLUDES_NCP = 0x04,
// This protocol includes the corresponding NCP protocol (e.g.: IPCP + IP).
// All protocol values will also be checked against Protocol() & 0x7FFF.
};