PPP: Port to the new stack.

Signed-off-by: Augustin Cavalier <[email protected]>

This is a squash of the 42 commits by @mshlyn, as I couldn't find a
way to break them into logical chunks. I did not include these in the build,
as it appears that they only partially work anyway, and much more cleanup is
still needed. However, this is a huge improvement on what was in the tree
before, which looked horrendous and didn't even compile (as it was designed
for the old stack).

Mostly fixes #812.
This commit is contained in:
mshlyn
2016-01-02 07:22:13 -05:00
committed by Augustin Cavalier
parent 7121057cb7
commit e3724c38cb
62 changed files with 5214 additions and 2293 deletions
+1 -1
View File
@@ -134,7 +134,7 @@ SYSTEM_NETWORK_DATALINK_PROTOCOLS =
loopback_frame
;
#SYSTEM_NETWORK_PPP = ipcp modem pap pppoe ;
#SYSTEM_NETWORK_PPP = ipcp modem pap pppoe KPPPManager ;
SYSTEM_NETWORK_PROTOCOLS =
icmp icmp6 ipv4 ipv6
+1 -1
View File
@@ -250,7 +250,7 @@ AddFilesToPackage add-ons kernel network : dns_resolver ;
AddFilesToPackage add-ons kernel network devices : $(SYSTEM_NETWORK_DEVICES) ;
AddFilesToPackage add-ons kernel network datalink_protocols
: $(SYSTEM_NETWORK_DATALINK_PROTOCOLS) ;
AddFilesToPackage add-ons kernel network ppp: $(SYSTEM_NETWORK_PPP) ;
AddFilesToPackage add-ons kernel network ppp : $(SYSTEM_NETWORK_PPP) ;
AddFilesToPackage add-ons kernel network protocols
: $(SYSTEM_NETWORK_PROTOCOLS) ;
+1 -1
View File
@@ -209,7 +209,7 @@ AddFilesToPackage add-ons kernel network : dns_resolver ;
AddFilesToPackage add-ons kernel network devices : $(SYSTEM_NETWORK_DEVICES) ;
AddFilesToPackage add-ons kernel network datalink_protocols
: $(SYSTEM_NETWORK_DATALINK_PROTOCOLS) ;
AddFilesToPackage add-ons kernel network ppp: $(SYSTEM_NETWORK_PPP) ;
AddFilesToPackage add-ons kernel network ppp : $(SYSTEM_NETWORK_PPP) ;
AddFilesToPackage add-ons kernel network protocols
: $(SYSTEM_NETWORK_PROTOCOLS) ;
+1
View File
@@ -6,3 +6,4 @@ SubInclude HAIKU_TOP src add-ons kernel network dns_resolver ;
SubInclude HAIKU_TOP src add-ons kernel network notifications ;
SubInclude HAIKU_TOP src add-ons kernel network protocols ;
SubInclude HAIKU_TOP src add-ons kernel network stack ;
SubInclude HAIKU_TOP src add-ons kernel network ppp ;
+4 -1
View File
@@ -1,7 +1,10 @@
SubDir HAIKU_TOP src add-ons kernel network ppp ;
SubInclude HAIKU_TOP src add-ons kernel network ppp ipcp ;
SubInclude HAIKU_TOP src add-ons kernel network ppp modem ;
# SubInclude HAIKU_TOP src add-ons kernel network ppp modem ;
SubInclude HAIKU_TOP src add-ons kernel network ppp pap ;
SubInclude HAIKU_TOP src add-ons kernel network ppp pppoe ;
SubInclude HAIKU_TOP src add-ons kernel network ppp shared ;
SubInclude HAIKU_TOP src add-ons kernel network ppp ppp ;
SubInclude HAIKU_TOP src add-ons kernel network ppp ppp_frame ;
SubInclude HAIKU_TOP src add-ons kernel network ppp ppp_manager ;
+26 -16
View File
@@ -1,41 +1,51 @@
SubDir HAIKU_TOP src add-ons kernel network ppp ipcp ;
SetSubDirSupportedPlatformsBeOSCompatible ;
SubDirC++Flags -fno-rtti ;
if $(TARGET_PLATFORM) != haiku {
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
# We need the public network headers also when not compiling for Haiku.
# Unfortunately we get more than we want, namely all POSIX headers.
UseHeaders [ FStandardOSHeaders ] : true ;
# Needed for the atomic_add64() prototype.
}
# for kernel_cpp.h and BLocker
UseHeaders [ FDirName $(HAIKU_TOP) headers cpp ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
# We need the public network headers also when not compiling for Haiku.
# Unfortunately we get more than we want, namely all POSIX headers.
UsePrivateKernelHeaders ;
UsePrivateHeaders net ;
UsePrivateHeaders libroot net ;
UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
libkernelppp headers ] : true ;
{
SubDirC++Flags -fno-rtti ;
}
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp pppoe
] : true ;
KernelAddon ipcp :
# imported from libnet
atomic.S
kernel_cpp.cpp
# imported from kernel util
inet_addr.c
ipcp.cpp
Protocol.cpp
;
SEARCH on [ FGristFiles inet_addr.c ]
= [ FDirName $(HAIKU_TOP) src kits network compat libnet ] ;
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
SEARCH on [ FGristFiles kernel_cpp.cpp ]
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
SEARCH on [ FGristFiles atomic.S ]
= [ FDirName $(HAIKU_TOP) src system libroot os arch $(TARGET_ARCH) ] ;
LinkAgainst ipcp : libkernelppp.a ;
# Installation
HaikuInstall install-networking
: /boot/home/config/add-ons/kernel/obos_network/ppp
: /boot/home/config/add-ons/kernel/network/ppp
: ipcp ;
File diff suppressed because it is too large Load Diff
+33 -31
View File
@@ -9,9 +9,11 @@
#include <driver_settings.h>
#include <KPPPProtocol.h>
#include <Locker.h>
#include <arpa/inet.h>
#include <net_datalink.h>
#include <net_datalink_protocol.h>
#include <net/route.h>
#define IPCP_PROTOCOL 0x8021
@@ -60,46 +62,46 @@ class IPCP : public KPPPProtocol {
public:
IPCP(KPPPInterface& interface, driver_parameter *settings);
virtual ~IPCP();
virtual void Uninit();
ppp_state State() const
{ return fState; }
virtual status_t StackControl(uint32 op, void *data);
virtual bool Up();
virtual bool Down();
virtual status_t Send(struct mbuf *packet,
virtual status_t Send(net_buffer *packet,
uint16 protocolNumber = IPCP_PROTOCOL);
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber);
status_t ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber);
virtual status_t Receive(net_buffer *packet, uint16 protocolNumber);
status_t ReceiveIPPacket(net_buffer *packet, uint16 protocolNumber);
virtual void Pulse();
private:
bool ParseSideRequests(const driver_parameter *requests, ppp_side side);
void UpdateAddresses();
void RemoveRoutes();
// 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);
void RCREvent(net_buffer *packet);
void RCRGoodEvent(net_buffer *packet);
void RCRBadEvent(net_buffer *nak, net_buffer *reject);
void RCAEvent(net_buffer *packet);
void RCNEvent(net_buffer *packet);
void RTREvent(net_buffer *packet);
void RTAEvent(net_buffer *packet);
void RUCEvent(net_buffer *packet);
void RXJBadEvent(net_buffer *packet);
// actions
void IllegalEvent(ppp_event event);
void ReportUpFailedEvent();
@@ -108,27 +110,27 @@ class IPCP : public KPPPProtocol {
void InitializeRestartCount();
void ResetRestartCount();
bool SendConfigureRequest();
bool SendConfigureAck(struct mbuf *packet);
bool SendConfigureNak(struct mbuf *packet);
bool SendConfigureAck(net_buffer *packet);
bool SendConfigureNak(net_buffer *packet);
bool SendTerminateRequest();
bool SendTerminateAck(struct mbuf *request = NULL);
bool SendCodeReject(struct mbuf *packet);
bool SendTerminateAck(net_buffer *request = NULL);
bool SendCodeReject(net_buffer *packet);
private:
ipcp_configuration fLocalConfiguration, fPeerConfiguration;
ipcp_requests fLocalRequests, fPeerRequests;
// default route
struct sockaddr_in fGateway;
rtentry *fDefaultRoute;
net_route *fDefaultRoute;
// used for local requests
bool fRequestPrimaryDNS, fRequestSecondaryDNS;
// for state machine
ppp_state fState;
vint32 fID;
int32 fID;
// counters and timers
int32 fMaxRequest, fMaxTerminate, fMaxNak;
int32 fRequestCounter, fTerminateCounter, fNakCounter;
+32 -23
View File
@@ -5,21 +5,24 @@
#include <KernelExport.h>
#include <driver_settings.h>
#include <core_funcs.h>
#include <net_module.h>
#include <NetBufferUtilities.h>
#include <net_buffer.h>
#include <net_stack.h>
#include <KPPPDefs.h>
#include <KPPPInterface.h>
#include <KPPPModule.h>
#include "Protocol.h"
#define IPCP_MODULE_NAME NETWORK_MODULES_ROOT "/ppp/ipcp"
#define IPCP_MODULE_NAME NETWORK_MODULES_ROOT "ppp/ipcp"
struct protosw *gProto[IPPROTO_MAX];
struct core_module_info *core = NULL;
status_t std_ops(int32 op, ...);
net_stack_module_info *gStackModule = NULL;
net_buffer_module_info *gBufferModule = NULL;
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// TODO: Remove isascii() (needed for inet_aton()) when our kernel is finished!
@@ -28,7 +31,7 @@ extern "C"
int
isascii(char c)
{
return c & ~0x7f == 0; // If c is a 7 bit value.
return ((c & (~0x7f)) == 0); // If c is a 7 bit value.
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
@@ -38,22 +41,22 @@ bool
add_to(KPPPInterface& mainInterface, KPPPInterface *subInterface,
driver_parameter *settings, ppp_module_key_type type)
{
if(type != PPP_PROTOCOL_KEY_TYPE)
if (type != PPP_PROTOCOL_KEY_TYPE)
return B_ERROR;
IPCP *ipcp;
bool success;
if(subInterface) {
if (subInterface) {
ipcp = new IPCP(*subInterface, settings);
success = subInterface->AddProtocol(ipcp);
} else {
ipcp = new IPCP(mainInterface, settings);
success = mainInterface.AddProtocol(ipcp);
}
TRACE("IPCP: add_to(): %s\n",
success && ipcp && ipcp->InitCheck() == B_OK ? "OK" : "ERROR");
return success && ipcp && ipcp->InitCheck() == B_OK;
}
@@ -71,24 +74,30 @@ static ppp_module_info ipcp_module = {
_EXPORT
status_t
std_ops(int32 op, ...)
std_ops(int32 op, ...)
{
switch(op) {
switch (op) {
case B_MODULE_INIT:
if(get_module(NET_CORE_MODULE_NAME, (module_info**) &core) != B_OK)
if (get_module(NET_STACK_MODULE_NAME,
(module_info**) &gStackModule) != B_OK)
return B_ERROR;
memset(gProto, 0, sizeof(struct protosw*) * IPPROTO_MAX);
add_protosw(gProto, NET_LAYER1);
return B_OK;
if (get_module(NET_BUFFER_MODULE_NAME,
(module_info **)&gBufferModule) != B_OK) {
put_module(NET_STACK_MODULE_NAME);
return B_ERROR;
}
return B_OK;
break;
case B_MODULE_UNINIT:
put_module(NET_CORE_MODULE_NAME);
break;
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
break;
default:
return B_ERROR;
}
return B_OK;
}
+3 -9
View File
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src add-ons kernel network ppp pap ;
SetSubDirSupportedPlatformsBeOSCompatible ;
SubDirC++Flags -fno-rtti ;
if $(TARGET_PLATFORM) != haiku {
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
@@ -8,20 +9,13 @@ if $(TARGET_PLATFORM) != haiku {
# Unfortunately we get more than we want, namely all POSIX headers.
}
# for kernel_cpp.h and BLocker
UseHeaders [ FDirName $(HAIKU_TOP) headers cpp ] : true ;
UsePrivateKernelHeaders ;
UsePrivateHeaders net ;
UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
libkernelppp headers ] : true ;
{
SubDirC++Flags -fno-rtti ;
}
KernelAddon pap :
pap.cpp
Protocol.cpp
@@ -31,5 +25,5 @@ LinkAgainst pap : libkernelppp.a ;
# Installation
HaikuInstall install-networking
: /boot/home/config/add-ons/kernel/obos_network/ppp
: /boot/home/config/add-ons/kernel/haiku_network/ppp
: pap ;
+169 -145
View File
@@ -9,9 +9,9 @@
#include <cstring>
#include <netinet/in.h>
#include <core_funcs.h>
#include <sys/sockio.h>
#include <net_buffer.h>
#include <sys/sockio.h>
static const bigtime_t kPAPTimeout = 3000000;
// 3 seconds
@@ -34,20 +34,28 @@ PAPHandler::PAPHandler(PAP& owner, KPPPInterface& interface)
}
status_t
PAPHandler::SendingAck(const KPPPConfigurePacket& ack)
{
TRACE("%s::%s: We should activate PAP Protocol here\n", __FILE__, __func__);
return KPPPOptionHandler::SendingAck(ack);
}
status_t
PAPHandler::AddToRequest(KPPPConfigurePacket& request)
{
// only local authenticators send requests to peer
if(Owner().Side() != PPP_PEER_SIDE)
if (Owner().Side() != PPP_PEER_SIDE)
return B_OK;
authentication_item item;
item.type = kAuthenticationType;
item.length = sizeof(item);
item.protocolNumber = htons(PAP_PROTOCOL);
request.AddItem((ppp_configure_item*) &item);
return B_OK;
}
@@ -57,15 +65,15 @@ PAPHandler::ParseRequest(const KPPPConfigurePacket& request,
int32 index, KPPPConfigurePacket& nak, KPPPConfigurePacket& reject)
{
// only local authenticators handle requests from peer
if(Owner().Side() != PPP_LOCAL_SIDE)
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 != kAuthenticationType
if (item->type != kAuthenticationType
|| item->length != 4 || ntohs(item->protocolNumber) != PAP_PROTOCOL)
return B_ERROR;
return B_OK;
}
@@ -92,9 +100,9 @@ PAP::~PAP()
status_t
PAP::InitCheck() const
{
if(Side() != PPP_LOCAL_SIDE && Side() != PPP_PEER_SIDE)
if (Side() != PPP_LOCAL_SIDE && Side() != PPP_PEER_SIDE)
return B_ERROR;
return KPPPProtocol::InitCheck();
}
@@ -103,14 +111,14 @@ bool
PAP::Up()
{
TRACE("PAP: Up() state=%d\n", State());
switch(State()) {
switch (State()) {
case INITIAL:
if(Side() == PPP_LOCAL_SIDE) {
if (Side() == PPP_LOCAL_SIDE) {
NewState(REQ_SENT);
InitializeRestartCount();
SendRequest();
} else if(Side() == PPP_PEER_SIDE) {
} else if (Side() == PPP_PEER_SIDE) {
NewState(WAITING_FOR_REQ);
InitializeRestartCount();
fNextTimeout = system_time() + kPAPTimeout;
@@ -119,11 +127,11 @@ PAP::Up()
return false;
}
break;
default:
;
}
return true;
}
@@ -132,8 +140,8 @@ bool
PAP::Down()
{
TRACE("PAP: Down() state=%d\n", State());
switch(Interface().Phase()) {
switch (Interface().Phase()) {
case PPP_DOWN_PHASE:
// interface finished terminating
case PPP_ESTABLISHED_PHASE:
@@ -141,82 +149,83 @@ PAP::Down()
NewState(INITIAL);
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)
PAP::Send(net_buffer *packet, uint16 protocolNumber)
{
// we do not encapsulate PAP packets
m_freem(packet);
TRACE("PAP: we should not send packet!\n");
if (packet != NULL)
gBufferModule->free(packet);
return B_ERROR;
}
status_t
PAP::Receive(struct mbuf *packet, uint16 protocolNumber)
PAP::Receive(net_buffer *packet, uint16 protocolNumber)
{
if(!packet)
if (!packet)
return B_ERROR;
if(protocolNumber != PAP_PROTOCOL)
if (protocolNumber != PAP_PROTOCOL)
return PPP_UNHANDLED;
ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*);
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return B_ERROR;
ppp_lcp_packet &data = bufferheader.Data();
// check if the packet is meant for us:
// only peer authenticators handle requests
if(data->code == PPP_CONFIGURE_REQUEST && Side() != PPP_PEER_SIDE)
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)
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)
int32 length = packet->size;
length -= ntohs(data.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) {
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;
}
@@ -224,19 +233,19 @@ PAP::Receive(struct mbuf *packet, uint16 protocolNumber)
void
PAP::Pulse()
{
if(fNextTimeout == 0 || fNextTimeout > system_time())
if (fNextTimeout == 0 || fNextTimeout > system_time())
return;
fNextTimeout = 0;
switch(State()) {
switch (State()) {
case REQ_SENT:
case WAITING_FOR_REQ:
if(fRequestCounter <= 0)
if (fRequestCounter <= 0)
TOBadEvent();
else
TOGoodEvent();
break;
default:
;
}
@@ -254,22 +263,22 @@ void
PAP::NewState(pap_state next)
{
TRACE("PAP: NewState(%d) state=%d\n", next, State());
// state changes
if(State() == INITIAL && next != State()) {
if(Side() == PPP_LOCAL_SIDE)
if (State() == INITIAL && next != State()) {
if (Side() == PPP_LOCAL_SIDE)
Interface().StateMachine().LocalAuthenticationRequested();
else if(Side() == PPP_PEER_SIDE)
else if (Side() == PPP_PEER_SIDE)
Interface().StateMachine().PeerAuthenticationRequested();
UpStarted();
} else if(State() == ACCEPTED && next != State())
} else if (State() == ACCEPTED && next != State())
DownStarted();
// maybe we do not need the timer anymore
if(next == INITIAL || next == ACCEPTED)
if (next == INITIAL || next == ACCEPTED)
fNextTimeout = 0;
fState = next;
}
@@ -278,16 +287,16 @@ void
PAP::TOGoodEvent()
{
TRACE("PAP: TOGoodEvent() state=%d\n", State());
switch(State()) {
switch (State()) {
case REQ_SENT:
SendRequest();
break;
case WAITING_FOR_REQ:
fNextTimeout = system_time() + kPAPTimeout;
break;
default:
;
}
@@ -298,21 +307,21 @@ void
PAP::TOBadEvent()
{
TRACE("PAP: TOBadEvent() state=%d\n", State());
switch(State()) {
switch (State()) {
case REQ_SENT:
case WAITING_FOR_REQ:
NewState(INITIAL);
if(State() == REQ_SENT)
if (State() == REQ_SENT)
Interface().StateMachine().LocalAuthenticationDenied(
Interface().Username());
else
Interface().StateMachine().PeerAuthenticationDenied(
Interface().Username());
UpFailedEvent();
break;
default:
;
}
@@ -320,27 +329,30 @@ PAP::TOBadEvent()
void
PAP::RREvent(struct mbuf *packet)
PAP::RREvent(net_buffer *packet)
{
TRACE("PAP: RREvent() state=%d\n", State());
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
int32 length = ntohs(request->length);
uint8 *data = request->data;
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return;
ppp_lcp_packet &request = bufferheader.Data();
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);
if (6 + *userLength + *passwordLength > length) {
gBufferModule->free(packet);
return;
}
char *peerUsername = (char*) userLength + 1,
*peerPassword = (char*) passwordLength + 1;
const char *username = Interface().Username(), *password = Interface().Password();
if(*userLength == strlen(username) && *passwordLength == strlen(password)
if (*userLength == strlen(username) && *passwordLength == strlen(password)
&& !strncmp(peerUsername, username, *userLength)
&& !strncmp(peerPassword, password, *passwordLength)) {
NewState(ACCEPTED);
@@ -357,60 +369,68 @@ PAP::RREvent(struct mbuf *packet)
void
PAP::RAEvent(struct mbuf *packet)
PAP::RAEvent(net_buffer *packet)
{
TRACE("PAP: RAEvent() state=%d\n", State());
if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) {
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return;
ppp_lcp_packet &lcp_hdr = bufferheader.Data();
if (fRequestID != lcp_hdr.id) {
// this packet is not a reply to our request
// TODO: log this event
m_freem(packet);
gBufferModule->free(packet);
return;
}
switch(State()) {
switch (State()) {
case REQ_SENT:
NewState(ACCEPTED);
Interface().StateMachine().LocalAuthenticationAccepted(
Interface().Username());
UpEvent();
break;
default:
;
}
m_freem(packet);
gBufferModule->free(packet);
}
void
PAP::RNEvent(struct mbuf *packet)
PAP::RNEvent(net_buffer *packet)
{
TRACE("PAP: RNEvent() state=%d\n", State());
if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) {
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return;
ppp_lcp_packet &lcp_hdr = bufferheader.Data();
if (fRequestID != lcp_hdr.id) {
// this packet is not a reply to our request
// TODO: log this event
m_freem(packet);
gBufferModule->free(packet);
return;
}
switch(State()) {
switch (State()) {
case REQ_SENT:
NewState(INITIAL);
Interface().StateMachine().LocalAuthenticationDenied(
Interface().Username());
UpFailedEvent();
break;
default:
;
}
m_freem(packet);
gBufferModule->free(packet);
}
@@ -425,72 +445,76 @@ bool
PAP::SendRequest()
{
TRACE("PAP: SendRequest() state=%d\n", State());
--fRequestCounter;
fNextTimeout = system_time() + kPAPTimeout;
struct mbuf *packet = m_gethdr(MT_DATA);
if(!packet)
net_buffer *packet = gBufferModule->create(256);
if (!packet)
return false;
ppp_lcp_packet *request;
gBufferModule->append_size(packet, 1492, (void **)&request);
const char *username = Interface().Username(), *password = Interface().Password();
packet->m_pkthdr.len = packet->m_len = 6 + strlen(username) + strlen(password);
// 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*);
uint16 packcketLenth = 6 + strlen(username) + strlen(password);
// 6 : lcp header 4 byte + username length 1 byte + password length 1 byte
request->code = PPP_CONFIGURE_REQUEST;
request->id = fRequestID = NextID();
request->length = htons(packet->m_len);
request->length = htons(packcketLenth);
uint8 *data = request->data;
data[0] = strlen(username);
memcpy(data + 1, username, strlen(username));
data[1 + data[0]] = strlen(password);
memcpy(data + 2 + data[0], password, strlen(password));
gBufferModule->trim(packet, packcketLenth);
return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
}
bool
PAP::SendAck(struct mbuf *packet)
PAP::SendAck(net_buffer *packet)
{
TRACE("PAP: SendAck() state=%d\n", State());
if(!packet)
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;
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return false;
ppp_lcp_packet &ack = bufferheader.Data();
ack.code = PPP_CONFIGURE_ACK;
ack.length = htons(5);
ack.data[0] = 0;
gBufferModule->trim(packet, 5);
bufferheader.Sync();
return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
}
bool
PAP::SendNak(struct mbuf *packet)
PAP::SendNak(net_buffer *packet)
{
TRACE("PAP: SendNak() state=%d\n", State());
if(!packet)
ERROR("PAP: SendNak() state=%d\n", State());
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;
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return false;
ppp_lcp_packet &nak = bufferheader.Data();
nak.code = PPP_CONFIGURE_NAK;
nak.length = htons(5);
nak.data[0] = 0;
gBufferModule->trim(packet, 5);
return Interface().Send(packet, PAP_PROTOCOL) == B_OK;
}
+18 -17
View File
@@ -31,11 +31,12 @@ class PAP;
class PAPHandler : public KPPPOptionHandler {
public:
PAPHandler(PAP& owner, KPPPInterface& interface);
PAP& Owner() const
{ return fOwner; }
virtual status_t AddToRequest(KPPPConfigurePacket& request);
virtual status_t SendingAck(const KPPPConfigurePacket&);
virtual status_t ParseRequest(const KPPPConfigurePacket& request,
int32 index, KPPPConfigurePacket& nak, KPPPConfigurePacket& reject);
@@ -48,17 +49,17 @@ class PAP : public KPPPProtocol {
public:
PAP(KPPPInterface& 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 status_t Send(net_buffer *packet, uint16 protocolNumber);
virtual status_t Receive(net_buffer *packet, uint16 protocolNumber);
virtual void Pulse();
private:
@@ -66,28 +67,28 @@ class PAP : public KPPPProtocol {
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);
void RREvent(net_buffer *packet);
void RAEvent(net_buffer *packet);
void RNEvent(net_buffer *packet);
// actions
void ReportUpFailedEvent();
void ReportUpEvent();
void ReportDownEvent();
void InitializeRestartCount();
bool SendRequest();
bool SendAck(struct mbuf *packet);
bool SendNak(struct mbuf *packet);
bool SendAck(net_buffer *packet);
bool SendNak(net_buffer *packet);
private:
// for state machine
pap_state fState;
vint32 fID;
int32 fID;
// counters and timers
int32 fMaxRequest;
int32 fRequestCounter;
+25 -20
View File
@@ -5,42 +5,41 @@
#include <KernelExport.h>
#include <driver_settings.h>
#include <core_funcs.h>
#include <net_module.h>
#include <net_buffer.h>
#include <net_stack.h>
#include <KPPPInterface.h>
#include <KPPPModule.h>
#include "Protocol.h"
#define PAP_MODULE_NAME NETWORK_MODULES_ROOT "/ppp/pap"
#define PAP_MODULE_NAME NETWORK_MODULES_ROOT "ppp/pap"
struct core_module_info *core = NULL;
net_stack_module_info *gStackModule = NULL;
net_buffer_module_info *gBufferModule = NULL;
status_t std_ops(int32 op, ...);
static
bool
static bool
add_to(KPPPInterface& mainInterface, KPPPInterface *subInterface,
driver_parameter *settings, ppp_module_key_type type)
{
if(type != PPP_AUTHENTICATOR_KEY_TYPE)
if (type != PPP_AUTHENTICATOR_KEY_TYPE)
return B_ERROR;
PAP *pap;
bool success;
if(subInterface) {
if (subInterface) {
pap = new PAP(*subInterface, settings);
success = subInterface->AddProtocol(pap);
} else {
pap = new PAP(mainInterface, settings);
success = mainInterface.AddProtocol(pap);
}
TRACE("PAP: add_to(): %s\n",
success && pap && pap->InitCheck() == B_OK ? "OK" : "ERROR");
return success && pap && pap->InitCheck() == B_OK;
}
@@ -58,22 +57,28 @@ static ppp_module_info pap_module = {
_EXPORT
status_t
std_ops(int32 op, ...)
std_ops(int32 op, ...)
{
switch(op) {
switch (op) {
case B_MODULE_INIT:
if(get_module(NET_CORE_MODULE_NAME, (module_info**) &core) != B_OK)
if (get_module(NET_STACK_MODULE_NAME, (module_info**) &gStackModule) != B_OK)
return B_ERROR;
if (get_module(NET_BUFFER_MODULE_NAME,
(module_info **)&gBufferModule) != B_OK) {
put_module(NET_STACK_MODULE_NAME);
return B_ERROR;
}
return B_OK;
case B_MODULE_UNINIT:
put_module(NET_CORE_MODULE_NAME);
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
break;
default:
return B_ERROR;
}
return B_OK;
}
@@ -0,0 +1,28 @@
SubDir HAIKU_TOP src add-ons kernel network ppp ppp ;
SetSubDirSupportedPlatformsBeOSCompatible ;
SubDirC++Flags -fno-rtti ;
if $(TARGET_PLATFORM) != haiku {
UseHeaders [ FStandardOSHeaders ] : true ;
# Needed for <support/Errors.h> and maybe other stuff.
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
# We need the public network headers also when not compiling for Haiku.
# Unfortunately we get more than we want, namely all POSIX headers.
}
UsePrivateKernelHeaders ;
UsePrivateHeaders net ;
UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
libkernelppp headers ] : true ;
KernelAddon ppp :
ppp.cpp
;
# Installation
HaikuInstall install-networking :
/boot/home/config/add-ons/kernel/network/ppp
: ppp ;
+388
View File
@@ -0,0 +1,388 @@
/*
* Copyright 2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Lin Longzhou, linlongzhou@163.com
*/
#include <errno.h>
#include <stdlib.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <new>
#include <ethernet.h>
#include <ether_driver.h>
#include <net_buffer.h>
#include <net_datalink_protocol.h>
#include <NetBufferUtilities.h>
#include <net_stack.h>
#include <KernelExport.h>
#include <KPPPManager.h>
#include <ppp_device.h>
#define PPP_HEADER_LENGTH (8 + ETHER_HEADER_LENGTH)
net_buffer* create_buffer_for_frame(uint8 *frame, uint16 frame_size);
static const bigtime_t kLinkCheckInterval = 1000000;
// 1 second
net_buffer_module_info *gBufferModule;
ppp_interface_module_info* gPPPInterfaceModule;
static net_stack_module_info *sStackModule;
static mutex sListLock;
static DoublyLinkedList<ppp_device> sCheckList;
static sem_id sLinkChangeSemaphore;
static thread_id sLinkCheckerThread;
// #pragma mark -
//
status_t
ppp_init(const char *name, net_device **_device)
{
// ppp device
dprintf("%s: entering!\n", __func__);
if (strncmp(name, "ppp", 3)) {
dprintf("[%s] not ppp device\n", name);
return B_BAD_VALUE;
}
dprintf("[%s] is ppp device\n", name);
status_t status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule);
if (status < B_OK)
return status;
// ppp_device *device = new (std::nothrow) ppp_device;
ppp_interface_id idInterface = gPPPInterfaceModule->CreateInterfaceWithName(name, 0);
KPPPInterface * pppInterface = gPPPInterfaceModule->GetInterface(idInterface);
if (idInterface <= 0 || pppInterface == NULL) {
if (idInterface <= 0)
dprintf("%s: idInterface:%ld\n", __func__, idInterface);
else
dprintf("%s: pppInterface == NULL %ld\n", __func__, idInterface);
put_module(NET_BUFFER_MODULE_NAME);
return B_NO_MEMORY;
}
// Ifnet available until interface up phase
ppp_device *device = (ppp_device *)pppInterface->Ifnet();
if (device == NULL) {
dprintf("%s: can not get ppp_device\n", __func__);
put_module(NET_BUFFER_MODULE_NAME);
return B_NO_MEMORY;
}
strcpy(device->name, name);
device->flags = (IFF_BROADCAST | IFF_LINK) & (~IFF_UP);
device->type = IFT_PPP;
device->mtu = 1492;
device->frame_size = 1500;
device->media = IFM_ACTIVE | IFM_ETHER;
device->header_length = PPP_HEADER_LENGTH;
status =sStackModule->init_fifo(&(device->ppp_fifo), "ppp_fifo", 10 * 1500);
// 10 ppp packet at most
if (status < B_OK)
return(status);
TRACE("[%s] finish\n", "allocate ppp_device");
*_device = device;
return B_OK;
}
status_t
ppp_uninit(net_device *device)
{
dprintf("%s: uninit ppp\n", __func__);
ppp_device *ppp_dev=(ppp_device *)device;
sStackModule->uninit_fifo(&(ppp_dev->ppp_fifo));
put_module(NET_BUFFER_MODULE_NAME);
// delete ppp_dev->KPPP_Interface;
delete ppp_dev;
return B_OK;
}
status_t
ppp_up(net_device *_device)
{
dprintf("ppp_up\n");
ppp_device *device = (ppp_device *)_device;
if (device->KPPP_Interface == NULL) {
dprintf("%s: warning! can not find pppinterface KPPP_Interface\n", __func__);
return B_ERROR;
}
if (device->KPPP_Interface->Up() != true) {
dprintf("%s: warning! KPPP_Interface->Up() failure\n", __func__);
return B_ERROR;
}
device->mtu = device->frame_size - device->header_length;
// s_pppoe_dev = device;
dprintf("%s: congratulations! Find pppinterface (device->KPPP_Interface)\n", __func__);
return B_OK;
}
void
ppp_down(net_device *_device)
{
dprintf("%s\n", __func__);
ppp_device *device = (ppp_device *)_device;
device->KPPP_Interface->Down();
MutexLocker _(sListLock);
// if the device is still part of the list, remove it
if (device->GetDoublyLinkedListLink()->next != NULL
|| device->GetDoublyLinkedListLink()->previous != NULL
|| device == sCheckList.Head())
sCheckList.Remove(device);
// device->KPPP_Interface = NULL;
return;
}
status_t
ppp_control(net_device *_device, int32 op, void *argument,
size_t length)
{
TRACE("%s %ld\n", __func__, op);
ppp_device *device = (ppp_device *)_device;
if (device->KPPP_Interface == NULL) {
dprintf("%s: can not find KPPP_Interface for ppp\n", __func__);
return B_OK;
}
return device->KPPP_Interface->Control(op, argument, length);
return B_OK;
}
status_t
ppp_send_data(net_device *_device, net_buffer *buffer)
{
TRACE("%s\n", __func__);
ppp_device *device = (ppp_device *)_device;
if (buffer->size > device->frame_size || buffer->size < device->header_length) {
device->stats.send.errors++;
dprintf("sorry! fail send ppp packet, size wrong!\n");
return B_BAD_VALUE;
}
if (device->KPPP_Interface == NULL) {
device->stats.send.errors++;
dprintf("Fail send ppp packet, no eth for ppp!\n");
return B_BAD_VALUE;
}
size_t net_buffer_size = buffer->size;
// store buffer->size in case buffer freed in KPPP_Interface->Send
status_t status = device->KPPP_Interface->Send(buffer, 0x0021); // IP_PROTOCOL 0x0021
if (status != B_OK) {
device->stats.send.errors++;
dprintf("KPPP_Interface->Send(buffer, 0x0021 IP) fail\n");
return B_BAD_VALUE;
}
device->stats.send.packets++;
device->stats.send.bytes += net_buffer_size;
return B_OK;
}
status_t
ppp_receive_data(net_device *_device, net_buffer **_buffer)
{
TRACE("%s\n", __func__);
ppp_device *device = (ppp_device *)_device;
if (device->KPPP_Interface == NULL)
return B_FILE_ERROR;
TRACE("%s: trying fifo_dequeue_buffer\n", __func__);
status_t status = sStackModule->fifo_dequeue_buffer(&(device->ppp_fifo), 0, 10000000, _buffer);
if (status < B_OK) {
TRACE("sorry! can not fifo_dequeue_buffer!\n");
return status;
}
// (*_buffer)->interface_address = NULL; // strange need to put here
device->stats.receive.bytes += (*_buffer)->size;
device->stats.receive.packets++;
return B_OK;
}
status_t
ppp_set_mtu(net_device *_device, size_t mtu)
{
ppp_device *device = (ppp_device *)_device;
if (mtu > device->frame_size - ETHER_HEADER_LENGTH - 8
|| mtu <= ETHER_HEADER_LENGTH + 8 + 10)
return B_BAD_VALUE;
device->mtu = mtu;
return B_OK;
}
status_t
ppp_set_promiscuous(net_device *_device, bool promiscuous)
{
return B_NOT_SUPPORTED;
}
status_t
ppp_set_media(net_device *device, uint32 media)
{
return B_NOT_SUPPORTED;
}
status_t
ppp_add_multicast(struct net_device *_device, const sockaddr *_address)
{
// ppp_device *device = (ppp_device *)_device;
if (_address->sa_family != AF_LINK)
return B_BAD_VALUE;
const sockaddr_dl *address = (const sockaddr_dl *)_address;
if (address->sdl_type != IFT_ETHER)
return B_BAD_VALUE;
return B_NOT_SUPPORTED;
}
status_t
ppp_remove_multicast(struct net_device *_device, const sockaddr *_address)
{
// ppp_device *device = (ppp_device *)_device;
if (_address->sa_family != AF_LINK)
return B_BAD_VALUE;
const sockaddr_dl *address = (const sockaddr_dl *)_address;
if (address->sdl_type != IFT_ETHER)
return B_BAD_VALUE;
return B_NOT_SUPPORTED;
}
static status_t
ppp_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
{
status_t status = get_module(NET_STACK_MODULE_NAME,
(module_info **)&sStackModule);
if (status < B_OK)
return status;
status = get_module(PPP_INTERFACE_MODULE_NAME,
(module_info**)&gPPPInterfaceModule);
if (status < B_OK) {
put_module(NET_STACK_MODULE_NAME);
return status;
}
new (&sCheckList) DoublyLinkedList<ppp_device>;
// static C++ objects are not initialized in the module startup
sLinkCheckerThread = -1;
sLinkChangeSemaphore = create_sem(0, "ppp link change");
if (sLinkChangeSemaphore < B_OK) {
put_module(PPP_INTERFACE_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
return sLinkChangeSemaphore;
}
mutex_init(&sListLock, "ppp devices");
return B_OK;
}
case B_MODULE_UNINIT:
{
delete_sem(sLinkChangeSemaphore);
status_t status;
wait_for_thread(sLinkCheckerThread, &status);
mutex_destroy(&sListLock);
put_module(PPP_INTERFACE_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
return B_OK;
}
default:
return B_ERROR;
}
}
net_device_module_info spppModule = {
{
"network/devices/ppp/v1",
0,
ppp_std_ops
},
ppp_init,
ppp_uninit,
ppp_up,
ppp_down,
ppp_control,
ppp_send_data,
ppp_receive_data,
ppp_set_mtu,
ppp_set_promiscuous,
ppp_set_media,
ppp_add_multicast,
ppp_remove_multicast,
};
module_info *modules[] = {
(module_info *)&spppModule,
NULL
};
@@ -0,0 +1,26 @@
SubDir HAIKU_TOP src add-ons kernel network ppp ppp_frame ;
SetSubDirSupportedPlatformsBeOSCompatible ;
SubDirC++Flags -fno-rtti ;
if $(TARGET_PLATFORM) != haiku {
UseHeaders [ FStandardOSHeaders ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
# We need the public network headers also when not compiling for Haiku.
# Unfortunately we get more than we want, namely all POSIX headers.
}
UsePrivateKernelHeaders ;
UsePrivateHeaders kernel net ;
UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
libkernelppp headers ] : true ;
KernelAddon ppp_frame :
ppp_frame.cpp
;
# Installation
HaikuInstall install-networking : /boot/home/config/add-ons/kernel/haiku_network/ppp
: ppp_frame ;
@@ -0,0 +1,265 @@
/*
* Copyright 2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Lin Longzhou, linlongzhou@163.com
*/
#include <ethernet.h>
#include <net/if_types.h>
#include <net_datalink_protocol.h>
#include <net_datalink.h>
#include <KernelExport.h>
#include <new>
#include <PPPControl.h>
#include <ppp_device.h>
struct ppp_frame_protocol : net_datalink_protocol {
};
static net_stack_module_info *sStackModule;
status_t
ppp_deframe(net_device* device, net_buffer* buffer)
{
TRACE("%s: buffer type:%lx\n", __func__, buffer->type);
return B_OK;
}
// #pragma mark -
status_t
ppp_frame_init(struct net_interface* interface, net_domain* domain,
net_datalink_protocol** _protocol)
{
// We only support a single type!
dprintf("in function: %s::%s\n", __FILE__, __func__);
if (interface->device->type != IFT_PPP)
return B_BAD_TYPE;
ppp_frame_protocol* protocol;
status_t status = sStackModule->register_device_deframer(interface->device,
&ppp_deframe);
if (status != B_OK)
return status;
status = sStackModule->register_domain_device_handler(
interface->device, B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_PPPOE), domain);
if (status != B_OK)
return status;
status = sStackModule->register_domain_device_handler(
interface->device, B_NET_FRAME_TYPE_IPV4, domain);
if (status != B_OK)
return status;
// Locally received buffers don't need a domain device handler, as the
// buffer reception is handled internally.
protocol = new(std::nothrow) ppp_frame_protocol;
if (protocol == NULL) {
sStackModule->unregister_device_deframer(interface->device);
return B_NO_MEMORY;
}
*_protocol = protocol;
return B_OK;
}
status_t
ppp_frame_uninit(net_datalink_protocol* protocol)
{
sStackModule->unregister_device_deframer(protocol->interface->device);
sStackModule->unregister_device_handler(protocol->interface->device, 0);
delete protocol;
TRACE("%s\n", __func__);
return B_OK;
}
status_t
ppp_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
{
TRACE("%s: next module is %s\n", __func__, protocol->next->module->info.name);
return protocol->next->module->send_data(protocol->next, buffer);
}
status_t
ppp_frame_up(net_datalink_protocol* protocol)
{
dprintf("in function: %s\n", __func__);
return protocol->next->module->interface_up(protocol->next);
}
void
ppp_frame_down(net_datalink_protocol* protocol)
{
dprintf("%s::%s: entry\n", __FILE__, __func__);
protocol->next->module->interface_down(protocol->next);
return;
}
status_t
ppp_frame_change_address(net_datalink_protocol* protocol,
net_interface_address* address, int32 option,
const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
{
TRACE("in function: %s::%s\n", __FILE__, __func__);
return protocol->next->module->change_address(protocol->next, address,
option, oldAddress, newAddress);
}
static status_t
PPP_module_control(int32 option, void* argument, size_t length)
{
// control_net_module_args* args=(control_net_module_args*)argument;
if (option < PPPC_CONTROL_MODULE || option > PPP_CONTROL_OPS_END)
return B_ERROR;
// if (args->name != PPP_INTERFACE_MODULE_NAME)
// return B_ERROR;
switch(option)
{
case PPPC_CREATE_INTERFACE:
// process_CreateInterface(args->data, args->length);
case PPPC_CREATE_INTERFACE_WITH_NAME:
case PPPC_DELETE_INTERFACE:
case PPPC_BRING_INTERFACE_UP:
case PPPC_BRING_INTERFACE_DOWN:
case PPPC_CONTROL_INTERFACE:
case PPPC_GET_INTERFACES:
case PPPC_COUNT_INTERFACES:
case PPPC_FIND_INTERFACE_WITH_SETTINGS:
// interface control
case PPPC_GET_INTERFACE_INFO:
case PPPC_SET_USERNAME:
case PPPC_SET_PASSWORD:
case PPPC_SET_ASK_BEFORE_CONNECTING:
// ppp_up uses this in order to finalize a connection request
case PPPC_SET_MRU:
case PPPC_SET_CONNECT_ON_DEMAND:
case PPPC_SET_AUTO_RECONNECT:
case PPPC_HAS_INTERFACE_SETTINGS:
case PPPC_GET_STATISTICS:
// handler access
case PPPC_CONTROL_DEVICE:
case PPPC_CONTROL_PROTOCOL:
case PPPC_CONTROL_OPTION_HANDLER:
case PPPC_CONTROL_LCP_EXTENSION:
case PPPC_CONTROL_CHILD:
// KPPPDevice
case PPPC_GET_DEVICE_INFO:
// KPPPProtocol
case PPPC_GET_PROTOCOL_INFO:
// Common/mixed ops
case PPPC_ENABLE:
case PPPC_GET_SIMPLE_HANDLER_INFO:
// these two control ops use the ppp_report_request structure
case PPPC_ENABLE_REPORTS:
case PPPC_DISABLE_REPORTS:
case PPP_CONTROL_OPS_END:
case PPPC_CONTROL_MODULE:
default:
return B_ERROR;
}
}
static status_t
ppp_frame_control(net_datalink_protocol* protocol, int32 option,
void* argument, size_t length)
{
TRACE("%s: option:%ld\n", __func__, option);
if (option >= PPPC_CONTROL_MODULE && option <=PPP_CONTROL_OPS_END)
{
status_t status =PPP_module_control(option, argument, length);
// gPPPInterfaceModule->ControlInterface(1, option, argument, length);
return status;
}
return protocol->next->module->control(protocol->next, option, argument,
length);
}
static status_t
ppp_frame_join_multicast(net_datalink_protocol* protocol,
const sockaddr* address)
{
TRACE("in function: %s\n", __func__);
return protocol->next->module->join_multicast(protocol->next, address);
}
static status_t
ppp_frame_leave_multicast(net_datalink_protocol* protocol,
const sockaddr* address)
{
TRACE("in function: %s\n", __func__);
return protocol->next->module->leave_multicast(protocol->next, address);
}
static status_t
pppoe_frame_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
if (get_module(NET_STACK_MODULE_NAME,
(module_info **)&sStackModule) != B_OK)
return B_ERROR;
return B_OK;
case B_MODULE_UNINIT:
put_module(NET_STACK_MODULE_NAME);
return B_OK;
default:
return B_ERROR;
}
}
static net_datalink_protocol_module_info sPPPFrameModule = {
{
"network/datalink_protocols/ppp_frame/v1",
0,
pppoe_frame_std_ops
},
ppp_frame_init,
ppp_frame_uninit,
ppp_frame_send_data,
ppp_frame_up,
ppp_frame_down,
ppp_frame_change_address,
ppp_frame_control,
ppp_frame_join_multicast,
ppp_frame_leave_multicast,
};
module_info* modules[] = {
(module_info*)&sPPPFrameModule,
NULL
};
@@ -0,0 +1,31 @@
SubDir HAIKU_TOP src add-ons kernel network ppp ppp_manager ;
SetSubDirSupportedPlatformsBeOSCompatible ;
SubDirC++Flags -fno-rtti ;
if $(TARGET_PLATFORM) != haiku {
UseHeaders [ FStandardOSHeaders ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
# We need the public network headers also when not compiling for Haiku.
# Unfortunately we get more than we want, namely all POSIX headers.
}
UsePrivateKernelHeaders ;
# UsePrivateHeaders net ;
UsePrivateHeaders kernel net ;
UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
libkernelppp headers ] : true ;
KernelAddon KPPPManager :
KPPPManager.cpp
;
LinkAgainst KPPPManager : libkernelppp.a ;
# Installation
HaikuInstall install-networking : /boot/home/config/add-ons/kernel/haiku_network/ppp
: KPPPManager ;
@@ -0,0 +1,373 @@
/*
* Copyright 2006-2014, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
* Lin Longzhou, linlongzhou@163.com
*/
#include <net_stack.h>
#include <NetBufferUtilities.h>
#include <KernelExport.h>
#include <lock.h>
#include <util/AutoLock.h>
#include <util/DoublyLinkedList.h>
#include <new>
#include <ppp_device.h>
#include <KPPPManager.h>
struct entry_private : ppp_interface_entry, DoublyLinkedListLinkImpl<entry_private> {
};
static DoublyLinkedList<entry_private> sEntryList;
net_buffer_module_info* gBufferModule = NULL;
net_stack_module_info* gStackModule = NULL;
// static struct net_interface* sinterface;
static mutex sListLock;
static uint32 ppp_interface_count;
// #pragma mark -
static KPPPInterface * GetInterface(ppp_interface_id ID);
static ppp_interface_id
CreateInterface(const driver_settings *settings, ppp_interface_id parentID)
{
MutexLocker _(sListLock); // auto_lock
if (parentID > 0) {
TRACE("Not support Multi_Link yet!\n");
return 0l;
}
if (settings == NULL) {
TRACE("No driver_settings yet!\n");
return 0l;
}
ppp_interface_count++;
if (GetInterface(ppp_interface_count) != NULL)
return 0l;
entry_private* pentry = new (std::nothrow) entry_private;
memset(pentry, 0, sizeof(entry_private));
pentry->accessing = ppp_interface_count;
sEntryList.Add(pentry);
KPPPInterface *device = new (std::nothrow) KPPPInterface(NULL,
pentry, ppp_interface_count, NULL, NULL);
if (device == NULL || pentry == NULL) {
TRACE("device or pentry is NULL\n");
ppp_interface_count--;
return 0l;
}
TRACE("setting ppp_interface_count %ld\n", ppp_interface_count);
return ppp_interface_count; // only support 1 ppp connection right now
}
static ppp_interface_id
CreateInterfaceWithName(const char *name, ppp_interface_id parentID)
{
MutexLocker _(sListLock); // auto_lock
if (parentID > 0) {
dprintf("Not support Multi_Link yet!\n");
return(0);
}
if (strncmp(name, "ppp", 3)) {
dprintf("%s is not ppp device!\n", name);
return(0);
}
ppp_interface_count++;
if (GetInterface(ppp_interface_count) != NULL) {
TRACE("PPP Interface already exist!\n");
return 0l;
}
entry_private* pentry = new (std::nothrow) entry_private;
memset(pentry, 0, sizeof(entry_private));
pentry->accessing = ppp_interface_count;
sEntryList.Add(pentry);
KPPPInterface* device = new (std::nothrow) KPPPInterface(name,
pentry, ppp_interface_count, NULL, NULL);
if (device == NULL || pentry == NULL) {
TRACE("can not create ppp interface!\n");
ppp_interface_count--;
return 0l;
}
TRACE("setting ppp_interface_count %ld\n", ppp_interface_count);
return ppp_interface_count;
}
static bool
DeleteInterface(ppp_interface_id ID)
{
MutexLocker _(sListLock); // auto_lock
DoublyLinkedList<entry_private>::Iterator iterator
= sEntryList.GetIterator();
while (iterator.HasNext()) {
entry_private* pentry = iterator.Next();
if ((ppp_interface_id)pentry->accessing == ID) {
pentry->deleting = true;
return true;
}
}
return false;
}
static bool
RemoveInterface(ppp_interface_id ID)
{
MutexLocker _(sListLock); // auto_lock
if (ID <= 0 || ID > ppp_interface_count)
return false;
DoublyLinkedList<entry_private>::Iterator iterator
= sEntryList.GetIterator();
while (iterator.HasNext()) {
entry_private* pentry = iterator.Next();
if ((ppp_interface_id)pentry->accessing == ID) {
pentry->deleting = true;
break;
}
}
return false;
}
static net_device *
RegisterInterface(ppp_interface_id ID)
{
// MutexLocker _(sListLock); // auto_lock
entry_private* entry = NULL;
DoublyLinkedList<entry_private>::Iterator iterator
= sEntryList.GetIterator();
while (iterator.HasNext()) {
entry_private* pentry = iterator.Next();
if ((ppp_interface_id)pentry->accessing == ID) {
entry = pentry;
break;
}
}
if (entry == NULL)
return NULL;
ppp_device *device = new (std::nothrow) ppp_device;
if (device == NULL)
return NULL;
memset(device, 0, sizeof(ppp_device));
device->KPPP_Interface = entry->interface;
return device;
}
static KPPPInterface *
GetInterface(ppp_interface_id ID)
{
// MutexLocker _(sListLock); // auto_lock
DoublyLinkedList<entry_private>::Iterator iterator
= sEntryList.GetIterator();
while (iterator.HasNext()) {
entry_private* pentry = iterator.Next();
TRACE("testing interface id:%ld\n", pentry->accessing);
if ((ppp_interface_id)(pentry->accessing) == ID) {
TRACE("get interface id:%ld\n", ID);
return pentry->interface;
}
}
TRACE("can not get interface id:%ld\n", ID);
return NULL;
}
static bool
UnregisterInterface(ppp_interface_id ID)
{
MutexLocker _(sListLock); // auto_lock
if (ID <= 0 || ID > ppp_interface_count)
return false;
return true;
}
static status_t
ControlInterface(ppp_interface_id ID, uint32 op, void *data, size_t length)
{
MutexLocker _(sListLock); // auto_lock
if (ID <= 0 || ID > ppp_interface_count)
return B_ERROR;
DoublyLinkedList<entry_private>::Iterator iterator
= sEntryList.GetIterator();
while (iterator.HasNext()) {
entry_private* pentry = iterator.Next();
if ((ppp_interface_id)pentry->accessing == ID)
return B_OK;
}
return B_ERROR;
}
static int32
GetInterfaces(ppp_interface_id *interfaces, int32 count, ppp_interface_filter filter)
{
MutexLocker _(sListLock);
if (count <= 0 || count > (int32)ppp_interface_count)
return(0);
uint32 ppp_count = 0;
DoublyLinkedList<entry_private>::Iterator iterator
= sEntryList.GetIterator();
while (iterator.HasNext()) {
entry_private* pentry = iterator.Next();
interfaces[ppp_count] = pentry->accessing;
ppp_count++;
}
return ppp_count;
}
static int32
CountInterfaces(ppp_interface_filter filter)
{
MutexLocker _(sListLock); // auto_lock
uint32 ppp_count = 0;
DoublyLinkedList<entry_private>::Iterator iterator
= sEntryList.GetIterator();
while (iterator.HasNext()) {
iterator.Next();
ppp_count++;
}
return ppp_count;
}
static void
EnableReports(ppp_report_type type, thread_id thread, int32 flags)
{
MutexLocker _(sListLock); // auto_lock
return; // need more portrait
}
static void
DisableReports(ppp_report_type type, thread_id thread)
{
MutexLocker _(sListLock); // auto_lock
return; // need more portrait
}
static bool
DoesReport(ppp_report_type type, thread_id thread)
{
MutexLocker _(sListLock); // auto_lock
return false; // need more portrait
}
static status_t
KPPPManager_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
mutex_init(&sListLock, "KPPPManager");
new (&sEntryList) DoublyLinkedList<entry_private>;
// static C++ objects are not initialized in the module startup
ppp_interface_count = 0;
if (get_module(NET_STACK_MODULE_NAME, (module_info**)&gStackModule)
!= B_OK)
return B_ERROR;
if (get_module(NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule)
!= B_OK) {
put_module(NET_STACK_MODULE_NAME);
return B_ERROR;
}
return B_OK;
case B_MODULE_UNINIT:
mutex_destroy(&sListLock);
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
return B_OK;
default:
return B_ERROR;
}
}
static ppp_interface_module_info sKPPPManagerModule = {
{
PPP_INTERFACE_MODULE_NAME,
0,
KPPPManager_std_ops
},
CreateInterface,
CreateInterfaceWithName,
DeleteInterface,
RemoveInterface,
RegisterInterface,
GetInterface,
UnregisterInterface,
ControlInterface,
GetInterfaces,
CountInterfaces,
EnableReports,
DisableReports,
DoesReport
};
module_info* modules[] = {
(module_info*)&sKPPPManagerModule,
NULL
};
@@ -3,11 +3,12 @@
* Distributed under the terms of the MIT License.
*/
#include <ByteOrder.h>
#include <NetBufferUtilities.h>
#include <net_buffer.h>
#include "DiscoveryPacket.h"
#include <core_funcs.h>
DiscoveryPacket::DiscoveryPacket(uint8 code, uint16 sessionID)
: fCode(code),
fSessionID(sessionID),
@@ -16,18 +17,26 @@ DiscoveryPacket::DiscoveryPacket(uint8 code, uint16 sessionID)
}
DiscoveryPacket::DiscoveryPacket(struct mbuf *packet, uint32 start)
DiscoveryPacket::DiscoveryPacket(net_buffer *packet, uint32 start)
{
// decode packet
uint8 *data = mtod(packet, uint8*);
data += start;
pppoe_header *header = (pppoe_header*) data;
NetBufferHeaderReader<pppoe_header> bufferheader(packet);
if (bufferheader.Status() != B_OK) {
dprintf("NetBufferHeaderReader create fail\n");
fInitStatus = B_ERROR;
return;
}
pppoe_header &header = bufferheader.Data();
SetCode(header->code);
SetCode(header.code);
uint16 length = ntohs(header->length);
uint16 length = ntohs(header.length);
if(length > packet->m_len - PPPoE_HEADER_SIZE - start) {
if(length > packet->size - PPPoE_HEADER_SIZE) {
dprintf("packet size less than pppoe payload\n");
dprintf("pppoe payload:%d\n", length);
dprintf("PPPoE_HEADER_SIZE:%d\n", PPPoE_HEADER_SIZE);
dprintf("packet->size:%ld\n", packet->size);
fInitStatus = B_ERROR;
return;
// there are no tags (or one corrupted tag)
@@ -37,7 +46,7 @@ DiscoveryPacket::DiscoveryPacket(struct mbuf *packet, uint32 start)
pppoe_tag *tag;
while(position <= length - 4) {
tag = (pppoe_tag*) (header->data + position);
tag = (pppoe_tag*) (header.data + position);
position += ntohs(tag->length) + 4;
AddTag(ntohs(tag->type), tag->data, ntohs(tag->length));
@@ -116,13 +125,21 @@ DiscoveryPacket::TagWithType(uint16 type) const
}
struct mbuf*
DiscoveryPacket::ToMbuf(uint32 MTU, uint32 reserve)
net_buffer*
DiscoveryPacket::ToNetBuffer(uint32 MTU)
{
struct mbuf *packet = m_gethdr(MT_DATA);
packet->m_data += reserve;
pppoe_header *header = mtod(packet, pppoe_header*);
net_buffer *packet = gBufferModule->create(256);
if (packet == NULL) {
dprintf("create buffer failure\n");
return NULL;
}
pppoe_header *header ;
status_t status = gBufferModule->append_size(packet, 1492, (void **)&header);
if (status != B_OK) {
dprintf("append size failure\n");
return NULL;
}
header->version = PPPoE_VERSION;
header->type = PPPoE_TYPE;
@@ -137,7 +154,7 @@ DiscoveryPacket::ToMbuf(uint32 MTU, uint32 reserve)
// make sure we have enough space left
if(MTU - length < tag->length) {
m_freem(packet);
gBufferModule->free(packet);
return NULL;
}
@@ -150,7 +167,11 @@ DiscoveryPacket::ToMbuf(uint32 MTU, uint32 reserve)
}
header->length = htons(length);
packet->m_pkthdr.len = packet->m_len = length + PPPoE_HEADER_SIZE;
status = gBufferModule->trim(packet, length + PPPoE_HEADER_SIZE);
if (status != B_OK) {
dprintf("trim buffer failure\n");
return NULL;
}
return packet;
}
@@ -10,6 +10,7 @@
#include <TemplateList.h>
#define ETHER_HDR_LEN 14
enum PPPoE_TAG_TYPE {
END_OF_LIST = 0x0000,
@@ -37,13 +38,13 @@ typedef struct pppoe_tag {
uint16 type;
uint16 length;
uint8 data[0];
};
} pppoe_tag;
class DiscoveryPacket {
public:
DiscoveryPacket(uint8 code, uint16 sessionID = 0x0000);
DiscoveryPacket(struct mbuf *packet, uint32 start = 0);
DiscoveryPacket(net_buffer *packet, uint32 start = 0);
~DiscoveryPacket();
status_t InitCheck() const
@@ -66,8 +67,8 @@ class DiscoveryPacket {
pppoe_tag *TagAt(int32 index) const;
pppoe_tag *TagWithType(uint16 type) const;
struct mbuf *ToMbuf(uint32 MTU, uint32 reserve = ETHER_HDR_LEN);
// the user is responsible for freeing the mbuf
net_buffer *ToNetBuffer(uint32 MTU);
// the user is responsible for freeing the net_buffer
private:
uint8 fCode;
+3 -9
View File
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src add-ons kernel network ppp pppoe ;
SetSubDirSupportedPlatformsBeOSCompatible ;
SubDirC++Flags -fno-rtti ;
if $(TARGET_PLATFORM) != haiku {
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
@@ -8,20 +9,13 @@ if $(TARGET_PLATFORM) != haiku {
# Unfortunately we get more than we want, namely all POSIX headers.
}
# for kernel_cpp.h and BLocker
UseHeaders [ FDirName $(HAIKU_TOP) headers cpp ] : true ;
UsePrivateKernelHeaders ;
UsePrivateHeaders net ;
UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName kernel util ] ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
libkernelppp headers ] : true ;
{
SubDirC++Flags -fno-rtti ;
}
KernelAddon pppoe :
pppoe.cpp
PPPoEDevice.cpp
@@ -32,5 +26,5 @@ LinkAgainst pppoe : libkernelppp.a ;
# Installation
HaikuInstall install-networking
: /boot/home/config/add-ons/kernel/obos_network/ppp
: /boot/home/config/add-ons/kernel/haiku/ppp
: pppoe ;
+8 -3
View File
@@ -8,10 +8,15 @@
#include <SupportDefs.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <ethernet.h>
#include <ether_driver.h>
#include <net_stack.h>
class PPPoEDevice;
#define B_NET_FRAME_TYPE_PPPOE B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_PPPOE)
#define B_NET_FRAME_TYPE_PPPOE_DISCOVERY B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_PPPOE_DISCOVERY)
#define PPPoE_QUERY_REPORT_SIZE 2048
#define PPPoE_QUERY_REPORT 'PoEQ'
@@ -60,14 +65,14 @@ typedef struct complete_pppoe_header {
// defined in pppoe.cpp
extern ifnet *FindPPPoEInterface(const char *name);
extern net_device *FindPPPoEInterface(const char *name);
extern uint32 NewHostUniq();
extern void add_device(PPPoEDevice *device);
extern void remove_device(PPPoEDevice *device);
#if DEBUG
// defined in PPPoEDevice.cpp
extern void dump_packet(struct mbuf *packet);
extern void dump_packet(net_buffer *packet);
#endif // DEBUG
@@ -3,41 +3,57 @@
* Distributed under the terms of the MIT License.
*/
#include <cstdlib>
#include <ByteOrder.h>
#include <net/if_dl.h>
#include <net_stack.h>
#include <ethernet.h>
#include <ether_driver.h>
#include "PPPoEDevice.h"
#include "DiscoveryPacket.h"
#include <core_funcs.h>
#include <cstdlib>
// from libkernelppp
#include <settings_tools.h>
extern net_stack_module_info *gStackModule;
extern net_buffer_module_info *gBufferModule;
extern status_t
pppoe_input(void *cookie, net_device *_device, net_buffer *packet);
#if DEBUG
static char sDigits[] = "0123456789ABCDEF";
void
dump_packet(struct mbuf *packet)
dump_packet(net_buffer *packet)
{
if(!packet)
if (!packet)
return;
uint8 *data = mtod(packet, uint8*);
BufferHeaderReader<uint8> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return;
uint8 &buffer = bufferheader.Data();
uint8 *data = &buffer;
uint8 buffer[33];
uint8 bufferIndex = 0;
TRACE("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++) {
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) {
if (bufferIndex == 32 || index == packet->m_len - 1) {
buffer[bufferIndex] = 0;
TRACE("%s\n", buffer);
bufferIndex = 0;
}
}
}
#endif
@@ -54,30 +70,39 @@ PPPoEDevice::PPPoEDevice(KPPPInterface& interface, driver_parameter *settings)
{
#if DEBUG
TRACE("PPPoEDevice: Constructor\n");
if(!settings || !settings->parameters)
if (!settings || !settings->parameters)
TRACE("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
if (!settings)
dprintf("%s::%s: settings is NULL\n", __FILE__, __func__);
// find ethernet device
const char *interfaceName = get_parameter_value(PPPoE_INTERFACE_KEY, settings);
if(!interfaceName)
return;
finterfaceName = get_parameter_value(PPPoE_INTERFACE_KEY, settings);
TRACE("%s::%s: finterfaceName is %s\n", __FILE__, __func__,
finterfaceName ? finterfaceName : "NULL");
fACName = get_parameter_value(PPPoE_AC_NAME_KEY, settings);
TRACE("fACName is %s\n", fACName ? fACName : "NULL");
fServiceName = get_parameter_value(PPPoE_SERVICE_NAME_KEY, settings);
fEthernetIfnet = FindPPPoEInterface(interfaceName);
TRACE("fServiceName is %s\n", fServiceName ? fServiceName : "NULL");
// fEthernetIfnet = FindPPPoEInterface(interfaceName);
#if DEBUG
if(!fEthernetIfnet)
if (!fEthernetIfnet)
TRACE("PPPoEDevice::ctor: could not find ethernet interface\n");
else
TRACE("%s::%s: Find Ethernet device", __FILE__, __func__);
#endif
}
@@ -85,8 +110,10 @@ PPPoEDevice::PPPoEDevice(KPPPInterface& interface, driver_parameter *settings)
status_t
PPPoEDevice::InitCheck() const
{
return EthernetIfnet() && EthernetIfnet()->output
&& KPPPDevice::InitCheck() == B_OK ? B_OK : B_ERROR;
if (KPPPDevice::InitCheck() != B_OK)
dprintf("%s::%s: KPPPDevice::InitCheck() has error\n", __FILE__, __func__);
return KPPPDevice::InitCheck() == B_OK ? B_OK : B_ERROR;
}
@@ -94,72 +121,103 @@ bool
PPPoEDevice::Up()
{
TRACE("PPPoEDevice: Up()\n");
if(InitCheck() != B_OK)
if (InitCheck() != B_OK)
return false;
if(IsUp())
if (IsUp())
return true;
fEthernetIfnet = FindPPPoEInterface(finterfaceName);
if (fEthernetIfnet == NULL) {
dprintf("%s::%s: fEthernetIfnet %s not found\n", __FILE__, __func__, finterfaceName);
return false;
}
memcpy(fEtherAddr, fEthernetIfnet->address.data, ETHER_ADDRESS_LENGTH);
dprintf("ppp's corresponding addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
fEtherAddr[0], fEtherAddr[1], fEtherAddr[2], fEtherAddr[3],
fEtherAddr[4], fEtherAddr[5]);
if (fEthernetIfnet->module == NULL) {
dprintf("%s::%s: fEthernetIfnet->module not found\n", __FILE__,
__func__);
return false;
}
add_device(this);
fState = INITIAL;
// reset state
if(fAttempts > PPPoE_MAX_ATTEMPTS) {
if (fAttempts > PPPoE_MAX_ATTEMPTS) {
fAttempts = 0;
return false;
}
++fAttempts;
// reset connection settings
memset(fPeer, 0xFF, sizeof(fPeer));
// create PADI
DiscoveryPacket discovery(PADI);
if(ServiceName())
if (ServiceName())
discovery.AddTag(SERVICE_NAME, ServiceName(), strlen(ServiceName()));
else
discovery.AddTag(SERVICE_NAME, NULL, 0);
discovery.AddTag(HOST_UNIQ, &fHostUniq, sizeof(fHostUniq));
discovery.AddTag(END_OF_LIST, NULL, 0);
// set up PPP header
struct mbuf *packet = discovery.ToMbuf(MTU());
if(!packet)
net_buffer *packet = discovery.ToNetBuffer(MTU());
if (!packet)
return false;
// create destination
struct ether_header *ethernetHeader;
struct sockaddr destination;
memset(&destination, 0, sizeof(destination));
destination.sa_family = AF_UNSPEC;
// raw packet with ethernet header
ethernetHeader = (struct ether_header*) destination.sa_data;
ethernetHeader->ether_type = ETHERTYPE_PPPOEDISC;
memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer));
// create ether header
NetBufferPrepend<ether_header> ethernetHeader(packet);
if (ethernetHeader.Status() != B_OK)
return false;
ether_header &header = ethernetHeader.Data();
memset(header.destination, 0xff, ETHER_ADDRESS_LENGTH);
memcpy(header.source, fEtherAddr, ETHER_ADDRESS_LENGTH);
header.type = htons(ETHER_TYPE_PPPOE_DISCOVERY);
ethernetHeader.Sync();
// raw packet with ethernet header
// check if we are allowed to go up now (user intervention might disallow that)
if(fAttempts > 0 && !UpStarted()) {
if (fAttempts > 0 && !UpStarted()) {
fAttempts = 0;
remove_device(this);
DownEvent();
return true;
// there was no error
}
fState = PADI_SENT;
// needed before sending, otherwise we might not get all packets
if(EthernetIfnet()->output(EthernetIfnet(), packet, &destination, NULL) != B_OK) {
status_t status = gStackModule->register_device_handler(fEthernetIfnet,
B_NET_FRAME_TYPE_PPPOE_DISCOVERY, &pppoe_input, NULL);
if (status != B_OK)
return false;
status = gStackModule->register_device_handler(fEthernetIfnet,
B_NET_FRAME_TYPE_PPPOE, &pppoe_input, NULL);
if (status != B_OK)
return false;
if (EthernetIfnet()->module->send_data(EthernetIfnet(), packet) != B_OK) {
fState = INITIAL;
fAttempts = 0;
ERROR("PPPoEDevice::Up(): EthernetIfnet()->output() failed!\n");
return false;
}
dprintf("PPPoEDevice::Up(): EthernetIfnet()->output() success!\n");
fNextTimeout = system_time() + PPPoE_TIMEOUT;
return true;
}
@@ -168,36 +226,41 @@ bool
PPPoEDevice::Down()
{
TRACE("PPPoEDevice: Down()\n");
gStackModule->unregister_device_handler(fEthernetIfnet,
B_NET_FRAME_TYPE_PPPOE_DISCOVERY);
gStackModule->unregister_device_handler(fEthernetIfnet,
B_NET_FRAME_TYPE_PPPOE);
remove_device(this);
if(InitCheck() != B_OK)
if (InitCheck() != B_OK)
return false;
fState = INITIAL;
fAttempts = 0;
fNextTimeout = 0;
// disable timeouts
if(!IsUp()) {
if (!IsUp()) {
DownEvent();
return true;
}
DownStarted();
// this tells StateMachine that DownEvent() does not mean we lost connection
// create PADT
DiscoveryPacket discovery(PADT, SessionID());
discovery.AddTag(END_OF_LIST, NULL, 0);
struct mbuf *packet = discovery.ToMbuf(MTU());
if(!packet) {
ERROR("PPPoEDevice::Down(): ToMbuf() failed; MTU=%ld\n", MTU());
net_buffer *packet = discovery.ToNetBuffer(MTU());
if (!packet) {
ERROR("PPPoEDevice::Down(): ToNetBuffer() failed; MTU=%ld\n", MTU());
DownEvent();
return false;
}
// create destination
struct ether_header *ethernetHeader;
struct sockaddr destination;
@@ -205,15 +268,15 @@ PPPoEDevice::Down()
destination.sa_family = AF_UNSPEC;
// raw packet with ethernet header
ethernetHeader = (struct ether_header*) destination.sa_data;
ethernetHeader->ether_type = ETHERTYPE_PPPOEDISC;
memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer));
ethernetHeader->type = ETHER_TYPE_PPPOE_DISCOVERY;
memcpy(ethernetHeader->destination, fPeer, sizeof(fPeer));
// reset connection settings
memset(fPeer, 0xFF, sizeof(fPeer));
EthernetIfnet()->output(EthernetIfnet(), packet, &destination, NULL);
EthernetIfnet()->module->send_data(EthernetIfnet(), packet);
DownEvent();
return true;
}
@@ -242,220 +305,261 @@ PPPoEDevice::CountOutputBytes() const
status_t
PPPoEDevice::Send(struct mbuf *packet, uint16 protocolNumber)
PPPoEDevice::Send(net_buffer *packet, uint16 protocolNumber)
{
// Send() is only for PPP packets. PPPoE packets are sent directly to ethernet.
TRACE("PPPoEDevice: Send()\n");
if(!packet)
if (!packet)
return B_ERROR;
else if(InitCheck() != B_OK || protocolNumber != 0) {
else if (InitCheck() != B_OK || protocolNumber != 0) {
ERROR("PPPoEDevice::Send(): InitCheck() != B_OK!\n");
m_freem(packet);
gBufferModule->free(packet);
return B_ERROR;
}
if(!IsUp()) {
if (!IsUp()) {
ERROR("PPPoEDevice::Send(): no connection!\n");
m_freem(packet);
gBufferModule->free(packet);
return PPP_NO_CONNECTION;
}
uint16 length = packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : packet->m_len;
uint16 length = packet->size;
// encapsulate packet into pppoe header
M_PREPEND(packet, PPPoE_HEADER_SIZE);
pppoe_header *header = mtod(packet, pppoe_header*);
header->version = PPPoE_VERSION;
header->type = PPPoE_TYPE;
header->code = 0x00;
header->sessionID = SessionID();
header->length = htons(length);
// create destination
struct ether_header *ethernetHeader;
struct sockaddr destination;
memset(&destination, 0, sizeof(destination));
destination.sa_family = AF_UNSPEC;
// raw packet with ethernet header
ethernetHeader = (struct ether_header*) destination.sa_data;
ethernetHeader->ether_type = ETHERTYPE_PPPOE;
memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer));
if(!packet || !mtod(packet, pppoe_header*))
NetBufferPrepend<pppoe_header> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return B_ERROR;
pppoe_header &header = bufferheader.Data();
header.version = PPPoE_VERSION;
header.type = PPPoE_TYPE;
header.code = 0x00;
header.sessionID = SessionID();
header.length = htons(length);
bufferheader.Sync();
// create ether header
NetBufferPrepend<ether_header> ethernetHeader(packet);
if (ethernetHeader.Status() != B_OK)
return false;
ether_header &ethheader = ethernetHeader.Data();
memcpy(ethheader.destination, fPeer, ETHER_ADDRESS_LENGTH);
memcpy(ethheader.source, fEtherAddr, ETHER_ADDRESS_LENGTH);
ethheader.type = htons(ETHER_TYPE_PPPOE);
ethernetHeader.Sync();
// raw packet with ethernet header
if (!packet)
ERROR("PPPoEDevice::Send(): packet is NULL!\n");
if(EthernetIfnet()->output(EthernetIfnet(), packet, &destination, NULL) != B_OK) {
if (EthernetIfnet()->module->send_data(EthernetIfnet(), packet) != B_OK) {
ERROR("PPPoEDevice::Send(): EthernetIfnet()->output() failed!\n");
remove_device(this);
DownEvent();
// DownEvent() without DownStarted() indicates connection lost
return PPP_NO_CONNECTION;
}
return B_OK;
}
status_t
PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
PPPoEDevice::Receive(net_buffer *packet, uint16 protocolNumber)
{
if(!packet)
TRACE("%s entering %s: protocolNumber:%x\n", __FILE__, __func__, protocolNumber);
if (!packet)
return B_ERROR;
else if(InitCheck() != B_OK || IsDown()) {
m_freem(packet);
if (InitCheck() != B_OK || IsDown()) {
dprintf("PPPoED InitCheck fail or IsDown\n");
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive fail\n");
return B_ERROR;
}
complete_pppoe_header *completeHeader = mtod(packet, complete_pppoe_header*);
if(!completeHeader) {
m_freem(packet);
return B_ERROR;
}
uint8 ethernetSource[6];
memcpy(ethernetSource, completeHeader->ethernetHeader.ether_shost, sizeof(fPeer));
status_t result = B_OK;
if(completeHeader->ethernetHeader.ether_type == ETHERTYPE_PPPOE) {
m_adj(packet, ETHER_HDR_LEN);
pppoe_header *header = mtod(packet, pppoe_header*);
if(!IsUp() || header->version != PPPoE_VERSION || header->type != PPPoE_TYPE
|| header->code != 0x0 || header->sessionID != SessionID()) {
m_freem(packet);
struct sockaddr_dl& source = *(struct sockaddr_dl*)packet->source;
memcpy(ethernetSource, source.sdl_data, sizeof(fPeer));
int32 PPP_Packet_Type = B_NET_FRAME_TYPE(source.sdl_type,
ntohs(source.sdl_e_type));
// bufferheader.Remove();
// bufferheader.Sync();
if (PPP_Packet_Type == B_NET_FRAME_TYPE_PPPOE) {
TRACE("ETHER_TYPE_PPPOE\n");
NetBufferHeaderReader<pppoe_header> bufferheader(packet);
if (bufferheader.Status() != B_OK) {
TRACE("creat NetBufferHeaderReader fail\n");
return B_ERROR;
}
m_adj(packet, PPPoE_HEADER_SIZE);
pppoe_header &header = bufferheader.Data();
uint16 ppppoe_payload = ntohs(header.length);
if (!IsUp() || header.version != PPPoE_VERSION || header.type != PPPoE_TYPE
|| header.code != 0x0 || header.sessionID != SessionID()) {
// gBufferModule->free(packet);
TRACE("basic pppoe header check fail\n");
return B_ERROR;
}
bufferheader.Remove();
bufferheader.Sync();
// trim the packet according to actual pppoe_payload
gBufferModule->trim(packet, ppppoe_payload);
return Interface().ReceiveFromDevice(packet);
} else if(completeHeader->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC) {
m_adj(packet, ETHER_HDR_LEN);
pppoe_header *header = mtod(packet, pppoe_header*);
}
if (PPP_Packet_Type == B_NET_FRAME_TYPE_PPPOE_DISCOVERY) {
dprintf("ETHER_TYPE_PPPOE_DISCOVERY\n");
NetBufferHeaderReader<pppoe_header> bufferheader(packet);
if (bufferheader.Status() != B_OK) {
dprintf("create NetBufferHeaderReader fail\n");
return B_ERROR;
}
pppoe_header &header = bufferheader.Data();
// we do not need to check HOST_UNIQ tag as this is done in pppoe.cpp
if(header->version != PPPoE_VERSION || header->type != PPPoE_TYPE) {
m_freem(packet);
if (header.version != PPPoE_VERSION || header.type != PPPoE_TYPE) {
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive fail version type wrong\n");
return B_ERROR;
}
if(IsDown()) {
m_freem(packet);
if (IsDown()) {
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive fail PPPoEDev IsDown\n");
return B_ERROR;
}
DiscoveryPacket discovery(packet);
switch(discovery.Code()) {
case PADO: {
if(fState != PADI_SENT) {
m_freem(packet);
dprintf("processing PADO\n");
if (fState != PADI_SENT) {
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive faile not PADI_Sent \n");
return B_OK;
}
bool hasServiceName = false, hasACName = false;
pppoe_tag *tag;
DiscoveryPacket reply(PADR);
for(int32 index = 0; index < discovery.CountTags(); index++) {
for (int32 index = 0; index < discovery.CountTags(); index++) {
tag = discovery.TagAt(index);
if(!tag)
if (!tag)
continue;
switch(tag->type) {
switch (tag->type) {
case SERVICE_NAME:
if(!hasServiceName && (!ServiceName()
|| (strlen(ServiceName()) == tag->length)
if (!hasServiceName && (!ServiceName()
|| ((strlen(ServiceName()) == tag->length)
&& !memcmp(tag->data, ServiceName(),
tag->length))) {
tag->length)))) {
hasServiceName = true;
reply.AddTag(tag->type, tag->data, tag->length);
}
break;
case AC_NAME:
if(!hasACName && (!ACName()
|| (strlen(ACName()) == tag->length)
if (!hasACName && (!ACName()
|| ((strlen(ACName()) == tag->length)
&& !memcmp(tag->data, ACName(),
tag->length))) {
tag->length)))) {
hasACName = true;
reply.AddTag(tag->type, tag->data, tag->length);
}
break;
case AC_COOKIE:
case RELAY_SESSION_ID:
reply.AddTag(tag->type, tag->data, tag->length);
break;
case SERVICE_NAME_ERROR:
case AC_SYSTEM_ERROR:
case GENERIC_ERROR:
m_freem(packet);
// gBufferModule->free(packet);
dprintf("PPPoEDevice::generic error faile\n");
return B_ERROR;
break;
default:
;
}
}
if(!hasServiceName) {
m_freem(packet);
if (!hasServiceName) {
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive faile no svc name\n");
return B_ERROR;
}
dprintf("reply.AddTag\n");
reply.AddTag(HOST_UNIQ, &fHostUniq, sizeof(fHostUniq));
reply.AddTag(END_OF_LIST, NULL, 0);
struct mbuf *replyPacket = reply.ToMbuf(MTU());
if(!replyPacket) {
m_freem(packet);
net_buffer *replyPacket = reply.ToNetBuffer(MTU());
if (!replyPacket) {
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive fail no reply pack\n");
return B_ERROR;
}
memcpy(fPeer, ethernetSource, sizeof(fPeer));
// create destination
struct ether_header *ethernetHeader;
struct sockaddr destination;
memset(&destination, 0, sizeof(destination));
destination.sa_family = AF_UNSPEC;
// raw packet with ethernet header
ethernetHeader = (struct ether_header*) destination.sa_data;
ethernetHeader->ether_type = ETHERTYPE_PPPOEDISC;
memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer));
memcpy(fPeer, ethernetSource, ETHER_ADDRESS_LENGTH);
// create ether header
NetBufferPrepend<ether_header> ethernetHeader(replyPacket);
if (ethernetHeader.Status() != B_OK)
return false;
ether_header &header = ethernetHeader.Data();
memcpy(header.destination, fPeer, ETHER_ADDRESS_LENGTH);
memcpy(header.source, fEtherAddr, ETHER_ADDRESS_LENGTH);
header.type=htons(ETHER_TYPE_PPPOE_DISCOVERY);
ethernetHeader.Sync();
// raw packet with ethernet header
fState = PADR_SENT;
if(EthernetIfnet()->output(EthernetIfnet(), replyPacket, &destination,
NULL) != B_OK) {
m_freem(packet);
if (EthernetIfnet()->module->send_data(EthernetIfnet(), replyPacket) != B_OK) {
gBufferModule->free(replyPacket);
dprintf("PPPoEDevice::Receive fail send PADR\n");
return B_ERROR;
}
fNextTimeout = system_time() + PPPoE_TIMEOUT;
} break;
}
break;
case PADS:
if(fState != PADR_SENT
|| memcmp(ethernetSource, fPeer, sizeof(fPeer))) {
m_freem(packet);
dprintf("procesing PADS\n");
if (fState != PADR_SENT
|| memcmp(ethernetSource, fPeer, sizeof(fPeer))) {
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive PADS but no PADR sent\n");
return B_ERROR;
}
fSessionID = header->sessionID;
fSessionID = header.sessionID;
fState = OPENED;
fNextTimeout = 0;
UpEvent();
break;
case PADT:
if(!IsUp()
dprintf("procesing PADT\n");
if (!IsUp()
|| memcmp(ethernetSource, fPeer, sizeof(fPeer))
|| header->sessionID != SessionID()) {
m_freem(packet);
|| header.sessionID != SessionID()) {
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive fail not up yet\n");
return B_ERROR;
}
fState = INITIAL;
fAttempts = 0;
fSessionID = 0;
@@ -463,16 +567,17 @@ PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
remove_device(this);
DownEvent();
break;
default:
m_freem(packet);
dprintf("PPPoEDevice::Receive fail unknown pppoed code\n");
// gBufferModule->free(packet);
return B_ERROR;
}
} else
result = B_ERROR;
m_freem(packet);
return result;
}
dprintf("PPPoEDevice::Receive PADX fine!\n");
// gBufferModule->free(packet);
return B_OK;
}
@@ -480,13 +585,12 @@ void
PPPoEDevice::Pulse()
{
// We use Pulse() for timeout of connection establishment.
if(fNextTimeout == 0 || IsUp() || IsDown())
if (fNextTimeout == 0 || IsUp() || IsDown())
return;
// check if timed out
if(system_time() >= fNextTimeout) {
if(!Up())
if (system_time() >= fNextTimeout) {
if (!Up())
UpFailedEvent();
}
}
@@ -10,6 +10,9 @@
#include <KPPPDevice.h>
#include <net/if_types.h>
#include <net_stack.h>
enum pppoe_state {
INITIAL,
@@ -25,7 +28,7 @@ class PPPoEDevice : public KPPPDevice {
public:
PPPoEDevice(KPPPInterface& interface, driver_parameter *settings);
ifnet *EthernetIfnet() const
net_device *EthernetIfnet() const
{ return fEthernetIfnet; }
const uint8 *Peer() const
@@ -50,17 +53,19 @@ class PPPoEDevice : public KPPPDevice {
virtual uint32 CountOutputBytes() const;
virtual status_t Send(struct mbuf *packet, uint16 protocolNumber = 0);
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber = 0);
virtual status_t Send(net_buffer *packet, uint16 protocolNumber = 0);
virtual status_t Receive(net_buffer *packet, uint16 protocolNumber = 0);
virtual void Pulse();
private:
ifnet *fEthernetIfnet;
net_device *fEthernetIfnet;
uint8 fPeer[6];
uint8 fEtherAddr[6];
uint16 fSessionID;
uint32 fHostUniq;
const char *fACName, *fServiceName;
const char *finterfaceName;
uint32 fAttempts;
bigtime_t fNextTimeout;
+217 -130
View File
@@ -5,34 +5,46 @@
#include <KernelExport.h>
#include <driver_settings.h>
#include <core_funcs.h>
#include <net_module.h>
#include <ethernet_module.h>
#include <lock.h>
#include <util/AutoLock.h>
#include <ByteOrder.h>
#include <net/if_types.h>
#include <net/if_dl.h>
#include <net/if.h>
#include <sys/sockio.h>
#include <net_buffer.h>
#include <net_datalink.h> // for get_interface and control
#include <net_stack.h>
#include <NetBufferUtilities.h>
#include <KPPPInterface.h>
#include <KPPPModule.h>
#include <KPPPUtils.h>
#include <LockerHelper.h>
#include "PPPoEDevice.h"
#include "DiscoveryPacket.h"
typedef struct pppoe_query {
ifnet *ethernetIfnet;
net_device *ethernetIfnet;
uint32 hostUniq;
thread_id receiver;
} pppoe_query;
#define PPPoE_MODULE_NAME NETWORK_MODULES_ROOT "ppp/pppoe"
#define PPPoE_MODULE_NAME "network/ppp/pppoe"
net_stack_module_info *gStackModule = NULL;
net_buffer_module_info *gBufferModule = NULL;
net_datalink_module_info *sDatalinkModule = NULL;
struct core_module_info *core = NULL;
static struct ethernet_module_info *sEthernet;
static int32 sHostUniq = 0;
status_t std_ops(int32 op, ...);
static BLocker sLock("PPPoEList");
// static mutex sLock("PPPoEList");
static TemplateList<PPPoEDevice*> *sDevices;
static TemplateList<pppoe_query*> *sQueries;
@@ -44,51 +56,75 @@ SendQueryPacket(pppoe_query *query, DiscoveryPacket& discovery)
char data[PPPoE_QUERY_REPORT_SIZE];
uint32 position = sizeof(uint32);
pppoe_tag *acName = discovery.TagWithType(AC_NAME);
if(acName) {
if(acName->length >= PPPoE_QUERY_REPORT_SIZE)
if (acName) {
if (acName->length >= PPPoE_QUERY_REPORT_SIZE)
return;
memcpy(data + position, acName->data, acName->length);
position += acName->length;
}
data[position++] = 0;
pppoe_tag *tag;
for(int32 index = 0; index < discovery.CountTags(); index++) {
for (int32 index = 0; index < discovery.CountTags(); index++) {
tag = discovery.TagAt(index);
if(tag && tag->type == SERVICE_NAME) {
if(position + tag->length >= PPPoE_QUERY_REPORT_SIZE)
if (tag && tag->type == SERVICE_NAME) {
if (position + tag->length >= PPPoE_QUERY_REPORT_SIZE)
return;
memcpy(data + position, tag->data, tag->length);
position += tag->length;
data[position++] = 0;
}
}
memcpy(data, &position, sizeof(uint32));
// add the total length
send_data_with_timeout(query->receiver, PPPoE_QUERY_REPORT, data,
PPPoE_QUERY_REPORT_SIZE, 700000);
}
ifnet*
net_interface *
get_interface_by_name(net_domain *domain, const char *name)
{
ifreq request;
memset(&request, 0, sizeof(request));
size_t size = sizeof(request);
strlcpy(request.ifr_name, name, IF_NAMESIZE);
if (sDatalinkModule->control(domain, SIOCGIFINDEX, &request, &size) != B_OK) {
TRACE("sDatalinkModule->control failure\n");
return NULL;
}
return sDatalinkModule->get_interface(domain, request.ifr_index);
}
net_device*
FindPPPoEInterface(const char *name)
{
if(!name)
if (!name)
return NULL;
net_interface* ethernetInterfaceOfPPPOE = NULL;
net_domain* domain = NULL;
domain = gStackModule->get_domain(AF_INET);
ethernetInterfaceOfPPPOE = get_interface_by_name(domain, name);
if (ethernetInterfaceOfPPPOE == NULL) {
TRACE("get_interface_by_name can not find eth\n");
return NULL;
ifnet *current = get_interfaces();
for(; current; current = current->if_next) {
if(current->if_type == IFT_ETHER && current->if_name
&& !strcmp(current->if_name, name))
return current;
}
if (ethernetInterfaceOfPPPOE->device)
return ethernetInterfaceOfPPPOE->device;
return NULL;
}
@@ -104,9 +140,9 @@ void
add_device(PPPoEDevice *device)
{
TRACE("PPPoE: add_device()\n");
LockerHelper locker(sLock);
if(!sDevices->HasItem(device))
// MutexLocker locker(sLock);
if (!sDevices->HasItem(device))
sDevices->AddItem(device);
}
@@ -115,85 +151,125 @@ void
remove_device(PPPoEDevice *device)
{
TRACE("PPPoE: remove_device()\n");
LockerHelper locker(sLock);
// MutexLocker locker(sLock);
sDevices->RemoveItem(device);
}
static
void
pppoe_input(struct mbuf *packet)
status_t
pppoe_input(void *cookie, net_device *_device, net_buffer *packet)
{
if(!packet)
return;
ifnet *sourceIfnet = packet->m_pkthdr.rcvif;
complete_pppoe_header *header = mtod(packet, complete_pppoe_header*);
if (!packet)
return B_ERROR;
NetBufferHeaderReader<pppoe_header> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return B_ERROR;
pppoe_header &header = bufferheader.Data();
// remove the following lines when pppoe server is enabled
if (header.code == PADI) {
TRACE("PADI packet received, ignoreing!\n");
gBufferModule->free(packet);
return B_OK;
}
if (header.code == PADO || header.code == PADR || header.code == PADS || header.code == PADT)
{
uint8 peerEtherAddr[ETHER_ADDRESS_LENGTH];
struct sockaddr_dl& source = *(struct sockaddr_dl*)packet->source;
memcpy(peerEtherAddr, source.sdl_data, ETHER_ADDRESS_LENGTH);
const char *str = header.code == PADI ? "PADI" :
header.code == PADO ? "PADO" :
header.code == PADR ? "PADR" :
header.code == PADS ? "PADS" :
"PADT" ;
dprintf("%s from:%02x:%02x:%02x:%02x:%02x:%02x code:%02x\n", str,
peerEtherAddr[0], peerEtherAddr[1], peerEtherAddr[2],
peerEtherAddr[3], peerEtherAddr[4], peerEtherAddr[5],
header.code);
}
PPPoEDevice *device;
pppoe_query *query;
LockerHelper locker(sLock);
if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC
&& header->pppoeHeader.length <= PPPoE_QUERY_REPORT_SIZE) {
for(int32 index = 0; index < sDevices->CountItems(); index++) {
sockaddr_dl& linkAddress = *(sockaddr_dl*)packet->source;
int32 specificType = B_NET_FRAME_TYPE(linkAddress.sdl_type,
ntohs(linkAddress.sdl_e_type));
// MutexLocker locker(sLock);
if (specificType == B_NET_FRAME_TYPE_PPPOE_DISCOVERY
&& ntohs(header.length) <= PPPoE_QUERY_REPORT_SIZE) {
for (int32 index = 0; index < sDevices->CountItems(); index++) {
query = sQueries->ItemAt(index);
if(query && query->ethernetIfnet == sourceIfnet) {
if(header->pppoeHeader.code == PADO) {
if (query) {// && query->ethernetIfnet == sourceIfnet) {
if (header.code == PADO) {
DiscoveryPacket discovery(packet, ETHER_HDR_LEN);
if(discovery.InitCheck() != B_OK) {
if (discovery.InitCheck() != B_OK) {
ERROR("PPPoE: received corrupted discovery packet!\n");
m_freem(packet);
return;
// gBufferModule->free(packet);
return B_ERROR;
}
pppoe_tag *hostTag = discovery.TagWithType(HOST_UNIQ);
if(hostTag && hostTag->length == 4
if (hostTag && hostTag->length == 4
&& *((uint32*)hostTag->data) == query->hostUniq) {
SendQueryPacket(query, discovery);
m_freem(packet);
return;
// gBufferModule->free(packet);
return B_ERROR;
}
}
}
}
}
for(int32 index = 0; index < sDevices->CountItems(); index++) {
TRACE("in pppoed processing sDevices->CountItems(): %ld\n", sDevices->CountItems());
for (int32 index = 0; index < sDevices->CountItems(); index++) {
device = sDevices->ItemAt(index);
if(device && device->EthernetIfnet() == sourceIfnet) {
if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOE
&& header->pppoeHeader.sessionID == device->SessionID()) {
TRACE("device->SessionID() %d, header.sessionID: %d\n", device->SessionID(),
header.sessionID);
if (device) { // && device->EthernetIfnet() == sourceIfnet) {
if (specificType == B_NET_FRAME_TYPE_PPPOE
&& header.sessionID == device->SessionID()) {
TRACE("PPPoE: session packet\n");
device->Receive(packet);
return;
} else if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC
&& header->pppoeHeader.code != PADI
&& header->pppoeHeader.code != PADR
return B_OK;
}
if (specificType == B_NET_FRAME_TYPE_PPPOE_DISCOVERY
&& header.code != PADI
&& header.code != PADR
&& !device->IsDown()) {
TRACE("PPPoE: discovery packet\n");
DiscoveryPacket discovery(packet, ETHER_HDR_LEN);
if(discovery.InitCheck() != B_OK) {
if (discovery.InitCheck() != B_OK) {
ERROR("PPPoE: received corrupted discovery packet!\n");
m_freem(packet);
return;
gBufferModule->free(packet);
return B_OK;
}
pppoe_tag *tag = discovery.TagWithType(HOST_UNIQ);
if(header->pppoeHeader.code == PADT || (tag && tag->length == 4
&& *((uint32*)tag->data) == device->HostUniq())) {
if (header.code == PADT || (tag && tag->length == 4
&& *((uint32*)tag->data) == device->HostUniq())) {
device->Receive(packet);
return;
return B_OK;
}
}
}
}
ERROR("PPPoE: No device found for packet from: %s\n", sourceIfnet->if_name);
m_freem(packet);
ERROR("PPPoE: No device found for packet from: %s\n", "ethernet");
// gBufferModule->free(packet);
return B_ERROR;
}
@@ -202,22 +278,22 @@ bool
add_to(KPPPInterface& mainInterface, KPPPInterface *subInterface,
driver_parameter *settings, ppp_module_key_type type)
{
if(mainInterface.Mode() != PPP_CLIENT_MODE || type != PPP_DEVICE_KEY_TYPE)
if (mainInterface.Mode() != PPP_CLIENT_MODE || type != PPP_DEVICE_KEY_TYPE)
return B_ERROR;
PPPoEDevice *device;
bool success;
if(subInterface) {
if (subInterface) {
device = new PPPoEDevice(*subInterface, settings);
success = subInterface->SetDevice(device);
} else {
device = new PPPoEDevice(mainInterface, settings);
success = mainInterface.SetDevice(device);
}
TRACE("PPPoE: add_to(): %s\n",
success && device && device->InitCheck() == B_OK ? "OK" : "ERROR");
return success && device && device->InitCheck() == B_OK;
}
@@ -226,59 +302,62 @@ static
status_t
control(uint32 op, void *data, size_t length)
{
switch(op) {
switch (op) {
case PPPoE_GET_INTERFACES: {
int32 position = 0, count = 0;
char *names = (char*) data;
ifnet *current = get_interfaces();
for(; current; current = current->if_next) {
if(current->if_type == IFT_ETHER && current->if_name) {
if(position + strlen(current->if_name) + 1 > length)
net_device *current = NULL; // get_interfaces();
for (; current; current = NULL) {
if (current->type == IFT_ETHER && current->name) {
if (position + strlen(current->name) + 1 > length)
return B_NO_MEMORY;
strcpy(names + position, current->if_name);
position += strlen(current->if_name);
strcpy(names + position, current->name);
position += strlen(current->name);
names[position++] = 0;
++count;
}
}
return count;
}
case PPPoE_QUERY_SERVICES: {
// XXX: as all modules are loaded on-demand we must wait for the results
if(!data || length != sizeof(pppoe_query_request))
if (!data || length != sizeof(pppoe_query_request))
return B_ERROR;
pppoe_query_request *request = (pppoe_query_request*) data;
pppoe_query query;
query.ethernetIfnet = FindPPPoEInterface(request->interfaceName);
if(!query.ethernetIfnet)
if (!query.ethernetIfnet)
return B_BAD_VALUE;
query.hostUniq = NewHostUniq();
query.receiver = request->receiver;
sLock.Lock();
sQueries->AddItem(&query);
sLock.Unlock();
{
// MutexLocker tlocker(sLock);
TRACE("add query\n");
sQueries->AddItem(&query);
}
snooze(2000000);
// wait two seconds for results
sLock.Lock();
sQueries->RemoveItem(&query);
sLock.Unlock();
{
// MutexLocker tlocker(sLock);
TRACE("remove query\n");
sQueries->RemoveItem(&query);
}
} break;
default:
return B_ERROR;
}
return B_OK;
}
@@ -296,40 +375,48 @@ static ppp_module_info pppoe_module = {
_EXPORT
status_t
std_ops(int32 op, ...)
std_ops(int32 op, ...)
{
switch(op) {
case B_MODULE_INIT:
if(get_module(NET_CORE_MODULE_NAME, (module_info**)&core) != B_OK)
if (get_module(NET_STACK_MODULE_NAME,
(module_info**)&gStackModule) != B_OK)
return B_ERROR;
if(get_module(NET_ETHERNET_MODULE_NAME,
(module_info**) &sEthernet) != B_OK) {
put_module(NET_CORE_MODULE_NAME);
if (get_module(NET_DATALINK_MODULE_NAME,
(module_info **)&sDatalinkModule) != B_OK) {
put_module(NET_STACK_MODULE_NAME);
return B_ERROR;
}
set_max_linkhdr(2 + PPPoE_HEADER_SIZE + ETHER_HDR_LEN);
if (get_module(NET_BUFFER_MODULE_NAME,
(module_info **)&gBufferModule) != B_OK) {
put_module(NET_DATALINK_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
return B_ERROR;
}
// set_max_linkhdr(2 + PPPoE_HEADER_SIZE + ETHER_HDR_LEN);
// 2 bytes for PPP header
sDevices = new TemplateList<PPPoEDevice*>;
sQueries = new TemplateList<pppoe_query*>;
sEthernet->set_pppoe_receiver(pppoe_input);
TRACE("PPPoE: Registered PPPoE receiver.\n");
return B_OK;
return B_OK;
case B_MODULE_UNINIT:
delete sQueries;
delete sDevices;
sEthernet->unset_pppoe_receiver();
TRACE("PPPoE: Unregistered PPPoE receiver.\n");
put_module(NET_CORE_MODULE_NAME);
put_module(NET_ETHERNET_MODULE_NAME);
break;
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_DATALINK_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
break;
default:
return B_ERROR;
}
return B_OK;
}
@@ -10,6 +10,9 @@ if $(TARGET_PLATFORM) != haiku {
# Unfortunately we get more than we want, namely all POSIX headers.
}
UsePrivateKernelHeaders ;
UsePrivateHeaders net ;
UsePrivateHeaders libroot net ;
UsePrivateHeaders [ FDirName kernel ] ;
UsePrivateHeaders [ FDirName kernel util ] ;
@@ -37,7 +40,6 @@ KernelStaticLibrary libkernelppp.a :
KPPPReportManager.cpp
KPPPStateMachine.cpp
KPPPUtils.cpp
Locker.cpp
settings_tools.cpp
# integrated modules
@@ -49,7 +51,5 @@ KernelStaticLibrary libkernelppp.a :
SEARCH on [ FGristFiles kernel_cpp.cpp ]
= [ FDirName $(HAIKU_TOP) src system kernel util ] ;
SEARCH on [ FGristFiles Locker.cpp ]
= [ FDirName $(HAIKU_TOP) src system kernel disk_device_manager ] ;
SEARCH on [ FGristFiles atomic.S ]
= [ FDirName $(HAIKU_TOP) src system libroot os arch $(TARGET_ARCH) ] ;
@@ -5,18 +5,20 @@
/*! \class KPPPConfigurePacket
\brief Helper class for LCP configure packets.
This class allows iterating over configure items and adding/removing items.
*/
#include <ByteOrder.h>
#include <net_buffer.h>
#include <net_stack.h>
#include <KPPPConfigurePacket.h>
#include <KPPPInterface.h>
#include <core_funcs.h>
/*! \brief Constructor.
\param code The code value (e.g.: PPP_CONFIGURE_REQUEST) of this packet.
*/
KPPPConfigurePacket::KPPPConfigurePacket(uint8 code)
@@ -27,30 +29,33 @@ KPPPConfigurePacket::KPPPConfigurePacket(uint8 code)
//! Decodes a packet and adds its items to this object.
KPPPConfigurePacket::KPPPConfigurePacket(struct mbuf *packet)
KPPPConfigurePacket::KPPPConfigurePacket(net_buffer *packet)
{
// decode packet
ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*);
SetID(header->id);
if (!SetCode(header->code))
NetBufferHeaderReader<ppp_lcp_packet> bufferhead(packet);
if (bufferhead.Status() != B_OK)
return;
uint16 length = ntohs(header->length);
if (length < 6 || length > packet->m_len)
ppp_lcp_packet &header = bufferhead.Data();
SetID(header.id);
if (!SetCode(header.code))
return;
uint16 length = ntohs(header.length);
if (length < 6 || length > packet->size)
return;
// there are no items (or one corrupted item)
int32 position = 0;
ppp_configure_item *item;
while (position < length - 4) {
item = (ppp_configure_item*) (header->data + position);
item = (ppp_configure_item*) (header.data + position);
if (item->length < 2)
return;
// found a corrupted item
position += item->length;
AddItem(item);
}
@@ -72,23 +77,23 @@ KPPPConfigurePacket::SetCode(uint8 code)
// only configure codes are allowed!
if (code < PPP_CONFIGURE_REQUEST || code > PPP_CONFIGURE_REJECT)
return false;
fCode = code;
return true;
}
/*! \brief Adds a new configure item to this packet.
Make sure all values are correct because the item will be copied. If the item's
length field is incorrect you will get bad results.
\param item The item.
\param index Item's index. Adds after the last item if not specified or negative.
\return \c true if successful, \c false otherwise.
\sa ppp_configure_item
*/
bool
@@ -96,10 +101,10 @@ KPPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index)
{
if (!item || item->length < 2)
return false;
ppp_configure_item *add = (ppp_configure_item*) malloc(item->length);
memcpy(add, item, item->length);
bool status;
if (index < 0)
status = fItems.AddItem(add);
@@ -109,7 +114,7 @@ KPPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index)
free(add);
return false;
}
return true;
}
@@ -120,10 +125,10 @@ KPPPConfigurePacket::RemoveItem(ppp_configure_item *item)
{
if (!fItems.HasItem(item))
return false;
fItems.RemoveItem(item);
free(item);
return true;
}
@@ -133,10 +138,10 @@ ppp_configure_item*
KPPPConfigurePacket::ItemAt(int32 index) const
{
ppp_configure_item *item = fItems.ItemAt(index);
if (item == fItems.GetDefaultItem())
return NULL;
return item;
}
@@ -146,56 +151,71 @@ ppp_configure_item*
KPPPConfigurePacket::ItemWithType(uint8 type) const
{
ppp_configure_item *item;
for (int32 index = 0; index < CountItems(); index++) {
item = ItemAt(index);
if (item && item->type == type)
return item;
}
return NULL;
}
/*! \brief Converts this packet into an mbuf structure.
/*! \brief Converts this packet into an net_buffer structure.
ATTENTION: You are responsible for freeing this packet by calling \c m_freem()!
\param MRU The interface's maximum receive unit (MRU).
\param reserve Number of bytes to reserve at the beginning of the packet.
\return The mbuf structure or \c NULL on error (e.g.: too big for given MRU).
\return The net_buffer structure or \c NULL on error (e.g.: too big for given MRU).
*/
struct mbuf*
KPPPConfigurePacket::ToMbuf(uint32 MRU, uint32 reserve)
net_buffer*
KPPPConfigurePacket::ToNetBuffer(uint32 MRU)
{
struct mbuf *packet = m_gethdr(MT_DATA);
packet->m_data += reserve;
ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*);
net_buffer *buffer = gBufferModule->create(256);
if (buffer == NULL) {
TRACE("%s::%s: gBufferModule->create fail\n", __FILE__, __func__);
return(NULL);
}
ppp_lcp_packet *header;
status_t status = gBufferModule->append_size(buffer, 1492, (void **)&header);
if (status != B_OK) {
TRACE("%s::%s: gBufferModule->append_size\n", __FILE__, __func__);
gBufferModule->free(buffer);
return(NULL);
}
header->code = Code();
header->id = ID();
uint16 length = 0;
ppp_configure_item *item;
for (int32 index = 0; index < CountItems(); index++) {
item = ItemAt(index);
// make sure we have enough space left
if (MRU - length < item->length) {
m_freem(packet);
gBufferModule->free(buffer);
return NULL;
}
memcpy(header->data + length, item, item->length);
length += item->length;
}
length += 4;
header->length = htons(length);
packet->m_pkthdr.len = packet->m_len = length;
return packet;
status = gBufferModule->trim(buffer, length);
if (status < B_OK) {
dprintf("%s::%s: gBufferModule->trim\n", __FILE__, __func__);
gBufferModule->free(buffer);
return(NULL);
}
return buffer;
}
@@ -5,7 +5,7 @@
/*! \class KPPPDevice
\brief Represents a device at the lowest level of the communcation stack.
A device may be, for example: Modem, PPPoE, PPTP. \n
It encapsulates the packet and sends it over a line to the other end.
The device is the first layer that receives a packet.
@@ -14,13 +14,12 @@
#include <KPPPDevice.h>
#include <net/if.h>
#include <core_funcs.h>
#include <PPPControl.h>
/*! \brief Initializes the device.
\param name The device's type name (e.g.: PPPoE).
\param overhead Length of the header that is prepended to each packet.
\param interface Owning interface.
@@ -46,12 +45,13 @@ KPPPDevice::~KPPPDevice()
/*! \brief Allows private extensions.
If you override this method you must call the parent's method for unknown ops.
*/
status_t
KPPPDevice::Control(uint32 op, void *data, size_t length)
{
dprintf("KPPPDevice::Control\n");
switch (op) {
case PPPC_GET_DEVICE_INFO:
{
@@ -89,7 +89,7 @@ KPPPDevice::IsAllowedToSend() const
//! This method is never used.
status_t
KPPPDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
KPPPDevice::Receive(net_buffer *packet, uint16 protocolNumber)
{
// let the interface handle the packet
if (protocolNumber == 0)
@@ -100,10 +100,10 @@ KPPPDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
/*! \brief Report that device is going up.
Called by Up(). \n
From now on, the connection attempt can may be aborted by calling Down().
\return
- \c true: You are allowed to connect.
- \c false: You should abort immediately. Down() will \e not be called!
@@ -112,15 +112,15 @@ bool
KPPPDevice::UpStarted()
{
fConnectionPhase = PPP_ESTABLISHMENT_PHASE;
return Interface().StateMachine().TLSNotify();
}
/*! \brief Report that device is going down.
Called by Down().
\return
- \c true: You are allowed to disconnect.
- \c false: You must not disconnect!
@@ -129,7 +129,7 @@ bool
KPPPDevice::DownStarted()
{
fConnectionPhase = PPP_TERMINATION_PHASE;
return Interface().StateMachine().TLFNotify();
}
@@ -139,7 +139,7 @@ void
KPPPDevice::UpFailedEvent()
{
fConnectionPhase = PPP_DOWN_PHASE;
Interface().StateMachine().UpFailedEvent();
}
@@ -149,7 +149,7 @@ void
KPPPDevice::UpEvent()
{
fConnectionPhase = PPP_ESTABLISHED_PHASE;
Interface().StateMachine().UpEvent();
}
@@ -159,6 +159,6 @@ void
KPPPDevice::DownEvent()
{
fConnectionPhase = PPP_DOWN_PHASE;
Interface().StateMachine().DownEvent();
}
File diff suppressed because it is too large Load Diff
@@ -5,7 +5,7 @@
/*! \class KPPPLCP
\brief The LCP protocol.
Every PPP interface \e must have an LCP protocol. It is used for establishing
and terminating connections. \n
When establishing a connecition the LCP protocol determines connection-specific
@@ -20,9 +20,12 @@
#include <KPPPOptionHandler.h>
#include <netinet/in.h>
#include <core_funcs.h>
#include <net_buffer.h>
#include <sys/socket.h>
extern net_buffer_module_info *gBufferModule;
//! Creates a new LCP protocol for the given interface.
KPPPLCP::KPPPLCP(KPPPInterface& interface)
@@ -48,7 +51,7 @@ KPPPLCP::~KPPPLCP()
/*! \brief Adds a new option handler.
NOTE: You can only add option handlers in \c PPP_DOWN_PHASE. \n
There may only be one handler per option type!
*/
@@ -57,19 +60,19 @@ KPPPLCP::AddOptionHandler(KPPPOptionHandler *optionHandler)
{
if (!optionHandler || &optionHandler->Interface() != &Interface())
return false;
if (Interface().Phase() != PPP_DOWN_PHASE
|| OptionHandlerFor(optionHandler->Type()))
return false;
// a running connection may not change and there may only be
// one handler per option type
return fOptionHandlers.AddItem(optionHandler);
}
/*! \brief Removes an option handler, but does not delete it.
NOTE: You can only remove option handlers in \c PPP_DOWN_PHASE.
*/
bool
@@ -78,7 +81,7 @@ KPPPLCP::RemoveOptionHandler(KPPPOptionHandler *optionHandler)
if (Interface().Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
return fOptionHandlers.RemoveItem(optionHandler);
}
@@ -87,11 +90,12 @@ KPPPLCP::RemoveOptionHandler(KPPPOptionHandler *optionHandler)
KPPPOptionHandler*
KPPPLCP::OptionHandlerAt(int32 index) const
{
dprintf("total optionhandler count %ld\n", CountOptionHandlers());
KPPPOptionHandler *optionHandler = fOptionHandlers.ItemAt(index);
if (optionHandler == fOptionHandlers.GetDefaultItem())
return NULL;
return optionHandler;
}
@@ -103,14 +107,14 @@ KPPPLCP::OptionHandlerFor(uint8 type, int32 *start) const
// The iteration style in this method is strange C/C++.
// Explanation: I use this style because it makes extending all XXXFor
// methods simpler as that they look very similar, now.
int32 index = start ? *start : 0;
if (index < 0)
return NULL;
KPPPOptionHandler *current = OptionHandlerAt(index);
for (; current; current = OptionHandlerAt(++index)) {
if (current->Type() == type) {
if (start)
@@ -118,13 +122,13 @@ KPPPLCP::OptionHandlerFor(uint8 type, int32 *start) const
return current;
}
}
return NULL;
}
/*! \brief Adds a new LCP extension.
NOTE: You can only add LCP extensions in \c PPP_DOWN_PHASE.
*/
bool
@@ -132,17 +136,17 @@ KPPPLCP::AddLCPExtension(KPPPLCPExtension *lcpExtension)
{
if (!lcpExtension || &lcpExtension->Interface() != &Interface())
return false;
if (Interface().Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
return fLCPExtensions.AddItem(lcpExtension);
}
/*! \brief Removes an LCP extension, but does not delete it.
NOTE: You can only remove LCP extensions in \c PPP_DOWN_PHASE.
*/
bool
@@ -151,7 +155,7 @@ KPPPLCP::RemoveLCPExtension(KPPPLCPExtension *lcpExtension)
if (Interface().Phase() != PPP_DOWN_PHASE)
return false;
// a running connection may not change
return fLCPExtensions.RemoveItem(lcpExtension);
}
@@ -160,11 +164,12 @@ KPPPLCP::RemoveLCPExtension(KPPPLCPExtension *lcpExtension)
KPPPLCPExtension*
KPPPLCP::LCPExtensionAt(int32 index) const
{
dprintf("LCPExtension count %ld\n", CountLCPExtensions());
KPPPLCPExtension *lcpExtension = fLCPExtensions.ItemAt(index);
if (lcpExtension == fLCPExtensions.GetDefaultItem())
return NULL;
return lcpExtension;
}
@@ -176,14 +181,14 @@ KPPPLCP::LCPExtensionFor(uint8 code, int32 *start) const
// The iteration style in this method is strange C/C++.
// Explanation: I use this style because it makes extending all XXXFor
// methods simpler as that they look very similar, now.
int32 index = start ? *start : 0;
if (index < 0)
return NULL;
KPPPLCPExtension *current = LCPExtensionAt(index);
for (; current; current = LCPExtensionAt(++index)) {
if (current->Code() == code) {
if (start)
@@ -191,27 +196,11 @@ KPPPLCP::LCPExtensionFor(uint8 code, int32 *start) const
return current;
}
}
return NULL;
}
//! Returns the interface, target, and device overhead.
uint32
KPPPLCP::AdditionalOverhead() const
{
uint32 overhead = Interface().Overhead();
if (Target())
overhead += Target()->Overhead();
if (Interface().Device())
overhead += Interface().Device()->Overhead();
return overhead;
}
//! Always returns \c true.
bool
KPPPLCP::Up()
@@ -230,7 +219,7 @@ KPPPLCP::Down()
//! Sends a packet to the target (if there is one) or to the interface.
status_t
KPPPLCP::Send(struct mbuf *packet, uint16 protocolNumber)
KPPPLCP::Send(net_buffer *packet, uint16 protocolNumber)
{
if (Target())
return Target()->Send(packet, PPP_LCP_PROTOCOL);
@@ -241,39 +230,32 @@ KPPPLCP::Send(struct mbuf *packet, uint16 protocolNumber)
//! Decodes the LCP packet and passes it to the KPPPStateMachine or an LCP extension.
status_t
KPPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber)
KPPPLCP::Receive(net_buffer *packet, uint16 protocolNumber)
{
if (!packet)
return B_ERROR;
if (protocolNumber != PPP_LCP_PROTOCOL) {
ERROR("KPPPLCP::Receive(): wrong protocol number!\n");
return PPP_UNHANDLED;
}
ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*);
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return bufferHeader.Status();
ppp_lcp_packet &data = bufferHeader.Data();
// 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);
struct mbuf *copy = m_gethdr(MT_DATA);
if (copy) {
copy->m_data += AdditionalOverhead();
copy->m_pkthdr.len = copy->m_len = packet->m_len;
memcpy(copy->m_data, packet->m_data, copy->m_len);
}
if (ntohs(data->length) < 4)
net_buffer *copy = gBufferModule->duplicate(packet);
if (ntohs(data.length) < 4)
return B_ERROR;
bool handled = true;
switch (data->code) {
switch (data.code) {
case PPP_CONFIGURE_REQUEST:
StateMachine().RCREvent(packet);
break;
@@ -310,43 +292,43 @@ KPPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber)
break;
default:
m_freem(packet);
// gBufferModule->free(packet);
handled = false;
}
packet = copy;
if (!packet)
return handled ? B_OK : B_ERROR;
status_t result = B_OK;
// Try to find LCP extensions that can handle this code.
// We must duplicate the packet in order to ask all handlers.
int32 index = 0;
KPPPLCPExtension *lcpExtension = LCPExtensionFor(data->code, &index);
for (; lcpExtension; lcpExtension = LCPExtensionFor(data->code, &(++index))) {
KPPPLCPExtension *lcpExtension = LCPExtensionFor(data.code, &index);
for (; lcpExtension; lcpExtension = LCPExtensionFor(data.code, &(++index))) {
if (!lcpExtension->IsEnabled())
continue;
result = lcpExtension->Receive(packet, data->code);
result = lcpExtension->Receive(packet, data.code);
// check return value and return it on error
if (result == B_OK)
handled = true;
else if (result != PPP_UNHANDLED) {
m_freem(packet);
gBufferModule->free(packet);
return result;
}
}
if (!handled) {
StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT);
return PPP_REJECTED;
}
m_freem(packet);
gBufferModule->free(packet);
return result;
}
@@ -356,7 +338,7 @@ void
KPPPLCP::Pulse()
{
StateMachine().TimerEvent();
for (int32 index = 0; index < CountLCPExtensions(); index++)
LCPExtensionAt(index)->Pulse();
}
@@ -58,6 +58,7 @@ KPPPLCPExtension::InitCheck() const
status_t
KPPPLCPExtension::Control(uint32 op, void *data, size_t length)
{
dprintf("KPPPLCPExtension::Control\n");
switch (op) {
case PPPC_GET_SIMPLE_HANDLER_INFO:
{
@@ -5,7 +5,7 @@
/*! \class KPPPLayer
\brief An abstract layer that can encapsulate/send and receive packets.
All packet handlers should derive from this class. It does not define a protocol
number like KPPPProtocol does. It only has a header overhead and an encapsulation
level that is used to determine the order at which the packets get encapsulated
@@ -19,13 +19,15 @@
#include <KPPPLayer.h>
#include <net_buffer.h>
#include <cstdlib>
#include <cstring>
#include <core_funcs.h>
extern net_buffer_module_info *gBufferModule;
/*! \brief Creates a new layer.
If an error occurs in the constructor you should set \c fInitStatus.
*/
KPPPLayer::KPPPLayer(const char *name, ppp_level level, uint32 overhead)
@@ -56,11 +58,11 @@ KPPPLayer::InitCheck() const
//! Sends a packet to the next layer in the chain.
status_t
KPPPLayer::SendToNext(struct mbuf *packet, uint16 protocolNumber) const
KPPPLayer::SendToNext(net_buffer *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()) {
@@ -70,14 +72,14 @@ KPPPLayer::SendToNext(struct mbuf *packet, uint16 protocolNumber) const
return Next()->SendToNext(packet, protocolNumber);
} else {
ERROR("KPPPLayer: SendToNext() failed because there is no next handler!\n");
m_freem(packet);
gBufferModule->free(packet);
return B_ERROR;
}
}
/*! \brief You may override this for periodic tasks.
This method gets called every \c PPP_PULSE_RATE microseconds.
*/
void
@@ -92,7 +94,7 @@ void
KPPPLayer::SetName(const char *name)
{
free(fName);
if (name)
fName = strdup(name);
else
@@ -60,6 +60,7 @@ KPPPOptionHandler::InitCheck() const
status_t
KPPPOptionHandler::Control(uint32 op, void *data, size_t length)
{
dprintf("KPPPOptionHandler::Control\n");
switch (op) {
case PPPC_GET_SIMPLE_HANDLER_INFO:
{
@@ -9,7 +9,9 @@
#include <KPPPReportManager.h>
#include <LockerHelper.h>
#include <lock.h>
#include <util/AutoLock.h>
#include <KPPPUtils.h>
@@ -30,10 +32,10 @@ report_sender_thread(void *data)
/*! \brief Constructor.
\param lock The BLocker that should be used by this report manager.
*/
KPPPReportManager::KPPPReportManager(BLocker& lock)
KPPPReportManager::KPPPReportManager(mutex& lock)
: fLock(lock)
{
}
@@ -48,10 +50,10 @@ KPPPReportManager::~KPPPReportManager()
/*! \brief Send the given report message to the given thread.
\param thread The report receiver.
\param report The report message.
\return \c false on error.
*/
bool
@@ -59,7 +61,7 @@ KPPPReportManager::SendReport(thread_id thread, const ppp_report_packet *report)
{
if (!report)
return false;
if (thread == find_thread(NULL)) {
report_sender_info *info = new report_sender_info;
info->thread = thread;
@@ -68,7 +70,7 @@ KPPPReportManager::SendReport(thread_id thread, const ppp_report_packet *report)
B_NORMAL_PRIORITY, info));
return true;
}
send_data_with_timeout(thread, PPP_REPORT_CODE, &report, sizeof(report),
PPP_REPORT_TIMEOUT);
return true;
@@ -76,7 +78,7 @@ KPPPReportManager::SendReport(thread_id thread, const ppp_report_packet *report)
/*! \brief Requests report messages of a given \a type.
\param type The type of report.
\param thread The receiver thread.
\param flags Optional report flags. See \c ppp_report_flags for more information.
@@ -87,14 +89,14 @@ KPPPReportManager::EnableReports(ppp_report_type type, thread_id thread,
{
if (thread < 0 || type == PPP_ALL_REPORTS)
return;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
ppp_report_request *request = new ppp_report_request;
request->type = type;
request->thread = thread;
request->flags = flags;
fReportRequests.AddItem(request);
}
@@ -105,21 +107,21 @@ KPPPReportManager::DisableReports(ppp_report_type type, thread_id thread)
{
if (thread < 0)
return;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
ppp_report_request *request;
for (int32 i = 0; i < fReportRequests.CountItems(); i++) {
request = fReportRequests.ItemAt(i);
if (request->thread != thread)
continue;
if (request->type == type || type == PPP_ALL_REPORTS)
fReportRequests.RemoveItem(request);
}
// empty message queue
while (has_data(thread)) {
thread_id sender;
@@ -134,32 +136,32 @@ KPPPReportManager::DoesReport(ppp_report_type type, thread_id thread)
{
if (thread < 0)
return false;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
ppp_report_request *request;
for (int32 i = 0; i < fReportRequests.CountItems(); i++) {
request = fReportRequests.ItemAt(i);
if (request->thread == thread && request->type == type)
return true;
}
return false;
}
/*! \brief Send out report messages to all requestors.
You may append additional data to the report messages. The data length may not be
greater than \c PPP_REPORT_DATA_LIMIT.
\param type The report type.
\param code The report code belonging to the report type.
\param data Additional data.
\param length Length of the data.
\return \c false on error.
*/
bool
@@ -167,44 +169,44 @@ KPPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 le
{
TRACE("KPPPReportManager: Report(type=%d code=%ld length=%ld) to %ld receivers\n",
type, code, length, fReportRequests.CountItems());
if (length > PPP_REPORT_DATA_LIMIT)
return false;
if (fReportRequests.CountItems() == 0)
return true;
if (!data)
length = 0;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
status_t result;
thread_id me = find_thread(NULL);
ppp_report_packet report;
report.type = type;
report.code = code;
report.length = length;
memcpy(report.data, data, length);
ppp_report_request *request;
for (int32 index = 0; index < fReportRequests.CountItems(); index++) {
request = fReportRequests.ItemAt(index);
// do not send to yourself
if (request->thread == me)
continue;
result = send_data_with_timeout(request->thread, PPP_REPORT_CODE, &report,
sizeof(report), PPP_REPORT_TIMEOUT);
#if DEBUG
if (result == B_TIMED_OUT)
TRACE("KPPPReportManager::Report(): timed out sending\n");
#endif
if (result == B_BAD_THREAD_ID || result == B_NO_MEMORY
|| request->flags & PPP_REMOVE_AFTER_REPORT) {
fReportRequests.RemoveItem(request);
@@ -212,6 +214,6 @@ KPPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 le
continue;
}
}
return true;
}
File diff suppressed because it is too large Load Diff
@@ -7,8 +7,7 @@
#define _K_PPP_CONFIGURE_PACKET__H
#include <TemplateList.h>
struct mbuf;
#include <net_buffer.h>
//! An abstract configure item.
typedef struct ppp_configure_item {
@@ -29,7 +28,7 @@ class KPPPConfigurePacket {
public:
KPPPConfigurePacket(uint8 code);
KPPPConfigurePacket(struct mbuf *packet);
KPPPConfigurePacket(net_buffer *packet);
~KPPPConfigurePacket();
bool SetCode(uint8 code);
@@ -52,8 +51,8 @@ class KPPPConfigurePacket {
ppp_configure_item *ItemAt(int32 index) const;
ppp_configure_item *ItemWithType(uint8 type) const;
struct mbuf *ToMbuf(uint32 MRU, uint32 reserve = 0);
// the user is responsible for freeing the mbuf
net_buffer *ToNetBuffer(uint32 MRU);
// the user is responsible for freeing the net_buffer
private:
uint8 fCode, fID;
@@ -9,6 +9,8 @@
#include <KPPPDefs.h>
#include <KPPPLayer.h>
#include <net_buffer.h>
#ifndef _K_PPP_INTERFACE__H
#include <KPPPInterface.h>
#endif
@@ -96,8 +98,8 @@ class KPPPDevice : public KPPPLayer {
This should enqueue the packet and return immediately (never block).
The device is responsible for freeing the packet by calling \c m_freem().
*/
virtual status_t Send(struct mbuf *packet, uint16 protocolNumber) = 0;
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber);
virtual status_t Send(net_buffer *packet, uint16 protocolNumber) = 0;
virtual status_t Receive(net_buffer *packet, uint16 protocolNumber);
protected:
//! Use this to set the device's maximum transfer unit (in bytes).
@@ -30,6 +30,12 @@
#include <TemplateList.h>
#include <net_buffer.h>
#include <net_device.h>
#include <lock.h>
#include <util/AutoLock.h>
class KPPPDevice;
class KPPPProtocol;
class KPPPOptionHandler;
@@ -48,6 +54,8 @@ class KPPPInterface : public KPPPLayer {
KPPPInterface(const KPPPInterface& copy);
KPPPInterface& operator= (const KPPPInterface& copy);
public:
// we should set to private after finishing test
// only PPPManager may construct us!
KPPPInterface(const char *name, ppp_interface_entry *entry,
ppp_interface_id ID, const driver_settings *settings,
@@ -75,8 +83,8 @@ class KPPPInterface : public KPPPLayer {
{ return fLCP; }
//! Returns the interfac's ifnet structure that is exported to the netstack.
struct ifnet *Ifnet() const
{ return fIfnet; }
net_device *Ifnet() const
{ return fIfnet; }
const char *Username() const;
const char *Password() const;
@@ -220,11 +228,11 @@ class KPPPInterface : public KPPPLayer {
virtual bool IsAllowedToSend() const;
// always returns true
virtual status_t Send(struct mbuf *packet, uint16 protocolNumber);
virtual status_t Send(net_buffer *packet, uint16 protocolNumber);
// sends the packet to the next handler (normally the device)
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber);
virtual status_t Receive(net_buffer *packet, uint16 protocolNumber);
status_t ReceiveFromDevice(struct mbuf *packet);
status_t ReceiveFromDevice(net_buffer *packet);
// This must not block KPPPDevice::Send()!
void Pulse();
@@ -255,7 +263,7 @@ class KPPPInterface : public KPPPLayer {
ppp_interface_id fID;
// the manager assigns an ID to every interface
driver_settings *fSettings;
struct ifnet *fIfnet;
net_device *fIfnet;
char *fUsername, *fPassword;
@@ -288,7 +296,7 @@ class KPPPInterface : public KPPPLayer {
KPPPStateMachine fStateMachine;
KPPPLCP fLCP;
KPPPReportManager fReportManager;
BLocker& fLock;
mutex& fLock;
int32 fDeleteCounter;
};
@@ -20,6 +20,9 @@
#include <KPPPStateMachine.h>
#endif
#include <net_buffer.h>
#include <NetBufferUtilities.h>
class KPPPLCPExtension;
class KPPPOptionHandler;
@@ -79,15 +82,12 @@ class KPPPLCP : public KPPPProtocol {
KPPPProtocol *Target() const
{ return fTarget; }
uint32 AdditionalOverhead() const;
// the overhead caused by the target, the device, and the interface
virtual bool Up();
virtual bool Down();
virtual status_t Send(struct mbuf *packet,
virtual status_t Send(net_buffer *packet,
uint16 protocolNumber = PPP_LCP_PROTOCOL);
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber);
virtual status_t Receive(net_buffer *packet, uint16 protocolNumber);
virtual void Pulse();
@@ -51,7 +51,7 @@ class KPPPLCPExtension {
// called by netstack (forwarded by KPPPInterface)
//! Must be overridden. Called when an LCP packet with your code is received.
virtual status_t Receive(struct mbuf *packet, uint8 code) = 0;
virtual status_t Receive(net_buffer *packet, uint8 code) = 0;
virtual void Reset();
virtual void Pulse();
@@ -8,6 +8,7 @@
#include <KPPPDefs.h>
#include <net_buffer.h>
class KPPPLayer {
protected:
@@ -48,11 +49,11 @@ class KPPPLayer {
virtual bool IsAllowedToSend() const = 0;
//! Send a packet with the given protocol number.
virtual status_t Send(struct mbuf *packet, uint16 protocolNumber) = 0;
virtual status_t Send(net_buffer *packet, uint16 protocolNumber) = 0;
//! Receive a packet with the given protocol number.
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber) = 0;
virtual status_t Receive(net_buffer *packet, uint16 protocolNumber) = 0;
status_t SendToNext(struct mbuf *packet, uint16 protocolNumber) const;
status_t SendToNext(net_buffer *packet, uint16 protocolNumber) const;
// send the packet to the next layer
virtual void Pulse();
@@ -6,12 +6,12 @@
#ifndef _K_PPP_MANAGER__H
#define _K_PPP_MANAGER__H
#include "net_module.h"
#include <module.h>
#include <net_device.h>
#include <PPPControl.h>
#include <PPPReportDefs.h>
#define PPP_INTERFACE_MODULE_NAME NETWORK_MODULES_ROOT "interfaces/ppp"
#define PPP_INTERFACE_MODULE_NAME NETWORK_MODULES_ROOT "/ppp/KPPPManager/v1"
#define PPP_UNDEFINED_INTERFACE_ID 0
// CreateInterface() returns this value on failure
@@ -34,8 +34,7 @@ typedef struct ppp_interface_entry {
deletes them when they are not needed anymore.
*/
typedef struct ppp_interface_module_info {
kernel_net_module_info knminfo;
//!< Exports needed network module functions.
struct module_info info;
ppp_interface_id (*CreateInterface)(const driver_settings *settings,
ppp_interface_id parentID);
@@ -46,7 +45,9 @@ typedef struct ppp_interface_module_info {
bool (*RemoveInterface)(ppp_interface_id ID);
// remove the interface from database (make sure you can delete it yourself!)
ifnet *(*RegisterInterface)(ppp_interface_id ID);
net_device *(*RegisterInterface)(ppp_interface_id ID);
KPPPInterface *(*GetInterface)(ppp_interface_id ID);
// for accessing KPPPInterface directly
bool (*UnregisterInterface)(ppp_interface_id ID);
status_t (*ControlInterface)(ppp_interface_id ID, uint32 op, void *data,
@@ -105,9 +105,9 @@ class KPPPProtocol : public KPPPLayer {
virtual bool IsAllowedToSend() const;
//! Encapsulate the packet with the given protocol number.
virtual status_t Send(struct mbuf *packet, uint16 protocolNumber) = 0;
virtual status_t Send(net_buffer *packet, uint16 protocolNumber) = 0;
//! Receive a packet with the given protocol number.
virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber) = 0;
virtual status_t Receive(net_buffer *packet, uint16 protocolNumber) = 0;
protected:
//! \brief Requests Up() to be called.
@@ -13,10 +13,13 @@
#include <TemplateList.h>
#include <lock.h>
#include <util/AutoLock.h>
class KPPPReportManager {
public:
KPPPReportManager(BLocker& lock);
KPPPReportManager(mutex& lock);
~KPPPReportManager();
static bool SendReport(thread_id thread, const ppp_report_packet *report);
@@ -30,7 +33,7 @@ class KPPPReportManager {
// returns false if reply was bad (or an error occured)
private:
BLocker& fLock;
mutex& fLock;
TemplateList<ppp_report_request*> fReportRequests;
};
@@ -14,7 +14,8 @@ class KPPPProtocol;
#include <KPPPInterface.h>
#endif
#include <Locker.h>
#include <lock.h>
#include <util/AutoLock.h>
class PPPManager;
class KPPPInterface;
@@ -30,7 +31,7 @@ class KPPPStateMachine {
// may only be constructed/destructed by KPPPInterface
KPPPStateMachine(KPPPInterface& interface);
~KPPPStateMachine();
// copies are not allowed!
KPPPStateMachine(const KPPPStateMachine& copy);
KPPPStateMachine& operator= (const KPPPStateMachine& copy);
@@ -42,28 +43,28 @@ class KPPPStateMachine {
//! Returns the LCP protocol object belonging to this state machine.
KPPPLCP& LCP() const
{ return fLCP; }
//! Returns the current state as defined in RFC 1661.
ppp_state State() const
{ return fState; }
//! Returns the internal phase.
ppp_phase Phase() const
{ return fPhase; }
uint8 NextID();
//! Sets our packets' magic number. Used by Link-Quality-Monitoring.
void SetMagicNumber(uint32 magicNumber)
{ fMagicNumber = magicNumber; }
//! Returns our packets' magic number.
uint32 MagicNumber() const
{ return fMagicNumber; }
// public actions
bool Reconfigure();
bool SendEchoRequest();
bool SendDiscardRequest();
// public events:
// NOTE: Local/PeerAuthenticationAccepted/Denied MUST be called before
// Up(Failed)/DownEvent in order to allow changing the configuration of
@@ -77,7 +78,7 @@ class KPPPStateMachine {
//! Returns our local authentication status.
ppp_authentication_status LocalAuthenticationStatus() const
{ return fLocalAuthenticationStatus; }
void PeerAuthenticationRequested();
void PeerAuthenticationAccepted(const char *name);
void PeerAuthenticationDenied(const char *name);
@@ -87,17 +88,17 @@ class KPPPStateMachine {
//! Returns the peer's authentication status.
ppp_authentication_status PeerAuthenticationStatus() const
{ return fPeerAuthenticationStatus; }
// sub-interface events
void UpFailedEvent(KPPPInterface& interface);
void UpEvent(KPPPInterface& interface);
void DownEvent(KPPPInterface& interface);
// protocol events
void UpFailedEvent(KPPPProtocol *protocol);
void UpEvent(KPPPProtocol *protocol);
void DownEvent(KPPPProtocol *protocol);
// device events
bool TLSNotify();
bool TLFNotify();
@@ -109,30 +110,30 @@ class KPPPStateMachine {
// private StateMachine methods
void NewState(ppp_state next);
void NewPhase(ppp_phase next);
// private events
void OpenEvent();
void ContinueOpenEvent();
void CloseEvent();
void TOGoodEvent();
void TOBadEvent();
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, uint16 protocolNumber,
void RCRGoodEvent(net_buffer *packet);
void RCRBadEvent(net_buffer *nak, net_buffer *reject);
void RCAEvent(net_buffer *packet);
void RCNEvent(net_buffer *packet);
void RTREvent(net_buffer *packet);
void RTAEvent(net_buffer *packet);
void RUCEvent(net_buffer *packet, uint16 protocolNumber,
uint8 code = PPP_PROTOCOL_REJECT);
void RXJGoodEvent(struct mbuf *packet);
void RXJBadEvent(struct mbuf *packet);
void RXREvent(struct mbuf *packet);
void RXJGoodEvent(net_buffer *packet);
void RXJBadEvent(net_buffer *packet);
void RXREvent(net_buffer *packet);
// general events (for Good/Bad events)
void TimerEvent();
void RCREvent(struct mbuf *packet);
void RXJEvent(struct mbuf *packet);
void RCREvent(net_buffer *packet);
void RXJEvent(net_buffer *packet);
// actions
void IllegalEvent(ppp_event event);
void ThisLayerUp();
@@ -142,42 +143,42 @@ class KPPPStateMachine {
void InitializeRestartCount();
void ZeroRestartCount();
bool SendConfigureRequest();
bool SendConfigureAck(struct mbuf *packet);
bool SendConfigureNak(struct mbuf *packet);
bool SendConfigureAck(net_buffer *packet);
bool SendConfigureNak(net_buffer *packet);
bool SendTerminateRequest();
bool SendTerminateAck(struct mbuf *request = NULL);
bool SendCodeReject(struct mbuf *packet, uint16 protocolNumber, uint8 code);
bool SendEchoReply(struct mbuf *request);
bool SendTerminateAck(net_buffer *request = NULL);
bool SendCodeReject(net_buffer *packet, uint16 protocolNumber, uint8 code);
bool SendEchoReply(net_buffer *request);
void BringProtocolsUp();
uint32 BringPhaseUp();
void DownProtocols();
void ResetLCPHandlers();
private:
KPPPInterface& fInterface;
KPPPLCP& fLCP;
ppp_state fState;
ppp_phase fPhase;
vint32 fID;
int32 fID;
uint32 fMagicNumber;
int32 fLastConnectionReportCode;
ppp_authentication_status fLocalAuthenticationStatus,
fPeerAuthenticationStatus;
char *fLocalAuthenticationName, *fPeerAuthenticationName;
// 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;
mutex fLock;
};
@@ -11,6 +11,76 @@
#include <PPPDefs.h>
#define IF_NAMESIZE 32
// copied from if.h
struct control_net_module_args {
char ifr_name[IF_NAMESIZE];
const char* name;
uint32 op;
void* data;
size_t length;
// union {
// struct sockaddr ifr_addr;
// struct sockaddr ifr_dstaddr;
// struct sockaddr ifr_broadaddr;
// struct sockaddr ifr_mask;
// struct ifreq_stats ifr_stats;
// struct route_entry ifr_route;
// int ifr_flags;
// int ifr_index;
// int ifr_metric;
// int ifr_mtu;
// int ifr_media;
// int ifr_type;
// int ifr_reqcap;
// int ifr_count;
// uint8_t* ifr_data;
// };
};
// copied from libppp
enum {
// Paranoia mode: be far away of B_DEVICE_OP_CODES_END opcodes!!!
// You never know what another device driver ioctl() will do
// if think our NET_STACK_* is in fact his DO_RISKY_BUSINESS opcode, or whatever...
NET_IOCTL_BASE = 0xbe230000,
NET_STACK_IOCTL_BASE = NET_IOCTL_BASE + 0x200
};
enum {
NET_STACK_SOCKET = NET_STACK_IOCTL_BASE, // socket_args *
NET_STACK_BIND, // sockaddr_args *
NET_STACK_RECVFROM, // struct msghdr *
NET_STACK_RECV, // transfer_args *
NET_STACK_SENDTO, // struct msghdr *
NET_STACK_SEND, // transfer_args *
NET_STACK_LISTEN, // int_args * (value = backlog)
NET_STACK_ACCEPT, // sockaddr_args *
NET_STACK_CONNECT, // sockaddr_args *
NET_STACK_SHUTDOWN, // int_args * (value = how)
NET_STACK_GETSOCKOPT, // sockopt_args *
NET_STACK_SETSOCKOPT, // sockopt_args *
NET_STACK_GETSOCKNAME, // sockaddr_args *
NET_STACK_GETPEERNAME, // sockaddr_args *
NET_STACK_SYSCTL, // sysctl_args *
NET_STACK_SELECT, // select_args *
NET_STACK_DESELECT, // select_args *
NET_STACK_GET_COOKIE, // void **
NET_STACK_STOP,
NET_STACK_NOTIFY_SOCKET_EVENT, // notify_socket_event_args * (userland stack only)
NET_STACK_CONTROL_NET_MODULE,
NET_STACK_IOCTL_MAX
};
// various constants
#define PPP_HANDLER_NAME_LENGTH_LIMIT 63
// if the name is longer than this value it will be truncated to fit the structure
@@ -10,8 +10,6 @@
#include <directories.h>
#include "net_module.h"
typedef uint32 ppp_interface_id;
@@ -37,7 +35,8 @@ typedef uint32 ppp_interface_id;
#define PPP_SERVER_MODE_VALUE "Server"
// path defines
#define PPP_MODULES_PATH NETWORK_MODULES_ROOT "ppp"
#define NETWORK_MODULES_ROOT "network"
#define PPP_MODULES_PATH NETWORK_MODULES_ROOT "/ppp"
#define PTP_INTERFACE_SETTINGS_PATH \
kUserSettingsDirectory "/kernel/drivers/ptpnet"
// TODO: should be: /etc/ptpnet
@@ -0,0 +1,18 @@
#ifndef __PPP_DEV_H
#define __PPP_DEV_H
#include <net_device.h>
#include <net_stack.h>
#include <KPPPInterface.h>
#include <lock.h>
#include <util/AutoLock.h>
#include <util/DoublyLinkedList.h>
struct ppp_device : net_device, DoublyLinkedListLinkImpl<ppp_device> {
KPPPInterface * KPPP_Interface;
uint32 frame_size;
net_fifo ppp_fifo;
};
#endif
@@ -10,6 +10,7 @@ if $(TARGET_PLATFORM) != haiku {
# Unfortunately we get more than we want, namely all POSIX headers.
}
UsePrivateKernelHeaders ;
UsePrivateHeaders net ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libppp
headers ] : true ;
@@ -19,18 +20,18 @@ UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
StaticLibrary libppp.a :
strlcat.c
driver_settings.c
driver_settings.cpp
settings_tools.cpp
KPPPUtils.cpp
_libppputils.cpp
PPPInterface.cpp
PPPInterfaceListener.cpp
PPPManager.cpp
MessageDriverSettingsUtils.cpp
: libnetwork.so libbnetapi.so
;
SEARCH on [ FGristFiles strlcat.c ] = [ FDirName $(HAIKU_TOP) src system libroot posix string ] ;
SEARCH on [ FGristFiles driver_settings.c ] = [ FDirName $(HAIKU_TOP) src system libroot os ] ;
SEARCH on [ FGristFiles driver_settings.cpp ] = [ FDirName $(HAIKU_TOP) src system libroot os ] ;
SEARCH on [ FGristFiles settings_tools.cpp ] = [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libkernelppp ] ;
SEARCH on [ FGristFiles KPPPUtils.cpp ] = [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libkernelppp ] ;
@@ -13,13 +13,20 @@
#include "PPPInterface.h"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <unistd.h>
#include "_libppputils.h"
#include <Path.h>
#include <Directory.h>
#include <Entry.h>
#include <net/if.h>
#include <NetworkDevice.h>
#include <NetworkInterface.h>
/*! \brief Sets the interface to \a ID.
@@ -27,7 +34,9 @@
*/
PPPInterface::PPPInterface(ppp_interface_id ID)
{
fFD = open(get_stack_driver_path(), O_RDWR);
// printf("direct constructor\n");
int family = AF_INET;
fFD = socket(family, SOCK_DGRAM, 0);
SetTo(ID);
}
@@ -36,7 +45,10 @@ PPPInterface::PPPInterface(ppp_interface_id ID)
//! Copy constructor.
PPPInterface::PPPInterface(const PPPInterface& copy)
{
fFD = open(get_stack_driver_path(), O_RDWR);
// printf("Copy constructor\n");
// fFD = open(get_stack_driver_path(), O_RDWR);
int family = AF_INET;
fFD = socket(family, SOCK_DGRAM, 0);
SetTo(copy.ID());
}
@@ -45,6 +57,7 @@ PPPInterface::PPPInterface(const PPPInterface& copy)
//! Destructor.
PPPInterface::~PPPInterface()
{
// printf("Destructor\n");
if (fFD >= 0)
close(fFD);
}
@@ -64,6 +77,7 @@ PPPInterface::InitCheck() const
{
if (fFD < 0)
return B_ERROR;
if (fID == PPP_UNDEFINED_INTERFACE_ID)
return B_BAD_INDEX;
@@ -87,19 +101,29 @@ PPPInterface::InitCheck() const
status_t
PPPInterface::SetTo(ppp_interface_id ID)
{
if (fFD < 0)
// printf("Set To %ld begin=============================\n", ID);
if (fFD < 0) {
printf("No fFD\n");
return B_ERROR;
}
fID = ID;
ppp_interface_info_t info;
// printf("SetTo info:%p\n", &info);
if (GetInterfaceInfo(&info)) {
fName = info.info.name;
fID = ID;
// printf("%s fine: name:%s, fID:%ld\n", __func__, info.info.name, fID);
} else {
fName = "";
fID = PPP_UNDEFINED_INTERFACE_ID;
// printf("%s fail: name:%s, fID:%ld\n", __func__, "", fID);
return B_ERROR;
}
// printf("Set To %ld end =============================\n", ID);
return B_OK;
}
@@ -119,23 +143,32 @@ PPPInterface::SetTo(ppp_interface_id ID)
status_t
PPPInterface::Control(uint32 op, void *data, size_t length) const
{
if (InitCheck() != B_OK)
if (InitCheck() != B_OK) {
printf("%s:InitCheck fail\n", __func__);
return InitCheck();
ppp_control_info control;
}
ppp_control_info info;
control_net_module_args args;
sprintf(args.ifr_name, "%s", "ppp1");
args.name = PPP_INTERFACE_MODULE_NAME;
args.op = PPPC_CONTROL_INTERFACE;
args.data = &control;
args.length = sizeof(control);
control.index = ID();
control.op = op;
control.data = data;
control.length = length;
return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args);
args.data = &info;
args.length = sizeof(ppp_control_info);
info.index = ID();
info.op = op;
info.data = data;
info.length = length;
printf("PPPInterface::Control: ppp_control_info %p control_net_module_args %p data %p \n", &info, &args, data);
status_t status = ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args);
if (status != B_OK)
printf("%s:%s: fail\n", __FILE__, __func__);
return status;
}
@@ -143,6 +176,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length) const
bool
PPPInterface::SetUsername(const char *username) const
{
printf("PPPInterface::SetUsername\n");
if (InitCheck() != B_OK || !username)
return false;
@@ -155,6 +189,7 @@ PPPInterface::SetUsername(const char *username) const
bool
PPPInterface::SetPassword(const char *password) const
{
printf("PPPInterface::SetPassword\n");
if (InitCheck() != B_OK || !password)
return false;
@@ -167,6 +202,7 @@ PPPInterface::SetPassword(const char *password) const
bool
PPPInterface::SetAskBeforeConnecting(bool askBeforeConnecting) const
{
printf("PPPInterface::SetAskBeforeConnecting\n");
if (InitCheck() != B_OK)
return false;
@@ -188,6 +224,7 @@ PPPInterface::SetAskBeforeConnecting(bool askBeforeConnecting) const
status_t
PPPInterface::GetSettingsEntry(BEntry *entry) const
{
printf("PPPInterface::GetSettingsEntry\n");
if (InitCheck() != B_OK)
return InitCheck();
else if (!entry || strlen(Name()) == 0)
@@ -205,10 +242,103 @@ PPPInterface::GetSettingsEntry(BEntry *entry) const
bool
PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const
{
// printf("%s info at:%p", __func__, info);
if (InitCheck() != B_OK || !info) {
// printf("InitCheck fail %s info at:%p", __func__, info);
return false;
}
return Control(PPPC_GET_INTERFACE_INFO, info, sizeof(ppp_interface_info_t))
== B_OK;
}
bool
PPPInterface::ControlDevice(ppp_device_info_t *info) const
{
// printf("%s info at:%p", __func__, info);
if (InitCheck() != B_OK || !info)
return false;
return Control(PPPC_GET_INTERFACE_INFO, &info, sizeof(ppp_interface_info_t))
ppp_control_info controlInfo;
controlInfo.op = PPPC_GET_DEVICE_INFO;
controlInfo.index = 0;
controlInfo.data = info;
controlInfo.length = sizeof(ppp_device_info_t);
return Control(PPPC_CONTROL_DEVICE, &controlInfo, sizeof(ppp_control_info))
== B_OK;
}
bool
PPPInterface::ControlOptionHandler(ppp_simple_handler_info_t *info, uint32 handlerindex, uint32 handlerOP) const
{
// printf("%s info at:%p", __func__, info);
if (InitCheck() != B_OK || !info)
return false;
ppp_control_info controlInfo;
controlInfo.index = handlerindex;
controlInfo.op = handlerOP;
controlInfo.data = info;
controlInfo.length = sizeof(ppp_simple_handler_info_t);
return Control(PPPC_CONTROL_OPTION_HANDLER, &controlInfo, sizeof(ppp_control_info))
== B_OK;
}
bool
PPPInterface::ControlChild(void *info, uint32 childindex, uint32 childOP) const
{
// printf("%s info at:%p", __func__, info);
if (InitCheck() != B_OK || !info)
return false;
ppp_control_info controlInfo;
controlInfo.index = childindex;
controlInfo.op = childOP;
controlInfo.data = info;
// controlInfo.length = sizeof(ppp_simple_handler_info_t);
return Control(PPPC_CONTROL_CHILD, &controlInfo, sizeof(ppp_control_info))
== B_OK;
}
bool
PPPInterface::ControlLCPExtension(ppp_simple_handler_info_t *info, uint32 LCPExtensionindex, uint32 LCPExtensionOP) const
{
// printf("%s info at:%p", __func__, info);
if (InitCheck() != B_OK || !info)
return false;
ppp_control_info controlInfo;
controlInfo.index = LCPExtensionindex;
controlInfo.op = LCPExtensionOP;
controlInfo.data = info;
controlInfo.length = sizeof(ppp_simple_handler_info_t);
return Control(PPPC_CONTROL_LCP_EXTENSION, &controlInfo, sizeof(ppp_control_info))
== B_OK;
}
bool
PPPInterface::ControlProtocol(ppp_protocol_info_t *info, uint32 protocolindex, uint32 protocolOP) const
{
// printf("%s info at:%p", __func__, info);
if (InitCheck() != B_OK || !info)
return false;
ppp_control_info controlInfo;
controlInfo.index = protocolindex;
controlInfo.op = protocolOP;
controlInfo.data = info;
controlInfo.length = sizeof(ppp_protocol_info_t);
return Control(PPPC_CONTROL_PROTOCOL, &controlInfo, sizeof(ppp_control_info))
== B_OK;
}
@@ -222,6 +352,7 @@ PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const
bool
PPPInterface::GetStatistics(ppp_statistics *statistics) const
{
printf("PPPInterface::GetStatistics\n");
if (!statistics)
return false;
@@ -233,6 +364,7 @@ PPPInterface::GetStatistics(ppp_statistics *statistics) const
bool
PPPInterface::HasSettings(const driver_settings *settings) const
{
printf("PPPInterface::HasSettings\n");
if (InitCheck() != B_OK || !settings)
return false;
@@ -250,9 +382,24 @@ PPPInterface::Up() const
{
if (InitCheck() != B_OK)
return false;
BNetworkInterface interface(Name());
if (!interface.Exists())
return false;
int32 currentFlags = interface.Flags();
currentFlags |= IFF_UP;
status_t status = interface.SetFlags(currentFlags);
if (status != B_OK)
return false;
return true;
int32 id = ID();
control_net_module_args args;
sprintf(args.ifr_name, "%s", "ppp1");
args.name = PPP_INTERFACE_MODULE_NAME;
args.op = PPPC_BRING_INTERFACE_UP;
args.data = &id;
@@ -268,9 +415,24 @@ PPPInterface::Down() const
{
if (InitCheck() != B_OK)
return false;
BNetworkInterface interface(Name());
if (!interface.Exists())
return false;
int32 currentFlags = interface.Flags();
currentFlags &= ~IFF_UP;
status_t status = interface.SetFlags(currentFlags);
if (status != B_OK)
return false;
return true;
int32 id = ID();
control_net_module_args args;
sprintf(args.ifr_name, "%s", "ppp1");
args.name = PPP_INTERFACE_MODULE_NAME;
args.op = PPPC_BRING_INTERFACE_DOWN;
args.data = &id;
@@ -292,6 +454,7 @@ bool
PPPInterface::EnableReports(ppp_report_type type, thread_id thread,
int32 flags) const
{
printf("PPPInterface::EnableReports\n");
ppp_report_request request;
request.type = type;
request.thread = thread;
@@ -311,6 +474,7 @@ PPPInterface::EnableReports(ppp_report_type type, thread_id thread,
bool
PPPInterface::DisableReports(ppp_report_type type, thread_id thread) const
{
printf("PPPInterface::DisableReports\n");
ppp_report_request request;
request.type = type;
request.thread = thread;
@@ -20,16 +20,49 @@
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <settings_tools.h>
#include <unistd.h>
#include "_libppputils.h"
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <Message.h>
#include <Messenger.h>
#include <NetworkDevice.h>
#include <NetworkInterface.h>
#include <NetworkRoster.h>
#include <NetServer.h>
//! Constructor. Does nothing special.
PPPManager::PPPManager()
{
fFD = open(get_stack_driver_path(), O_RDWR);
// fFD = open(get_stack_driver_path(), O_RDWR);
int family = AF_INET;
fFD = socket(family, SOCK_DGRAM, 0);
// FileDescriptorCloser closer(socket);
// ifaliasreq request;
// strlcpy(request.ifra_name, name, IF_NAMESIZE);
// request.ifra_index = address.Index();
// request.ifra_flags = address.Flags();
// memcpy(&request.ifra_addr, &address.Address().SockAddr(),
// address.Address().Length());
// memcpy(&request.ifra_mask, &address.Mask().SockAddr(),
// address.Mask().Length());
// memcpy(&request.ifra_broadaddr, &address.Broadcast().SockAddr(),
// address.Broadcast().Length());
// if (ioctl(socket, option, &request, sizeof(struct ifaliasreq)) < 0)
// return errno;
}
@@ -133,6 +166,7 @@ PPPManager::Control(uint32 op, void *data, size_t length) const
return B_ERROR;
control_net_module_args args;
sprintf(args.ifr_name, "%s", "ppp1");
args.name = PPP_INTERFACE_MODULE_NAME;
args.op = op;
args.data = data;
@@ -169,6 +203,7 @@ PPPManager::ControlModule(const char *name, uint32 op, void *data,
return B_ERROR;
control_net_module_args args;
sprintf(args.ifr_name, "%s", "ppp1");
args.name = name;
args.op = op;
args.data = data;
@@ -207,13 +242,72 @@ PPPManager::CreateInterface(const driver_settings *settings) const
ppp_interface_id
PPPManager::CreateInterfaceWithName(const char *name) const
{
ppp_interface_description_info info;
info.u.name = name;
ppp_interface_id ID = InterfaceWithName(name);
if (ID != PPP_UNDEFINED_INTERFACE_ID)
return ID;
BNetworkInterface interface(name);
if (!interface.Exists()) {
// the interface does not exist yet, we have to add it first
BNetworkRoster& roster = BNetworkRoster::Default();
status_t status = roster.AddInterface(interface);
if (status != B_OK) {
fprintf(stderr, "PPPManager::CreateInterfaceWithName: Could not add interface: %s\n",
strerror(status));
return PPP_UNDEFINED_INTERFACE_ID;
}
return InterfaceWithName(name);
}
return PPP_UNDEFINED_INTERFACE_ID;
// ppp_interface_description_info info;
// info.u.name = name;
//
// if (Control(PPPC_CREATE_INTERFACE_WITH_NAME, &info, sizeof(info)) != B_OK)
// return PPP_UNDEFINED_INTERFACE_ID;
// else
// return info.interface;
}
/*! It will remove the complete interface with all
of its addresses.
*/
bool
delete_interface(const char* name)
{
BNetworkInterface interface(name);
// Delete interface
BNetworkRoster& roster = BNetworkRoster::Default();
status_t status = roster.RemoveInterface(interface);
if (status != B_OK) {
fprintf(stderr, "delete_interface: Could not delete interface %s\n",
name);
return false;
}
return true;
}
//! Deletes the interface with the given \a name.
bool
PPPManager::DeleteInterface(const char* name) const
{
ppp_interface_id ID = InterfaceWithName(name);
if (ID == PPP_UNDEFINED_INTERFACE_ID)
return false;
return delete_interface(name);
if (Control(PPPC_CREATE_INTERFACE_WITH_NAME, &info, sizeof(info)) != B_OK)
return PPP_UNDEFINED_INTERFACE_ID;
else
return info.interface;
}
@@ -253,18 +347,22 @@ PPPManager::Interfaces(int32 *count,
// loop until we get all interfaces
while (true) {
requestCount = *count = CountInterfaces(filter);
if (*count == -1)
if (*count <= 0) {
printf("No interface, count, first round:%ld\n", *count);
return NULL;
}
requestCount += 10;
// request some more interfaces in case some are added in the mean time
interfaces = new ppp_interface_id[requestCount];
// printf("interfaces addr: %p\n, requestCount: %ld", interfaces, requestCount);
*count = GetInterfaces(interfaces, requestCount, filter);
if (*count == -1) {
if (*count <= 0) {
printf("No interface, count second round:%ld\n", *count);
delete interfaces;
return NULL;
}
if (*count < requestCount)
break;
@@ -345,12 +443,17 @@ PPPManager::InterfaceWithName(const char *name) const
int32 count;
ppp_interface_id *interfaces = Interfaces(&count, PPP_REGISTERED_INTERFACES);
if (!interfaces)
if (!interfaces || count <= 0) {
printf("ERROR: Could not get ppp name:%s\n", name);
return PPP_UNDEFINED_INTERFACE_ID;
}
// printf("first ID:%ld count:%ld\n", interfaces[0], count);
ppp_interface_id id = PPP_UNDEFINED_INTERFACE_ID;
PPPInterface interface;
ppp_interface_info_t info;
// printf("internal info is at: %p\n", &info);
for (int32 index = 0; index < count; index++) {
interface.SetTo(interfaces[index]);
@@ -374,11 +477,79 @@ PPPManager::InterfaceWithName(const char *name) const
}
//! Returns the number of existing interfaces or a negative value on error.
bool
is_ppp_interface(const char* name)
{
// size_t length = strlen(name);
// if (length < 8)
// putchar('\t');
// else
// printf("\n\t");
// get link level interface for this interface
BNetworkInterface interface(name);
BNetworkAddress linkAddress;
status_t status = interface.GetHardwareAddress(linkAddress);
if (status == B_OK) {
// const char *type = "unknown";
switch (linkAddress.LinkLevelType()) {
case IFT_ETHER:
// type = "Ethernet";
// printf("%s\n", type);
break;
case IFT_LOOP:
// type = "Local Loopback";
// printf("%s\n", type);
break;
case IFT_MODEM:
// type = "Modem";
// printf("%s\n", type);
break;
case IFT_PPP:
// type = "PPP";
// printf("%s\n", type);
return true;
break;
default:
// printf("%s\n", type);
;
}
}
return false;
}
//! Returns the number of ppp interfaces
int32
count_ppp_interface(void)
{
int32 count = 0;
// get a list of all ppp interfaces
BNetworkRoster& roster = BNetworkRoster::Default();
BNetworkInterface interface;
uint32 cookie = 0;
while (roster.GetNextInterface(&cookie, interface) == B_OK) {
if (is_ppp_interface(interface.Name()))
count++;
}
return count;
}
//! Returns the number of existing interfaces or a negative value on error.
int32
PPPManager::CountInterfaces(ppp_interface_filter filter) const
{
return Control(PPPC_COUNT_INTERFACES, &filter, sizeof(filter));
// return Control(PPPC_COUNT_INTERFACES, &filter, sizeof(filter));
return count_ppp_interface();
}
@@ -1,24 +0,0 @@
/*
* Copyright 2003-2007, Waldemar Kornewald <wkornew@gmx.net>
* Distributed under the terms of the MIT License.
*/
#include <OS.h>
#include "_libppputils.h"
#include <cstdlib>
#include <cstring>
char*
get_stack_driver_path()
{
char *path;
// user-defined stack driver path?
path = getenv("NET_STACK_DRIVER_PATH");
if (path)
return path;
// use the default stack driver path
return NET_STACK_DRIVER_PATH;
}
@@ -1,15 +0,0 @@
/*
* Copyright 2003-2007, Waldemar Kornewald <wkornew@gmx.net>
* Distributed under the terms of the MIT License.
*/
#ifndef __libppputils__h
#define __libppputils__h
#include <net_stack_driver.h>
char *get_stack_driver_path();
#endif
@@ -39,6 +39,12 @@ class PPPInterface {
bool GetInterfaceInfo(ppp_interface_info_t *info) const;
bool GetStatistics(ppp_statistics *statistics) const;
bool HasSettings(const driver_settings *settings) const;
bool ControlDevice(ppp_device_info_t *info) const;
bool ControlProtocol(ppp_protocol_info_t *info, uint32 protocolindex, uint32 procotolOP) const;
bool ControlOptionHandler(ppp_simple_handler_info_t *info, uint32 handlerindex, uint32 handlerOP) const;
bool ControlLCPExtension(ppp_simple_handler_info_t *info, uint32 LCPExtensionindex, uint32 LCPExtensionOP) const;
bool ControlChild(void *info, uint32 childindex, uint32 childOP) const;
bool Up() const;
bool Down() const;
@@ -6,6 +6,7 @@
#ifndef _PPP_MANAGER__H
#define _PPP_MANAGER__H
#include <Directory.h>
#include <KPPPManager.h>
#include <String.h>
@@ -33,6 +34,7 @@ class PPPManager {
ppp_interface_id CreateInterface(const driver_settings *settings) const;
ppp_interface_id CreateInterfaceWithName(const char *name) const;
bool DeleteInterface(ppp_interface_id ID) const;
bool DeleteInterface(const char* name) const;
ppp_interface_id *Interfaces(int32 *count,
ppp_interface_filter filter = PPP_REGISTERED_INTERFACES) const;
@@ -833,6 +833,9 @@ init_stack()
// TODO: for now!
register_domain_datalink_protocols(AF_INET, IFT_LOOP,
"network/datalink_protocols/loopback_frame/v1", NULL);
// add ppp datalink protocol
register_domain_datalink_protocols(AF_INET, IFT_PPP,
"network/datalink_protocols/ppp_frame/v1", NULL);
register_domain_datalink_protocols(AF_INET6, IFT_LOOP,
"network/datalink_protocols/loopback_frame/v1", NULL);
register_domain_datalink_protocols(AF_INET, IFT_ETHER,
+2 -2
View File
@@ -10,8 +10,8 @@ SubInclude HAIKU_TOP src bin network ftpd ;
SubInclude HAIKU_TOP src bin network ifconfig ;
SubInclude HAIKU_TOP src bin network mount_nfs ;
SubInclude HAIKU_TOP src bin network netstat ;
#SubInclude HAIKU_TOP src bin network pppconfig ;
#SubInclude HAIKU_TOP src bin network ppp_up ;
SubInclude HAIKU_TOP src bin network pppconfig ;
SubInclude HAIKU_TOP src bin network ppp_up ;
SubInclude HAIKU_TOP src bin network ping ;
SubInclude HAIKU_TOP src bin network ping6 ;
SubInclude HAIKU_TOP src bin network route ;
+6 -3
View File
@@ -1,4 +1,4 @@
SubDir HAIKU_TOP src bin ppp_up ;
SubDir HAIKU_TOP src bin network ppp_up ;
SetSubDirSupportedPlatforms $(HAIKU_BONE_COMPATIBLE_PLATFORMS) ;
@@ -8,7 +8,10 @@ if ! $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
# Unfortunately we get more than we want, namely all POSIX headers.
}
UsePrivateHeaders net ;
UsePrivateKernelHeaders ;
UsePrivateHeaders net app libroot shared interface libbe be root tracker textencoding
root ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libppp
headers ] : true ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
@@ -24,7 +27,7 @@ BinCommand ppp_up :
PPPStatusWindow.cpp
PPPUpApplication.cpp
:
libppp.a be
libppp.a be $(TARGET_LIBSUPC++) translation $(HAIKU_LOCALE_LIBS) root $(TARGET_NETWORK_LIBS)
;
# Installation
+2 -1
View File
@@ -6,8 +6,9 @@
#ifndef STATUS_VIEW__H
#define STATUS_VIEW__H
#include <View.h>
#include <Button.h>
#include <PPPInterface.h>
#include <StringView.h>
class PPPStatusView : public BView {
+3 -2
View File
@@ -1,4 +1,4 @@
SubDir HAIKU_TOP src bin pppconfig ;
SubDir HAIKU_TOP src bin network pppconfig ;
SetSubDirSupportedPlatforms $(HAIKU_BONE_COMPATIBLE_PLATFORMS) ;
@@ -8,6 +8,7 @@ if ! $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
# Unfortunately we get more than we want, namely all POSIX headers.
}
UsePrivateKernelHeaders ;
UsePrivateHeaders net ;
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libppp
headers ] : true ;
@@ -17,7 +18,7 @@ UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared
BinCommand pppconfig :
pppconfig.cpp
:
be libppp.a
be libppp.a $(TARGET_LIBSUPC++) $(TARGET_NETWORK_LIBS)
;
# Installation -- in the test directory for the time being
+488 -41
View File
@@ -40,33 +40,35 @@ status_t
show(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES)
{
PPPManager manager;
if(manager.InitCheck() != B_OK) {
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
int32 count;
int32 count = 0;
ppp_interface_id *interfaces = manager.Interfaces(&count, filter);
if(!interfaces) {
if (!interfaces || count <= 0) {
fprintf(stderr, "Error: Could not get interfaces information!\n");
return -1;
}
fprintf(stderr, "Get %ld ppp interfaces, first is %ld!\n", count, interfaces[0]);
ppp_interface_info_t info;
PPPInterface interface;
printf("Listing PPP interfaces:\n");
// print out information for each interface
for(int32 index = 0; index < count; index++) {
for (int32 index = 0; index < count; index++) {
interface.SetTo(interfaces[index]);
if(interface.InitCheck() == B_OK) {
if (interface.InitCheck() == B_OK) {
interface.GetInterfaceInfo(&info);
printf("\n");
// type and unit (if it has one)
if(info.info.if_unit >= 0) {
if (info.info.if_unit >= 0) {
printf("Type: Visible\n");
printf("\tInterface: ppp%ld\n", info.info.if_unit);
} else
@@ -79,9 +81,9 @@ show(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES)
// mode
printf("\tMode: ");
if(info.info.mode == PPP_CLIENT_MODE)
if (info.info.mode == PPP_CLIENT_MODE)
printf("Client\n");
else if(info.info.mode == PPP_SERVER_MODE)
else if (info.info.mode == PPP_SERVER_MODE)
printf("Server\n");
else
printf("Unknown\n");
@@ -118,13 +120,13 @@ status_t
create(const char *name, bool bringUp = true)
{
PPPManager manager;
if(manager.InitCheck() != B_OK) {
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.CreateInterfaceWithName(name));
if(interface.InitCheck() != B_OK) {
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not create interface: %s!\n", name);
return -1;
}
@@ -134,13 +136,13 @@ create(const char *name, bool bringUp = true)
ppp_interface_info_t info;
interface.GetInterfaceInfo(&info);
if(info.info.if_unit >= 0)
if (info.info.if_unit >= 0)
printf("Interface: ppp%ld\n", info.info.if_unit);
else
printf("This interface is hidden! You can delete it by typing:\n"
"pppconfig delete %ld\n", interface.ID());
if(bringUp) {
if (bringUp) {
interface.Up();
printf("Connecting in background...\n");
}
@@ -153,22 +155,22 @@ static
status_t
connect(const char *name)
{
if(!name || strlen(name) == 0)
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if(manager.InitCheck() != B_OK) {
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if(interface.InitCheck() != B_OK) {
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
if(!interface.Up()) {
if (!interface.Up()) {
fprintf(stderr, "Error: Could not connect!\n");
return -1;
}
@@ -181,24 +183,435 @@ connect(const char *name)
static
status_t
disconnect(const char *name)
setuser(const char *name, const char* user)
{
if(!name || strlen(name) == 0)
if (!name || strlen(name) == 0)
return -1;
if (!user || strlen(user) == 0)
return -1;
PPPManager manager;
if(manager.InitCheck() != B_OK) {
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if(interface.InitCheck() != B_OK) {
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
if(!interface.Down()) {
if (!interface.SetUsername(user)) {
fprintf(stderr, "Error: Could not SetUsername %s!\n", user);
return -1;
}
return 0;
}
static
status_t
setpass(const char *name, const char* pass)
{
if (!name || strlen(name) == 0)
return -1;
if (!pass || strlen(pass) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
if (!interface.SetPassword(pass)) {
fprintf(stderr, "Error: Could not SetUsername %s!\n", pass);
return -1;
}
return 0;
}
static
status_t
setaskbeforeconnect(const char *name, const char* connect)
{
if (!name || strlen(name) == 0)
return -1;
bool askBeforeConnecting = false;
if (connect || !strcmp(connect, "true") || !strcmp(connect, "ask") ||
!strcmp(connect, "yes") || !strcmp(connect, "y"))
askBeforeConnecting = true;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
if (!interface.SetAskBeforeConnecting(askBeforeConnecting)) {
fprintf(stderr, "Error: Could not connect %s!\n", connect);
return -1;
}
return 0;
}
static
status_t
getstatistics(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
ppp_statistics pppStatistics;
if (interface.GetStatistics(&pppStatistics) != B_OK) {
fprintf(stderr, "Error: Could not getstatistics: %s!\n", name);
return -1;
}
return 0;
}
static
status_t
hassettings(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
driver_settings settings;
if (interface.HasSettings(&settings) != B_OK) {
fprintf(stderr, "Error: Could not getstatistics: %s!\n", name);
return -1;
}
return 0;
}
static
status_t
enablereports(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
ppp_report_type type = PPP_ALL_REPORTS;
thread_id thread = 0;
int32 flags = 0;
if (interface.EnableReports(type, thread, flags) != true) {
fprintf(stderr, "Error: Could not EnableReports: %s!\n", name);
return -1;
}
return 0;
}
static
status_t
disablereports(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
ppp_report_type type = PPP_ALL_REPORTS;
thread_id thread = 0;
if (interface.DisableReports(type, thread) != true) {
fprintf(stderr, "Error: Could not EnableReports: %s!\n", name);
return -1;
}
return 0;
}
static
status_t
controlchild(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
ppp_simple_handler_info_t info;
if (interface.ControlChild(&info, 0, PPPC_GET_SIMPLE_HANDLER_INFO) != true) {
fprintf(stderr, "Error: Could not PPPC_GET_SIMPLE_HANDLER_INFO: %s!\n", name);
return -1;
}
printf("LCPExtensionHandler: %s\n", info.info.name);
printf("isEnabled: %d\n", info.info.isEnabled);
if (interface.ControlChild(&info, 0, PPPC_ENABLE) != true) {
fprintf(stderr, "Error: Could not PPPC_ENABLE: %s!\n", name);
return -1;
}
return 0;
}
static
status_t
controllcpextension(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
ppp_simple_handler_info_t info;
if (interface.ControlLCPExtension(&info, 1, PPPC_GET_SIMPLE_HANDLER_INFO) != true) {
fprintf(stderr, "Error: Could not PPPC_GET_SIMPLE_HANDLER_INFO: %s!\n", name);
return -1;
}
printf("LCPExtensionHandler: %s\n", info.info.name);
printf("isEnabled: %d\n", info.info.isEnabled);
if (interface.ControlLCPExtension(&info, 1, PPPC_ENABLE) != true) {
fprintf(stderr, "Error: Could not PPPC_ENABLE: %s!\n", name);
return -1;
}
return 0;
}
static
status_t
controloptionhandler(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
ppp_simple_handler_info_t info;
if (interface.ControlOptionHandler(&info, 0, PPPC_GET_SIMPLE_HANDLER_INFO) != true) {
fprintf(stderr, "Error: Could not PPPC_GET_SIMPLE_HANDLER_INFO: %s!\n", name);
return -1;
}
printf("protocol: %s\n", info.info.name);
printf("isEnabled: %d\n", info.info.isEnabled);
if (interface.ControlOptionHandler(&info, 0, PPPC_ENABLE) != true) {
fprintf(stderr, "Error: Could not PPPC_ENABLE: %s!\n", name);
return -1;
}
return 0;
}
static
status_t
controlprotocol(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
ppp_protocol_info_t info;
if (interface.ControlProtocol(&info, 0, PPPC_GET_PROTOCOL_INFO) != true) {
fprintf(stderr, "Error: Could not PPPC_GET_PROTOCOL_INFO: %s!\n", name);
return -1;
}
printf("protocol: %s\n", info.info.name);
printf("type: %s\n", info.info.type);
printf("activationPhase: %d\n", info.info.activationPhase);
printf("addressFamily: %ld\n", info.info.addressFamily);
printf("flags: %ld\n", info.info.flags);
printf("side: %d\n", info.info.side);
printf("level: %d\n", info.info.level);
printf("connectionPhase: %d\n", info.info.connectionPhase);
printf("protocolNumber: %d\n", info.info.protocolNumber);
printf("isEnabled: %d\n", info.info.isEnabled);
printf("isUpRequested: %d\n", info.info.isUpRequested);
if (interface.ControlProtocol(&info, 0, PPPC_ENABLE) != true) {
fprintf(stderr, "Error: Could not PPPC_ENABLE: %s!\n", name);
return -1;
}
return 0;
}
static
status_t
controldevice(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
ppp_device_info_t info;
if (interface.ControlDevice(&info) != true) {
fprintf(stderr, "Error: Could not ControlDevice: %s!\n", name);
return -1;
}
printf("name: %s\n", info.info.name);
printf("MTU: %ld\n", info.info.MTU);
printf("inputTransferRate: %ld\n", info.info.inputTransferRate);
printf("outputTransferRate: %ld\n", info.info.outputTransferRate);
printf("outputBytesCount: %ld\n", info.info.outputBytesCount);
printf("isUp: %d\n", info.info.isUp);
return 0;
}
static
status_t
disconnect(const char *name)
{
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
if (!interface.Down()) {
fprintf(stderr, "Error: Could not disconnect!\n");
return -1;
}
@@ -211,16 +624,16 @@ static
status_t
delete_interface(const char *name)
{
if(!name || strlen(name) == 0)
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if(manager.InitCheck() != B_OK) {
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
if(!manager.DeleteInterface(manager.InterfaceWithName(name))) {
if (!manager.DeleteInterface(name)) {
fprintf(stderr, "Error: Could not delete interface!\n");
return -1;
}
@@ -233,26 +646,33 @@ static
status_t
show_details(const char *name)
{
if(!name || strlen(name) == 0)
if (!name || strlen(name) == 0)
return -1;
PPPManager manager;
if(manager.InitCheck() != B_OK) {
if (manager.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not load interface manager!\n");
return -1;
}
PPPInterface interface(manager.InterfaceWithName(name));
if(interface.InitCheck() != B_OK) {
ppp_interface_id ID = manager.InterfaceWithName(name);
if (ID <= 0) {
fprintf(stderr, "Error: Could not find interface: %s!\n", name);
return -1;
}
PPPInterface interface(ID);
if (interface.InitCheck() != B_OK) {
fprintf(stderr, "Error: Could not find interface ID: %ld!\n", ID);
return -1;
}
ppp_interface_info_t info;
// printf("ppp_interface_info_t addr:%p\n", &info);
interface.GetInterfaceInfo(&info);
// type and name (if it has one)
if(info.info.if_unit >= 0) {
if (info.info.if_unit >= 0) {
printf("Type: Visible\n");
printf("Interface: ppp%ld\n", info.info.if_unit);
} else
@@ -277,9 +697,9 @@ show_details(const char *name)
// mode
printf("Mode: ");
if(info.info.mode == PPP_CLIENT_MODE)
if (info.info.mode == PPP_CLIENT_MODE)
printf("Client\n");
else if(info.info.mode == PPP_SERVER_MODE)
else if (info.info.mode == PPP_SERVER_MODE)
printf("Server\n");
else
printf("Unknown\n");
@@ -310,24 +730,51 @@ show_details(const char *name)
int
main(int argc, char *argv[])
{
if(argc == 2) {
if(!strcmp(argv[1], "show") || !strcmp(argv[1], "-a"))
if (argc == 2) {
if (!strcmp(argv[1], "show") || !strcmp(argv[1], "-a"))
return show(PPP_ALL_INTERFACES);
else
return print_help();
}if(argc == 3) {
if(!strcmp(argv[1], "init"))
}if (argc == 3) {
if (!strcmp(argv[1], "init"))
return create(argv[2], false);
else if(!strcmp(argv[1], "create"))
else if (!strcmp(argv[1], "create"))
return create(argv[2], true);
else if(!strcmp(argv[1], "connect"))
else if (!strcmp(argv[1], "connect"))
return connect(argv[2]);
else if(!strcmp(argv[1], "disconnect"))
else if (!strcmp(argv[1], "disconnect"))
return disconnect(argv[2]);
else if(!strcmp(argv[1], "delete"))
else if (!strcmp(argv[1], "delete"))
return delete_interface(argv[2]);
else if(!strcmp(argv[1], "details"))
else if (!strcmp(argv[1], "details"))
return show_details(argv[2]);
else if (!strcmp(argv[1], "getstatistics"))
return getstatistics(argv[2]);
else if (!strcmp(argv[1], "hassettings"))
return hassettings(argv[2]);
else if (!strcmp(argv[1], "enablereports"))
return enablereports(argv[2]);
else if (!strcmp(argv[1], "disablereports"))
return disablereports(argv[2]);
else if (!strcmp(argv[1], "controldevice"))
return controldevice(argv[2]);
else if (!strcmp(argv[1], "controlprotocol"))
return controlprotocol(argv[2]);
else if (!strcmp(argv[1], "controloptionhandler"))
return controloptionhandler(argv[2]);
else if (!strcmp(argv[1], "controllcpextension"))
return controllcpextension(argv[2]);
else if (!strcmp(argv[1], "controlchild"))
return controlchild(argv[2]);
else
return print_help();
} if (argc == 4) {
if (!strcmp(argv[1], "setuser"))
return setuser(argv[2], argv[3]);
else if (!strcmp(argv[1], "setpass"))
return setpass(argv[2], argv[3]);
else if (!strcmp(argv[1], "setaskbeforeconnect"))
return setaskbeforeconnect(argv[2], argv[3]);
else
return print_help();
} else