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
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 ;
+23 -13
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 [ FStandardOSHeaders ] : true ;
# Needed for the atomic_add64() prototype.
}
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.
}
# for kernel_cpp.h and BLocker
UseHeaders [ FDirName $(HAIKU_TOP) headers cpp ] : true ;
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 ;
+372 -166
View File
@@ -13,11 +13,29 @@
#include <KPPPInterface.h>
#include <settings_tools.h>
#include <PPPoEDevice.h>
#include <cstring>
#include <netinet/in_var.h>
#include <core_funcs.h>
#include <arpa/inet.h>
#include <net_buffer.h>
#include <net_stack.h>
#include <net/route.h>
#include <sys/sockio.h>
// For updating resolv.conf
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define RESOLV_CONF_FILE "/boot/system/settings/network/resolv.conf"
extern net_buffer_module_info *gBufferModule;
static struct net_datalink_module_info *sDatalinkModule;
static struct net_stack_module_info *sStackModule;
#if DEBUG
#include <unistd.h>
@@ -26,7 +44,7 @@ static int sFD;
// the file descriptor for debug output
static char sDigits[] = "0123456789ABCDEF";
void
dump_packet(struct mbuf *packet, const char *direction)
dump_packet(net_buffer *packet, const char *direction)
{
if (!packet)
return;
@@ -87,6 +105,8 @@ IPCP::IPCP(KPPPInterface& interface, driver_parameter *settings)
ParseSideRequests(get_parameter_with_name(IPCP_PEER_SIDE_KEY, Settings()),
PPP_PEER_SIDE);
get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule);
get_module(NET_DATALINK_MODULE_NAME, (module_info **)&sDatalinkModule);
#if DEBUG
sFD = open("/boot/home/ipcpdebug", O_WRONLY | O_CREAT | O_TRUNC);
#endif
@@ -95,6 +115,9 @@ IPCP::IPCP(KPPPInterface& interface, driver_parameter *settings)
IPCP::~IPCP()
{
put_module(NET_DATALINK_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
#if DEBUG
close(sFD);
#endif
@@ -205,7 +228,7 @@ IPCP::Down()
status_t
IPCP::Send(struct mbuf *packet, uint16 protocolNumber)
IPCP::Send(net_buffer *packet, uint16 protocolNumber)
{
TRACE("IPCP: Send(0x%X)\n", protocolNumber);
@@ -220,13 +243,13 @@ IPCP::Send(struct mbuf *packet, uint16 protocolNumber)
ERROR("IPCP: Send() failed because of wrong state or protocol number!\n");
m_freem(packet);
gBufferModule->free(packet);
return B_ERROR;
}
status_t
IPCP::Receive(struct mbuf *packet, uint16 protocolNumber)
IPCP::Receive(net_buffer *packet, uint16 protocolNumber)
{
TRACE("IPCP: Receive(0x%X)\n", protocolNumber);
@@ -239,21 +262,16 @@ IPCP::Receive(struct mbuf *packet, uint16 protocolNumber)
if (protocolNumber != IPCP_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();
// 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)
if (ntohs(data.length) < 4)
return B_ERROR;
// packet is freed by event methods
switch(data->code) {
switch (data.code) {
case PPP_CONFIGURE_REQUEST:
RCREvent(packet);
break;
@@ -290,23 +308,26 @@ IPCP::Receive(struct mbuf *packet, uint16 protocolNumber)
status_t
IPCP::ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber)
IPCP::ReceiveIPPacket(net_buffer *packet, uint16 protocolNumber)
{
if (protocolNumber != IP_PROTOCOL || State() != PPP_OPENED_STATE)
return PPP_UNHANDLED;
// TODO: add VJC support (the packet would be decoded here)
if (gProto[IPPROTO_IP] && gProto[IPPROTO_IP]->pr_input) {
if (packet)
{
#if DEBUG
dump_packet(packet, "incoming");
#endif
Interface().UpdateIdleSince();
gProto[IPPROTO_IP]->pr_input(packet, 0);
TRACE("We got 1 IP packet from %s::%s\n", __FILE__, __func__);
gBufferModule->free(packet);
return B_OK;
} else {
ERROR("IPCP: Error: Could not find input function for IP!\n");
m_freem(packet);
gBufferModule->free(packet);
return B_ERROR;
}
}
@@ -374,6 +395,7 @@ IPCP::ParseSideRequests(const driver_parameter *requests, ppp_side side)
// all values are IP addresses, so parse the address here
if (strcasecmp(requests->parameters[index].values[0], "auto")) {
address = inet_addr(requests->parameters[index].values[0]);
// address = INADDR_ANY;
if (address == INADDR_NONE)
continue;
}
@@ -398,75 +420,155 @@ IPCP::ParseSideRequests(const driver_parameter *requests, ppp_side side)
}
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);
}
status_t
set_interface_address(net_domain* domain, struct ifaliasreq* inreq)
{
size_t size = sizeof(struct ifaliasreq);
return sDatalinkModule->control(domain, B_SOCKET_SET_ALIAS, inreq, &size);
}
void
IPCP::UpdateAddresses()
{
TRACE("%s::%s: entering UpdateAddresses\n", __FILE__, __func__);
RemoveRoutes();
if (State() != PPP_OPENED_STATE && !Interface().DoesConnectOnDemand())
return;
struct in_aliasreq inreq;
struct ifreq ifreqAddress, ifreqDestination;
memset(&inreq, 0, sizeof(struct in_aliasreq));
memset(&ifreqAddress, 0, sizeof(struct ifreq));
memset(&ifreqDestination, 0, sizeof(struct ifreq));
memset(&fGateway, 0, sizeof(struct sockaddr_in));
TRACE("%s::%s: entering ChangeAddress\n", __FILE__, __func__);
if (sDatalinkModule == NULL) {
TRACE("%s::%s: some module not found!\n", __FILE__, __func__);
return;
}
struct sockaddr newAddr = {6, AF_INET, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
struct sockaddr netmask = {6, AF_INET, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
struct sockaddr broadaddr = {6, AF_INET, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
// create local address
inreq.ifra_addr.sin_family = AF_INET;
if (fLocalRequests.address != INADDR_ANY)
inreq.ifra_addr.sin_addr.s_addr = fLocalRequests.address;
else if(fLocalConfiguration.address == INADDR_ANY)
inreq.ifra_addr.sin_addr.s_addr = 0x010F0F0F; // was: INADDR_BROADCAST
else
inreq.ifra_addr.sin_addr.s_addr = fLocalConfiguration.address;
inreq.ifra_addr.sin_len = sizeof(struct sockaddr_in);
memcpy(&ifreqAddress.ifr_addr, &inreq.ifra_addr, sizeof(struct sockaddr_in));
memcpy(newAddr.sa_data + 2, &fLocalRequests.address, sizeof(in_addr_t));
else if (fLocalConfiguration.address == INADDR_ANY) {
in_addr_t inaddrBroadcast = 0x010F0F0F; // was: INADDR_BROADCAST
memcpy(newAddr.sa_data + 2, &inaddrBroadcast, sizeof(in_addr_t));
} else
memcpy(newAddr.sa_data + 2, &fLocalConfiguration.address, sizeof(in_addr_t));
// create destination address
fGateway.sin_family = AF_INET;
if(fPeerRequests.address != INADDR_ANY)
fGateway.sin_addr.s_addr = fPeerRequests.address;
else if(fPeerConfiguration.address == INADDR_ANY)
fGateway.sin_addr.s_addr = 0x020F0F0F; // was: INADDR_BROADCAST
else
fGateway.sin_addr.s_addr = fPeerConfiguration.address;
fGateway.sin_len = sizeof(struct sockaddr_in);
memcpy(&inreq.ifra_dstaddr, &fGateway,
sizeof(struct sockaddr_in));
memcpy(&ifreqDestination.ifr_dstaddr, &inreq.ifra_dstaddr,
sizeof(struct sockaddr_in));
struct ifaliasreq inreq;
memset(&inreq, 0, sizeof(struct ifaliasreq));
memcpy(inreq.ifra_name, Interface().Name(), IF_NAMESIZE);
memcpy(&inreq.ifra_addr, &newAddr, sizeof(struct sockaddr));
memcpy(&inreq.ifra_mask, &netmask, sizeof(struct sockaddr));
memcpy(&inreq.ifra_broadaddr, &broadaddr, sizeof(struct sockaddr));
inreq.ifra_index = -1;
// create a new interface address
// Is it OK when we already have one?
// test case: ifconfig ppp up
// ifconfig ppp down
// ifconfig ppp up
// check if some weird things happen
// create netmask
inreq.ifra_mask.sin_family = AF_INET;
inreq.ifra_mask.sin_addr.s_addr = fLocalRequests.netmask;
inreq.ifra_mask.sin_len = sizeof(struct sockaddr_in);
net_domain* domain = sStackModule->get_domain(AF_INET);
status_t status = set_interface_address(domain, &inreq);
// tell stack to use these values
if(in_control(NULL, SIOCAIFADDR, (caddr_t) &inreq,
Interface().Ifnet()) != B_OK)
ERROR("IPCP: UpdateAddress(): SIOCAIFADDR returned error!\n");
if(in_control(NULL, SIOCSIFADDR, (caddr_t) &ifreqAddress,
Interface().Ifnet()) != B_OK)
ERROR("IPCP: UpdateAddress(): SIOCSIFADDR returned error!\n");
if(in_control(NULL, SIOCSIFDSTADDR, (caddr_t) &ifreqDestination,
Interface().Ifnet()) != B_OK)
ERROR("IPCP: UpdateAddress(): SIOCSIFDSTADDR returned error!\n");
memcpy(&inreq.ifra_addr, &inreq.ifra_mask, sizeof(struct sockaddr_in));
// SIOCISFNETMASK wants the netmask to be in ifra_addr
if(in_control(NULL, SIOCSIFNETMASK, (caddr_t) &inreq,
Interface().Ifnet()) != B_OK)
ERROR("IPCP: UpdateAddress(): SIOCSIFNETMASK returned error!\n");
if (status != B_OK) {
TRACE("%s:%s: set_interface_address Fail!!!!\n", __FILE__, __func__);
return;
}
TRACE("%s:%s: set_interface_address fine\n", __FILE__, __func__);
net_interface* pppInterface = get_interface_by_name(domain, Interface().Name());
if (pppInterface == NULL) {
TRACE("%s::%s: pppInterface not found!\n", __FILE__, __func__);
return;
}
net_interface_address* pppInterfaceAddress = NULL;
while (sDatalinkModule->get_next_interface_address(pppInterface,
&pppInterfaceAddress)) {
if (pppInterfaceAddress->domain->family != AF_INET)
continue;
break;
}
// add default/subnet route
if(Side() == PPP_LOCAL_SIDE) {
if(rtrequest(RTM_ADD, (struct sockaddr*) &inreq.ifra_mask,
(struct sockaddr*) &fGateway, (struct sockaddr*) &inreq.ifra_mask,
RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK)
ERROR("IPCP: UpdateAddress(): could not add default/subnet route!\n");
if (Side() == PPP_LOCAL_SIDE && pppInterfaceAddress != NULL) {
struct sockaddr addrGateway = {8, AF_INET, {0x00, 0x00, 0x00, 0x00,
0x00, 0x00} };
--fDefaultRoute->rt_refcnt;
// create destination address
if (fPeerRequests.address != INADDR_ANY)
memcpy(addrGateway.sa_data + 2, &fPeerRequests.address,
sizeof(in_addr_t));
else if (fPeerConfiguration.address == INADDR_ANY) {
in_addr_t gateway = 0x020F0F0F;
memcpy(addrGateway.sa_data + 2, &gateway, sizeof(in_addr_t));
// was: INADDR_BROADCAST
} else
memcpy(addrGateway.sa_data + 2, &fPeerConfiguration.address,
sizeof(in_addr_t));
net_route defaultRoute;
defaultRoute.destination = NULL;
defaultRoute.mask = NULL;
defaultRoute.gateway = &addrGateway;
defaultRoute.flags = RTF_DEFAULT | RTF_GATEWAY;
defaultRoute.interface_address = pppInterfaceAddress;
// route->interface_address;
status_t status = sDatalinkModule->add_route(domain, &defaultRoute);
if (status == B_OK)
dprintf("%s::%s: add route default OK!\n", __FILE__, __func__);
else
dprintf("%s::%s: add route default Fail!\n", __FILE__, __func__);
sDatalinkModule->put_interface_address(pppInterfaceAddress);
}
if (Side() == PPP_LOCAL_SIDE) {
int file;
int primary_dns, secondary_dns;
char buf[256];
file = open(RESOLV_CONF_FILE, O_RDWR);
primary_dns = ntohl(fLocalConfiguration.primaryDNS);
secondary_dns = ntohl(fLocalConfiguration.secondaryDNS);
sprintf(buf, "%s\t%d.%d.%d.%d\n%s\t%d.%d.%d.%d\n",
"nameserver",
(primary_dns & 0xff000000) >> 24,
(primary_dns & 0x00ff0000) >> 16,
(primary_dns & 0x0000ff00) >> 8,
(primary_dns & 0x000000ff),
"nameserver",
(secondary_dns & 0xff000000) >> 24,
(secondary_dns & 0x00ff0000) >> 16,
(secondary_dns & 0x0000ff00) >> 8,
(secondary_dns & 0x000000ff));
write(file, buf, strlen(buf));
close(file);
}
}
@@ -474,7 +576,57 @@ IPCP::UpdateAddresses()
void
IPCP::RemoveRoutes()
{
// note: netstack creates and deletes destination route automatically
// note:
// haiku supports multi default route. But for Desktop, ppp is generally
// the only default route. So is it necessary to remove other default
// route?
TRACE("%s::%s: entering RemoveRoutes!\n", __FILE__, __func__);
char *ethernetName = NULL;
PPPoEDevice* pppoeDevice = (PPPoEDevice *)Interface().Device();
if (pppoeDevice == NULL)
return;
ethernetName = pppoeDevice->EthernetIfnet()->name;
if (ethernetName == NULL)
return;
net_domain* domain = sStackModule->get_domain(AF_INET);
net_interface* pppInterface = get_interface_by_name(domain, ethernetName);
if (pppInterface == NULL) {
TRACE("%s::%s: pppInterface not found!\n", __FILE__, __func__);
return;
}
net_interface_address* pppInterfaceAddress = NULL;
while (sDatalinkModule->get_next_interface_address(pppInterface,
&pppInterfaceAddress)) {
if (pppInterfaceAddress->domain->family != AF_INET)
continue;
net_route oldDefaultRoute;
oldDefaultRoute.destination = NULL;
oldDefaultRoute.mask = NULL;
oldDefaultRoute.gateway = NULL;
oldDefaultRoute.flags= RTF_DEFAULT;
oldDefaultRoute.interface_address = pppInterfaceAddress;
status_t status = sDatalinkModule->remove_route(domain, &oldDefaultRoute);
// current: can not get the system default route so we fake
// one default route for delete
// Todo: save the oldDefaultRoute to fDefaultRoute
// restore the fDefaultRoute when ppp is down
sDatalinkModule->put_interface_address(pppInterfaceAddress);
if (status == B_OK)
dprintf("IPCP::RemoveRoutes: remove old default route OK!\n");
else
dprintf("IPCP::RemoveRoutes: remove old default route Fail!\n");
break;
}
if (fDefaultRoute) {
struct sockaddr_in netmask;
@@ -484,9 +636,9 @@ IPCP::RemoveRoutes()
netmask.sin_addr.s_addr = fLocalRequests.netmask;
netmask.sin_len = sizeof(struct sockaddr_in);
if(rtrequest(RTM_DELETE, (struct sockaddr*) &netmask,
(struct sockaddr*) &fGateway, (struct sockaddr*) &netmask,
RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK)
// if (rtrequest(RTM_DELETE, (struct sockaddr*) &netmask,
// (struct sockaddr*) &fGateway, (struct sockaddr*) &netmask,
// RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK)
ERROR("IPCP: RemoveRoutes(): could not remove default/subnet route!\n");
fDefaultRoute = NULL;
@@ -571,7 +723,7 @@ IPCP::TOBadEvent()
void
IPCP::RCREvent(struct mbuf *packet)
IPCP::RCREvent(net_buffer *packet)
{
TRACE("IPCP: RCREvent() state=%d\n", State());
@@ -579,8 +731,13 @@ IPCP::RCREvent(struct mbuf *packet)
KPPPConfigurePacket nak(PPP_CONFIGURE_NAK);
KPPPConfigurePacket reject(PPP_CONFIGURE_REJECT);
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return;
ppp_lcp_packet &lcpHeader = bufferheader.Data();
// we should not use the same id as the peer
if(fID == mtod(packet, ppp_lcp_packet*)->id)
if (fID == lcpHeader.id)
fID -= 128;
nak.SetID(request.ID());
@@ -620,7 +777,7 @@ IPCP::RCREvent(struct mbuf *packet)
case IPCP_SECONDARY_DNS:
if (item->length != 6) {
// the packet is invalid
m_freem(packet);
gBufferModule->free(packet);
NewState(PPP_INITIAL_STATE);
ReportUpFailedEvent();
return;
@@ -630,7 +787,7 @@ IPCP::RCREvent(struct mbuf *packet)
if (*wishedAddress == INADDR_ANY) {
if (*requestedAddress == INADDR_ANY) {
// we do not have an address for you
m_freem(packet);
gBufferModule->free(packet);
NewState(PPP_INITIAL_STATE);
ReportUpFailedEvent();
return;
@@ -665,19 +822,18 @@ IPCP::RCREvent(struct mbuf *packet)
}
if (nak.CountItems() > 0) {
RCRBadEvent(nak.ToMbuf(Interface().MRU(), Interface().PacketOverhead()), NULL);
m_freem(packet);
RCRBadEvent(nak.ToNetBuffer(Interface().MRU()), NULL);
gBufferModule->free(packet);
} else if (reject.CountItems() > 0) {
RCRBadEvent(NULL, reject.ToMbuf(Interface().MRU(),
Interface().PacketOverhead()));
m_freem(packet);
RCRBadEvent(NULL, reject.ToNetBuffer(Interface().MRU()));
gBufferModule->free(packet);
} else
RCRGoodEvent(packet);
}
void
IPCP::RCRGoodEvent(struct mbuf *packet)
IPCP::RCRGoodEvent(net_buffer *packet)
{
TRACE("IPCP: RCRGoodEvent() state=%d\n", State());
@@ -709,16 +865,36 @@ IPCP::RCRGoodEvent(struct mbuf *packet)
break;
default:
m_freem(packet);
gBufferModule->free(packet);
}
}
void
IPCP::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
IPCP::RCRBadEvent(net_buffer *nak, net_buffer *reject)
{
TRACE("IPCP: RCRBadEvent() state=%d\n", State());
uint16 lcpHdrRejectLength = 0;
uint16 lcpHdrNakLength = 0;
if (nak) {
NetBufferHeaderReader<ppp_lcp_packet> nakBufferHeaderReader(nak);
if (nakBufferHeaderReader.Status() != B_OK)
return;
ppp_lcp_packet &lcpNakPacket = nakBufferHeaderReader.Data();
lcpHdrNakLength = lcpNakPacket.length;
}
if (reject) {
NetBufferHeaderReader<ppp_lcp_packet> rejectBufferHeaderReader(reject);
if (rejectBufferHeaderReader.Status() != B_OK)
return;
ppp_lcp_packet &lcpRejectPacket = rejectBufferHeaderReader.Data();
lcpHdrRejectLength = lcpRejectPacket.length;
}
switch (State()) {
case PPP_OPENED_STATE:
NewState(PPP_REQ_SENT_STATE);
@@ -732,9 +908,9 @@ IPCP::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
case PPP_INITIAL_STATE:
case PPP_REQ_SENT_STATE:
case PPP_ACK_RCVD_STATE:
if(nak && ntohs(mtod(nak, ppp_lcp_packet*)->length) > 3)
if (nak && ntohs(lcpHdrNakLength) > 3)
SendConfigureNak(nak);
else if(reject && ntohs(mtod(reject, ppp_lcp_packet*)->length) > 3)
else if (reject && ntohs(lcpHdrRejectLength) > 3)
SendConfigureNak(reject);
return;
// prevents the nak/reject from being m_freem()'d
@@ -744,22 +920,26 @@ IPCP::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
}
if (nak)
m_freem(nak);
gBufferModule->free(nak);
if (reject)
m_freem(reject);
gBufferModule->free(reject);
}
void
IPCP::RCAEvent(struct mbuf *packet)
IPCP::RCAEvent(net_buffer *packet)
{
TRACE("IPCP: RCAEvent() state=%d\n", State());
ERROR("IPCP: RCAEvent() 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 &lcpHeader = bufferheader.Data();
if (fRequestID != lcpHeader.id) {
// this packet is not a reply to our request
// TODO: log this event
m_freem(packet);
gBufferModule->free(packet);
return;
}
@@ -849,20 +1029,25 @@ IPCP::RCAEvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
void
IPCP::RCNEvent(struct mbuf *packet)
IPCP::RCNEvent(net_buffer *packet)
{
TRACE("IPCP: RCNEvent() 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 &lcpHeader = bufferheader.Data();
if (fRequestID != lcpHeader.id) {
// this packet is not a reply to our request
// TODO: log this event
m_freem(packet);
gBufferModule->free(packet);
return;
}
@@ -935,7 +1120,7 @@ IPCP::RCNEvent(struct mbuf *packet)
default:
// DNS and addresses must be supported if we set them to auto
m_freem(packet);
gBufferModule->free(packet);
NewState(PPP_INITIAL_STATE);
ReportUpFailedEvent();
return;
@@ -962,17 +1147,22 @@ IPCP::RCNEvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
void
IPCP::RTREvent(struct mbuf *packet)
IPCP::RTREvent(net_buffer *packet)
{
TRACE("IPCP: RTREvent() state=%d\n", State());
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return;
ppp_lcp_packet &lcpHeader = bufferheader.Data();
// we should not use the same ID as the peer
if(fID == mtod(packet, ppp_lcp_packet*)->id)
if (fID == lcpHeader.id)
fID -= 128;
switch (State()) {
@@ -988,33 +1178,37 @@ IPCP::RTREvent(struct mbuf *packet)
case PPP_REQ_SENT_STATE:
SendTerminateAck(packet);
return;
// do not m_freem() packet
// do not free packet
case PPP_OPENED_STATE:
NewState(PPP_CLOSING_STATE);
ResetRestartCount();
SendTerminateAck(packet);
return;
// do not m_freem() packet
// do not free packet
default:
;
}
m_freem(packet);
gBufferModule->free(packet);
}
void
IPCP::RTAEvent(struct mbuf *packet)
IPCP::RTAEvent(net_buffer *packet)
{
TRACE("IPCP: RTAEvent() state=%d\n", State());
if(fTerminateID != mtod(packet, ppp_lcp_packet*)->id) {
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return;
ppp_lcp_packet &lcpHeader = bufferheader.Data();
if (fTerminateID != lcpHeader.id) {
// this packet is not a reply to our request
// TODO: log this event
m_freem(packet);
gBufferModule->free(packet);
return;
}
@@ -1041,12 +1235,12 @@ IPCP::RTAEvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
void
IPCP::RUCEvent(struct mbuf *packet)
IPCP::RUCEvent(net_buffer *packet)
{
TRACE("IPCP: RUCEvent() state=%d\n", State());
@@ -1055,7 +1249,7 @@ IPCP::RUCEvent(struct mbuf *packet)
void
IPCP::RXJBadEvent(struct mbuf *packet)
IPCP::RXJBadEvent(net_buffer *packet)
{
TRACE("IPCP: RXJBadEvent() state=%d\n", State());
@@ -1086,7 +1280,7 @@ IPCP::RXJBadEvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
@@ -1128,7 +1322,9 @@ IPCP::ReportDownEvent()
memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration));
memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration));
UpdateAddresses();
// don't update address if connect on demand is enabled
dprintf("ppp down, and leaving old address and rotues\n");
// UpdateAddresses();
DownEvent();
}
@@ -1169,12 +1365,12 @@ IPCP::SendConfigureRequest()
// add address
ipItem.type = IPCP_ADDRESS;
if (fLocalRequests.address == INADDR_ANY)
ipItem.address = fLocalConfiguration.address;
ipItem.address = (fLocalConfiguration.address);
else
ipItem.address = fLocalRequests.address;
ipItem.address =(fLocalRequests.address);
request.AddItem((ppp_configure_item*) &ipItem);
TRACE("IPCP: SCR: confaddr=%lX; reqaddr=%lX; addr=%lX\n",
TRACE("IPCP: SCR: confaddr=%X; reqaddr=%X; addr=%X\n",
fLocalConfiguration.address, fLocalRequests.address,
((ip_item*)request.ItemAt(0))->address);
@@ -1196,20 +1392,26 @@ IPCP::SendConfigureRequest()
// TODO: add VJC support
return Send(request.ToMbuf(Interface().MRU(),
Interface().PacketOverhead())) == B_OK;
return Send(request.ToNetBuffer(Interface().MRU())) == B_OK;
}
bool
IPCP::SendConfigureAck(struct mbuf *packet)
IPCP::SendConfigureAck(net_buffer *packet)
{
TRACE("IPCP: SendConfigureAck() state=%d\n", State());
if (!packet)
return false;
mtod(packet, ppp_lcp_packet*)->code = PPP_CONFIGURE_ACK;
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return false;
ppp_lcp_packet &lcpheader = bufferheader.Data();
lcpheader.code = PPP_CONFIGURE_ACK;
bufferheader.Sync();
KPPPConfigurePacket ack(packet);
// verify items
@@ -1271,22 +1473,29 @@ IPCP::SendConfigureAck(struct mbuf *packet)
bool
IPCP::SendConfigureNak(struct mbuf *packet)
IPCP::SendConfigureNak(net_buffer *packet)
{
TRACE("IPCP: SendConfigureNak() state=%d\n", State());
if (!packet)
return false;
ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*);
if(nak->code == PPP_CONFIGURE_NAK) {
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return false;
ppp_lcp_packet &nak = bufferheader.Data();
if (nak.code == PPP_CONFIGURE_NAK) {
if (fNakCounter == 0) {
// We sent enough naks. Let's try a reject.
nak->code = PPP_CONFIGURE_REJECT;
nak.code = PPP_CONFIGURE_REJECT;
} else
--fNakCounter;
}
bufferheader.Sync();
return Send(packet) == B_OK;
}
@@ -1299,81 +1508,78 @@ IPCP::SendTerminateRequest()
--fTerminateCounter;
fNextTimeout = system_time() + kIPCPStateMachineTimeout;
struct mbuf *packet = m_gethdr(MT_DATA);
net_buffer *packet = gBufferModule->create(256);
if (!packet)
return false;
packet->m_pkthdr.len = packet->m_len = 4;
ppp_lcp_packet *request;
status_t status = gBufferModule->append_size(packet, 1492, (void **)(&request));
if (status != B_OK)
return false;
// reserve some space for other protocols
packet->m_data += Interface().PacketOverhead();
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
request->code = PPP_TERMINATE_REQUEST;
request->id = fTerminateID = NextID();
request->length = htons(4);
status = gBufferModule->trim(packet, 4);
if (status != B_OK)
return false;
return Send(packet) == B_OK;
}
bool
IPCP::SendTerminateAck(struct mbuf *request)
IPCP::SendTerminateAck(net_buffer *request)
{
TRACE("IPCP: SendTerminateAck() state=%d\n", State());
struct mbuf *reply = request;
ppp_lcp_packet *ack;
net_buffer *reply = request;
if (!reply) {
reply = m_gethdr(MT_DATA);
if(!reply)
reply = gBufferModule->create(256);
ppp_lcp_packet *ack;
status_t status = gBufferModule->append_size(reply, 1492, (void **)(&ack));
if (status != B_OK) {
gBufferModule->free(reply);
return false;
reply->m_data += Interface().PacketOverhead();
reply->m_pkthdr.len = reply->m_len = 4;
ack = mtod(reply, ppp_lcp_packet*);
}
ack->id = NextID();
} else
ack = mtod(reply, ppp_lcp_packet*);
ack->code = PPP_TERMINATE_ACK;
ack->length = htons(4);
gBufferModule->trim(reply, 4);
} else {
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(reply);
if (bufferHeader.Status() < B_OK)
return false;
ppp_lcp_packet &ack = bufferHeader.Data();
ack.code = PPP_TERMINATE_ACK;
ack.length = htons(4);
}
return Send(reply) == B_OK;
}
bool
IPCP::SendCodeReject(struct mbuf *packet)
IPCP::SendCodeReject(net_buffer *packet)
{
TRACE("IPCP: SendCodeReject() state=%d\n", State());
if (!packet)
return false;
M_PREPEND(packet, 4);
// add some space for the header
NetBufferPrepend<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() != B_OK)
return false;
// adjust packet if too big
int32 adjust = Interface().MRU();
if(packet->m_flags & M_PKTHDR) {
adjust -= packet->m_pkthdr.len;
} else
adjust -= packet->m_len;
ppp_lcp_packet &reject = bufferHeader.Data();
if(adjust < 0)
m_adj(packet, adjust);
reject.code = PPP_CODE_REJECT;
reject.id = NextID();
reject.length = htons(packet->size);
ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*);
reject->code = PPP_CODE_REJECT;
reject->id = NextID();
if(packet->m_flags & M_PKTHDR)
reject->length = htons(packet->m_pkthdr.len);
else
reject->length = htons(packet->m_len);
bufferHeader.Sync();
return Send(packet) == B_OK;
}
+21 -19
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
@@ -71,10 +73,10 @@ class IPCP : public KPPPProtocol {
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:
@@ -90,15 +92,15 @@ class IPCP : public KPPPProtocol {
// 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);
@@ -108,11 +110,11 @@ 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;
@@ -120,14 +122,14 @@ class IPCP : public KPPPProtocol {
// 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;
+20 -11
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
@@ -75,14 +78,20 @@ 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;
memset(gProto, 0, sizeof(struct protosw*) * IPPROTO_MAX);
add_protosw(gProto, NET_LAYER1);
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);
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
break;
default:
+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 ;
+79 -55
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,6 +34,14 @@ 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)
{
@@ -159,16 +167,18 @@ PAP::Down()
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)
return B_ERROR;
@@ -176,31 +186,30 @@ PAP::Receive(struct mbuf *packet, uint16 protocolNumber)
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);
int32 length = packet->size;
length -= ntohs(data.length);
if(ntohs(data->length) < 4)
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;
@@ -320,19 +329,22 @@ 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);
gBufferModule->free(packet);
return;
}
@@ -357,15 +369,19 @@ 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;
}
@@ -381,20 +397,24 @@ PAP::RAEvent(struct mbuf *packet)
;
}
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;
}
@@ -410,7 +430,7 @@ PAP::RNEvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
@@ -429,68 +449,72 @@ PAP::SendRequest()
--fRequestCounter;
fNextTimeout = system_time() + kPAPTimeout;
struct mbuf *packet = m_gethdr(MT_DATA);
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();
uint16 packcketLenth = 6 + strlen(username) + strlen(password);
// 6 : lcp header 4 byte + username length 1 byte + password length 1 byte
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*);
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)
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);
NetBufferHeaderReader<ppp_lcp_packet> bufferheader(packet);
if (bufferheader.Status() != B_OK)
return false;
ppp_lcp_packet &ack = bufferheader.Data();
ack->data[0] = 0;
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());
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;
}
@@ -36,6 +36,7 @@ class PAPHandler : public KPPPOptionHandler {
{ 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);
@@ -57,8 +58,8 @@ class PAP : public KPPPProtocol {
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:
@@ -70,9 +71,9 @@ class PAP : public KPPPProtocol {
// 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();
@@ -80,13 +81,13 @@ class PAP : public KPPPProtocol {
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;
+15 -10
View File
@@ -5,23 +5,22 @@
#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)
{
@@ -62,12 +61,18 @@ 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_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:
@@ -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, [email protected]
*/
#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, [email protected]
*/
#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, [email protected]
* Lin Longzhou, [email protected]
*/
#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;
net_buffer *packet = gBufferModule->create(256);
if (packet == NULL) {
dprintf("create buffer failure\n");
return NULL;
}
pppoe_header *header = mtod(packet, pppoe_header*);
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,25 +3,39 @@
* 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)
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;
@@ -38,6 +52,8 @@ dump_packet(struct mbuf *packet)
}
}
}
#endif
@@ -62,22 +78,31 @@ PPPoEDevice::PPPoEDevice(KPPPInterface& interface, driver_parameter *settings)
// 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);
fServiceName = get_parameter_value(PPPoE_SERVICE_NAME_KEY, settings);
TRACE("fACName is %s\n", fACName ? fACName : "NULL");
fEthernetIfnet = FindPPPoEInterface(interfaceName);
fServiceName = get_parameter_value(PPPoE_SERVICE_NAME_KEY, settings);
TRACE("fServiceName is %s\n", fServiceName ? fServiceName : "NULL");
// fEthernetIfnet = FindPPPoEInterface(interfaceName);
#if DEBUG
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;
}
@@ -101,6 +128,24 @@ PPPoEDevice::Up()
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;
@@ -125,19 +170,21 @@ PPPoEDevice::Up()
discovery.AddTag(END_OF_LIST, NULL, 0);
// set up PPP header
struct mbuf *packet = discovery.ToMbuf(MTU());
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;
// 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
ethernetHeader = (struct ether_header*) destination.sa_data;
ethernetHeader->ether_type = ETHERTYPE_PPPOEDISC;
memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer));
// check if we are allowed to go up now (user intervention might disallow that)
if (fAttempts > 0 && !UpStarted()) {
@@ -151,13 +198,24 @@ PPPoEDevice::Up()
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;
@@ -169,6 +227,11 @@ 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)
@@ -191,9 +254,9 @@ PPPoEDevice::Down()
DiscoveryPacket discovery(PADT, SessionID());
discovery.AddTag(END_OF_LIST, NULL, 0);
struct mbuf *packet = discovery.ToMbuf(MTU());
net_buffer *packet = discovery.ToNetBuffer(MTU());
if (!packet) {
ERROR("PPPoEDevice::Down(): ToMbuf() failed; MTU=%ld\n", MTU());
ERROR("PPPoEDevice::Down(): ToNetBuffer() failed; MTU=%ld\n", MTU());
DownEvent();
return false;
}
@@ -205,13 +268,13 @@ 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,7 +305,7 @@ 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.
@@ -252,41 +315,46 @@ PPPoEDevice::Send(struct mbuf *packet, uint16 protocolNumber)
return B_ERROR;
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()) {
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);
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 destination
struct ether_header *ethernetHeader;
struct sockaddr destination;
memset(&destination, 0, sizeof(destination));
destination.sa_family = AF_UNSPEC;
// 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
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*))
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();
@@ -299,57 +367,83 @@ PPPoEDevice::Send(struct mbuf *packet, uint16 protocolNumber)
status_t
PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
PPPoEDevice::Receive(net_buffer *packet, uint16 protocolNumber)
{
TRACE("%s entering %s: protocolNumber:%x\n", __FILE__, __func__, protocolNumber);
if (!packet)
return B_ERROR;
else if(InitCheck() != B_OK || IsDown()) {
m_freem(packet);
return B_ERROR;
}
complete_pppoe_header *completeHeader = mtod(packet, complete_pppoe_header*);
if(!completeHeader) {
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;
}
uint8 ethernetSource[6];
memcpy(ethernetSource, completeHeader->ethernetHeader.ether_shost, sizeof(fPeer));
status_t result = B_OK;
struct sockaddr_dl& source = *(struct sockaddr_dl*)packet->source;
memcpy(ethernetSource, source.sdl_data, sizeof(fPeer));
if(completeHeader->ethernetHeader.ether_type == ETHERTYPE_PPPOE) {
m_adj(packet, ETHER_HDR_LEN);
pppoe_header *header = mtod(packet, pppoe_header*);
int32 PPP_Packet_Type = B_NET_FRAME_TYPE(source.sdl_type,
ntohs(source.sdl_e_type));
// bufferheader.Remove();
// bufferheader.Sync();
if(!IsUp() || header->version != PPPoE_VERSION || header->type != PPPoE_TYPE
|| header->code != 0x0 || header->sessionID != SessionID()) {
m_freem(packet);
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;
}
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;
}
m_adj(packet, PPPoE_HEADER_SIZE);
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);
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive fail PPPoEDev IsDown\n");
return B_ERROR;
}
DiscoveryPacket discovery(packet);
switch(discovery.Code()) {
case PADO: {
dprintf("processing PADO\n");
if (fState != PADI_SENT) {
m_freem(packet);
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive faile not PADI_Sent \n");
return B_OK;
}
@@ -364,9 +458,9 @@ PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
switch (tag->type) {
case SERVICE_NAME:
if (!hasServiceName && (!ServiceName()
|| (strlen(ServiceName()) == tag->length)
|| ((strlen(ServiceName()) == tag->length)
&& !memcmp(tag->data, ServiceName(),
tag->length))) {
tag->length)))) {
hasServiceName = true;
reply.AddTag(tag->type, tag->data, tag->length);
}
@@ -374,9 +468,9 @@ PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
case AC_NAME:
if (!hasACName && (!ACName()
|| (strlen(ACName()) == tag->length)
|| ((strlen(ACName()) == tag->length)
&& !memcmp(tag->data, ACName(),
tag->length))) {
tag->length)))) {
hasACName = true;
reply.AddTag(tag->type, tag->data, tag->length);
}
@@ -390,7 +484,8 @@ PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
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;
@@ -400,59 +495,68 @@ PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
}
if (!hasServiceName) {
m_freem(packet);
// 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());
net_buffer *replyPacket = reply.ToNetBuffer(MTU());
if (!replyPacket) {
m_freem(packet);
// gBufferModule->free(packet);
dprintf("PPPoEDevice::Receive fail no reply pack\n");
return B_ERROR;
}
memcpy(fPeer, ethernetSource, sizeof(fPeer));
memcpy(fPeer, ethernetSource, ETHER_ADDRESS_LENGTH);
// create destination
struct ether_header *ethernetHeader;
struct sockaddr destination;
memset(&destination, 0, sizeof(destination));
destination.sa_family = AF_UNSPEC;
// 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
ethernetHeader = (struct ether_header*) destination.sa_data;
ethernetHeader->ether_type = ETHERTYPE_PPPOEDISC;
memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer));
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:
dprintf("procesing PADS\n");
if (fState != PADR_SENT
|| memcmp(ethernetSource, fPeer, sizeof(fPeer))) {
m_freem(packet);
// 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:
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;
}
@@ -465,14 +569,15 @@ PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber)
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,7 +585,6 @@ void
PPPoEDevice::Pulse()
{
// We use Pulse() for timeout of connection establishment.
if (fNextTimeout == 0 || IsUp() || IsDown())
return;
@@ -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;
+152 -65
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;
@@ -76,19 +88,43 @@ SendQueryPacket(pppoe_query *query, DiscoveryPacket& discovery)
}
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)
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;
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;
}
if (ethernetInterfaceOfPPPOE->device)
return ethernetInterfaceOfPPPOE->device;
return NULL;
}
@@ -105,7 +141,7 @@ add_device(PPPoEDevice *device)
{
TRACE("PPPoE: add_device()\n");
LockerHelper locker(sLock);
// MutexLocker locker(sLock);
if (!sDevices->HasItem(device))
sDevices->AddItem(device);
}
@@ -116,84 +152,124 @@ 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;
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);
}
ifnet *sourceIfnet = packet->m_pkthdr.rcvif;
complete_pppoe_header *header = mtod(packet, complete_pppoe_header*);
PPPoEDevice *device;
pppoe_query *query;
LockerHelper locker(sLock);
sockaddr_dl& linkAddress = *(sockaddr_dl*)packet->source;
int32 specificType = B_NET_FRAME_TYPE(linkAddress.sdl_type,
ntohs(linkAddress.sdl_e_type));
if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC
&& header->pppoeHeader.length <= PPPoE_QUERY_REPORT_SIZE) {
// 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) {
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
&& *((uint32*)hostTag->data) == query->hostUniq) {
SendQueryPacket(query, discovery);
m_freem(packet);
return;
// gBufferModule->free(packet);
return B_ERROR;
}
}
}
}
}
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) {
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
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;
}
@@ -231,14 +307,14 @@ control(uint32 op, void *data, size_t length)
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;
}
@@ -263,16 +339,19 @@ control(uint32 op, void *data, size_t length)
query.hostUniq = NewHostUniq();
query.receiver = request->receiver;
sLock.Lock();
{
// MutexLocker tlocker(sLock);
TRACE("add query\n");
sQueries->AddItem(&query);
sLock.Unlock();
}
snooze(2000000);
// wait two seconds for results
sLock.Lock();
{
// MutexLocker tlocker(sLock);
TRACE("remove query\n");
sQueries->RemoveItem(&query);
sLock.Unlock();
}
} break;
default:
@@ -300,30 +379,38 @@ 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;
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);
put_module(NET_BUFFER_MODULE_NAME);
put_module(NET_DATALINK_MODULE_NAME);
put_module(NET_STACK_MODULE_NAME);
break;
default:
@@ -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) ] ;
@@ -9,11 +9,13 @@
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.
@@ -27,18 +29,21 @@ 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*);
NetBufferHeaderReader<ppp_lcp_packet> bufferhead(packet);
if (bufferhead.Status() != B_OK)
return;
ppp_lcp_packet &header = bufferhead.Data();
SetID(header->id);
if (!SetCode(header->code))
SetID(header.id);
if (!SetCode(header.code))
return;
uint16 length = ntohs(header->length);
uint16 length = ntohs(header.length);
if (length < 6 || length > packet->m_len)
if (length < 6 || length > packet->size)
return;
// there are no items (or one corrupted item)
@@ -46,7 +51,7 @@ KPPPConfigurePacket::KPPPConfigurePacket(struct mbuf *packet)
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
@@ -157,22 +162,31 @@ KPPPConfigurePacket::ItemWithType(uint8 type) const
}
/*! \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;
net_buffer *buffer = gBufferModule->create(256);
if (buffer == NULL) {
TRACE("%s::%s: gBufferModule->create fail\n", __FILE__, __func__);
return(NULL);
}
ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*);
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();
@@ -185,7 +199,7 @@ KPPPConfigurePacket::ToMbuf(uint32 MRU, uint32 reserve)
// make sure we have enough space left
if (MRU - length < item->length) {
m_freem(packet);
gBufferModule->free(buffer);
return NULL;
}
@@ -195,7 +209,13 @@ KPPPConfigurePacket::ToMbuf(uint32 MRU, uint32 reserve)
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;
}
@@ -14,7 +14,6 @@
#include <KPPPDevice.h>
#include <net/if.h>
#include <core_funcs.h>
#include <PPPControl.h>
@@ -52,6 +51,7 @@ KPPPDevice::~KPPPDevice()
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)
@@ -23,7 +23,11 @@
// void (KernelExport.h) and once with int (stdio.h).
#include <cstdio>
#include <cstring>
#include <core_funcs.h>
#include <ByteOrder.h>
#include <net_buffer.h>
#include <net_stack.h>
#include <ppp_device.h>
// now our headers...
#include <KPPPInterface.h>
@@ -38,7 +42,8 @@
#include <KPPPUtils.h>
// general helper classes not only belonging to us
#include <LockerHelper.h>
// #include <lock.h>
// #include <util/AutoLock.h>
// tools only for us :)
#include "settings_tools.h"
@@ -62,6 +67,9 @@ typedef struct reconnect_info {
uint32 delay;
} reconnect_info;
extern net_buffer_module_info *gBufferModule;
extern net_stack_module_info *gStackModule;
status_t reconnect_thread(void *data);
// other functions
@@ -95,7 +103,7 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry,
fParent(NULL),
fIsMultilink(false),
fAutoReconnect(false),
fConnectOnDemand(false),
fConnectOnDemand(true),
fAskBeforeConnecting(false),
fMode(PPP_CLIENT_MODE),
fLocalPFCState(PPP_PFC_DISABLED),
@@ -250,10 +258,11 @@ KPPPInterface::~KPPPInterface()
// This lock is not released until we are actually deleted.
while (true) {
Down();
fLock.Lock();
{
MutexLocker (fLock);
if (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE)
break;
fLock.Unlock();
}
}
Report(PPP_DESTRUCTION_REPORT, 0, &fID, sizeof(ppp_interface_id));
@@ -296,7 +305,9 @@ KPPPInterface::~KPPPInterface()
void
KPPPInterface::Delete()
{
LockerHelper locker(fLock);
// MutexLocker locker(fLock);
// alreay locked in KPPPStatemachine::DownEvent
// uncomment this line will cause double lock
if (fDeleteCounter > 0)
return;
@@ -364,7 +375,9 @@ KPPPInterface::SetMRU(uint32 MRU)
if (Device() && MRU > Device()->MTU() - 2)
return false;
LockerHelper locker(fLock);
// MutexLocker locker(fLock);
// uncomment this line will cause double lock
// alreay locked in ::Up and ::KPPPInterface
fMRU = MRU;
@@ -406,7 +419,298 @@ KPPPInterface::PacketOverhead() const
status_t
KPPPInterface::Control(uint32 op, void *data, size_t length)
{
switch (op) {
TRACE("%s:%s\n", __FILE__, __func__);
control_net_module_args* args = (control_net_module_args*)data;
if (op != NET_STACK_CONTROL_NET_MODULE) {
dprintf("unknow op!!\n");
return B_BAD_VALUE;
}
switch (args->op) {
case PPPC_COUNT_INTERFACES:
{
// should be implepented
dprintf("PPPC_COUNT_INTERFACES should be implepentd\n");
return B_OK;
}
case PPPC_GET_INTERFACES:
{
dprintf("PPPC_GET_INTERFACES\n");
ppp_get_interfaces_info* info = (ppp_get_interfaces_info*)args->data;
dprintf("info->interfaces: %p\n", info->interfaces);
*(info->interfaces) = 1;
info->resultCount = 1;
return B_OK;
}
case PPPC_CONTROL_INTERFACE:
{
dprintf("PPPC_CONTROL_INTERFACE\n");
ppp_control_info* control = (ppp_control_info*)args->data;
switch (control->op) {
case PPPC_GET_INTERFACE_INFO:
{
dprintf("PPPC_GET_INTERFACE_INFO\n");
if (control->length < sizeof(ppp_interface_info_t) || !control->data) {
dprintf("size wrong!\n");
return B_ERROR;
}
ppp_interface_info *info = (ppp_interface_info*) control->data;
dprintf("info addr:%p\n", info);
memset(info, 0, sizeof(ppp_interface_info_t));
if (Name())
strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT);
if (Ifnet())
info->if_unit = Ifnet()->index;
else
info->if_unit = -1;
info->mode = Mode();
info->state = State();
info->phase = Phase();
info->localAuthenticationStatus =
StateMachine().LocalAuthenticationStatus();
info->peerAuthenticationStatus =
StateMachine().PeerAuthenticationStatus();
info->localPFCState = LocalPFCState();
info->peerPFCState = PeerPFCState();
info->pfcOptions = PFCOptions();
info->protocolsCount = CountProtocols();
info->optionHandlersCount = LCP().CountOptionHandlers();
info->LCPExtensionsCount = 0;
info->childrenCount = CountChildren();
info->MRU = MRU();
info->interfaceMTU = InterfaceMTU();
info->connectAttempt = fConnectAttempt;
info->connectRetriesLimit = fConnectRetriesLimit;
info->connectRetryDelay = ConnectRetryDelay();
info->reconnectDelay = ReconnectDelay();
info->connectedSince = ConnectedSince();
info->idleSince = IdleSince();
info->disconnectAfterIdleSince = DisconnectAfterIdleSince();
info->doesConnectOnDemand = DoesConnectOnDemand();
info->doesAutoReconnect = DoesAutoReconnect();
info->hasDevice = Device();
info->isMultilink = IsMultilink();
info->hasParent = Parent();
break;
}
case PPPC_SET_USERNAME:
{
dprintf("PPPC_SET_USERNAME\n");
if (control->length > PPP_HANDLER_NAME_LENGTH_LIMIT || !control->data) {
dprintf("size wrong!\n");
return B_ERROR;
}
MutexLocker locker(fLock);
// login information can only be changed before we authenticate
if (Phase() >= PPP_AUTHENTICATION_PHASE)
return B_NOT_ALLOWED;
free(fUsername);
fUsername = control->data ? strdup((const char*) control->data) : strdup("");
dprintf("set ppp user name to %s\n", fUsername);
break;
}
case PPPC_SET_PASSWORD:
{
dprintf("PPPC_SET_PASSWORD\n");
if (control->length > PPP_HANDLER_NAME_LENGTH_LIMIT || !control->data) {
dprintf("size wrong!\n");
return B_ERROR;
}
MutexLocker locker(fLock);
// login information can only be changed before we authenticate
if (Phase() >= PPP_AUTHENTICATION_PHASE)
return B_NOT_ALLOWED;
free(fPassword);
fPassword = control->data ? strdup((const char*) control->data) : strdup("");
dprintf("set ppp password to %s!\n", fPassword);
break;
}
case PPPC_SET_ASK_BEFORE_CONNECTING:
{
dprintf("PPPC_SET_ASK_BEFORE_CONNECTING\n");
if (control->length < sizeof(uint32) || !control->data) {
dprintf("size wrong!\n");
return B_ERROR;
}
SetAskBeforeConnecting(*((uint32*)control->data));
dprintf("goto PPPC_SET_ASK_BEFORE_CONNECTING here!\n");
break;
}
case PPPC_GET_STATISTICS:
{
dprintf("PPPC_GET_STATISTICS\n");
if (control->length < sizeof(ppp_statistics) || !control->data) {
dprintf("size wrong!\n");
return B_ERROR;
}
dprintf("should PPPC_GET_STATISTICS here!\n");
memcpy(control->data, &fStatistics, sizeof(ppp_statistics));
break;
}
case PPPC_HAS_INTERFACE_SETTINGS:
{
dprintf("PPPC_HAS_INTERFACE_SETTINGS\n");
if (control->length < sizeof(driver_settings) || !control->data) {
dprintf("size wrong!\n");
return B_ERROR;
}
dprintf("should PPPC_HAS_INTERFACE_SETTINGS here!\n");
if (equal_interface_settings(Settings(), (driver_settings*)control->data))
return B_OK;
else
return B_ERROR;
break;
}
case PPPC_ENABLE_REPORTS:
{
dprintf("PPPC_ENABLE_REPORTS\n");
if (control->length < sizeof(ppp_report_request) || !control->data) {
dprintf("size wrong!\n");
return B_ERROR;
}
dprintf("should PPPC_ENABLE_REPORTS here!\n");
MutexLocker locker(fLock);
ppp_report_request *request = (ppp_report_request*) control->data;
// first, we send an initial state report
if (request->type == PPP_CONNECTION_REPORT) {
ppp_report_packet report;
report.type = PPP_CONNECTION_REPORT;
report.code = StateMachine().fLastConnectionReportCode;
report.length = sizeof(fID);
KPPPReportManager::SendReport(request->thread, &report);
if (request->flags & PPP_REMOVE_AFTER_REPORT)
return B_OK;
}
ReportManager().EnableReports(request->type, request->thread,
request->flags);
break;
}
case PPPC_DISABLE_REPORTS:
{
dprintf("PPPC_DISABLE_REPORTS\n");
if (control->length < sizeof(ppp_report_request) || !control->data) {
dprintf("size wrong!\n");
return B_ERROR;
}
dprintf("should PPPC_DISABLE_REPORTS here!\n");
ppp_report_request *request = (ppp_report_request*) control->data;
ReportManager().DisableReports(request->type, request->thread);
break;
}
case PPPC_CONTROL_DEVICE:
{
dprintf("PPPC_CONTROL_DEVICE\n");
if (control->length < sizeof(ppp_control_info) || !control->data)
return B_ERROR;
ppp_control_info *controlInfo = (ppp_control_info*) control->data;
if (controlInfo->index != 0 || !Device())
{
dprintf("index is 0 or no Device\n");
return B_BAD_INDEX;
}
return Device()->Control(controlInfo->op, controlInfo->data, controlInfo->length);
}
case PPPC_CONTROL_PROTOCOL:
{
dprintf("PPPC_CONTROL_PROTOCOL\n");
if (control->length < sizeof(ppp_control_info) || !control->data)
return B_ERROR;
ppp_control_info *controlInfo = (ppp_control_info*) control->data;
KPPPProtocol *protocol = ProtocolAt(controlInfo->index);
if (!protocol)
return B_BAD_INDEX;
return protocol->Control(controlInfo->op, controlInfo->data, controlInfo->length);
}
case PPPC_CONTROL_OPTION_HANDLER:
{
dprintf("PPPC_CONTROL_OPTION_HANDLER\n");
if (control->length < sizeof(ppp_control_info) || !control->data)
return B_ERROR;
ppp_control_info *controlInfo = (ppp_control_info*) control->data;
KPPPOptionHandler *optionHandler = LCP().OptionHandlerAt(controlInfo->index);
if (!optionHandler) {
dprintf("optionHandler no avail\n");
return B_BAD_INDEX;
}
return optionHandler->Control(controlInfo->op, controlInfo->data,
controlInfo->length);
}
case PPPC_CONTROL_LCP_EXTENSION:
{
dprintf("PPPC_CONTROL_LCP_EXTENSION\n");
if (control->length < sizeof(ppp_control_info) || !control->data)
return B_ERROR;
ppp_control_info *controlInfo = (ppp_control_info*) control->data;
KPPPLCPExtension *lcpExtension = LCP().LCPExtensionAt(controlInfo->index);
if (!lcpExtension)
return B_BAD_INDEX;
return lcpExtension->Control(controlInfo->op, controlInfo->data,
controlInfo->length);
}
case PPPC_CONTROL_CHILD:
{
dprintf("PPPC_CONTROL_CHILD\n");
if (control->length < sizeof(ppp_control_info) || !control->data)
return B_ERROR;
ppp_control_info *controlInfo = (ppp_control_info*) control->data;
KPPPInterface *child = ChildAt(controlInfo->index);
if (!child)
return B_BAD_INDEX;
return child->Control(controlInfo->op, controlInfo->data, controlInfo->length);
}
default :
return B_ERROR;
}
return B_OK;
}
case PPPC_GET_INTERFACE_INFO:
{
if (length < sizeof(ppp_interface_info_t) || !data)
@@ -417,7 +721,7 @@ KPPPInterface::Control(uint32 op, void *data, size_t length)
if (Name())
strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT);
if (Ifnet())
info->if_unit = Ifnet()->if_unit;
info->if_unit = Ifnet()->index;
else
info->if_unit = -1;
info->mode = Mode();
@@ -456,7 +760,7 @@ KPPPInterface::Control(uint32 op, void *data, size_t length)
if (!data)
return B_ERROR;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
// login information can only be changed before we authenticate
if (Phase() >= PPP_AUTHENTICATION_PHASE)
return B_NOT_ALLOWED;
@@ -471,7 +775,7 @@ KPPPInterface::Control(uint32 op, void *data, size_t length)
if (!data)
return B_ERROR;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
// login information can only be changed before we authenticate
if (Phase() >= PPP_AUTHENTICATION_PHASE)
return B_NOT_ALLOWED;
@@ -524,7 +828,7 @@ KPPPInterface::Control(uint32 op, void *data, size_t length)
if (length < sizeof(ppp_report_request) || !data)
return B_ERROR;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
ppp_report_request *request = (ppp_report_request*) data;
// first, we send an initial state report
if (request->type == PPP_CONNECTION_REPORT) {
@@ -625,6 +929,7 @@ KPPPInterface::Control(uint32 op, void *data, size_t length)
}
default:
dprintf("bad ppp_interface_control!\n");
return B_BAD_VALUE;
}
@@ -656,7 +961,7 @@ KPPPInterface::SetDevice(KPPPDevice *device)
return false;
// main interfaces do not have devices
LockerHelper locker(fLock);
MutexLocker locker(fLock);
if (Phase() != PPP_DOWN_PHASE)
return false;
@@ -704,7 +1009,7 @@ KPPPInterface::AddProtocol(KPPPProtocol *protocol)
|| protocol->Level() == PPP_INTERFACE_LEVEL)
return false;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
if (Phase() != PPP_DOWN_PHASE)
return false;
@@ -768,7 +1073,7 @@ KPPPInterface::RemoveProtocol(KPPPProtocol *protocol)
TRACE("KPPPInterface: RemoveProtocol(%X)\n",
protocol ? protocol->ProtocolNumber() : 0);
LockerHelper locker(fLock);
MutexLocker locker(fLock);
if (Phase() != PPP_DOWN_PHASE)
return false;
@@ -809,7 +1114,7 @@ KPPPInterface::RemoveProtocol(KPPPProtocol *protocol)
int32
KPPPInterface::CountProtocols() const
{
LockerHelper locker(fLock);
MutexLocker locker(fLock);
KPPPProtocol *protocol = FirstProtocol();
@@ -825,7 +1130,7 @@ KPPPInterface::CountProtocols() const
KPPPProtocol*
KPPPInterface::ProtocolAt(int32 index) const
{
LockerHelper locker(fLock);
MutexLocker locker(fLock);
KPPPProtocol *protocol = FirstProtocol();
@@ -849,7 +1154,8 @@ KPPPInterface::ProtocolFor(uint16 protocolNumber, KPPPProtocol *start) const
{
TRACE("KPPPInterface: ProtocolFor(%X)\n", protocolNumber);
LockerHelper locker(fLock);
// MutexLocker locker(fLock);
// already locked in ::Receive, uncomment this line will cause double lock
KPPPProtocol *current = start ? start : FirstProtocol();
@@ -874,7 +1180,7 @@ KPPPInterface::AddChild(KPPPInterface *child)
if (!child)
return false;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
if (fChildren.HasItem(child) || !fChildren.AddItem(child))
return false;
@@ -891,7 +1197,7 @@ KPPPInterface::RemoveChild(KPPPInterface *child)
{
TRACE("KPPPInterface: RemoveChild(%lX)\n", child ? child->ID() : 0);
LockerHelper locker(fLock);
MutexLocker locker(fLock);
if (!fChildren.RemoveItem(child))
return false;
@@ -912,7 +1218,7 @@ KPPPInterface::ChildAt(int32 index) const
{
TRACE("KPPPInterface: ChildAt(%ld)\n", index);
LockerHelper locker(fLock);
MutexLocker locker(fLock);
KPPPInterface *child = fChildren.ItemAt(index);
@@ -945,7 +1251,7 @@ KPPPInterface::SetConnectOnDemand(bool connectOnDemand)
TRACE("KPPPInterface: SetConnectOnDemand(%s)\n", connectOnDemand ? "true" : "false");
LockerHelper locker(fLock);
MutexLocker locker(fLock);
// Only clients support ConnectOnDemand.
if (Mode() != PPP_CLIENT_MODE) {
@@ -973,10 +1279,10 @@ KPPPInterface::SetConnectOnDemand(bool connectOnDemand)
// check if we need to set/unset flags
if (connectOnDemand) {
if (Ifnet())
Ifnet()->if_flags |= IFF_UP;
Ifnet()->flags |= IFF_UP;
} else if (!connectOnDemand && Phase() < PPP_ESTABLISHED_PHASE) {
if (Ifnet())
Ifnet()->if_flags &= ~IFF_UP;
Ifnet()->flags &= ~IFF_UP;
}
}
@@ -985,14 +1291,14 @@ KPPPInterface::SetConnectOnDemand(bool connectOnDemand)
void
KPPPInterface::SetAskBeforeConnecting(bool ask)
{
LockerHelper locker(fLock);
MutexLocker locker(fLock);
bool old = fAskBeforeConnecting;
fAskBeforeConnecting = ask;
if (old && fAskBeforeConnecting == false && State() == PPP_STARTING_STATE
&& Phase() == PPP_DOWN_PHASE) {
locker.UnlockNow();
// locker.Unlock();
StateMachine().ContinueOpenEvent();
}
}
@@ -1004,7 +1310,7 @@ KPPPInterface::SetPFCOptions(uint8 pfcOptions)
{
TRACE("KPPPInterface: SetPFCOptions(0x%X)\n", pfcOptions);
LockerHelper locker(fLock);
MutexLocker locker(fLock);
if (PFCOptions() & PPP_FREEZE_PFC_OPTIONS)
return false;
@@ -1032,7 +1338,7 @@ KPPPInterface::Up()
if (IsUp())
return true;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
StateMachine().OpenEvent();
return true;
@@ -1059,7 +1365,7 @@ KPPPInterface::Down()
send_data_with_timeout(fReconnectThread, 0, NULL, 0, 200);
// tell the reconnect thread to abort its attempt (if it's still waiting)
LockerHelper locker(fLock);
MutexLocker locker(fLock);
StateMachine().CloseEvent();
return true;
@@ -1075,6 +1381,12 @@ KPPPInterface::WaitForConnection()
if (InitCheck() != B_OK)
return false;
// just delay ~3 seconds to wait for ppp go up
for (uint32 i = 0; i < 10000; i++)
for (uint32 j = 0; j < 3000000; j++)
return true; // for temporary
ReportManager().EnableReports(PPP_CONNECTION_REPORT, find_thread(NULL));
ppp_report_packet report;
@@ -1097,6 +1409,7 @@ KPPPInterface::WaitForConnection()
}
ReportManager().DisableReports(PPP_CONNECTION_REPORT, find_thread(NULL));
dprintf("KPPPInterface: WaitForConnection():%s\n", successful ? "True" : "False");
return successful;
}
@@ -1233,7 +1546,7 @@ KPPPInterface::IsAllowedToSend() const
- \c B_ERROR: Some error occured.
*/
status_t
KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber)
KPPPInterface::Send(net_buffer *packet, uint16 protocolNumber)
{
TRACE("KPPPInterface: Send(0x%X)\n", protocolNumber);
@@ -1244,18 +1557,21 @@ KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber)
// do we have a device?
// did we load all modules?
if (InitCheck() != B_OK) {
m_freem(packet);
ERROR("InitCheck() fail\n");
gBufferModule->free(packet);
return B_ERROR;
}
// go up if ConnectOnDemand is enabled and we are disconnected
// TODO: our new netstack will simplify ConnectOnDemand handling, so
// we do not have to handle it here
if ((protocolNumber != PPP_LCP_PROTOCOL && DoesConnectOnDemand()
&& (Phase() == PPP_DOWN_PHASE
|| Phase() == PPP_ESTABLISHMENT_PHASE)
&& !Up()) || !WaitForConnection()) {
m_freem(packet);
&& !Up()) && !WaitForConnection()) {
dprintf("DoesConnectOnDemand fail!\n");
// gBufferModule->free(packet);
return B_ERROR;
}
@@ -1279,52 +1595,61 @@ KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber)
#endif
// make sure that protocol is allowed to send and everything is up
if (!Device()->IsUp() || !protocol || !protocol->IsEnabled()
if (Device()->IsUp() && protocolNumber == 0x0021) {
// IP_PROTOCOL 0x0021
TRACE("send IP packet!\n");
} else if (!Device()->IsUp() || !protocol || !protocol->IsEnabled()
|| !IsProtocolAllowed(*protocol)) {
ERROR("KPPPInterface::Send(): cannot send!\n");
m_freem(packet);
ERROR("KPPPInterface::Send(): Device is down, throw packet away!!\n");
// gBufferModule->free(packet);
return B_ERROR;
}
// encode in ppp frame and consider using PFC
if (UseLocalPFC() && protocolNumber & 0xFF00 == 0) {
M_PREPEND(packet, 1);
if (UseLocalPFC() && (protocolNumber & 0xFF00) == 0) {
TRACE("%s::%s should not go here\n", __FILE__, __func__);
NetBufferPrepend<uint8> bufferHeader(packet);
if (bufferHeader.Status() != B_OK)
return bufferHeader.Status();
if (packet == NULL)
return B_ERROR;
uint8 &header = bufferHeader.Data();
// memcpy(header.destination, ether_pppoe_ppp_header, 1);
header = (protocolNumber & 0x00FF);
// bufferHeader.Sync();
uint8 *header = mtod(packet, uint8*);
*header = protocolNumber & 0xFF;
} else {
M_PREPEND(packet, 2);
NetBufferPrepend<uint16> bufferHeader(packet);
if (bufferHeader.Status() != B_OK)
return bufferHeader.Status();
if (packet == NULL)
return B_ERROR;
uint16 &header = bufferHeader.Data();
// set protocol (the only header field)
protocolNumber = htons(protocolNumber);
uint16 *header = mtod(packet, uint16*);
*header = protocolNumber;
header = htons(protocolNumber);
// bufferHeader.Sync();
}
// pass to device if we're either not a multilink interface or a child interface
if (!IsMultilink() || Parent()) {
// check if packet is too big for device
uint32 length = packet->m_flags & M_PKTHDR ? (uint32) packet->m_pkthdr.len :
packet->m_len;
uint32 length = packet->size;
if (length > MRU()) {
m_freem(packet);
dprintf("packet too large!\n");
gBufferModule->free(packet);
return B_ERROR;
}
atomic_add64(&fStatistics.bytesSent, length);
atomic_add64(&fStatistics.packetsSent, 1);
TRACE("%s::%s SendToNext\n", __FILE__, __func__);
return SendToNext(packet, 0);
// this is normally the device, but there can be something inbetween
} else {
// the multilink protocol should have sent it to some child interface
m_freem(packet);
TRACE("It is weird to go here!\n");
gBufferModule->free(packet);
return B_ERROR;
}
}
@@ -1348,25 +1673,37 @@ KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber)
- \c PPP_DISCARDED: The protocol handler(s) did not handle this packet.
*/
status_t
KPPPInterface::Receive(struct mbuf *packet, uint16 protocolNumber)
KPPPInterface::Receive(net_buffer *packet, uint16 protocolNumber)
{
TRACE("KPPPInterface: Receive(0x%X)\n", protocolNumber);
if (!packet)
return B_ERROR;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
int32 result = PPP_REJECTED;
// assume we have no handler
// Set our interface as the receiver.
// The real netstack protocols (IP, IPX, etc.) might get confused if our
// interface is a main interface and at the same time not registered
// because then there is no receiver interface.
// PPP NCPs should be aware of that!
if (packet->m_flags & M_PKTHDR && Ifnet() != NULL)
packet->m_pkthdr.rcvif = Ifnet();
if (protocolNumber == 0x0021 && Device() && Device()->IsUp()) {
// IP_PROTOCOL 0x0021
TRACE("%s::%s: receiving IP packet\n", __FILE__, __func__);
ppp_device* dev=(ppp_device*)Ifnet();
if (dev)
return gStackModule->fifo_enqueue_buffer(&(dev->ppp_fifo), packet);
else {
dprintf("%s::%s: no ppp_device\n", __FILE__, __func__);
return B_ERROR;
}
}
// // Set our interface as the receiver.
// // The real netstack protocols (IP, IPX, etc.) might get confused if our
// // interface is a main interface and at the same time not registered
// // because then there is no receiver interface.
// // PPP NCPs should be aware of that!
// if (packet->m_flags & M_PKTHDR && Ifnet() != NULL)
// packet->m_pkthdr.rcvif = Ifnet();
// Find handler and let it parse the packet.
// The handler does need not be up because if we are a server
@@ -1396,7 +1733,7 @@ KPPPInterface::Receive(struct mbuf *packet, uint16 protocolNumber)
return Parent()->Receive(packet, protocolNumber);
if (result == PPP_UNHANDLED) {
m_freem(packet);
gBufferModule->free(packet);
return PPP_DISCARDED;
} else {
StateMachine().RUCEvent(packet, protocolNumber);
@@ -1419,7 +1756,7 @@ KPPPInterface::Receive(struct mbuf *packet, uint16 protocolNumber)
- \c PPP_DISCARDED: The protocol handler(s) did not handle this packet.
*/
status_t
KPPPInterface::ReceiveFromDevice(struct mbuf *packet)
KPPPInterface::ReceiveFromDevice(net_buffer *packet)
{
TRACE("KPPPInterface: ReceiveFromDevice()\n");
@@ -1427,20 +1764,37 @@ KPPPInterface::ReceiveFromDevice(struct mbuf *packet)
return B_ERROR;
if (InitCheck() != B_OK) {
m_freem(packet);
gBufferModule->free(packet);
return B_ERROR;
}
uint32 length = packet->m_flags & M_PKTHDR ? (uint32) packet->m_pkthdr.len :
packet->m_len;
uint32 length = packet->size;
// decode ppp frame and recognize PFC
uint16 protocolNumber = *mtod(packet, uint8*);
if (protocolNumber & 1) {
m_adj(packet, 1);
NetBufferHeaderReader<uint16> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return bufferHeader.Status();
uint16 &header = bufferHeader.Data();
uint16 protocolNumber = ntohs(header); // copy the protocol number
TRACE("%s::%s: ppp protocol number:%x\n", __FILE__, __func__, protocolNumber);
bufferHeader.Remove();
bufferHeader.Sync();
// PFC only use 1 byte for protocol, the next byte is in first byte of message
if (protocolNumber & (1UL<<8)) {
NetBufferPrepend<uint8> bufferprepend(packet);
if (bufferprepend.Status() < B_OK) {
gBufferModule->free(packet);
return bufferprepend.Status();
}
uint8 &prepend = bufferprepend.Data();
prepend = (uint8)(protocolNumber & 0x00FF);
// bufferprepend.Sync();
TRACE("%s::%s:PFC protocol:%x\n", __FILE__, __func__, protocolNumber>>8);
} else {
protocolNumber = ntohs(*mtod(packet, uint16*));
m_adj(packet, 2);
TRACE("%s::%s:Non-PFC protocol:%x\n", __FILE__, __func__, protocolNumber);
}
atomic_add64(&fStatistics.bytesReceived, length);
@@ -1453,7 +1807,7 @@ KPPPInterface::ReceiveFromDevice(struct mbuf *packet)
void
KPPPInterface::Pulse()
{
LockerHelper locker(fLock);
MutexLocker locker(fLock);
if (Device())
Device()->Pulse();
@@ -1485,7 +1839,7 @@ KPPPInterface::RegisterInterface()
return true;
// we are already registered
LockerHelper locker(fLock);
MutexLocker locker(fLock);
// only MainInterfaces get an ifnet
if (IsMultilink() && Parent() && Parent()->RegisterInterface())
@@ -1496,11 +1850,13 @@ KPPPInterface::RegisterInterface()
fIfnet = fManager->RegisterInterface(ID());
if (!fIfnet)
if (!fIfnet) {
dprintf("%s:%s: damn it no fIfnet device\n", __FILE__, __func__);
return false;
}
if (DoesConnectOnDemand())
fIfnet->if_flags |= IFF_UP;
fIfnet->flags |= IFF_UP;
CalculateInterfaceMTU();
CalculateBaudRate();
@@ -1519,7 +1875,7 @@ KPPPInterface::UnregisterInterface()
return true;
// we are already unregistered
LockerHelper locker(fLock);
MutexLocker locker(fLock);
// only MainInterfaces get an ifnet
if (IsMultilink() && Parent())
@@ -1587,7 +1943,7 @@ KPPPInterface::StackControlEachHandler(uint32 op, void *data)
status_t result = B_BAD_VALUE, tmp;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
KPPPProtocol *protocol = FirstProtocol();
for (; protocol; protocol = protocol->NextProtocol()) {
@@ -1613,7 +1969,9 @@ KPPPInterface::CalculateInterfaceMTU()
{
TRACE("KPPPInterface: CalculateInterfaceMTU()\n");
LockerHelper locker(fLock);
// MutexLocker locker(fLock);
// uncomment this line will cause double lock
// alreay locked in ::KPPPInterface
fInterfaceMTU = fMRU;
fHeaderLength = 2;
@@ -1628,8 +1986,9 @@ KPPPInterface::CalculateInterfaceMTU()
fInterfaceMTU -= fHeaderLength;
if (Ifnet()) {
Ifnet()->if_mtu = fInterfaceMTU;
Ifnet()->if_hdrlen = fHeaderLength;
Ifnet()->mtu = fInterfaceMTU;
Ifnet()->header_length = fHeaderLength;
return;
}
if (Parent())
@@ -1643,19 +2002,20 @@ KPPPInterface::CalculateBaudRate()
{
TRACE("KPPPInterface: CalculateBaudRate()\n");
LockerHelper locker(fLock);
// MutexLocker locker(fLock); // uncomment this will cause double lock
if (!Ifnet())
return;
if (Device())
fIfnet->if_baudrate = max_c(Device()->InputTransferRate(),
fIfnet->link_speed = max_c(Device()->InputTransferRate(),
Device()->OutputTransferRate());
else {
fIfnet->if_baudrate = 0;
fIfnet->link_speed = 0;
for (int32 index = 0; index < CountChildren(); index++)
if (ChildAt(index)->Ifnet())
fIfnet->if_baudrate += ChildAt(index)->Ifnet()->if_baudrate;
fIfnet->link_speed += ChildAt(index)->Ifnet()->link_speed;
return;
}
}
@@ -1666,7 +2026,7 @@ KPPPInterface::Reconnect(uint32 delay)
{
TRACE("KPPPInterface: Reconnect(%ld)\n", delay);
LockerHelper locker(fLock);
MutexLocker locker(fLock);
if (fReconnectThread != -1)
return;
@@ -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)
@@ -87,6 +90,7 @@ 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())
@@ -160,6 +164,7 @@ 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())
@@ -196,22 +201,6 @@ KPPPLCP::LCPExtensionFor(uint8 code, int32 *start) const
}
//! 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,7 +230,7 @@ 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;
@@ -251,29 +240,22 @@ KPPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber)
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);
}
net_buffer *copy = gBufferModule->duplicate(packet);
if (ntohs(data->length) < 4)
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,7 +292,7 @@ KPPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber)
break;
default:
m_freem(packet);
// gBufferModule->free(packet);
handled = false;
}
@@ -324,18 +306,18 @@ KPPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber)
// 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;
}
}
@@ -345,7 +327,7 @@ KPPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber)
return PPP_REJECTED;
}
m_freem(packet);
gBufferModule->free(packet);
return result;
}
@@ -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:
{
@@ -19,10 +19,12 @@
#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.
@@ -56,7 +58,7 @@ 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;
@@ -70,7 +72,7 @@ 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;
}
}
@@ -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>
@@ -33,7 +35,7 @@ report_sender_thread(void *data)
\param lock The BLocker that should be used by this report manager.
*/
KPPPReportManager::KPPPReportManager(BLocker& lock)
KPPPReportManager::KPPPReportManager(mutex& lock)
: fLock(lock)
{
}
@@ -88,7 +90,7 @@ 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;
@@ -106,7 +108,7 @@ KPPPReportManager::DisableReports(ppp_report_type type, thread_id thread)
if (thread < 0)
return;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
ppp_report_request *request;
@@ -135,7 +137,7 @@ KPPPReportManager::DoesReport(ppp_report_type type, thread_id thread)
if (thread < 0)
return false;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
ppp_report_request *request;
@@ -177,7 +179,7 @@ KPPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 le
if (!data)
length = 0;
LockerHelper locker(fLock);
MutexLocker locker(fLock);
status_t result;
thread_id me = find_thread(NULL);
@@ -22,8 +22,12 @@
#include <KPPPUtils.h>
#include <net/if.h>
#include <core_funcs.h>
#include <ByteOrder.h>
#include <net_buffer.h>
#include <NetBufferUtilities.h>
extern net_buffer_module_info *gBufferModule;
static const bigtime_t kPPPStateMachineTimeout = 3000000;
// 3 seconds
@@ -49,8 +53,9 @@ KPPPStateMachine::KPPPStateMachine(KPPPInterface& interface)
fTerminateID(0),
fEchoID(0),
fNextTimeout(0),
fLock("KPPPStateMachine")
fLock(mutex())
{
mutex_init(&fLock, "KPPPStateMachine");
}
@@ -114,8 +119,8 @@ KPPPStateMachine::NewPhase(ppp_phase next)
// The report threads get their notification later.
if (Phase() == PPP_ESTABLISHED_PHASE && next != Phase()) {
if (Interface().Ifnet()) {
Interface().Ifnet()->if_flags &= ~IFF_RUNNING;
Interface().Ifnet()->if_flags &= ~IFF_UP;
// Interface().Ifnet()->flags &= ~IFF_RUNNING;
Interface().Ifnet()->flags &= ~IFF_UP;
}
if (Interface().Parent())
@@ -128,7 +133,7 @@ KPPPStateMachine::NewPhase(ppp_phase next)
Interface().fConnectedSince = system_time();
if (Interface().Ifnet())
Interface().Ifnet()->if_flags |= IFF_UP | IFF_RUNNING;
Interface().Ifnet()->flags |= IFF_UP;// | IFF_RUNNING;
Interface().fConnectAttempt = 0;
// when we Reconnect() this becomes 1 (the first connection attempt)
@@ -172,20 +177,32 @@ KPPPStateMachine::SendEchoRequest()
if (State() != PPP_OPENED_STATE)
return false;
struct mbuf *packet = m_gethdr(MT_DATA);
if (!packet)
net_buffer *packet = gBufferModule->create(256);
if (packet == NULL)
return false;
packet->m_data += LCP().AdditionalOverhead();
packet->m_pkthdr.len = packet->m_len = 8;
// echo requests are at least eight bytes long
void *data;
status_t status = gBufferModule->append_size(packet, 1492, &data);
if (status == B_OK && data == NULL) {
gBufferModule->free(packet);
return false;
}
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
request->code = PPP_ECHO_REQUEST;
request->id = NextID();
fEchoID = request->id;
request->length = htons(packet->m_len);
memcpy(request->data, &fMagicNumber, sizeof(fMagicNumber));
// echo requests are at least eight bytes long
ppp_lcp_packet request;
request.code = PPP_ECHO_REQUEST;
request.id = NextID();
request.length = htons(8);
fEchoID = request.id;
memcpy(data, &request, sizeof(request));
memcpy(request.data, &fMagicNumber, sizeof(fMagicNumber));
status = gBufferModule->trim(packet, sizeof(request) + sizeof(fMagicNumber));
if (status < B_OK) {
gBufferModule->free(packet);
return false;
}
return LCP().Send(packet) == B_OK;
}
@@ -197,22 +214,33 @@ KPPPStateMachine::SendDiscardRequest()
{
TRACE("KPPPSM: SendDiscardRequest() state=%d phase=%d\n", State(), Phase());
if (State() != PPP_OPENED_STATE)
net_buffer *packet = gBufferModule->create(256);
if (packet == NULL)
return false;
struct mbuf *packet = m_gethdr(MT_DATA);
if (!packet)
void *data;
status_t status = gBufferModule->append_size(packet, 1492, &data);
if (status == B_OK && data == NULL) {
gBufferModule->free(packet);
return false;
}
packet->m_data += LCP().AdditionalOverhead();
packet->m_pkthdr.len = packet->m_len = 8;
// discard requests are at least eight bytes long
// echo requests are at least eight bytes long
ppp_lcp_packet request;
request.code = PPP_DISCARD_REQUEST;
request.id = NextID();
request.length = htons(8);
fEchoID = request.id;
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
request->code = PPP_DISCARD_REQUEST;
request->id = NextID();
request->length = htons(packet->m_len);
memcpy(request->data, &fMagicNumber, sizeof(fMagicNumber));
memcpy(data, &request, sizeof(request));
memcpy(request.data, &fMagicNumber, sizeof(fMagicNumber));
status = gBufferModule->trim(packet, sizeof(request) + sizeof(fMagicNumber));
if (status < B_OK) {
gBufferModule->free(packet);
return false;
}
return LCP().Send(packet) == B_OK;
}
@@ -893,42 +921,49 @@ KPPPStateMachine::TOBadEvent()
// receive configure request (acceptable request)
void
KPPPStateMachine::RCRGoodEvent(struct mbuf *packet)
KPPPStateMachine::RCRGoodEvent(net_buffer *packet)
{
TRACE("KPPPSM: RCRGoodEvent() state=%d phase=%d\n", State(), Phase());
switch (State()) {
case PPP_INITIAL_STATE:
case PPP_STARTING_STATE:
TRACE("%s::%s: PPP_STARTING_STATE\n", __FILE__, __func__);
IllegalEvent(PPP_RCR_GOOD_EVENT);
m_freem(packet);
gBufferModule->free(packet);
break;
case PPP_CLOSED_STATE:
TRACE("%s::%s: PPP_CLOSED_STATE\n", __FILE__, __func__);
SendTerminateAck();
m_freem(packet);
gBufferModule->free(packet);
break;
case PPP_STOPPED_STATE:
TRACE("%s::%s: PPP_STOPPED_STATE\n", __FILE__, __func__);
// irc,scr,sca/8
// XXX: should we do nothing and wait for DownEvent()?
m_freem(packet);
gBufferModule->free(packet);
break;
case PPP_REQ_SENT_STATE:
NewState(PPP_ACK_SENT_STATE);
case PPP_ACK_SENT_STATE:
TRACE("%s::%s: PPP_ACK_SENT_STATE size %ld\n", __FILE__, __func__,
packet->size);
SendConfigureAck(packet);
break;
case PPP_ACK_RCVD_STATE:
TRACE("%s::%s: PPP_ACK_RCVD_STATE\n", __FILE__, __func__);
NewState(PPP_OPENED_STATE);
SendConfigureAck(packet);
ThisLayerUp();
break;
case PPP_OPENED_STATE:
TRACE("%s::%s: PPP_OPENED_STATE\n", __FILE__, __func__);
NewState(PPP_ACK_SENT_STATE);
NewPhase(PPP_ESTABLISHMENT_PHASE);
// indicates to handlers that we are reconfiguring
@@ -938,17 +973,21 @@ KPPPStateMachine::RCRGoodEvent(struct mbuf *packet)
break;
default:
m_freem(packet);
TRACE("free peer's ppp request packet\n");
gBufferModule->free(packet);
}
}
// receive configure request (unacceptable request)
void
KPPPStateMachine::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
KPPPStateMachine::RCRBadEvent(net_buffer *nak, net_buffer *reject)
{
TRACE("KPPPSM: RCRBadEvent() state=%d phase=%d\n", State(), Phase());
uint16 lenNak = 0;
uint16 lenReject = 0;
switch (State()) {
case PPP_INITIAL_STATE:
case PPP_STARTING_STATE:
@@ -978,9 +1017,25 @@ KPPPStateMachine::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
case PPP_REQ_SENT_STATE:
case PPP_ACK_RCVD_STATE:
if (nak && ntohs(mtod(nak, ppp_lcp_packet*)->length) > 3)
if (nak) {
NetBufferHeaderReader<ppp_lcp_packet> nakBufferHeader(nak);
if (nakBufferHeader.Status() < B_OK)
break;
ppp_lcp_packet &nakHeader = nakBufferHeader.Data();
lenNak = nakHeader.length;
}
if (reject) {
NetBufferHeaderReader<ppp_lcp_packet> rejectBufferHeader(reject);
if (rejectBufferHeader.Status() < B_OK)
break;
ppp_lcp_packet &rejectHeader = rejectBufferHeader.Data();
lenReject = rejectHeader.length;
}
if (nak && lenNak > 3)
SendConfigureNak(nak);
else if (reject && ntohs(mtod(reject, ppp_lcp_packet*)->length) > 3)
else if (reject && lenReject > 3)
SendConfigureNak(reject);
return;
// prevents the nak/reject from being m_freem()'d
@@ -990,24 +1045,29 @@ KPPPStateMachine::RCRBadEvent(struct mbuf *nak, struct mbuf *reject)
}
if (nak)
m_freem(nak);
gBufferModule->free(nak);
if (reject)
m_freem(reject);
gBufferModule->free(reject);
}
// receive configure ack
void
KPPPStateMachine::RCAEvent(struct mbuf *packet)
KPPPStateMachine::RCAEvent(net_buffer *packet)
{
TRACE("KPPPSM: RCAEvent() state=%d phase=%d\n", State(), Phase());
if (fRequestID != mtod(packet, ppp_lcp_packet*)->id) {
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return;
ppp_lcp_packet &header = bufferHeader.Data();
if (fRequestID != header.id) {
// this packet is not a reply to our request
// TODO:
// log this event
m_freem(packet);
gBufferModule->free(packet);
return;
}
@@ -1017,7 +1077,7 @@ KPPPStateMachine::RCAEvent(struct mbuf *packet)
for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
optionHandler = LCP().OptionHandlerAt(index);
if (optionHandler->ParseAck(ack) != B_OK) {
m_freem(packet);
gBufferModule->free(packet);
CloseEvent();
return;
}
@@ -1062,22 +1122,27 @@ KPPPStateMachine::RCAEvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
// receive configure nak/reject
void
KPPPStateMachine::RCNEvent(struct mbuf *packet)
KPPPStateMachine::RCNEvent(net_buffer *packet)
{
TRACE("KPPPSM: RCNEvent() state=%d phase=%d\n", State(), Phase());
if (fRequestID != mtod(packet, ppp_lcp_packet*)->id) {
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return;
ppp_lcp_packet &header = bufferHeader.Data();
if (fRequestID != header.id) {
// this packet is not a reply to our request
// TODO:
// log this event
m_freem(packet);
gBufferModule->free(packet);
return;
}
@@ -1089,13 +1154,13 @@ KPPPStateMachine::RCNEvent(struct mbuf *packet)
if (nak_reject.Code() == PPP_CONFIGURE_NAK) {
if (optionHandler->ParseNak(nak_reject) != B_OK) {
m_freem(packet);
gBufferModule->free(packet);
CloseEvent();
return;
}
} else if (nak_reject.Code() == PPP_CONFIGURE_REJECT) {
if (optionHandler->ParseReject(nak_reject) != B_OK) {
m_freem(packet);
gBufferModule->free(packet);
CloseEvent();
return;
}
@@ -1135,18 +1200,23 @@ KPPPStateMachine::RCNEvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
// receive terminate request
void
KPPPStateMachine::RTREvent(struct mbuf *packet)
KPPPStateMachine::RTREvent(net_buffer *packet)
{
TRACE("KPPPSM: RTREvent() state=%d phase=%d\n", State(), Phase());
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return;
ppp_lcp_packet &header = bufferHeader.Data();
// we should not use the same ID as the peer
if (fID == mtod(packet, ppp_lcp_packet*)->id)
if (fID == header.id)
fID -= 128;
fLocalAuthenticationStatus = PPP_NOT_AUTHENTICATED;
@@ -1156,7 +1226,7 @@ KPPPStateMachine::RTREvent(struct mbuf *packet)
case PPP_INITIAL_STATE:
case PPP_STARTING_STATE:
IllegalEvent(PPP_RTR_EVENT);
m_freem(packet);
gBufferModule->free(packet);
break;
case PPP_ACK_RCVD_STATE:
@@ -1186,16 +1256,21 @@ KPPPStateMachine::RTREvent(struct mbuf *packet)
// receive terminate ack
void
KPPPStateMachine::RTAEvent(struct mbuf *packet)
KPPPStateMachine::RTAEvent(net_buffer *packet)
{
TRACE("KPPPSM: RTAEvent() state=%d phase=%d\n", State(), Phase());
if (fTerminateID != mtod(packet, ppp_lcp_packet*)->id) {
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return;
ppp_lcp_packet &header = bufferHeader.Data();
if (fTerminateID != header.id) {
// this packet is not a reply to our request
// TODO:
// log this event
m_freem(packet);
gBufferModule->free(packet);
return;
}
@@ -1231,13 +1306,13 @@ KPPPStateMachine::RTAEvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
// receive unknown code
void
KPPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocolNumber,
KPPPStateMachine::RUCEvent(net_buffer *packet, uint16 protocolNumber,
uint8 code)
{
TRACE("KPPPSM: RUCEvent() state=%d phase=%d\n", State(), Phase());
@@ -1246,7 +1321,7 @@ KPPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocolNumber,
case PPP_INITIAL_STATE:
case PPP_STARTING_STATE:
IllegalEvent(PPP_RUC_EVENT);
m_freem(packet);
gBufferModule->free(packet);
break;
default:
@@ -1257,7 +1332,7 @@ KPPPStateMachine::RUCEvent(struct mbuf *packet, uint16 protocolNumber,
// receive code/protocol reject (acceptable such as IPX reject)
void
KPPPStateMachine::RXJGoodEvent(struct mbuf *packet)
KPPPStateMachine::RXJGoodEvent(net_buffer *packet)
{
TRACE("KPPPSM: RXJGoodEvent() state=%d phase=%d\n", State(), Phase());
@@ -1282,7 +1357,7 @@ KPPPStateMachine::RXJGoodEvent(struct mbuf *packet)
// receive code/protocol reject (catastrophic such as LCP reject)
void
KPPPStateMachine::RXJBadEvent(struct mbuf *packet)
KPPPStateMachine::RXJBadEvent(net_buffer *packet)
{
TRACE("KPPPSM: RXJBadEvent() state=%d phase=%d\n", State(), Phase());
@@ -1321,19 +1396,22 @@ KPPPStateMachine::RXJBadEvent(struct mbuf *packet)
break;
}
m_freem(packet);
gBufferModule->free(packet);
}
// receive echo request/reply, discard request
void
KPPPStateMachine::RXREvent(struct mbuf *packet)
KPPPStateMachine::RXREvent(net_buffer *packet)
{
TRACE("KPPPSM: RXREvent() state=%d phase=%d\n", State(), Phase());
ppp_lcp_packet *echo = mtod(packet, ppp_lcp_packet*);
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return;
ppp_lcp_packet &echo = bufferHeader.Data();
if (echo->code == PPP_ECHO_REPLY && echo->id != fEchoID) {
if (echo.code == PPP_ECHO_REPLY && echo.id != fEchoID) {
// TODO:
// log that we got a reply, but no request was sent
}
@@ -1345,7 +1423,7 @@ KPPPStateMachine::RXREvent(struct mbuf *packet)
break;
case PPP_OPENED_STATE:
if (echo->code == PPP_ECHO_REQUEST)
if (echo.code == PPP_ECHO_REQUEST)
SendEchoReply(packet);
return;
// this prevents the packet from being freed
@@ -1354,7 +1432,7 @@ KPPPStateMachine::RXREvent(struct mbuf *packet)
;
}
m_freem(packet);
gBufferModule->free(packet);
}
@@ -1397,20 +1475,27 @@ KPPPStateMachine::TimerEvent()
// ReceiveConfigureRequest
// Here we get a configure-request packet from LCP and aks all OptionHandlers
// Here we get a configure-request packet from LCP and ask all OptionHandlers
// if its values are acceptable. From here we call our Good/Bad counterparts.
void
KPPPStateMachine::RCREvent(struct mbuf *packet)
KPPPStateMachine::RCREvent(net_buffer *packet)
{
TRACE("KPPPSM: RCREvent() state=%d phase=%d\n", State(), Phase());
TRACE("KPPPSM: RCREvent() state=%d phase=%d lcppacket size=%ld\n", State(), Phase(),
packet->size);
KPPPConfigurePacket request(packet);
KPPPConfigurePacket nak(PPP_CONFIGURE_NAK);
KPPPConfigurePacket reject(PPP_CONFIGURE_REJECT);
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return;
ppp_lcp_packet &header = bufferHeader.Data();
// we should not use the same id as the peer
if (fID == mtod(packet, ppp_lcp_packet*)->id)
if (fID == header.id)
fID -= 128;
// or maybe we should use peer's ID plus 1 ?
nak.SetID(request.ID());
reject.SetID(request.ID());
@@ -1423,11 +1508,23 @@ KPPPStateMachine::RCREvent(struct mbuf *packet)
optionHandler = LCP().OptionHandlerFor(request.ItemAt(index)->type);
if (!optionHandler || !optionHandler->IsEnabled()) {
ERROR("KPPPSM::RCREvent():unknown type:%d\n", request.ItemAt(index)->type);
TRACE("KPPPSM::RCREvent():unknown type:%d\n", request.ItemAt(index)->type);
if (request.ItemAt(index)->type == 0x5)
{
// type 0x5 is Magic Number, Need no processing.
TRACE("Peer Magic Number:%02x %02x %02x %02x\n",
(request.ItemAt(index)->data)[0],
(request.ItemAt(index)->data)[1],
(request.ItemAt(index)->data)[2],
(request.ItemAt(index)->data)[3]);
continue;
} else {
// unhandled items should be added to the reject
TRACE("why come here %ld\n", index);
reject.AddItem(request.ItemAt(index));
continue;
}
}
TRACE("KPPPSM::RCREvent(): OH=%s\n",
optionHandler->Name() ? optionHandler->Name() : "Unknown");
@@ -1435,13 +1532,14 @@ KPPPStateMachine::RCREvent(struct mbuf *packet)
if (result == PPP_UNHANDLED) {
// unhandled items should be added to the reject
TRACE("PPP_UNHANDLED %ld\n", index);
reject.AddItem(request.ItemAt(index));
continue;
} else if (result != B_OK) {
// the request contains a value that has been sent more than
// once or the value is corrupted
ERROR("KPPPSM::RCREvent(): OptionHandler returned parse error!\n");
m_freem(packet);
gBufferModule->free(packet);
CloseEvent();
return;
}
@@ -1460,7 +1558,7 @@ KPPPStateMachine::RCREvent(struct mbuf *packet)
// the request contains a value that has been sent more than
// once or the value is corrupted
ERROR("KPPPSM::RCREvent():OptionHandler returned append error!\n");
m_freem(packet);
gBufferModule->free(packet);
CloseEvent();
return;
}
@@ -1469,11 +1567,13 @@ KPPPStateMachine::RCREvent(struct mbuf *packet)
}
if (reject.CountItems() > 0) {
RCRBadEvent(NULL, reject.ToMbuf(Interface().MRU(), LCP().AdditionalOverhead()));
m_freem(packet);
TRACE("%s:reject number more than 0\n", __func__);
RCRBadEvent(NULL, reject.ToNetBuffer(Interface().MRU()));
gBufferModule->free(packet);
} else if (nak.CountItems() > 0) {
RCRBadEvent(nak.ToMbuf(Interface().MRU(), LCP().AdditionalOverhead()), NULL);
m_freem(packet);
TRACE("%s:nak number more than 0\n", __func__);
RCRBadEvent(nak.ToNetBuffer(Interface().MRU()), NULL);
gBufferModule->free(packet);
} else
RCRGoodEvent(packet);
}
@@ -1483,21 +1583,24 @@ KPPPStateMachine::RCREvent(struct mbuf *packet)
// LCP received a code/protocol-reject packet and we look if it is acceptable.
// From here we call our Good/Bad counterparts.
void
KPPPStateMachine::RXJEvent(struct mbuf *packet)
KPPPStateMachine::RXJEvent(net_buffer *packet)
{
TRACE("KPPPSM: RXJEvent() state=%d phase=%d\n", State(), Phase());
ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*);
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return;
ppp_lcp_packet &reject = bufferHeader.Data();
if (reject->code == PPP_CODE_REJECT) {
uint8 rejectedCode = reject->data[0];
if (reject.code == PPP_CODE_REJECT) {
uint8 rejectedCode = reject.data[0];
// test if the rejected code belongs to the minimum LCP requirements
if (rejectedCode >= PPP_MIN_LCP_CODE && rejectedCode <= PPP_MAX_LCP_CODE) {
if (Interface().IsMultilink() && !Interface().Parent()) {
// Main interfaces do not have states between STARTING and OPENED.
// An RXJBadEvent() would enter one of those states which is bad.
m_freem(packet);
gBufferModule->free(packet);
CloseEvent();
} else
RXJBadEvent(packet);
@@ -1514,10 +1617,10 @@ KPPPStateMachine::RXJEvent(struct mbuf *packet)
lcpExtension->SetEnabled(false);
}
m_freem(packet);
} else if (reject->code == PPP_PROTOCOL_REJECT) {
gBufferModule->free(packet);
} else if (reject.code == PPP_PROTOCOL_REJECT) {
// disable all handlers for rejected protocol type
uint16 rejected = *((uint16*) reject->data);
uint16 rejected = *((uint16*) reject.data);
// rejected protocol number
if (rejected == PPP_LCP_PROTOCOL) {
@@ -1541,7 +1644,7 @@ KPPPStateMachine::RXJEvent(struct mbuf *packet)
if (Interface().Parent())
Interface().Parent()->StateMachine().RXJEvent(packet);
else
m_freem(packet);
gBufferModule->free(packet);
}
}
@@ -1552,7 +1655,7 @@ KPPPStateMachine::IllegalEvent(ppp_event event)
{
// TODO:
// update error statistics
ERROR("KPPPSM: IllegalEvent(event=%d) state=%d phase=%d\n",
TRACE("KPPPSM: IllegalEvent(event=%d) state=%d phase=%d\n",
event, State(), Phase());
}
@@ -1643,48 +1746,60 @@ KPPPStateMachine::SendConfigureRequest()
}
}
return LCP().Send(request.ToMbuf(Interface().MRU(),
LCP().AdditionalOverhead())) == B_OK;
return LCP().Send(request.ToNetBuffer(Interface().MRU())) == B_OK;
}
bool
KPPPStateMachine::SendConfigureAck(struct mbuf *packet)
KPPPStateMachine::SendConfigureAck(net_buffer *packet)
{
TRACE("KPPPSM: SendConfigureAck() state=%d phase=%d\n", State(), Phase());
if (!packet)
return false;
mtod(packet, ppp_lcp_packet*)->code = PPP_CONFIGURE_ACK;
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return false;
ppp_lcp_packet &header = bufferHeader.Data();
header.code = PPP_CONFIGURE_ACK;
bufferHeader.Sync();
KPPPConfigurePacket ack(packet);
// notify all option handlers that we are sending an ack for each value
for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) {
if (LCP().OptionHandlerAt(index)->SendingAck(ack) != B_OK) {
m_freem(packet);
TRACE("%s::%s: SendingAck %ld fail\n", __FILE__, __func__, index);
gBufferModule->free(packet);
CloseEvent();
return false;
}
}
TRACE("%s::%s: LCP().Send\n", __FILE__, __func__);
return LCP().Send(packet) == B_OK;
}
bool
KPPPStateMachine::SendConfigureNak(struct mbuf *packet)
KPPPStateMachine::SendConfigureNak(net_buffer *packet)
{
TRACE("KPPPSM: SendConfigureNak() state=%d phase=%d\n", State(), Phase());
if (!packet)
return false;
ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*);
if (nak->code == PPP_CONFIGURE_NAK) {
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return false;
ppp_lcp_packet &nak = bufferHeader.Data();
if (nak.code == PPP_CONFIGURE_NAK) {
if (fNakCounter == 0) {
// We sent enough naks. Let's try a reject.
nak->code = PPP_CONFIGURE_REJECT;
nak.code = PPP_CONFIGURE_REJECT;
} else
--fNakCounter;
}
@@ -1701,55 +1816,60 @@ KPPPStateMachine::SendTerminateRequest()
--fTerminateCounter;
fNextTimeout = system_time() + kPPPStateMachineTimeout;
struct mbuf *packet = m_gethdr(MT_DATA);
net_buffer *buffer = gBufferModule->create(256);
if (buffer == NULL)
return false;
ppp_lcp_packet *packet;
status_t status = gBufferModule->append_size(buffer, 1492, (void **)&packet);
if (status == B_OK && packet == NULL) {
gBufferModule->free(buffer);
return false;
}
if (!packet)
return false;
packet->m_pkthdr.len = packet->m_len = 4;
packet->code = PPP_TERMINATE_REQUEST;
packet->id = fTerminateID = NextID();
packet->length = htons(4);
// reserve some space for other protocols
packet->m_data += LCP().AdditionalOverhead();
status = gBufferModule->trim(buffer, 4);
if (status < B_OK) {
gBufferModule->free(buffer);
return false;
}
ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*);
request->code = PPP_TERMINATE_REQUEST;
request->id = fTerminateID = NextID();
request->length = htons(4);
return LCP().Send(packet) == B_OK;
return LCP().Send(buffer) == B_OK;
}
bool
KPPPStateMachine::SendTerminateAck(struct mbuf *request)
KPPPStateMachine::SendTerminateAck(net_buffer *request)
{
TRACE("KPPPSM: SendTerminateAck() state=%d phase=%d\n", State(), Phase());
struct mbuf *reply = request;
net_buffer *reply = request;
ppp_lcp_packet *ack;
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(request);
if (bufferHeader.Status() < B_OK)
return false;
ppp_lcp_packet &ack = bufferHeader.Data();
if (!reply) {
reply = m_gethdr(MT_DATA);
if (!reply)
return false;
ack.length = htons(4);
ack.id = NextID();
}
reply->m_data += LCP().AdditionalOverhead();
reply->m_pkthdr.len = reply->m_len = 4;
ack = mtod(reply, ppp_lcp_packet*);
ack->id = NextID();
} else
ack = mtod(reply, ppp_lcp_packet*);
ack->code = PPP_TERMINATE_ACK;
ack->length = htons(4);
ack.code = PPP_TERMINATE_ACK;
ack.length = htons(4);
return LCP().Send(reply) == B_OK;
}
bool
KPPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocolNumber, uint8 code)
KPPPStateMachine::SendCodeReject(net_buffer *packet, uint16 protocolNumber, uint8 code)
{
TRACE("KPPPSM: SendCodeReject(protocolNumber=%X;code=%d) state=%d phase=%d\n",
protocolNumber, code, State(), Phase());
@@ -1764,52 +1884,40 @@ KPPPStateMachine::SendCodeReject(struct mbuf *packet, uint16 protocolNumber, uin
else
length = 4;
M_PREPEND(packet, length);
// add some space for the header
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(packet);
if (bufferHeader.Status() < B_OK)
return false;
ppp_lcp_packet &reject = bufferHeader.Data();
// adjust packet if too big
int32 adjust = Interface().MRU();
if (packet->m_flags & M_PKTHDR) {
adjust -= packet->m_pkthdr.len;
} else
adjust -= packet->m_len;
if (adjust < 0)
m_adj(packet, adjust);
ppp_lcp_packet *reject = mtod(packet, ppp_lcp_packet*);
reject->code = code;
reject->id = NextID();
if (packet->m_flags & M_PKTHDR)
reject->length = htons(packet->m_pkthdr.len);
else
reject->length = htons(packet->m_len);
reject.code = code;
reject.id = NextID();
reject.length = htons(length);
protocolNumber = htons(protocolNumber);
if (code == PPP_PROTOCOL_REJECT)
memcpy(&reject->data, &protocolNumber, sizeof(protocolNumber));
memcpy(&reject.data, &protocolNumber, sizeof(protocolNumber));
return LCP().Send(packet) == B_OK;
}
bool
KPPPStateMachine::SendEchoReply(struct mbuf *request)
KPPPStateMachine::SendEchoReply(net_buffer *request)
{
TRACE("KPPPSM: SendEchoReply() state=%d phase=%d\n", State(), Phase());
if (!request)
return false;
ppp_lcp_packet *reply = mtod(request, ppp_lcp_packet*);
reply->code = PPP_ECHO_REPLY;
NetBufferHeaderReader<ppp_lcp_packet> bufferHeader(request);
if (bufferHeader.Status() < B_OK)
return false;
ppp_lcp_packet &reply = bufferHeader.Data();
reply.code = PPP_ECHO_REPLY;
// the request becomes a reply
if (request->m_flags & M_PKTHDR)
request->m_pkthdr.len = 8;
request->m_len = 8;
memcpy(reply->data, &fMagicNumber, sizeof(fMagicNumber));
memcpy(reply.data, &fMagicNumber, sizeof(fMagicNumber));
return LCP().Send(request) == B_OK;
}
@@ -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,7 +83,7 @@ class KPPPInterface : public KPPPLayer {
{ return fLCP; }
//! Returns the interfac's ifnet structure that is exported to the netstack.
struct ifnet *Ifnet() const
net_device *Ifnet() const
{ return fIfnet; }
const char *Username() 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;
@@ -116,22 +117,22 @@ class KPPPStateMachine {
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);
@@ -142,12 +143,12 @@ 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();
@@ -162,7 +163,7 @@ class KPPPStateMachine {
ppp_state fState;
ppp_phase fPhase;
vint32 fID;
int32 fID;
uint32 fMagicNumber;
int32 fLastConnectionReportCode;
@@ -177,7 +178,7 @@ class KPPPStateMachine {
// 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);
args.data = &info;
args.length = sizeof(ppp_control_info);
control.index = ID();
control.op = op;
control.data = data;
control.length = length;
info.index = ID();
info.op = op;
info.data = data;
info.length = length;
return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args);
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;
@@ -251,8 +383,23 @@ 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;
@@ -269,8 +416,23 @@ 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 (Control(PPPC_CREATE_INTERFACE_WITH_NAME, &info, sizeof(info)) != B_OK)
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;
else
return info.interface;
}
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);
}
@@ -253,14 +347,18 @@ 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;
}
@@ -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
@@ -40,6 +40,12 @@ class PPPInterface {
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
+452 -5
View File
@@ -45,14 +45,16 @@ show(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES)
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;
@@ -179,6 +181,417 @@ connect(const char *name)
}
static
status_t
setuser(const char *name, const char* user)
{
if (!name || strlen(name) == 0)
return -1;
if (!user || strlen(user) == 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.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)
@@ -220,7 +633,7 @@ delete_interface(const char *name)
return -1;
}
if(!manager.DeleteInterface(manager.InterfaceWithName(name))) {
if (!manager.DeleteInterface(name)) {
fprintf(stderr, "Error: Could not delete interface!\n");
return -1;
}
@@ -242,13 +655,20 @@ show_details(const char *name)
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)
@@ -328,6 +748,33 @@ main(int argc, char *argv[])
return delete_interface(argv[2]);
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