diff --git a/build/jam/images/definitions/minimum b/build/jam/images/definitions/minimum index eba4c4f797..0ba75d0aea 100644 --- a/build/jam/images/definitions/minimum +++ b/build/jam/images/definitions/minimum @@ -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 diff --git a/build/jam/packages/Haiku b/build/jam/packages/Haiku index 2f6a054541..4539aadd54 100644 --- a/build/jam/packages/Haiku +++ b/build/jam/packages/Haiku @@ -250,7 +250,7 @@ AddFilesToPackage add-ons kernel network : dns_resolver ; AddFilesToPackage add-ons kernel network devices : $(SYSTEM_NETWORK_DEVICES) ; AddFilesToPackage add-ons kernel network datalink_protocols : $(SYSTEM_NETWORK_DATALINK_PROTOCOLS) ; -AddFilesToPackage add-ons kernel network ppp: $(SYSTEM_NETWORK_PPP) ; +AddFilesToPackage add-ons kernel network ppp : $(SYSTEM_NETWORK_PPP) ; AddFilesToPackage add-ons kernel network protocols : $(SYSTEM_NETWORK_PROTOCOLS) ; diff --git a/build/jam/packages/HaikuBootstrap b/build/jam/packages/HaikuBootstrap index 8d910047c3..72e57ea9b6 100644 --- a/build/jam/packages/HaikuBootstrap +++ b/build/jam/packages/HaikuBootstrap @@ -209,7 +209,7 @@ AddFilesToPackage add-ons kernel network : dns_resolver ; AddFilesToPackage add-ons kernel network devices : $(SYSTEM_NETWORK_DEVICES) ; AddFilesToPackage add-ons kernel network datalink_protocols : $(SYSTEM_NETWORK_DATALINK_PROTOCOLS) ; -AddFilesToPackage add-ons kernel network ppp: $(SYSTEM_NETWORK_PPP) ; +AddFilesToPackage add-ons kernel network ppp : $(SYSTEM_NETWORK_PPP) ; AddFilesToPackage add-ons kernel network protocols : $(SYSTEM_NETWORK_PROTOCOLS) ; diff --git a/src/add-ons/kernel/network/Jamfile b/src/add-ons/kernel/network/Jamfile index 7667873344..5862dab5b7 100644 --- a/src/add-ons/kernel/network/Jamfile +++ b/src/add-ons/kernel/network/Jamfile @@ -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 ; diff --git a/src/add-ons/kernel/network/ppp/Jamfile b/src/add-ons/kernel/network/ppp/Jamfile index 2a05e24e02..0124e016cc 100644 --- a/src/add-ons/kernel/network/ppp/Jamfile +++ b/src/add-ons/kernel/network/ppp/Jamfile @@ -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 ; diff --git a/src/add-ons/kernel/network/ppp/ipcp/Jamfile b/src/add-ons/kernel/network/ppp/ipcp/Jamfile index cb3a5e29e6..9a77ff1c78 100644 --- a/src/add-ons/kernel/network/ppp/ipcp/Jamfile +++ b/src/add-ons/kernel/network/ppp/ipcp/Jamfile @@ -1,41 +1,51 @@ SubDir HAIKU_TOP src add-ons kernel network ppp ipcp ; SetSubDirSupportedPlatformsBeOSCompatible ; +SubDirC++Flags -fno-rtti ; if $(TARGET_PLATFORM) != haiku { - UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ; - # We need the public network headers also when not compiling for Haiku. - # Unfortunately we get more than we want, namely all POSIX headers. + UseHeaders [ FStandardOSHeaders ] : true ; + # Needed for the atomic_add64() prototype. } -# for kernel_cpp.h and BLocker -UseHeaders [ FDirName $(HAIKU_TOP) headers cpp ] : true ; +UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ; + # We need the public network headers also when not compiling for Haiku. + # Unfortunately we get more than we want, namely all POSIX headers. + +UsePrivateKernelHeaders ; UsePrivateHeaders net ; + +UsePrivateHeaders libroot net ; UsePrivateHeaders [ FDirName kernel ] ; UsePrivateHeaders [ FDirName kernel util ] ; UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libkernelppp headers ] : true ; - - -{ - SubDirC++Flags -fno-rtti ; -} - +UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp pppoe + ] : true ; KernelAddon ipcp : - # imported from libnet + atomic.S + kernel_cpp.cpp + + # imported from kernel util inet_addr.c - + ipcp.cpp Protocol.cpp ; + SEARCH on [ FGristFiles inet_addr.c ] - = [ FDirName $(HAIKU_TOP) src kits network compat libnet ] ; + = [ FDirName $(HAIKU_TOP) src system kernel util ] ; + +SEARCH on [ FGristFiles kernel_cpp.cpp ] + = [ FDirName $(HAIKU_TOP) src system kernel util ] ; +SEARCH on [ FGristFiles atomic.S ] + = [ FDirName $(HAIKU_TOP) src system libroot os arch $(TARGET_ARCH) ] ; LinkAgainst ipcp : libkernelppp.a ; -# Installation + HaikuInstall install-networking - : /boot/home/config/add-ons/kernel/obos_network/ppp + : /boot/home/config/add-ons/kernel/network/ppp : ipcp ; diff --git a/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp b/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp index 71054406e0..f6595afa90 100644 --- a/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp +++ b/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp @@ -13,11 +13,29 @@ #include #include +#include + #include -#include -#include + +#include +#include +#include +#include #include +// For updating resolv.conf +#include +#include +#include +#include +#include +#include + +#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 @@ -26,23 +44,23 @@ 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) + if (!packet) return; - + uint8 *data = mtod(packet, uint8*); uint8 buffer[128]; uint8 bufferIndex = 0; - + sprintf((char*) buffer, "Dumping %s packet;len=%ld;pkthdr.len=%d\n", direction, packet->m_len, packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : -1); write(sFD, buffer, strlen((char*) buffer)); - - for(uint32 index = 0; index < packet->m_len; index++) { + + for (uint32 index = 0; index < packet->m_len; index++) { buffer[bufferIndex++] = sDigits[data[index] >> 4]; buffer[bufferIndex++] = sDigits[data[index] & 0x0F]; - if(bufferIndex == 32 || index == packet->m_len - 1) { + if (bufferIndex == 32 || index == packet->m_len - 1) { buffer[bufferIndex++] = '\n'; buffer[bufferIndex] = 0; write(sFD, buffer, strlen((char*) buffer)); @@ -75,18 +93,20 @@ IPCP::IPCP(KPPPInterface& interface, driver_parameter *settings) // reset configurations memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration)); memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration)); - + // reset requests memset(&fLocalRequests, 0, sizeof(ipcp_requests)); memset(&fPeerRequests, 0, sizeof(ipcp_requests)); - + // Parse settings: // "Local" and "Peer" describe each side's settings ParseSideRequests(get_parameter_with_name(IPCP_LOCAL_SIDE_KEY, Settings()), PPP_LOCAL_SIDE); 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 @@ -112,28 +135,28 @@ status_t IPCP::StackControl(uint32 op, void *data) { TRACE("IPCP: StackControl(op=%ld)\n", op); - + // TODO: // check values - - switch(op) { + + switch (op) { case SIOCSIFADDR: break; - + case SIOCSIFFLAGS: break; - + case SIOCSIFDSTADDR: break; - + case SIOCSIFNETMASK: break; - + default: ERROR("IPCP: Unknown ioctl: %ld\n", op); return KPPPProtocol::StackControl(op, data); } - + return B_OK; } @@ -142,23 +165,23 @@ bool IPCP::Up() { TRACE("IPCP: Up() state=%d\n", State()); - + // Servers do not send a configure-request when Up() is called. They wait until // the client requests this protocol. - if(Interface().Mode() == PPP_SERVER_MODE) + if (Interface().Mode() == PPP_SERVER_MODE) return true; - - switch(State()) { + + switch (State()) { case PPP_INITIAL_STATE: NewState(PPP_REQ_SENT_STATE); InitializeRestartCount(); SendConfigureRequest(); break; - + default: ; } - + return true; } @@ -167,49 +190,49 @@ bool IPCP::Down() { TRACE("IPCP: Down() state=%d\n", State()); - - switch(Interface().Phase()) { + + switch (Interface().Phase()) { case PPP_DOWN_PHASE: // interface finished terminating NewState(PPP_INITIAL_STATE); ReportDownEvent(); // this will also reset and update addresses break; - + /* case PPP_TERMINATION_PHASE: // interface is terminating break; - + case PPP_ESTABLISHMENT_PHASE: // interface is reconfiguring break; -*/ +*/ case PPP_ESTABLISHED_PHASE: // terminate this NCP individually (block until we finished terminating) - if(State() != PPP_INITIAL_STATE && State() != PPP_CLOSING_STATE) { + if (State() != PPP_INITIAL_STATE && State() != PPP_CLOSING_STATE) { NewState(PPP_CLOSING_STATE); InitializeRestartCount(); SendTerminateRequest(); } - - while(State() == PPP_CLOSING_STATE) + + while (State() == PPP_CLOSING_STATE) snooze(50000); break; - + default: ; } - + return true; } status_t -IPCP::Send(struct mbuf *packet, uint16 protocolNumber) +IPCP::Send(net_buffer *packet, uint16 protocolNumber) { TRACE("IPCP: Send(0x%X)\n", protocolNumber); - - if((protocolNumber == IP_PROTOCOL && State() == PPP_OPENED_STATE) + + if ((protocolNumber == IP_PROTOCOL && State() == PPP_OPENED_STATE) || protocolNumber == IPCP_PROTOCOL) { #if DEBUG dump_packet(packet, "outgoing"); @@ -217,96 +240,94 @@ IPCP::Send(struct mbuf *packet, uint16 protocolNumber) Interface().UpdateIdleSince(); return SendToNext(packet, 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); - - if(!packet) + + if (!packet) return B_ERROR; - - if(protocolNumber == IP_PROTOCOL) + + if (protocolNumber == IP_PROTOCOL) return ReceiveIPPacket(packet, protocolNumber); - - if(protocolNumber != IPCP_PROTOCOL) + + if (protocolNumber != IPCP_PROTOCOL) return PPP_UNHANDLED; - - ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*); - - // 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) + + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) return B_ERROR; - + ppp_lcp_packet &data = bufferheader.Data(); + + 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; - + case PPP_CONFIGURE_ACK: RCAEvent(packet); break; - + case PPP_CONFIGURE_NAK: case PPP_CONFIGURE_REJECT: RCNEvent(packet); break; - + case PPP_TERMINATE_REQUEST: RTREvent(packet); break; - + case PPP_TERMINATE_ACK: RTAEvent(packet); break; - + case PPP_CODE_REJECT: RXJBadEvent(packet); // we implemented the minimum requirements break; - + default: RUCEvent(packet); return PPP_REJECTED; } - + return B_OK; } status_t -IPCP::ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber) +IPCP::ReceiveIPPacket(net_buffer *packet, uint16 protocolNumber) { - if(protocolNumber != IP_PROTOCOL || State() != PPP_OPENED_STATE) + 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; } } @@ -315,27 +336,27 @@ IPCP::ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber) void IPCP::Pulse() { - if(fNextTimeout == 0 || fNextTimeout > system_time()) + if (fNextTimeout == 0 || fNextTimeout > system_time()) return; fNextTimeout = 0; - - switch(State()) { + + switch (State()) { case PPP_CLOSING_STATE: - if(fTerminateCounter <= 0) + if (fTerminateCounter <= 0) TOBadEvent(); else TOGoodEvent(); break; - + case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: - if(fRequestCounter <= 0) + if (fRequestCounter <= 0) TOBadEvent(); else TOGoodEvent(); break; - + default: ; } @@ -345,128 +366,209 @@ IPCP::Pulse() bool IPCP::ParseSideRequests(const driver_parameter *requests, ppp_side side) { - if(!requests) + if (!requests) return false; - + ipcp_requests *selectedRequests; - - if(side == PPP_LOCAL_SIDE) { + + if (side == PPP_LOCAL_SIDE) { selectedRequests = &fLocalRequests; fRequestPrimaryDNS = fRequestSecondaryDNS = false; } else selectedRequests = &fPeerRequests; - + memset(selectedRequests, 0, sizeof(ipcp_requests)); // reset current requests - + // The following values are allowed: // "Address" the ip address that will be suggested // "Netmask" the netmask that should be used // "PrimaryDNS" primary DNS server // "SecondaryDNS" secondary DNS server // Setting any value to 0.0.0.0 or "auto" means it should be chosen automatically. - + in_addr_t address = INADDR_ANY; - for(int32 index = 0; index < requests->parameter_count; index++) { - if(requests->parameters[index].value_count == 0) + for (int32 index = 0; index < requests->parameter_count; index++) { + if (requests->parameters[index].value_count == 0) continue; - + // all values are IP addresses, so parse the address here - if(strcasecmp(requests->parameters[index].values[0], "auto")) { + if (strcasecmp(requests->parameters[index].values[0], "auto")) { address = inet_addr(requests->parameters[index].values[0]); - if(address == INADDR_NONE) + // address = INADDR_ANY; + if (address == INADDR_NONE) continue; } - - if(!strcasecmp(requests->parameters[index].name, IPCP_IP_ADDRESS_KEY)) + + if (!strcasecmp(requests->parameters[index].name, IPCP_IP_ADDRESS_KEY)) selectedRequests->address = address; - else if(!strcasecmp(requests->parameters[index].name, IPCP_NETMASK_KEY)) + else if (!strcasecmp(requests->parameters[index].name, IPCP_NETMASK_KEY)) selectedRequests->netmask = address; - else if(!strcasecmp(requests->parameters[index].name, IPCP_PRIMARY_DNS_KEY)) { + else if (!strcasecmp(requests->parameters[index].name, IPCP_PRIMARY_DNS_KEY)) { selectedRequests->primaryDNS = address; - if(side == PPP_LOCAL_SIDE) + if (side == PPP_LOCAL_SIDE) fRequestPrimaryDNS = true; - } else if(!strcasecmp(requests->parameters[index].name, + } else if (!strcasecmp(requests->parameters[index].name, IPCP_SECONDARY_DNS_KEY)) { selectedRequests->secondaryDNS = address; - if(side == PPP_LOCAL_SIDE) + if (side == PPP_LOCAL_SIDE) fRequestSecondaryDNS = true; } } - + return true; } +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()) + + 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)); - - // 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)); - - // 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)); - - // 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); - - // 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"); - + + 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}}; + + if (fLocalRequests.address != INADDR_ANY) + 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)); + + 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 + + net_domain* domain = sStackModule->get_domain(AF_INET); + status_t status = set_interface_address(domain, &inreq); + + 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"); - - --fDefaultRoute->rt_refcnt; + if (Side() == PPP_LOCAL_SIDE && pppInterfaceAddress != NULL) { + struct sockaddr addrGateway = {8, AF_INET, {0x00, 0x00, 0x00, 0x00, + 0x00, 0x00} }; + + // 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,21 +576,71 @@ IPCP::UpdateAddresses() void IPCP::RemoveRoutes() { - // note: netstack creates and deletes destination route automatically - - if(fDefaultRoute) { + // 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; memset(&netmask, 0, sizeof(struct sockaddr_in)); - + netmask.sin_family = AF_INET; 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; } } @@ -505,17 +657,17 @@ void IPCP::NewState(ppp_state next) { TRACE("IPCP: NewState(%d) state=%d\n", next, State()); - + // report state changes - if(State() == PPP_INITIAL_STATE && next != State()) + if (State() == PPP_INITIAL_STATE && next != State()) UpStarted(); - else if(State() == PPP_OPENED_STATE && next != State()) + else if (State() == PPP_OPENED_STATE && next != State()) DownStarted(); - + // maybe we do not need the timer anymore - if(next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE) + if (next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE) fNextTimeout = 0; - + fState = next; } @@ -524,22 +676,22 @@ void IPCP::TOGoodEvent() { #if DEBUG -printf("IPCP: TOGoodEvent() state=%d\n", State()); + printf("IPCP: TOGoodEvent() state=%d\n", State()); #endif - - switch(State()) { + + switch (State()) { case PPP_CLOSING_STATE: SendTerminateRequest(); break; - + case PPP_ACK_RCVD_STATE: NewState(PPP_REQ_SENT_STATE); - + case PPP_REQ_SENT_STATE: case PPP_ACK_SENT_STATE: SendConfigureRequest(); break; - + default: IllegalEvent(PPP_TO_GOOD_EVENT); } @@ -550,20 +702,20 @@ void IPCP::TOBadEvent() { TRACE("IPCP: TOBadEvent() state=%d\n", State()); - - switch(State()) { + + switch (State()) { case PPP_CLOSING_STATE: NewState(PPP_INITIAL_STATE); ReportDownEvent(); break; - + case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: NewState(PPP_INITIAL_STATE); ReportUpFailedEvent(); break; - + default: IllegalEvent(PPP_TO_BAD_EVENT); } @@ -571,71 +723,76 @@ IPCP::TOBadEvent() void -IPCP::RCREvent(struct mbuf *packet) +IPCP::RCREvent(net_buffer *packet) { TRACE("IPCP: RCREvent() state=%d\n", State()); - + KPPPConfigurePacket request(packet); KPPPConfigurePacket nak(PPP_CONFIGURE_NAK); KPPPConfigurePacket reject(PPP_CONFIGURE_REJECT); - + + NetBufferHeaderReader 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()); reject.SetID(request.ID()); - + // parse each item ppp_configure_item *item; in_addr_t *requestedAddress, *wishedAddress = NULL; - for(int32 index = 0; index < request.CountItems(); index++) { + for (int32 index = 0; index < request.CountItems(); index++) { item = request.ItemAt(index); - if(!item) + if (!item) continue; - + // addresses have special handling to reduce code size - switch(item->type) { + switch (item->type) { case IPCP_ADDRESSES: // abandoned by the standard case IPCP_ADDRESS: wishedAddress = &fPeerRequests.address; break; - + case IPCP_PRIMARY_DNS: wishedAddress = &fPeerRequests.primaryDNS; break; - + case IPCP_SECONDARY_DNS: wishedAddress = &fPeerRequests.secondaryDNS; break; } - + // now parse item - switch(item->type) { + switch (item->type) { case IPCP_ADDRESSES: // abandoned by the standard case IPCP_ADDRESS: case IPCP_PRIMARY_DNS: case IPCP_SECONDARY_DNS: - if(item->length != 6) { + if (item->length != 6) { // the packet is invalid - m_freem(packet); + gBufferModule->free(packet); NewState(PPP_INITIAL_STATE); ReportUpFailedEvent(); return; } - + requestedAddress = (in_addr_t*) item->data; - if(*wishedAddress == INADDR_ANY) { - if(*requestedAddress == INADDR_ANY) { + 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; } - } else if(*requestedAddress != *wishedAddress) { + } else if (*requestedAddress != *wishedAddress) { // we do not want this address ip_item ipItem; ipItem.type = item->type; @@ -644,18 +801,18 @@ IPCP::RCREvent(struct mbuf *packet) nak.AddItem((ppp_configure_item*) &ipItem); } break; - + // case IPCP_COMPRESSION_PROTOCOL: // TODO: implement me! // break; - + default: reject.AddItem(item); } } - + // append additional values to the nak - if(!request.ItemWithType(IPCP_ADDRESS) && fPeerRequests.address == INADDR_ANY) { + if (!request.ItemWithType(IPCP_ADDRESS) && fPeerRequests.address == INADDR_ANY) { // The peer did not provide us his address. Tell him to do so. ip_item ipItem; ipItem.type = IPCP_ADDRESS; @@ -663,430 +820,467 @@ IPCP::RCREvent(struct mbuf *packet) ipItem.address = INADDR_ANY; nak.AddItem((ppp_configure_item*) &ipItem); } - - if(nak.CountItems() > 0) { - RCRBadEvent(nak.ToMbuf(Interface().MRU(), Interface().PacketOverhead()), NULL); - m_freem(packet); - } else if(reject.CountItems() > 0) { - RCRBadEvent(NULL, reject.ToMbuf(Interface().MRU(), - Interface().PacketOverhead())); - m_freem(packet); + + if (nak.CountItems() > 0) { + RCRBadEvent(nak.ToNetBuffer(Interface().MRU()), NULL); + gBufferModule->free(packet); + } else if (reject.CountItems() > 0) { + 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()); - - switch(State()) { + + switch (State()) { case PPP_INITIAL_STATE: NewState(PPP_ACK_SENT_STATE); InitializeRestartCount(); SendConfigureRequest(); SendConfigureAck(packet); break; - + case PPP_REQ_SENT_STATE: NewState(PPP_ACK_SENT_STATE); - + case PPP_ACK_SENT_STATE: SendConfigureAck(packet); break; - + case PPP_ACK_RCVD_STATE: NewState(PPP_OPENED_STATE); SendConfigureAck(packet); ReportUpEvent(); break; - + case PPP_OPENED_STATE: NewState(PPP_ACK_SENT_STATE); SendConfigureRequest(); SendConfigureAck(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()); - - switch(State()) { + + uint16 lcpHdrRejectLength = 0; + uint16 lcpHdrNakLength = 0; + + if (nak) { + NetBufferHeaderReader nakBufferHeaderReader(nak); + if (nakBufferHeaderReader.Status() != B_OK) + return; + ppp_lcp_packet &lcpNakPacket = nakBufferHeaderReader.Data(); + lcpHdrNakLength = lcpNakPacket.length; + } + + + if (reject) { + NetBufferHeaderReader 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); SendConfigureRequest(); - + case PPP_ACK_SENT_STATE: - if(State() == PPP_ACK_SENT_STATE) + if (State() == PPP_ACK_SENT_STATE) NewState(PPP_REQ_SENT_STATE); // OPENED_STATE might have set this already - + 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 - + default: ; } - - if(nak) - m_freem(nak); - if(reject) - m_freem(reject); + + if (nak) + gBufferModule->free(nak); + if (reject) + gBufferModule->free(reject); } void -IPCP::RCAEvent(struct mbuf *packet) +IPCP::RCAEvent(net_buffer *packet) { - TRACE("IPCP: RCAEvent() state=%d\n", State()); - - if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) { + ERROR("IPCP: RCAEvent() state=%d\n", State()); + + NetBufferHeaderReader 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; } - + // parse this ack KPPPConfigurePacket ack(packet); ppp_configure_item *item; in_addr_t *requestedAddress, *wishedAddress = NULL, *configuredAddress = NULL; - for(int32 index = 0; index < ack.CountItems(); index++) { + for (int32 index = 0; index < ack.CountItems(); index++) { item = ack.ItemAt(index); - if(!item) + if (!item) continue; - + // addresses have special handling to reduce code size - switch(item->type) { + switch (item->type) { case IPCP_ADDRESSES: // abandoned by the standard case IPCP_ADDRESS: wishedAddress = &fLocalRequests.address; configuredAddress = &fLocalConfiguration.address; break; - + case IPCP_PRIMARY_DNS: wishedAddress = &fLocalRequests.primaryDNS; configuredAddress = &fLocalConfiguration.primaryDNS; break; - + case IPCP_SECONDARY_DNS: wishedAddress = &fLocalRequests.secondaryDNS; configuredAddress = &fLocalConfiguration.secondaryDNS; break; } - + // now parse item - switch(item->type) { + switch (item->type) { case IPCP_ADDRESSES: // abandoned by the standard case IPCP_ADDRESS: case IPCP_PRIMARY_DNS: case IPCP_SECONDARY_DNS: requestedAddress = (in_addr_t*) item->data; - if((*wishedAddress == INADDR_ANY && *requestedAddress != INADDR_ANY) + if ((*wishedAddress == INADDR_ANY && *requestedAddress != INADDR_ANY) || *wishedAddress == *requestedAddress) *configuredAddress = *requestedAddress; break; - + // case IPCP_COMPRESSION_PROTOCOL: // TODO: implement me // break; - + default: ; } } - + // if address was not specified we should select the given one - if(!ack.ItemWithType(IPCP_ADDRESS)) + if (!ack.ItemWithType(IPCP_ADDRESS)) fLocalConfiguration.address = fLocalRequests.address; - - - switch(State()) { + + + switch (State()) { case PPP_INITIAL_STATE: IllegalEvent(PPP_RCA_EVENT); break; - + case PPP_REQ_SENT_STATE: NewState(PPP_ACK_RCVD_STATE); InitializeRestartCount(); break; - + case PPP_ACK_RCVD_STATE: NewState(PPP_REQ_SENT_STATE); SendConfigureRequest(); break; - + case PPP_ACK_SENT_STATE: NewState(PPP_OPENED_STATE); InitializeRestartCount(); ReportUpEvent(); break; - + case PPP_OPENED_STATE: NewState(PPP_REQ_SENT_STATE); SendConfigureRequest(); break; - + default: ; } - - 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 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; } - + // parse this nak/reject KPPPConfigurePacket nak_reject(packet); ppp_configure_item *item; in_addr_t *requestedAddress; - if(nak_reject.Code() == PPP_CONFIGURE_NAK) - for(int32 index = 0; index < nak_reject.CountItems(); index++) { + if (nak_reject.Code() == PPP_CONFIGURE_NAK) + for (int32 index = 0; index < nak_reject.CountItems(); index++) { item = nak_reject.ItemAt(index); - if(!item) + if (!item) continue; - - switch(item->type) { + + switch (item->type) { case IPCP_ADDRESSES: // abandoned by the standard case IPCP_ADDRESS: - if(item->length != 6) + if (item->length != 6) continue; - + requestedAddress = (in_addr_t*) item->data; - if(fLocalRequests.address == INADDR_ANY + if (fLocalRequests.address == INADDR_ANY && *requestedAddress != INADDR_ANY) fLocalConfiguration.address = *requestedAddress; // this will be used in our next request break; - + // case IPCP_COMPRESSION_PROTOCOL: // TODO: implement me! // break; - + case IPCP_PRIMARY_DNS: - if(item->length != 6) + if (item->length != 6) continue; - + requestedAddress = (in_addr_t*) item->data; - if(fRequestPrimaryDNS + if (fRequestPrimaryDNS && fLocalRequests.primaryDNS == INADDR_ANY && *requestedAddress != INADDR_ANY) fLocalConfiguration.primaryDNS = *requestedAddress; // this will be used in our next request break; - + case IPCP_SECONDARY_DNS: - if(item->length != 6) + if (item->length != 6) continue; - + requestedAddress = (in_addr_t*) item->data; - if(fRequestSecondaryDNS + if (fRequestSecondaryDNS && fLocalRequests.secondaryDNS == INADDR_ANY && *requestedAddress != INADDR_ANY) fLocalConfiguration.secondaryDNS = *requestedAddress; // this will be used in our next request break; - + default: ; } } - else if(nak_reject.Code() == PPP_CONFIGURE_REJECT) - for(int32 index = 0; index < nak_reject.CountItems(); index++) { + else if (nak_reject.Code() == PPP_CONFIGURE_REJECT) + for (int32 index = 0; index < nak_reject.CountItems(); index++) { item = nak_reject.ItemAt(index); - if(!item) + if (!item) continue; - - switch(item->type) { + + switch (item->type) { // case IPCP_COMPRESSION_PROTOCOL: // TODO: implement me! // break; - + 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; } } - - switch(State()) { + + switch (State()) { case PPP_INITIAL_STATE: IllegalEvent(PPP_RCN_EVENT); break; - + case PPP_REQ_SENT_STATE: case PPP_ACK_SENT_STATE: InitializeRestartCount(); - + case PPP_ACK_RCVD_STATE: case PPP_OPENED_STATE: - if(State() == PPP_ACK_RCVD_STATE || State() == PPP_OPENED_STATE) + if (State() == PPP_ACK_RCVD_STATE || State() == PPP_OPENED_STATE) NewState(PPP_REQ_SENT_STATE); SendConfigureRequest(); break; - + default: ; } - - 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 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()) { + + switch (State()) { case PPP_INITIAL_STATE: IllegalEvent(PPP_RTR_EVENT); break; - + case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: NewState(PPP_REQ_SENT_STATE); - + case PPP_CLOSING_STATE: 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 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; } - - switch(State()) { + + switch (State()) { case PPP_INITIAL_STATE: IllegalEvent(PPP_RTA_EVENT); break; - + case PPP_CLOSING_STATE: NewState(PPP_INITIAL_STATE); ReportDownEvent(); break; - + case PPP_ACK_RCVD_STATE: NewState(PPP_REQ_SENT_STATE); break; - + case PPP_OPENED_STATE: NewState(PPP_REQ_SENT_STATE); SendConfigureRequest(); break; - + default: ; } - - m_freem(packet); + + gBufferModule->free(packet); } void -IPCP::RUCEvent(struct mbuf *packet) +IPCP::RUCEvent(net_buffer *packet) { TRACE("IPCP: RUCEvent() state=%d\n", State()); - + SendCodeReject(packet); } void -IPCP::RXJBadEvent(struct mbuf *packet) +IPCP::RXJBadEvent(net_buffer *packet) { TRACE("IPCP: RXJBadEvent() state=%d\n", State()); - - switch(State()) { + + switch (State()) { case PPP_INITIAL_STATE: IllegalEvent(PPP_RXJ_BAD_EVENT); break; - + case PPP_CLOSING_STATE: NewState(PPP_INITIAL_STATE); ReportDownEvent(); break; - + case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: NewState(PPP_INITIAL_STATE); ReportUpFailedEvent(); break; - + case PPP_OPENED_STATE: NewState(PPP_CLOSING_STATE); InitializeRestartCount(); SendTerminateRequest(); break; - + default: ; } - - m_freem(packet); + + gBufferModule->free(packet); } @@ -1105,9 +1299,9 @@ IPCP::ReportUpFailedEvent() // reset configurations memset(&fLocalConfiguration, 0, sizeof(ipcp_configuration)); memset(&fPeerConfiguration, 0, sizeof(ipcp_configuration)); - + UpdateAddresses(); - + UpFailedEvent(); } @@ -1116,7 +1310,7 @@ void IPCP::ReportUpEvent() { UpdateAddresses(); - + UpEvent(); } @@ -1127,9 +1321,11 @@ IPCP::ReportDownEvent() // reset configurations 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(); } @@ -1156,137 +1352,150 @@ bool IPCP::SendConfigureRequest() { TRACE("IPCP: SendConfigureRequest() state=%d\n", State()); - + --fRequestCounter; fNextTimeout = system_time() + kIPCPStateMachineTimeout; - + KPPPConfigurePacket request(PPP_CONFIGURE_REQUEST); request.SetID(NextID()); fRequestID = request.ID(); ip_item ipItem; ipItem.length = 6; - + // add address ipItem.type = IPCP_ADDRESS; - if(fLocalRequests.address == INADDR_ANY) - ipItem.address = fLocalConfiguration.address; + if (fLocalRequests.address == INADDR_ANY) + 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); - + // add primary DNS (if needed) - if(fRequestPrimaryDNS && fLocalRequests.primaryDNS == INADDR_ANY) { + if (fRequestPrimaryDNS && fLocalRequests.primaryDNS == INADDR_ANY) { ipItem.type = IPCP_PRIMARY_DNS; ipItem.address = fLocalConfiguration.primaryDNS; // at first this is 0.0.0.0, but a nak might have set it to a correct value request.AddItem((ppp_configure_item*) &ipItem); } - + // add secondary DNS (if needed) - if(fRequestSecondaryDNS && fLocalRequests.primaryDNS == INADDR_ANY) { + if (fRequestSecondaryDNS && fLocalRequests.primaryDNS == INADDR_ANY) { ipItem.type = IPCP_SECONDARY_DNS; ipItem.address = fLocalConfiguration.secondaryDNS; // at first this is 0.0.0.0, but a nak might have set it to a correct value request.AddItem((ppp_configure_item*) &ipItem); } - + // 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) + + if (!packet) return false; - - mtod(packet, ppp_lcp_packet*)->code = PPP_CONFIGURE_ACK; + + NetBufferHeaderReader 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 ppp_configure_item *item; in_addr_t *requestedAddress, *wishedAddress = NULL, *configuredAddress = NULL; - for(int32 index = 0; index < ack.CountItems(); index++) { + for (int32 index = 0; index < ack.CountItems(); index++) { item = ack.ItemAt(index); - if(!item) + if (!item) continue; - + // addresses have special handling to reduce code size - switch(item->type) { + switch (item->type) { case IPCP_ADDRESSES: // abandoned by the standard case IPCP_ADDRESS: wishedAddress = &fPeerRequests.address; configuredAddress = &fPeerConfiguration.address; break; - + case IPCP_PRIMARY_DNS: wishedAddress = &fPeerRequests.primaryDNS; configuredAddress = &fPeerConfiguration.primaryDNS; break; - + case IPCP_SECONDARY_DNS: wishedAddress = &fPeerRequests.secondaryDNS; configuredAddress = &fPeerConfiguration.secondaryDNS; break; } - + // now parse item - switch(item->type) { + switch (item->type) { case IPCP_ADDRESSES: // abandoned by the standard case IPCP_ADDRESS: case IPCP_PRIMARY_DNS: case IPCP_SECONDARY_DNS: requestedAddress = (in_addr_t*) item->data; - if((*wishedAddress == INADDR_ANY && *requestedAddress != INADDR_ANY) + if ((*wishedAddress == INADDR_ANY && *requestedAddress != INADDR_ANY) || *wishedAddress == *requestedAddress) *configuredAddress = *requestedAddress; break; - + // case IPCP_COMPRESSION_PROTOCOL: // TODO: implement me! // break; - + default: ; } } - + // if address was not specified we should select the given one - if(!ack.ItemWithType(IPCP_ADDRESS)) + if (!ack.ItemWithType(IPCP_ADDRESS)) fPeerConfiguration.address = fPeerRequests.address; - + return Send(packet) == B_OK; } bool -IPCP::SendConfigureNak(struct mbuf *packet) +IPCP::SendConfigureNak(net_buffer *packet) { TRACE("IPCP: SendConfigureNak() state=%d\n", State()); - - if(!packet) + + if (!packet) return false; - - ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*); - if(nak->code == PPP_CONFIGURE_NAK) { - if(fNakCounter == 0) { + + NetBufferHeaderReader 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; } @@ -1295,85 +1504,82 @@ bool IPCP::SendTerminateRequest() { TRACE("IPCP: SendTerminateRequest() state=%d\n", State()); - + --fTerminateCounter; fNextTimeout = system_time() + kIPCPStateMachineTimeout; - - struct mbuf *packet = m_gethdr(MT_DATA); - if(!packet) + + net_buffer *packet = gBufferModule->create(256); + if (!packet) return false; - - packet->m_pkthdr.len = packet->m_len = 4; - - // reserve some space for other protocols - packet->m_data += Interface().PacketOverhead(); - - ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*); + + ppp_lcp_packet *request; + status_t status = gBufferModule->append_size(packet, 1492, (void **)(&request)); + if (status != B_OK) + return false; + 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; - - if(!reply) { - reply = m_gethdr(MT_DATA); - if(!reply) + + net_buffer *reply = request; + + 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); - + ack->code = PPP_TERMINATE_ACK; + ack->length = htons(4); + gBufferModule->trim(reply, 4); + } else { + NetBufferHeaderReader 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) + + if (!packet) return false; - - M_PREPEND(packet, 4); - // add some space for the header - - // 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 = 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); - + + NetBufferPrepend bufferHeader(packet); + if (bufferHeader.Status() != B_OK) + return false; + + ppp_lcp_packet &reject = bufferHeader.Data(); + + reject.code = PPP_CODE_REJECT; + reject.id = NextID(); + reject.length = htons(packet->size); + + bufferHeader.Sync(); + return Send(packet) == B_OK; } diff --git a/src/add-ons/kernel/network/ppp/ipcp/Protocol.h b/src/add-ons/kernel/network/ppp/ipcp/Protocol.h index 626619b9a2..f8dd13f4a5 100644 --- a/src/add-ons/kernel/network/ppp/ipcp/Protocol.h +++ b/src/add-ons/kernel/network/ppp/ipcp/Protocol.h @@ -9,9 +9,11 @@ #include #include -#include #include +#include +#include +#include #define IPCP_PROTOCOL 0x8021 @@ -60,46 +62,46 @@ class IPCP : public KPPPProtocol { public: IPCP(KPPPInterface& interface, driver_parameter *settings); virtual ~IPCP(); - + virtual void Uninit(); - + ppp_state State() const { return fState; } - + virtual status_t StackControl(uint32 op, void *data); - + virtual bool Up(); virtual bool Down(); - - virtual status_t Send(struct mbuf *packet, + + virtual status_t Send(net_buffer *packet, uint16 protocolNumber = IPCP_PROTOCOL); - virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber); - status_t ReceiveIPPacket(struct mbuf *packet, uint16 protocolNumber); + virtual status_t Receive(net_buffer *packet, uint16 protocolNumber); + status_t ReceiveIPPacket(net_buffer *packet, uint16 protocolNumber); virtual void Pulse(); private: bool ParseSideRequests(const driver_parameter *requests, ppp_side side); void UpdateAddresses(); void RemoveRoutes(); - + // for state machine void NewState(ppp_state next); uint8 NextID(); // return the next id for IPCP packets - + // events void TOGoodEvent(); void TOBadEvent(); - void RCREvent(struct mbuf *packet); - void RCRGoodEvent(struct mbuf *packet); - void RCRBadEvent(struct mbuf *nak, struct mbuf *reject); - void RCAEvent(struct mbuf *packet); - void RCNEvent(struct mbuf *packet); - void RTREvent(struct mbuf *packet); - void RTAEvent(struct mbuf *packet); - void RUCEvent(struct mbuf *packet); - void RXJBadEvent(struct mbuf *packet); - + void RCREvent(net_buffer *packet); + void RCRGoodEvent(net_buffer *packet); + void RCRBadEvent(net_buffer *nak, net_buffer *reject); + void RCAEvent(net_buffer *packet); + void RCNEvent(net_buffer *packet); + void RTREvent(net_buffer *packet); + void RTAEvent(net_buffer *packet); + void RUCEvent(net_buffer *packet); + void RXJBadEvent(net_buffer *packet); + // actions void IllegalEvent(ppp_event event); void ReportUpFailedEvent(); @@ -108,27 +110,27 @@ class IPCP : public KPPPProtocol { void InitializeRestartCount(); void ResetRestartCount(); bool SendConfigureRequest(); - bool SendConfigureAck(struct mbuf *packet); - bool SendConfigureNak(struct mbuf *packet); + bool SendConfigureAck(net_buffer *packet); + bool SendConfigureNak(net_buffer *packet); bool SendTerminateRequest(); - bool SendTerminateAck(struct mbuf *request = NULL); - bool SendCodeReject(struct mbuf *packet); + bool SendTerminateAck(net_buffer *request = NULL); + bool SendCodeReject(net_buffer *packet); private: ipcp_configuration fLocalConfiguration, fPeerConfiguration; ipcp_requests fLocalRequests, fPeerRequests; - + // default route struct sockaddr_in fGateway; - rtentry *fDefaultRoute; - + net_route *fDefaultRoute; + // used for local requests bool fRequestPrimaryDNS, fRequestSecondaryDNS; - + // for state machine ppp_state fState; - vint32 fID; - + int32 fID; + // counters and timers int32 fMaxRequest, fMaxTerminate, fMaxNak; int32 fRequestCounter, fTerminateCounter, fNakCounter; diff --git a/src/add-ons/kernel/network/ppp/ipcp/ipcp.cpp b/src/add-ons/kernel/network/ppp/ipcp/ipcp.cpp index fbf413787f..bfa2f4292d 100644 --- a/src/add-ons/kernel/network/ppp/ipcp/ipcp.cpp +++ b/src/add-ons/kernel/network/ppp/ipcp/ipcp.cpp @@ -5,21 +5,24 @@ #include #include -#include -#include +#include +#include +#include + +#include #include #include #include "Protocol.h" +#define IPCP_MODULE_NAME NETWORK_MODULES_ROOT "/ppp/ipcp" -#define IPCP_MODULE_NAME NETWORK_MODULES_ROOT "ppp/ipcp" - -struct protosw *gProto[IPPROTO_MAX]; -struct core_module_info *core = NULL; status_t std_ops(int32 op, ...); +net_stack_module_info *gStackModule = NULL; +net_buffer_module_info *gBufferModule = NULL; + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // TODO: Remove isascii() (needed for inet_aton()) when our kernel is finished! @@ -28,7 +31,7 @@ extern "C" int isascii(char c) { - return c & ~0x7f == 0; // If c is a 7 bit value. + return ((c & (~0x7f)) == 0); // If c is a 7 bit value. } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX @@ -38,22 +41,22 @@ bool add_to(KPPPInterface& mainInterface, KPPPInterface *subInterface, driver_parameter *settings, ppp_module_key_type type) { - if(type != PPP_PROTOCOL_KEY_TYPE) + if (type != PPP_PROTOCOL_KEY_TYPE) return B_ERROR; - + IPCP *ipcp; bool success; - if(subInterface) { + if (subInterface) { ipcp = new IPCP(*subInterface, settings); success = subInterface->AddProtocol(ipcp); } else { ipcp = new IPCP(mainInterface, settings); success = mainInterface.AddProtocol(ipcp); } - + TRACE("IPCP: add_to(): %s\n", success && ipcp && ipcp->InitCheck() == B_OK ? "OK" : "ERROR"); - + return success && ipcp && ipcp->InitCheck() == B_OK; } @@ -71,24 +74,30 @@ static ppp_module_info ipcp_module = { _EXPORT status_t -std_ops(int32 op, ...) +std_ops(int32 op, ...) { - switch(op) { + switch (op) { case B_MODULE_INIT: - if(get_module(NET_CORE_MODULE_NAME, (module_info**) &core) != B_OK) + if (get_module(NET_STACK_MODULE_NAME, + (module_info**) &gStackModule) != B_OK) return B_ERROR; - memset(gProto, 0, sizeof(struct protosw*) * IPPROTO_MAX); - add_protosw(gProto, NET_LAYER1); - return B_OK; - + if (get_module(NET_BUFFER_MODULE_NAME, + (module_info **)&gBufferModule) != B_OK) { + put_module(NET_STACK_MODULE_NAME); + return B_ERROR; + } + return B_OK; + break; + case B_MODULE_UNINIT: - put_module(NET_CORE_MODULE_NAME); - break; - + put_module(NET_BUFFER_MODULE_NAME); + put_module(NET_STACK_MODULE_NAME); + break; + default: return B_ERROR; } - + return B_OK; } diff --git a/src/add-ons/kernel/network/ppp/pap/Jamfile b/src/add-ons/kernel/network/ppp/pap/Jamfile index f6781b512d..935a09020f 100644 --- a/src/add-ons/kernel/network/ppp/pap/Jamfile +++ b/src/add-ons/kernel/network/ppp/pap/Jamfile @@ -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 ; diff --git a/src/add-ons/kernel/network/ppp/pap/Protocol.cpp b/src/add-ons/kernel/network/ppp/pap/Protocol.cpp index 29d87606d9..904f49bf18 100644 --- a/src/add-ons/kernel/network/ppp/pap/Protocol.cpp +++ b/src/add-ons/kernel/network/ppp/pap/Protocol.cpp @@ -9,9 +9,9 @@ #include #include -#include -#include +#include +#include static const bigtime_t kPAPTimeout = 3000000; // 3 seconds @@ -34,20 +34,28 @@ PAPHandler::PAPHandler(PAP& owner, KPPPInterface& interface) } +status_t +PAPHandler::SendingAck(const KPPPConfigurePacket& ack) +{ + TRACE("%s::%s: We should activate PAP Protocol here\n", __FILE__, __func__); + return KPPPOptionHandler::SendingAck(ack); +} + + status_t PAPHandler::AddToRequest(KPPPConfigurePacket& request) { // only local authenticators send requests to peer - if(Owner().Side() != PPP_PEER_SIDE) + if (Owner().Side() != PPP_PEER_SIDE) return B_OK; - + authentication_item item; item.type = kAuthenticationType; item.length = sizeof(item); item.protocolNumber = htons(PAP_PROTOCOL); - + request.AddItem((ppp_configure_item*) &item); - + return B_OK; } @@ -57,15 +65,15 @@ PAPHandler::ParseRequest(const KPPPConfigurePacket& request, int32 index, KPPPConfigurePacket& nak, KPPPConfigurePacket& reject) { // only local authenticators handle requests from peer - if(Owner().Side() != PPP_LOCAL_SIDE) + if (Owner().Side() != PPP_LOCAL_SIDE) return B_OK; - + // we merely check if the values are correct authentication_item *item = (authentication_item*) request.ItemAt(index); - if(item->type != kAuthenticationType + if (item->type != kAuthenticationType || item->length != 4 || ntohs(item->protocolNumber) != PAP_PROTOCOL) return B_ERROR; - + return B_OK; } @@ -92,9 +100,9 @@ PAP::~PAP() status_t PAP::InitCheck() const { - if(Side() != PPP_LOCAL_SIDE && Side() != PPP_PEER_SIDE) + if (Side() != PPP_LOCAL_SIDE && Side() != PPP_PEER_SIDE) return B_ERROR; - + return KPPPProtocol::InitCheck(); } @@ -103,14 +111,14 @@ bool PAP::Up() { TRACE("PAP: Up() state=%d\n", State()); - - switch(State()) { + + switch (State()) { case INITIAL: - if(Side() == PPP_LOCAL_SIDE) { + if (Side() == PPP_LOCAL_SIDE) { NewState(REQ_SENT); InitializeRestartCount(); SendRequest(); - } else if(Side() == PPP_PEER_SIDE) { + } else if (Side() == PPP_PEER_SIDE) { NewState(WAITING_FOR_REQ); InitializeRestartCount(); fNextTimeout = system_time() + kPAPTimeout; @@ -119,11 +127,11 @@ PAP::Up() return false; } break; - + default: ; } - + return true; } @@ -132,8 +140,8 @@ bool PAP::Down() { TRACE("PAP: Down() state=%d\n", State()); - - switch(Interface().Phase()) { + + switch (Interface().Phase()) { case PPP_DOWN_PHASE: // interface finished terminating case PPP_ESTABLISHED_PHASE: @@ -141,82 +149,83 @@ PAP::Down() NewState(INITIAL); DownEvent(); break; - + /* case PPP_TERMINATION_PHASE: // interface is terminating break; - + case PPP_ESTABLISHMENT_PHASE: // interface is reconfiguring break; -*/ +*/ default: ; } - + return true; } status_t -PAP::Send(struct mbuf *packet, uint16 protocolNumber) +PAP::Send(net_buffer *packet, uint16 protocolNumber) { // we do not encapsulate PAP packets - m_freem(packet); + TRACE("PAP: we should not send packet!\n"); + if (packet != NULL) + gBufferModule->free(packet); return B_ERROR; } status_t -PAP::Receive(struct mbuf *packet, uint16 protocolNumber) +PAP::Receive(net_buffer *packet, uint16 protocolNumber) { - if(!packet) + if (!packet) return B_ERROR; - - if(protocolNumber != PAP_PROTOCOL) + + if (protocolNumber != PAP_PROTOCOL) return PPP_UNHANDLED; - - ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*); - + + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) + return B_ERROR; + ppp_lcp_packet &data = bufferheader.Data(); + // check if the packet is meant for us: // only peer authenticators handle requests - if(data->code == PPP_CONFIGURE_REQUEST && Side() != PPP_PEER_SIDE) + if (data.code == PPP_CONFIGURE_REQUEST && Side() != PPP_PEER_SIDE) return PPP_UNHANDLED; // only local authenticators handle acks and naks - if((data->code == PPP_CONFIGURE_ACK || data->code == PPP_CONFIGURE_NAK) + if ((data.code == PPP_CONFIGURE_ACK || data.code == PPP_CONFIGURE_NAK) && Side() != PPP_LOCAL_SIDE) return PPP_UNHANDLED; - + // remove padding - int32 length = packet->m_len; - if(packet->m_flags & M_PKTHDR) - length = packet->m_pkthdr.len; - length -= ntohs(data->length); - if(length) - m_adj(packet, -length); - - if(ntohs(data->length) < 4) + int32 length = packet->size; + length -= ntohs(data.length); + + if (ntohs(data.length) < 4) return B_ERROR; - + // packet is freed by event methods // code values are the same as for LCP (but very reduced) - switch(data->code) { + switch (data.code) { case PPP_CONFIGURE_REQUEST: RREvent(packet); break; - + case PPP_CONFIGURE_ACK: RAEvent(packet); break; - + case PPP_CONFIGURE_NAK: RNEvent(packet); break; - + default: return PPP_UNHANDLED; } - + return B_OK; } @@ -224,19 +233,19 @@ PAP::Receive(struct mbuf *packet, uint16 protocolNumber) void PAP::Pulse() { - if(fNextTimeout == 0 || fNextTimeout > system_time()) + if (fNextTimeout == 0 || fNextTimeout > system_time()) return; fNextTimeout = 0; - - switch(State()) { + + switch (State()) { case REQ_SENT: case WAITING_FOR_REQ: - if(fRequestCounter <= 0) + if (fRequestCounter <= 0) TOBadEvent(); else TOGoodEvent(); break; - + default: ; } @@ -254,22 +263,22 @@ void PAP::NewState(pap_state next) { TRACE("PAP: NewState(%d) state=%d\n", next, State()); - + // state changes - if(State() == INITIAL && next != State()) { - if(Side() == PPP_LOCAL_SIDE) + if (State() == INITIAL && next != State()) { + if (Side() == PPP_LOCAL_SIDE) Interface().StateMachine().LocalAuthenticationRequested(); - else if(Side() == PPP_PEER_SIDE) + else if (Side() == PPP_PEER_SIDE) Interface().StateMachine().PeerAuthenticationRequested(); - + UpStarted(); - } else if(State() == ACCEPTED && next != State()) + } else if (State() == ACCEPTED && next != State()) DownStarted(); - + // maybe we do not need the timer anymore - if(next == INITIAL || next == ACCEPTED) + if (next == INITIAL || next == ACCEPTED) fNextTimeout = 0; - + fState = next; } @@ -278,16 +287,16 @@ void PAP::TOGoodEvent() { TRACE("PAP: TOGoodEvent() state=%d\n", State()); - - switch(State()) { + + switch (State()) { case REQ_SENT: SendRequest(); break; - + case WAITING_FOR_REQ: fNextTimeout = system_time() + kPAPTimeout; break; - + default: ; } @@ -298,21 +307,21 @@ void PAP::TOBadEvent() { TRACE("PAP: TOBadEvent() state=%d\n", State()); - - switch(State()) { + + switch (State()) { case REQ_SENT: case WAITING_FOR_REQ: NewState(INITIAL); - if(State() == REQ_SENT) + if (State() == REQ_SENT) Interface().StateMachine().LocalAuthenticationDenied( Interface().Username()); else Interface().StateMachine().PeerAuthenticationDenied( Interface().Username()); - + UpFailedEvent(); break; - + default: ; } @@ -320,27 +329,30 @@ PAP::TOBadEvent() void -PAP::RREvent(struct mbuf *packet) +PAP::RREvent(net_buffer *packet) { TRACE("PAP: RREvent() state=%d\n", State()); - - ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*); - int32 length = ntohs(request->length); - uint8 *data = request->data; + + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) + return; + ppp_lcp_packet &request = bufferheader.Data(); + int32 length = ntohs(request.length); + uint8 *data = request.data; uint8 *userLength = data; uint8 *passwordLength = data + 1 + data[0]; - + // make sure the length values are all okay - if(6 + *userLength + *passwordLength > length) { - m_freem(packet); + if (6 + *userLength + *passwordLength > length) { + gBufferModule->free(packet); return; } - + char *peerUsername = (char*) userLength + 1, *peerPassword = (char*) passwordLength + 1; const char *username = Interface().Username(), *password = Interface().Password(); - - if(*userLength == strlen(username) && *passwordLength == strlen(password) + + if (*userLength == strlen(username) && *passwordLength == strlen(password) && !strncmp(peerUsername, username, *userLength) && !strncmp(peerPassword, password, *passwordLength)) { NewState(ACCEPTED); @@ -357,60 +369,68 @@ PAP::RREvent(struct mbuf *packet) void -PAP::RAEvent(struct mbuf *packet) +PAP::RAEvent(net_buffer *packet) { TRACE("PAP: RAEvent() state=%d\n", State()); - - if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) { + + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) + return; + ppp_lcp_packet &lcp_hdr = bufferheader.Data(); + if (fRequestID != lcp_hdr.id) { // this packet is not a reply to our request - + // TODO: log this event - m_freem(packet); + gBufferModule->free(packet); return; } - - switch(State()) { + + switch (State()) { case REQ_SENT: NewState(ACCEPTED); Interface().StateMachine().LocalAuthenticationAccepted( Interface().Username()); UpEvent(); break; - + default: ; } - - m_freem(packet); + + gBufferModule->free(packet); } void -PAP::RNEvent(struct mbuf *packet) +PAP::RNEvent(net_buffer *packet) { TRACE("PAP: RNEvent() state=%d\n", State()); - - if(fRequestID != mtod(packet, ppp_lcp_packet*)->id) { + + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) + return; + ppp_lcp_packet &lcp_hdr = bufferheader.Data(); + if (fRequestID != lcp_hdr.id) { // this packet is not a reply to our request - + // TODO: log this event - m_freem(packet); + gBufferModule->free(packet); return; } - - switch(State()) { + + switch (State()) { case REQ_SENT: NewState(INITIAL); Interface().StateMachine().LocalAuthenticationDenied( Interface().Username()); UpFailedEvent(); break; - + default: ; } - - m_freem(packet); + + gBufferModule->free(packet); } @@ -425,72 +445,76 @@ bool PAP::SendRequest() { TRACE("PAP: SendRequest() state=%d\n", State()); - + --fRequestCounter; fNextTimeout = system_time() + kPAPTimeout; - - struct mbuf *packet = m_gethdr(MT_DATA); - if(!packet) + + net_buffer *packet = gBufferModule->create(256); + if (!packet) return false; - + + ppp_lcp_packet *request; + gBufferModule->append_size(packet, 1492, (void **)&request); + const char *username = Interface().Username(), *password = Interface().Password(); - - packet->m_pkthdr.len = packet->m_len = 6 + strlen(username) + strlen(password); - - // reserve some space for overhead (we are lazy and reserve too much) - packet->m_data += Interface().PacketOverhead(); - - ppp_lcp_packet *request = mtod(packet, ppp_lcp_packet*); + uint16 packcketLenth = 6 + strlen(username) + strlen(password); + // 6 : lcp header 4 byte + username length 1 byte + password length 1 byte + request->code = PPP_CONFIGURE_REQUEST; request->id = fRequestID = NextID(); - request->length = htons(packet->m_len); + request->length = htons(packcketLenth); uint8 *data = request->data; data[0] = strlen(username); memcpy(data + 1, username, strlen(username)); data[1 + data[0]] = strlen(password); memcpy(data + 2 + data[0], password, strlen(password)); - + + gBufferModule->trim(packet, packcketLenth); + return Interface().Send(packet, PAP_PROTOCOL) == B_OK; } bool -PAP::SendAck(struct mbuf *packet) +PAP::SendAck(net_buffer *packet) { TRACE("PAP: SendAck() state=%d\n", State()); - - if(!packet) + + if (!packet) return false; - - ppp_lcp_packet *ack = mtod(packet, ppp_lcp_packet*); - ack->code = PPP_CONFIGURE_ACK; - packet->m_len = 5; - if(packet->m_flags & M_PKTHDR) - packet->m_pkthdr.len = 5; - ack->length = htons(packet->m_len); - - ack->data[0] = 0; - + + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) + return false; + ppp_lcp_packet &ack = bufferheader.Data(); + + ack.code = PPP_CONFIGURE_ACK; + ack.length = htons(5); + ack.data[0] = 0; + gBufferModule->trim(packet, 5); + + bufferheader.Sync(); + return Interface().Send(packet, PAP_PROTOCOL) == B_OK; } bool -PAP::SendNak(struct mbuf *packet) +PAP::SendNak(net_buffer *packet) { - TRACE("PAP: SendNak() state=%d\n", State()); - - if(!packet) + ERROR("PAP: SendNak() state=%d\n", State()); + + if (!packet) return false; - - ppp_lcp_packet *nak = mtod(packet, ppp_lcp_packet*); - nak->code = PPP_CONFIGURE_NAK; - packet->m_len = 5; - if(packet->m_flags & M_PKTHDR) - packet->m_pkthdr.len = 5; - nak->length = htons(packet->m_len); - - nak->data[0] = 0; - + + NetBufferHeaderReader 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; } diff --git a/src/add-ons/kernel/network/ppp/pap/Protocol.h b/src/add-ons/kernel/network/ppp/pap/Protocol.h index 43a1bc7dea..db715862bf 100644 --- a/src/add-ons/kernel/network/ppp/pap/Protocol.h +++ b/src/add-ons/kernel/network/ppp/pap/Protocol.h @@ -31,11 +31,12 @@ class PAP; class PAPHandler : public KPPPOptionHandler { public: PAPHandler(PAP& owner, KPPPInterface& interface); - + PAP& Owner() const { return fOwner; } - + virtual status_t AddToRequest(KPPPConfigurePacket& request); + virtual status_t SendingAck(const KPPPConfigurePacket&); virtual status_t ParseRequest(const KPPPConfigurePacket& request, int32 index, KPPPConfigurePacket& nak, KPPPConfigurePacket& reject); @@ -48,17 +49,17 @@ class PAP : public KPPPProtocol { public: PAP(KPPPInterface& interface, driver_parameter *settings); virtual ~PAP(); - + virtual status_t InitCheck() const; - + pap_state State() const { return fState; } - + virtual bool Up(); virtual bool Down(); - - virtual status_t Send(struct mbuf *packet, uint16 protocolNumber); - virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber); + + virtual status_t Send(net_buffer *packet, uint16 protocolNumber); + virtual status_t Receive(net_buffer *packet, uint16 protocolNumber); virtual void Pulse(); private: @@ -66,28 +67,28 @@ class PAP : public KPPPProtocol { void NewState(pap_state next); uint8 NextID(); // return the next id for PAP packets - + // events void TOGoodEvent(); void TOBadEvent(); - void RREvent(struct mbuf *packet); - void RAEvent(struct mbuf *packet); - void RNEvent(struct mbuf *packet); - + void RREvent(net_buffer *packet); + void RAEvent(net_buffer *packet); + void RNEvent(net_buffer *packet); + // actions void ReportUpFailedEvent(); void ReportUpEvent(); void ReportDownEvent(); void InitializeRestartCount(); bool SendRequest(); - bool SendAck(struct mbuf *packet); - bool SendNak(struct mbuf *packet); + bool SendAck(net_buffer *packet); + bool SendNak(net_buffer *packet); private: // for state machine pap_state fState; - vint32 fID; - + int32 fID; + // counters and timers int32 fMaxRequest; int32 fRequestCounter; diff --git a/src/add-ons/kernel/network/ppp/pap/pap.cpp b/src/add-ons/kernel/network/ppp/pap/pap.cpp index 5805238bdb..714df952ab 100644 --- a/src/add-ons/kernel/network/ppp/pap/pap.cpp +++ b/src/add-ons/kernel/network/ppp/pap/pap.cpp @@ -5,42 +5,41 @@ #include #include -#include -#include + +#include +#include #include #include #include "Protocol.h" +#define PAP_MODULE_NAME NETWORK_MODULES_ROOT "/ppp/pap" -#define PAP_MODULE_NAME NETWORK_MODULES_ROOT "ppp/pap" - -struct core_module_info *core = NULL; +net_stack_module_info *gStackModule = NULL; +net_buffer_module_info *gBufferModule = NULL; status_t std_ops(int32 op, ...); - -static -bool +static bool add_to(KPPPInterface& mainInterface, KPPPInterface *subInterface, driver_parameter *settings, ppp_module_key_type type) { - if(type != PPP_AUTHENTICATOR_KEY_TYPE) + if (type != PPP_AUTHENTICATOR_KEY_TYPE) return B_ERROR; - + PAP *pap; bool success; - if(subInterface) { + if (subInterface) { pap = new PAP(*subInterface, settings); success = subInterface->AddProtocol(pap); } else { pap = new PAP(mainInterface, settings); success = mainInterface.AddProtocol(pap); } - + TRACE("PAP: add_to(): %s\n", success && pap && pap->InitCheck() == B_OK ? "OK" : "ERROR"); - + return success && pap && pap->InitCheck() == B_OK; } @@ -58,22 +57,28 @@ static ppp_module_info pap_module = { _EXPORT status_t -std_ops(int32 op, ...) +std_ops(int32 op, ...) { - switch(op) { + switch (op) { case B_MODULE_INIT: - if(get_module(NET_CORE_MODULE_NAME, (module_info**) &core) != B_OK) + if (get_module(NET_STACK_MODULE_NAME, (module_info**) &gStackModule) != B_OK) return B_ERROR; + if (get_module(NET_BUFFER_MODULE_NAME, + (module_info **)&gBufferModule) != B_OK) { + put_module(NET_STACK_MODULE_NAME); + return B_ERROR; + } return B_OK; - + case B_MODULE_UNINIT: - put_module(NET_CORE_MODULE_NAME); + put_module(NET_BUFFER_MODULE_NAME); + put_module(NET_STACK_MODULE_NAME); break; - + default: return B_ERROR; } - + return B_OK; } diff --git a/src/add-ons/kernel/network/ppp/ppp/Jamfile b/src/add-ons/kernel/network/ppp/ppp/Jamfile new file mode 100644 index 0000000000..fb2871010e --- /dev/null +++ b/src/add-ons/kernel/network/ppp/ppp/Jamfile @@ -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 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 ; diff --git a/src/add-ons/kernel/network/ppp/ppp/ppp.cpp b/src/add-ons/kernel/network/ppp/ppp/ppp.cpp new file mode 100644 index 0000000000..a596f22d11 --- /dev/null +++ b/src/add-ons/kernel/network/ppp/ppp/ppp.cpp @@ -0,0 +1,388 @@ +/* + * Copyright 2014, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Lin Longzhou, linlongzhou@163.com + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#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 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; + // 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 +}; diff --git a/src/add-ons/kernel/network/ppp/ppp_frame/Jamfile b/src/add-ons/kernel/network/ppp/ppp_frame/Jamfile new file mode 100644 index 0000000000..f983095ae0 --- /dev/null +++ b/src/add-ons/kernel/network/ppp/ppp_frame/Jamfile @@ -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 ; diff --git a/src/add-ons/kernel/network/ppp/ppp_frame/ppp_frame.cpp b/src/add-ons/kernel/network/ppp/ppp_frame/ppp_frame.cpp new file mode 100644 index 0000000000..219b658a22 --- /dev/null +++ b/src/add-ons/kernel/network/ppp/ppp_frame/ppp_frame.cpp @@ -0,0 +1,265 @@ +/* + * Copyright 2014, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Lin Longzhou, linlongzhou@163.com + */ + + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +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 +}; diff --git a/src/add-ons/kernel/network/ppp/ppp_manager/Jamfile b/src/add-ons/kernel/network/ppp/ppp_manager/Jamfile new file mode 100644 index 0000000000..8b6f9d1470 --- /dev/null +++ b/src/add-ons/kernel/network/ppp/ppp_manager/Jamfile @@ -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 ; diff --git a/src/add-ons/kernel/network/ppp/ppp_manager/KPPPManager.cpp b/src/add-ons/kernel/network/ppp/ppp_manager/KPPPManager.cpp new file mode 100644 index 0000000000..ef0c19db04 --- /dev/null +++ b/src/add-ons/kernel/network/ppp/ppp_manager/KPPPManager.cpp @@ -0,0 +1,373 @@ +/* + * Copyright 2006-2014, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + * Lin Longzhou, linlongzhou@163.com + */ + +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + + +struct entry_private : ppp_interface_entry, DoublyLinkedListLinkImpl { +}; + +static DoublyLinkedList 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::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::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::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::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::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::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::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; + // 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 +}; diff --git a/src/add-ons/kernel/network/ppp/pppoe/DiscoveryPacket.cpp b/src/add-ons/kernel/network/ppp/pppoe/DiscoveryPacket.cpp index 3f7a227986..74670c14b3 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/DiscoveryPacket.cpp +++ b/src/add-ons/kernel/network/ppp/pppoe/DiscoveryPacket.cpp @@ -3,11 +3,12 @@ * Distributed under the terms of the MIT License. */ +#include +#include +#include + #include "DiscoveryPacket.h" -#include - - 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 bufferheader(packet); + if (bufferheader.Status() != B_OK) { + dprintf("NetBufferHeaderReader create fail\n"); + fInitStatus = B_ERROR; + return; + } + pppoe_header &header = bufferheader.Data(); - SetCode(header->code); + SetCode(header.code); - uint16 length = ntohs(header->length); + uint16 length = ntohs(header.length); - if(length > packet->m_len - PPPoE_HEADER_SIZE - start) { + if(length > packet->size - PPPoE_HEADER_SIZE) { + dprintf("packet size less than pppoe payload\n"); + dprintf("pppoe payload:%d\n", length); + dprintf("PPPoE_HEADER_SIZE:%d\n", PPPoE_HEADER_SIZE); + dprintf("packet->size:%ld\n", packet->size); fInitStatus = B_ERROR; return; // there are no tags (or one corrupted tag) @@ -37,7 +46,7 @@ DiscoveryPacket::DiscoveryPacket(struct mbuf *packet, uint32 start) pppoe_tag *tag; while(position <= length - 4) { - tag = (pppoe_tag*) (header->data + position); + tag = (pppoe_tag*) (header.data + position); position += ntohs(tag->length) + 4; AddTag(ntohs(tag->type), tag->data, ntohs(tag->length)); @@ -116,13 +125,21 @@ DiscoveryPacket::TagWithType(uint16 type) const } -struct mbuf* -DiscoveryPacket::ToMbuf(uint32 MTU, uint32 reserve) +net_buffer* +DiscoveryPacket::ToNetBuffer(uint32 MTU) { - struct mbuf *packet = m_gethdr(MT_DATA); - packet->m_data += reserve; - - pppoe_header *header = mtod(packet, pppoe_header*); + net_buffer *packet = gBufferModule->create(256); + if (packet == NULL) { + dprintf("create buffer failure\n"); + return NULL; + } + + pppoe_header *header ; + status_t status = gBufferModule->append_size(packet, 1492, (void **)&header); + if (status != B_OK) { + dprintf("append size failure\n"); + return NULL; + } header->version = PPPoE_VERSION; header->type = PPPoE_TYPE; @@ -137,7 +154,7 @@ DiscoveryPacket::ToMbuf(uint32 MTU, uint32 reserve) // make sure we have enough space left if(MTU - length < tag->length) { - m_freem(packet); + gBufferModule->free(packet); return NULL; } @@ -150,7 +167,11 @@ DiscoveryPacket::ToMbuf(uint32 MTU, uint32 reserve) } header->length = htons(length); - packet->m_pkthdr.len = packet->m_len = length + PPPoE_HEADER_SIZE; - + status = gBufferModule->trim(packet, length + PPPoE_HEADER_SIZE); + if (status != B_OK) { + dprintf("trim buffer failure\n"); + return NULL; + } + return packet; } diff --git a/src/add-ons/kernel/network/ppp/pppoe/DiscoveryPacket.h b/src/add-ons/kernel/network/ppp/pppoe/DiscoveryPacket.h index 6c0416ffe0..1e1f650062 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/DiscoveryPacket.h +++ b/src/add-ons/kernel/network/ppp/pppoe/DiscoveryPacket.h @@ -10,6 +10,7 @@ #include +#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; diff --git a/src/add-ons/kernel/network/ppp/pppoe/Jamfile b/src/add-ons/kernel/network/ppp/pppoe/Jamfile index c4abfdae2d..13087b05ed 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/Jamfile +++ b/src/add-ons/kernel/network/ppp/pppoe/Jamfile @@ -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 ; diff --git a/src/add-ons/kernel/network/ppp/pppoe/PPPoE.h b/src/add-ons/kernel/network/ppp/pppoe/PPPoE.h index 6bb9350532..4b14d15c21 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/PPPoE.h +++ b/src/add-ons/kernel/network/ppp/pppoe/PPPoE.h @@ -8,10 +8,15 @@ #include #include -#include + +#include +#include +#include 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 diff --git a/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp b/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp index 70c49ddd1d..e749483f0c 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp +++ b/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp @@ -3,41 +3,57 @@ * Distributed under the terms of the MIT License. */ +#include + +#include +#include +#include + +#include +#include + #include "PPPoEDevice.h" #include "DiscoveryPacket.h" -#include -#include - // from libkernelppp #include +extern net_stack_module_info *gStackModule; +extern net_buffer_module_info *gBufferModule; +extern status_t +pppoe_input(void *cookie, net_device *_device, net_buffer *packet); #if DEBUG static char sDigits[] = "0123456789ABCDEF"; void -dump_packet(struct mbuf *packet) +dump_packet(net_buffer *packet) { - if(!packet) + if (!packet) return; - - uint8 *data = mtod(packet, uint8*); + + BufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) + return; + uint8 &buffer = bufferheader.Data(); + uint8 *data = &buffer; uint8 buffer[33]; uint8 bufferIndex = 0; - + TRACE("Dumping packet;len=%ld;pkthdr.len=%d\n", packet->m_len, packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : -1); - - for(uint32 index = 0; index < packet->m_len; index++) { + + for (uint32 index = 0; index < packet->m_len; index++) { buffer[bufferIndex++] = sDigits[data[index] >> 4]; buffer[bufferIndex++] = sDigits[data[index] & 0x0F]; - if(bufferIndex == 32 || index == packet->m_len - 1) { + if (bufferIndex == 32 || index == packet->m_len - 1) { buffer[bufferIndex] = 0; TRACE("%s\n", buffer); bufferIndex = 0; } } } + + #endif @@ -54,30 +70,39 @@ PPPoEDevice::PPPoEDevice(KPPPInterface& interface, driver_parameter *settings) { #if DEBUG TRACE("PPPoEDevice: Constructor\n"); - if(!settings || !settings->parameters) + if (!settings || !settings->parameters) TRACE("PPPoEDevice::ctor: No settings!\n"); #endif - + interface.SetPFCOptions(PPP_ALLOW_PFC); // we do not want to fail just because the other side requests PFC - + memset(fPeer, 0xFF, sizeof(fPeer)); + SetMTU(1494); // MTU size does not contain PPP header - + + if (!settings) + dprintf("%s::%s: settings is NULL\n", __FILE__, __func__); + // find ethernet device - const char *interfaceName = get_parameter_value(PPPoE_INTERFACE_KEY, settings); - if(!interfaceName) - return; - + finterfaceName = get_parameter_value(PPPoE_INTERFACE_KEY, settings); + TRACE("%s::%s: finterfaceName is %s\n", __FILE__, __func__, + finterfaceName ? finterfaceName : "NULL"); + fACName = get_parameter_value(PPPoE_AC_NAME_KEY, settings); + TRACE("fACName is %s\n", fACName ? fACName : "NULL"); + fServiceName = get_parameter_value(PPPoE_SERVICE_NAME_KEY, settings); - - fEthernetIfnet = FindPPPoEInterface(interfaceName); - + TRACE("fServiceName is %s\n", fServiceName ? fServiceName : "NULL"); + + // fEthernetIfnet = FindPPPoEInterface(interfaceName); + #if DEBUG - if(!fEthernetIfnet) + if (!fEthernetIfnet) TRACE("PPPoEDevice::ctor: could not find ethernet interface\n"); + else + TRACE("%s::%s: Find Ethernet device", __FILE__, __func__); #endif } @@ -85,8 +110,10 @@ PPPoEDevice::PPPoEDevice(KPPPInterface& interface, driver_parameter *settings) status_t PPPoEDevice::InitCheck() const { - return EthernetIfnet() && EthernetIfnet()->output - && KPPPDevice::InitCheck() == B_OK ? B_OK : B_ERROR; + if (KPPPDevice::InitCheck() != B_OK) + dprintf("%s::%s: KPPPDevice::InitCheck() has error\n", __FILE__, __func__); + + return KPPPDevice::InitCheck() == B_OK ? B_OK : B_ERROR; } @@ -94,72 +121,103 @@ bool PPPoEDevice::Up() { TRACE("PPPoEDevice: Up()\n"); - - if(InitCheck() != B_OK) + + if (InitCheck() != B_OK) return false; - - if(IsUp()) + + if (IsUp()) return true; - + + fEthernetIfnet = FindPPPoEInterface(finterfaceName); + + if (fEthernetIfnet == NULL) { + dprintf("%s::%s: fEthernetIfnet %s not found\n", __FILE__, __func__, finterfaceName); + return false; + } + + memcpy(fEtherAddr, fEthernetIfnet->address.data, ETHER_ADDRESS_LENGTH); + dprintf("ppp's corresponding addr is %02x:%02x:%02x:%02x:%02x:%02x\n", + fEtherAddr[0], fEtherAddr[1], fEtherAddr[2], fEtherAddr[3], + fEtherAddr[4], fEtherAddr[5]); + + if (fEthernetIfnet->module == NULL) { + dprintf("%s::%s: fEthernetIfnet->module not found\n", __FILE__, + __func__); + return false; + } + add_device(this); - + fState = INITIAL; // reset state - - if(fAttempts > PPPoE_MAX_ATTEMPTS) { + + if (fAttempts > PPPoE_MAX_ATTEMPTS) { fAttempts = 0; return false; } - + ++fAttempts; // reset connection settings memset(fPeer, 0xFF, sizeof(fPeer)); - + // create PADI DiscoveryPacket discovery(PADI); - if(ServiceName()) + if (ServiceName()) discovery.AddTag(SERVICE_NAME, ServiceName(), strlen(ServiceName())); else discovery.AddTag(SERVICE_NAME, NULL, 0); discovery.AddTag(HOST_UNIQ, &fHostUniq, sizeof(fHostUniq)); discovery.AddTag(END_OF_LIST, NULL, 0); - + // set up PPP header - struct mbuf *packet = discovery.ToMbuf(MTU()); - if(!packet) + net_buffer *packet = discovery.ToNetBuffer(MTU()); + if (!packet) return false; - - // create destination - struct ether_header *ethernetHeader; - struct sockaddr destination; - memset(&destination, 0, sizeof(destination)); - destination.sa_family = AF_UNSPEC; - // raw packet with ethernet header - ethernetHeader = (struct ether_header*) destination.sa_data; - ethernetHeader->ether_type = ETHERTYPE_PPPOEDISC; - memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer)); - + + // create ether header + NetBufferPrepend ethernetHeader(packet); + if (ethernetHeader.Status() != B_OK) + return false; + ether_header &header = ethernetHeader.Data(); + + memset(header.destination, 0xff, ETHER_ADDRESS_LENGTH); + memcpy(header.source, fEtherAddr, ETHER_ADDRESS_LENGTH); + header.type = htons(ETHER_TYPE_PPPOE_DISCOVERY); + ethernetHeader.Sync(); + // raw packet with ethernet header + // check if we are allowed to go up now (user intervention might disallow that) - if(fAttempts > 0 && !UpStarted()) { + if (fAttempts > 0 && !UpStarted()) { fAttempts = 0; remove_device(this); DownEvent(); return true; // there was no error } - + fState = PADI_SENT; // needed before sending, otherwise we might not get all packets - - if(EthernetIfnet()->output(EthernetIfnet(), packet, &destination, NULL) != B_OK) { + + status_t status = gStackModule->register_device_handler(fEthernetIfnet, + B_NET_FRAME_TYPE_PPPOE_DISCOVERY, &pppoe_input, NULL); + if (status != B_OK) + return false; + + status = gStackModule->register_device_handler(fEthernetIfnet, + B_NET_FRAME_TYPE_PPPOE, &pppoe_input, NULL); + if (status != B_OK) + return false; + + if (EthernetIfnet()->module->send_data(EthernetIfnet(), packet) != B_OK) { fState = INITIAL; fAttempts = 0; ERROR("PPPoEDevice::Up(): EthernetIfnet()->output() failed!\n"); return false; } - + + dprintf("PPPoEDevice::Up(): EthernetIfnet()->output() success!\n"); fNextTimeout = system_time() + PPPoE_TIMEOUT; - + return true; } @@ -168,36 +226,41 @@ bool PPPoEDevice::Down() { TRACE("PPPoEDevice: Down()\n"); - + + gStackModule->unregister_device_handler(fEthernetIfnet, + B_NET_FRAME_TYPE_PPPOE_DISCOVERY); + gStackModule->unregister_device_handler(fEthernetIfnet, + B_NET_FRAME_TYPE_PPPOE); + remove_device(this); - - if(InitCheck() != B_OK) + + if (InitCheck() != B_OK) return false; - + fState = INITIAL; fAttempts = 0; fNextTimeout = 0; // disable timeouts - - if(!IsUp()) { + + if (!IsUp()) { DownEvent(); return true; } - + DownStarted(); // this tells StateMachine that DownEvent() does not mean we lost connection - + // create PADT DiscoveryPacket discovery(PADT, SessionID()); discovery.AddTag(END_OF_LIST, NULL, 0); - - struct mbuf *packet = discovery.ToMbuf(MTU()); - if(!packet) { - ERROR("PPPoEDevice::Down(): ToMbuf() failed; MTU=%ld\n", MTU()); + + net_buffer *packet = discovery.ToNetBuffer(MTU()); + if (!packet) { + ERROR("PPPoEDevice::Down(): ToNetBuffer() failed; MTU=%ld\n", MTU()); DownEvent(); return false; } - + // create destination struct ether_header *ethernetHeader; struct sockaddr destination; @@ -205,15 +268,15 @@ PPPoEDevice::Down() destination.sa_family = AF_UNSPEC; // raw packet with ethernet header ethernetHeader = (struct ether_header*) destination.sa_data; - ethernetHeader->ether_type = ETHERTYPE_PPPOEDISC; - memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer)); - + ethernetHeader->type = ETHER_TYPE_PPPOE_DISCOVERY; + memcpy(ethernetHeader->destination, fPeer, sizeof(fPeer)); + // reset connection settings memset(fPeer, 0xFF, sizeof(fPeer)); - - EthernetIfnet()->output(EthernetIfnet(), packet, &destination, NULL); + + EthernetIfnet()->module->send_data(EthernetIfnet(), packet); DownEvent(); - + return true; } @@ -242,220 +305,261 @@ PPPoEDevice::CountOutputBytes() const status_t -PPPoEDevice::Send(struct mbuf *packet, uint16 protocolNumber) +PPPoEDevice::Send(net_buffer *packet, uint16 protocolNumber) { // Send() is only for PPP packets. PPPoE packets are sent directly to ethernet. - + TRACE("PPPoEDevice: Send()\n"); - - if(!packet) + + if (!packet) return B_ERROR; - else if(InitCheck() != B_OK || protocolNumber != 0) { + else if (InitCheck() != B_OK || protocolNumber != 0) { ERROR("PPPoEDevice::Send(): InitCheck() != B_OK!\n"); - m_freem(packet); + gBufferModule->free(packet); return B_ERROR; } - - if(!IsUp()) { + + if (!IsUp()) { ERROR("PPPoEDevice::Send(): no connection!\n"); - m_freem(packet); + gBufferModule->free(packet); return PPP_NO_CONNECTION; } - - uint16 length = packet->m_flags & M_PKTHDR ? packet->m_pkthdr.len : packet->m_len; - + + uint16 length = packet->size; + // encapsulate packet into pppoe header - M_PREPEND(packet, PPPoE_HEADER_SIZE); - pppoe_header *header = mtod(packet, pppoe_header*); - header->version = PPPoE_VERSION; - header->type = PPPoE_TYPE; - header->code = 0x00; - header->sessionID = SessionID(); - header->length = htons(length); - - // create destination - struct ether_header *ethernetHeader; - struct sockaddr destination; - memset(&destination, 0, sizeof(destination)); - destination.sa_family = AF_UNSPEC; - // raw packet with ethernet header - ethernetHeader = (struct ether_header*) destination.sa_data; - ethernetHeader->ether_type = ETHERTYPE_PPPOE; - memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer)); - - if(!packet || !mtod(packet, pppoe_header*)) + NetBufferPrepend bufferheader(packet); + if (bufferheader.Status() != B_OK) + return B_ERROR; + pppoe_header &header = bufferheader.Data(); + header.version = PPPoE_VERSION; + header.type = PPPoE_TYPE; + header.code = 0x00; + header.sessionID = SessionID(); + header.length = htons(length); + bufferheader.Sync(); + + // create ether header + NetBufferPrepend ethernetHeader(packet); + if (ethernetHeader.Status() != B_OK) + return false; + ether_header ðheader = ethernetHeader.Data(); + + memcpy(ethheader.destination, fPeer, ETHER_ADDRESS_LENGTH); + memcpy(ethheader.source, fEtherAddr, ETHER_ADDRESS_LENGTH); + ethheader.type = htons(ETHER_TYPE_PPPOE); + ethernetHeader.Sync(); + // raw packet with ethernet header + + if (!packet) ERROR("PPPoEDevice::Send(): packet is NULL!\n"); - - if(EthernetIfnet()->output(EthernetIfnet(), packet, &destination, NULL) != B_OK) { + + if (EthernetIfnet()->module->send_data(EthernetIfnet(), packet) != B_OK) { ERROR("PPPoEDevice::Send(): EthernetIfnet()->output() failed!\n"); remove_device(this); DownEvent(); // DownEvent() without DownStarted() indicates connection lost return PPP_NO_CONNECTION; } - + return B_OK; } status_t -PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber) +PPPoEDevice::Receive(net_buffer *packet, uint16 protocolNumber) { - if(!packet) + TRACE("%s entering %s: protocolNumber:%x\n", __FILE__, __func__, protocolNumber); + if (!packet) return B_ERROR; - else if(InitCheck() != B_OK || IsDown()) { - m_freem(packet); + + if (InitCheck() != B_OK || IsDown()) { + dprintf("PPPoED InitCheck fail or IsDown\n"); + // gBufferModule->free(packet); + dprintf("PPPoEDevice::Receive fail\n"); return B_ERROR; } - - complete_pppoe_header *completeHeader = mtod(packet, complete_pppoe_header*); - if(!completeHeader) { - m_freem(packet); - return B_ERROR; - } - + uint8 ethernetSource[6]; - memcpy(ethernetSource, completeHeader->ethernetHeader.ether_shost, sizeof(fPeer)); - status_t result = B_OK; - - if(completeHeader->ethernetHeader.ether_type == ETHERTYPE_PPPOE) { - m_adj(packet, ETHER_HDR_LEN); - pppoe_header *header = mtod(packet, pppoe_header*); - - if(!IsUp() || header->version != PPPoE_VERSION || header->type != PPPoE_TYPE - || header->code != 0x0 || header->sessionID != SessionID()) { - m_freem(packet); + struct sockaddr_dl& source = *(struct sockaddr_dl*)packet->source; + memcpy(ethernetSource, source.sdl_data, sizeof(fPeer)); + + int32 PPP_Packet_Type = B_NET_FRAME_TYPE(source.sdl_type, + ntohs(source.sdl_e_type)); +// bufferheader.Remove(); +// bufferheader.Sync(); + + if (PPP_Packet_Type == B_NET_FRAME_TYPE_PPPOE) { + TRACE("ETHER_TYPE_PPPOE\n"); + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) { + TRACE("creat NetBufferHeaderReader fail\n"); return B_ERROR; } - - m_adj(packet, PPPoE_HEADER_SIZE); + pppoe_header &header = bufferheader.Data(); + uint16 ppppoe_payload = ntohs(header.length); + + if (!IsUp() || header.version != PPPoE_VERSION || header.type != PPPoE_TYPE + || header.code != 0x0 || header.sessionID != SessionID()) { + // gBufferModule->free(packet); + TRACE("basic pppoe header check fail\n"); + return B_ERROR; + } + + bufferheader.Remove(); + bufferheader.Sync(); + + // trim the packet according to actual pppoe_payload + gBufferModule->trim(packet, ppppoe_payload); + return Interface().ReceiveFromDevice(packet); - } else if(completeHeader->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC) { - m_adj(packet, ETHER_HDR_LEN); - pppoe_header *header = mtod(packet, pppoe_header*); - + } + + if (PPP_Packet_Type == B_NET_FRAME_TYPE_PPPOE_DISCOVERY) { + dprintf("ETHER_TYPE_PPPOE_DISCOVERY\n"); + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) { + dprintf("create NetBufferHeaderReader fail\n"); + return B_ERROR; + } + pppoe_header &header = bufferheader.Data(); + // we do not need to check HOST_UNIQ tag as this is done in pppoe.cpp - if(header->version != PPPoE_VERSION || header->type != PPPoE_TYPE) { - m_freem(packet); + if (header.version != PPPoE_VERSION || header.type != PPPoE_TYPE) { + // gBufferModule->free(packet); + dprintf("PPPoEDevice::Receive fail version type wrong\n"); return B_ERROR; } - - if(IsDown()) { - m_freem(packet); + + if (IsDown()) { + // gBufferModule->free(packet); + dprintf("PPPoEDevice::Receive fail PPPoEDev IsDown\n"); return B_ERROR; } - + DiscoveryPacket discovery(packet); switch(discovery.Code()) { case PADO: { - if(fState != PADI_SENT) { - m_freem(packet); + dprintf("processing PADO\n"); + if (fState != PADI_SENT) { + // gBufferModule->free(packet); + dprintf("PPPoEDevice::Receive faile not PADI_Sent \n"); return B_OK; } - + bool hasServiceName = false, hasACName = false; pppoe_tag *tag; DiscoveryPacket reply(PADR); - for(int32 index = 0; index < discovery.CountTags(); index++) { + for (int32 index = 0; index < discovery.CountTags(); index++) { tag = discovery.TagAt(index); - if(!tag) + if (!tag) continue; - - switch(tag->type) { + + switch (tag->type) { case SERVICE_NAME: - if(!hasServiceName && (!ServiceName() - || (strlen(ServiceName()) == tag->length) + if (!hasServiceName && (!ServiceName() + || ((strlen(ServiceName()) == tag->length) && !memcmp(tag->data, ServiceName(), - tag->length))) { + tag->length)))) { hasServiceName = true; reply.AddTag(tag->type, tag->data, tag->length); } break; - + case AC_NAME: - if(!hasACName && (!ACName() - || (strlen(ACName()) == tag->length) + if (!hasACName && (!ACName() + || ((strlen(ACName()) == tag->length) && !memcmp(tag->data, ACName(), - tag->length))) { + tag->length)))) { hasACName = true; reply.AddTag(tag->type, tag->data, tag->length); } break; - + case AC_COOKIE: case RELAY_SESSION_ID: reply.AddTag(tag->type, tag->data, tag->length); break; - + case SERVICE_NAME_ERROR: case AC_SYSTEM_ERROR: case GENERIC_ERROR: - m_freem(packet); + // gBufferModule->free(packet); + dprintf("PPPoEDevice::generic error faile\n"); return B_ERROR; break; - + default: ; } } - - if(!hasServiceName) { - m_freem(packet); + + if (!hasServiceName) { + // gBufferModule->free(packet); + dprintf("PPPoEDevice::Receive faile no svc name\n"); return B_ERROR; } - + + dprintf("reply.AddTag\n"); reply.AddTag(HOST_UNIQ, &fHostUniq, sizeof(fHostUniq)); reply.AddTag(END_OF_LIST, NULL, 0); - struct mbuf *replyPacket = reply.ToMbuf(MTU()); - if(!replyPacket) { - m_freem(packet); + net_buffer *replyPacket = reply.ToNetBuffer(MTU()); + if (!replyPacket) { + // gBufferModule->free(packet); + dprintf("PPPoEDevice::Receive fail no reply pack\n"); return B_ERROR; } - - memcpy(fPeer, ethernetSource, sizeof(fPeer)); - - // create destination - struct ether_header *ethernetHeader; - struct sockaddr destination; - memset(&destination, 0, sizeof(destination)); - destination.sa_family = AF_UNSPEC; - // raw packet with ethernet header - ethernetHeader = (struct ether_header*) destination.sa_data; - ethernetHeader->ether_type = ETHERTYPE_PPPOEDISC; - memcpy(ethernetHeader->ether_dhost, fPeer, sizeof(fPeer)); - + + memcpy(fPeer, ethernetSource, ETHER_ADDRESS_LENGTH); + + // create ether header + NetBufferPrepend ethernetHeader(replyPacket); + if (ethernetHeader.Status() != B_OK) + return false; + ether_header &header = ethernetHeader.Data(); + + memcpy(header.destination, fPeer, ETHER_ADDRESS_LENGTH); + memcpy(header.source, fEtherAddr, ETHER_ADDRESS_LENGTH); + header.type=htons(ETHER_TYPE_PPPOE_DISCOVERY); + ethernetHeader.Sync(); + // raw packet with ethernet header + fState = PADR_SENT; - - if(EthernetIfnet()->output(EthernetIfnet(), replyPacket, &destination, - NULL) != B_OK) { - m_freem(packet); + + if (EthernetIfnet()->module->send_data(EthernetIfnet(), replyPacket) != B_OK) { + gBufferModule->free(replyPacket); + dprintf("PPPoEDevice::Receive fail send PADR\n"); return B_ERROR; } - + fNextTimeout = system_time() + PPPoE_TIMEOUT; - } break; - + } + break; case PADS: - if(fState != PADR_SENT - || memcmp(ethernetSource, fPeer, sizeof(fPeer))) { - m_freem(packet); + dprintf("procesing PADS\n"); + if (fState != PADR_SENT + || memcmp(ethernetSource, fPeer, sizeof(fPeer))) { + // gBufferModule->free(packet); + dprintf("PPPoEDevice::Receive PADS but no PADR sent\n"); return B_ERROR; } - - fSessionID = header->sessionID; + + fSessionID = header.sessionID; fState = OPENED; fNextTimeout = 0; UpEvent(); break; - + case PADT: - if(!IsUp() + dprintf("procesing PADT\n"); + if (!IsUp() || memcmp(ethernetSource, fPeer, sizeof(fPeer)) - || header->sessionID != SessionID()) { - m_freem(packet); + || header.sessionID != SessionID()) { + // gBufferModule->free(packet); + dprintf("PPPoEDevice::Receive fail not up yet\n"); return B_ERROR; } - + fState = INITIAL; fAttempts = 0; fSessionID = 0; @@ -463,16 +567,17 @@ PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber) remove_device(this); DownEvent(); break; - + default: - m_freem(packet); + dprintf("PPPoEDevice::Receive fail unknown pppoed code\n"); + // gBufferModule->free(packet); return B_ERROR; } - } else - result = B_ERROR; - - m_freem(packet); - return result; + } + + dprintf("PPPoEDevice::Receive PADX fine!\n"); + // gBufferModule->free(packet); + return B_OK; } @@ -480,13 +585,12 @@ void PPPoEDevice::Pulse() { // We use Pulse() for timeout of connection establishment. - - if(fNextTimeout == 0 || IsUp() || IsDown()) + if (fNextTimeout == 0 || IsUp() || IsDown()) return; - + // check if timed out - if(system_time() >= fNextTimeout) { - if(!Up()) + if (system_time() >= fNextTimeout) { + if (!Up()) UpFailedEvent(); } } diff --git a/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.h b/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.h index 39550587a3..2357726daf 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.h +++ b/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.h @@ -10,6 +10,9 @@ #include +#include +#include + 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; diff --git a/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp b/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp index 5d0884a020..88cf36b4f7 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp +++ b/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp @@ -5,34 +5,46 @@ #include #include -#include -#include -#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include // for get_interface and control +#include +#include #include #include #include -#include #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 *sDevices; static TemplateList *sQueries; @@ -44,51 +56,75 @@ SendQueryPacket(pppoe_query *query, DiscoveryPacket& discovery) char data[PPPoE_QUERY_REPORT_SIZE]; uint32 position = sizeof(uint32); pppoe_tag *acName = discovery.TagWithType(AC_NAME); - - if(acName) { - if(acName->length >= PPPoE_QUERY_REPORT_SIZE) + + if (acName) { + if (acName->length >= PPPoE_QUERY_REPORT_SIZE) return; - + memcpy(data + position, acName->data, acName->length); position += acName->length; } - + data[position++] = 0; - + pppoe_tag *tag; - for(int32 index = 0; index < discovery.CountTags(); index++) { + for (int32 index = 0; index < discovery.CountTags(); index++) { tag = discovery.TagAt(index); - if(tag && tag->type == SERVICE_NAME) { - if(position + tag->length >= PPPoE_QUERY_REPORT_SIZE) + if (tag && tag->type == SERVICE_NAME) { + if (position + tag->length >= PPPoE_QUERY_REPORT_SIZE) return; - + memcpy(data + position, tag->data, tag->length); position += tag->length; data[position++] = 0; } } - + memcpy(data, &position, sizeof(uint32)); // add the total length - + send_data_with_timeout(query->receiver, PPPoE_QUERY_REPORT, data, PPPoE_QUERY_REPORT_SIZE, 700000); } -ifnet* +net_interface * +get_interface_by_name(net_domain *domain, const char *name) +{ + ifreq request; + memset(&request, 0, sizeof(request)); + size_t size = sizeof(request); + + strlcpy(request.ifr_name, name, IF_NAMESIZE); + + if (sDatalinkModule->control(domain, SIOCGIFINDEX, &request, &size) != B_OK) { + TRACE("sDatalinkModule->control failure\n"); + return NULL; + } + return sDatalinkModule->get_interface(domain, request.ifr_index); +} + + +net_device* FindPPPoEInterface(const char *name) { - if(!name) + if (!name) + return NULL; + + net_interface* ethernetInterfaceOfPPPOE = NULL; + net_domain* domain = NULL; + + domain = gStackModule->get_domain(AF_INET); + ethernetInterfaceOfPPPOE = get_interface_by_name(domain, name); + + if (ethernetInterfaceOfPPPOE == NULL) { + TRACE("get_interface_by_name can not find eth\n"); return NULL; - - ifnet *current = get_interfaces(); - for(; current; current = current->if_next) { - if(current->if_type == IFT_ETHER && current->if_name - && !strcmp(current->if_name, name)) - return current; } - + + if (ethernetInterfaceOfPPPOE->device) + return ethernetInterfaceOfPPPOE->device; + return NULL; } @@ -104,9 +140,9 @@ void add_device(PPPoEDevice *device) { TRACE("PPPoE: add_device()\n"); - - LockerHelper locker(sLock); - if(!sDevices->HasItem(device)) + + // MutexLocker locker(sLock); + if (!sDevices->HasItem(device)) sDevices->AddItem(device); } @@ -115,85 +151,125 @@ void remove_device(PPPoEDevice *device) { TRACE("PPPoE: remove_device()\n"); - - LockerHelper locker(sLock); + + // MutexLocker locker(sLock); sDevices->RemoveItem(device); } -static -void -pppoe_input(struct mbuf *packet) +status_t +pppoe_input(void *cookie, net_device *_device, net_buffer *packet) { - if(!packet) - return; - - ifnet *sourceIfnet = packet->m_pkthdr.rcvif; - complete_pppoe_header *header = mtod(packet, complete_pppoe_header*); + if (!packet) + return B_ERROR; + + NetBufferHeaderReader bufferheader(packet); + if (bufferheader.Status() != B_OK) + return B_ERROR; + + pppoe_header &header = bufferheader.Data(); + + // remove the following lines when pppoe server is enabled + if (header.code == PADI) { + TRACE("PADI packet received, ignoreing!\n"); + gBufferModule->free(packet); + return B_OK; + } + + if (header.code == PADO || header.code == PADR || header.code == PADS || header.code == PADT) + { + uint8 peerEtherAddr[ETHER_ADDRESS_LENGTH]; + struct sockaddr_dl& source = *(struct sockaddr_dl*)packet->source; + memcpy(peerEtherAddr, source.sdl_data, ETHER_ADDRESS_LENGTH); + const char *str = header.code == PADI ? "PADI" : + header.code == PADO ? "PADO" : + header.code == PADR ? "PADR" : + header.code == PADS ? "PADS" : + "PADT" ; + + dprintf("%s from:%02x:%02x:%02x:%02x:%02x:%02x code:%02x\n", str, + peerEtherAddr[0], peerEtherAddr[1], peerEtherAddr[2], + peerEtherAddr[3], peerEtherAddr[4], peerEtherAddr[5], + header.code); + } + PPPoEDevice *device; pppoe_query *query; - - LockerHelper locker(sLock); - - if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC - && header->pppoeHeader.length <= PPPoE_QUERY_REPORT_SIZE) { - for(int32 index = 0; index < sDevices->CountItems(); index++) { + + sockaddr_dl& linkAddress = *(sockaddr_dl*)packet->source; + int32 specificType = B_NET_FRAME_TYPE(linkAddress.sdl_type, + ntohs(linkAddress.sdl_e_type)); + + // MutexLocker locker(sLock); + + if (specificType == B_NET_FRAME_TYPE_PPPOE_DISCOVERY + && ntohs(header.length) <= PPPoE_QUERY_REPORT_SIZE) { + for (int32 index = 0; index < sDevices->CountItems(); index++) { query = sQueries->ItemAt(index); - - if(query && query->ethernetIfnet == sourceIfnet) { - if(header->pppoeHeader.code == PADO) { + + if (query) {// && query->ethernetIfnet == sourceIfnet) { + if (header.code == PADO) { DiscoveryPacket discovery(packet, ETHER_HDR_LEN); - if(discovery.InitCheck() != B_OK) { + if (discovery.InitCheck() != B_OK) { ERROR("PPPoE: received corrupted discovery packet!\n"); - m_freem(packet); - return; + // gBufferModule->free(packet); + return B_ERROR; } - + pppoe_tag *hostTag = discovery.TagWithType(HOST_UNIQ); - if(hostTag && hostTag->length == 4 + if (hostTag && hostTag->length == 4 && *((uint32*)hostTag->data) == query->hostUniq) { SendQueryPacket(query, discovery); - m_freem(packet); - return; + // gBufferModule->free(packet); + return B_ERROR; } } } } } - - for(int32 index = 0; index < sDevices->CountItems(); index++) { + + TRACE("in pppoed processing sDevices->CountItems(): %ld\n", sDevices->CountItems()); + + for (int32 index = 0; index < sDevices->CountItems(); index++) { device = sDevices->ItemAt(index); - - if(device && device->EthernetIfnet() == sourceIfnet) { - if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOE - && header->pppoeHeader.sessionID == device->SessionID()) { + + TRACE("device->SessionID() %d, header.sessionID: %d\n", device->SessionID(), + header.sessionID); + + if (device) { // && device->EthernetIfnet() == sourceIfnet) { + if (specificType == B_NET_FRAME_TYPE_PPPOE + && header.sessionID == device->SessionID()) { TRACE("PPPoE: session packet\n"); device->Receive(packet); - return; - } else if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC - && header->pppoeHeader.code != PADI - && header->pppoeHeader.code != PADR + return B_OK; + } + + if (specificType == B_NET_FRAME_TYPE_PPPOE_DISCOVERY + && header.code != PADI + && header.code != PADR && !device->IsDown()) { TRACE("PPPoE: discovery packet\n"); + DiscoveryPacket discovery(packet, ETHER_HDR_LEN); - if(discovery.InitCheck() != B_OK) { + if (discovery.InitCheck() != B_OK) { ERROR("PPPoE: received corrupted discovery packet!\n"); - m_freem(packet); - return; + gBufferModule->free(packet); + return B_OK; } - + pppoe_tag *tag = discovery.TagWithType(HOST_UNIQ); - if(header->pppoeHeader.code == PADT || (tag && tag->length == 4 - && *((uint32*)tag->data) == device->HostUniq())) { + if (header.code == PADT || (tag && tag->length == 4 + && *((uint32*)tag->data) == device->HostUniq())) { device->Receive(packet); - return; + return B_OK; } } } } - - ERROR("PPPoE: No device found for packet from: %s\n", sourceIfnet->if_name); - m_freem(packet); + + ERROR("PPPoE: No device found for packet from: %s\n", "ethernet"); + // gBufferModule->free(packet); + return B_ERROR; } @@ -202,22 +278,22 @@ bool add_to(KPPPInterface& mainInterface, KPPPInterface *subInterface, driver_parameter *settings, ppp_module_key_type type) { - if(mainInterface.Mode() != PPP_CLIENT_MODE || type != PPP_DEVICE_KEY_TYPE) + if (mainInterface.Mode() != PPP_CLIENT_MODE || type != PPP_DEVICE_KEY_TYPE) return B_ERROR; - + PPPoEDevice *device; bool success; - if(subInterface) { + if (subInterface) { device = new PPPoEDevice(*subInterface, settings); success = subInterface->SetDevice(device); } else { device = new PPPoEDevice(mainInterface, settings); success = mainInterface.SetDevice(device); } - + TRACE("PPPoE: add_to(): %s\n", success && device && device->InitCheck() == B_OK ? "OK" : "ERROR"); - + return success && device && device->InitCheck() == B_OK; } @@ -226,59 +302,62 @@ static status_t control(uint32 op, void *data, size_t length) { - switch(op) { + switch (op) { case PPPoE_GET_INTERFACES: { int32 position = 0, count = 0; char *names = (char*) data; - - ifnet *current = get_interfaces(); - for(; current; current = current->if_next) { - if(current->if_type == IFT_ETHER && current->if_name) { - if(position + strlen(current->if_name) + 1 > length) + + net_device *current = NULL; // get_interfaces(); + for (; current; current = NULL) { + if (current->type == IFT_ETHER && current->name) { + if (position + strlen(current->name) + 1 > length) return B_NO_MEMORY; - - strcpy(names + position, current->if_name); - position += strlen(current->if_name); + + strcpy(names + position, current->name); + position += strlen(current->name); names[position++] = 0; ++count; } } - + return count; } - + case PPPoE_QUERY_SERVICES: { // XXX: as all modules are loaded on-demand we must wait for the results - - if(!data || length != sizeof(pppoe_query_request)) + + if (!data || length != sizeof(pppoe_query_request)) return B_ERROR; - + pppoe_query_request *request = (pppoe_query_request*) data; - + pppoe_query query; query.ethernetIfnet = FindPPPoEInterface(request->interfaceName); - if(!query.ethernetIfnet) + if (!query.ethernetIfnet) return B_BAD_VALUE; - + query.hostUniq = NewHostUniq(); query.receiver = request->receiver; - - sLock.Lock(); - sQueries->AddItem(&query); - sLock.Unlock(); - + + { + // MutexLocker tlocker(sLock); + TRACE("add query\n"); + sQueries->AddItem(&query); + } + snooze(2000000); // wait two seconds for results - - sLock.Lock(); - sQueries->RemoveItem(&query); - sLock.Unlock(); + { + // MutexLocker tlocker(sLock); + TRACE("remove query\n"); + sQueries->RemoveItem(&query); + } } break; - + default: return B_ERROR; } - + return B_OK; } @@ -296,40 +375,48 @@ static ppp_module_info pppoe_module = { _EXPORT status_t -std_ops(int32 op, ...) +std_ops(int32 op, ...) { switch(op) { case B_MODULE_INIT: - if(get_module(NET_CORE_MODULE_NAME, (module_info**)&core) != B_OK) + if (get_module(NET_STACK_MODULE_NAME, + (module_info**)&gStackModule) != B_OK) return B_ERROR; - - if(get_module(NET_ETHERNET_MODULE_NAME, - (module_info**) &sEthernet) != B_OK) { - put_module(NET_CORE_MODULE_NAME); + + if (get_module(NET_DATALINK_MODULE_NAME, + (module_info **)&sDatalinkModule) != B_OK) { + put_module(NET_STACK_MODULE_NAME); return B_ERROR; } - - set_max_linkhdr(2 + PPPoE_HEADER_SIZE + ETHER_HDR_LEN); + + if (get_module(NET_BUFFER_MODULE_NAME, + (module_info **)&gBufferModule) != B_OK) { + put_module(NET_DATALINK_MODULE_NAME); + put_module(NET_STACK_MODULE_NAME); + return B_ERROR; + } + + // set_max_linkhdr(2 + PPPoE_HEADER_SIZE + ETHER_HDR_LEN); // 2 bytes for PPP header sDevices = new TemplateList; sQueries = new TemplateList; - sEthernet->set_pppoe_receiver(pppoe_input); - + TRACE("PPPoE: Registered PPPoE receiver.\n"); - return B_OK; - + return B_OK; + case B_MODULE_UNINIT: + delete sQueries; delete sDevices; - sEthernet->unset_pppoe_receiver(); TRACE("PPPoE: Unregistered PPPoE receiver.\n"); - put_module(NET_CORE_MODULE_NAME); - put_module(NET_ETHERNET_MODULE_NAME); - break; - + put_module(NET_BUFFER_MODULE_NAME); + put_module(NET_DATALINK_MODULE_NAME); + put_module(NET_STACK_MODULE_NAME); + break; + default: return B_ERROR; } - + return B_OK; } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/Jamfile b/src/add-ons/kernel/network/ppp/shared/libkernelppp/Jamfile index 3b701b50d7..fe4cd26321 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/Jamfile +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/Jamfile @@ -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) ] ; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPConfigurePacket.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPConfigurePacket.cpp index bbe5e39e6f..82207eb092 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPConfigurePacket.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPConfigurePacket.cpp @@ -5,18 +5,20 @@ /*! \class KPPPConfigurePacket \brief Helper class for LCP configure packets. - + This class allows iterating over configure items and adding/removing items. */ +#include +#include +#include + #include #include -#include - /*! \brief Constructor. - + \param code The code value (e.g.: PPP_CONFIGURE_REQUEST) of this packet. */ KPPPConfigurePacket::KPPPConfigurePacket(uint8 code) @@ -27,30 +29,33 @@ KPPPConfigurePacket::KPPPConfigurePacket(uint8 code) //! Decodes a packet and adds its items to this object. -KPPPConfigurePacket::KPPPConfigurePacket(struct mbuf *packet) +KPPPConfigurePacket::KPPPConfigurePacket(net_buffer *packet) { // decode packet - ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*); - - SetID(header->id); - if (!SetCode(header->code)) + NetBufferHeaderReader bufferhead(packet); + if (bufferhead.Status() != B_OK) return; - - uint16 length = ntohs(header->length); - - if (length < 6 || length > packet->m_len) + ppp_lcp_packet &header = bufferhead.Data(); + + SetID(header.id); + if (!SetCode(header.code)) + return; + + uint16 length = ntohs(header.length); + + if (length < 6 || length > packet->size) return; // there are no items (or one corrupted item) - + int32 position = 0; ppp_configure_item *item; - + while (position < length - 4) { - item = (ppp_configure_item*) (header->data + position); + item = (ppp_configure_item*) (header.data + position); if (item->length < 2) return; // found a corrupted item - + position += item->length; AddItem(item); } @@ -72,23 +77,23 @@ KPPPConfigurePacket::SetCode(uint8 code) // only configure codes are allowed! if (code < PPP_CONFIGURE_REQUEST || code > PPP_CONFIGURE_REJECT) return false; - + fCode = code; - + return true; } /*! \brief Adds a new configure item to this packet. - + Make sure all values are correct because the item will be copied. If the item's length field is incorrect you will get bad results. - + \param item The item. \param index Item's index. Adds after the last item if not specified or negative. - + \return \c true if successful, \c false otherwise. - + \sa ppp_configure_item */ bool @@ -96,10 +101,10 @@ KPPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index) { if (!item || item->length < 2) return false; - + ppp_configure_item *add = (ppp_configure_item*) malloc(item->length); memcpy(add, item, item->length); - + bool status; if (index < 0) status = fItems.AddItem(add); @@ -109,7 +114,7 @@ KPPPConfigurePacket::AddItem(const ppp_configure_item *item, int32 index) free(add); return false; } - + return true; } @@ -120,10 +125,10 @@ KPPPConfigurePacket::RemoveItem(ppp_configure_item *item) { if (!fItems.HasItem(item)) return false; - + fItems.RemoveItem(item); free(item); - + return true; } @@ -133,10 +138,10 @@ ppp_configure_item* KPPPConfigurePacket::ItemAt(int32 index) const { ppp_configure_item *item = fItems.ItemAt(index); - + if (item == fItems.GetDefaultItem()) return NULL; - + return item; } @@ -146,56 +151,71 @@ ppp_configure_item* KPPPConfigurePacket::ItemWithType(uint8 type) const { ppp_configure_item *item; - + for (int32 index = 0; index < CountItems(); index++) { item = ItemAt(index); if (item && item->type == type) return item; } - + return NULL; } -/*! \brief Converts this packet into an mbuf structure. - +/*! \brief Converts this packet into an net_buffer structure. + ATTENTION: You are responsible for freeing this packet by calling \c m_freem()! - + \param MRU The interface's maximum receive unit (MRU). \param reserve Number of bytes to reserve at the beginning of the packet. - - \return The mbuf structure or \c NULL on error (e.g.: too big for given MRU). + + \return The net_buffer structure or \c NULL on error (e.g.: too big for given MRU). */ -struct mbuf* -KPPPConfigurePacket::ToMbuf(uint32 MRU, uint32 reserve) +net_buffer* +KPPPConfigurePacket::ToNetBuffer(uint32 MRU) { - struct mbuf *packet = m_gethdr(MT_DATA); - packet->m_data += reserve; - - ppp_lcp_packet *header = mtod(packet, ppp_lcp_packet*); - + net_buffer *buffer = gBufferModule->create(256); + if (buffer == NULL) { + TRACE("%s::%s: gBufferModule->create fail\n", __FILE__, __func__); + return(NULL); + } + + ppp_lcp_packet *header; + status_t status = gBufferModule->append_size(buffer, 1492, (void **)&header); + if (status != B_OK) { + TRACE("%s::%s: gBufferModule->append_size\n", __FILE__, __func__); + gBufferModule->free(buffer); + return(NULL); + } + header->code = Code(); header->id = ID(); - + uint16 length = 0; ppp_configure_item *item; - + for (int32 index = 0; index < CountItems(); index++) { item = ItemAt(index); - + // make sure we have enough space left if (MRU - length < item->length) { - m_freem(packet); + gBufferModule->free(buffer); return NULL; } - + memcpy(header->data + length, item, item->length); length += item->length; } - + length += 4; header->length = htons(length); - packet->m_pkthdr.len = packet->m_len = length; - - return packet; + + status = gBufferModule->trim(buffer, length); + if (status < B_OK) { + dprintf("%s::%s: gBufferModule->trim\n", __FILE__, __func__); + gBufferModule->free(buffer); + return(NULL); + } + + return buffer; } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPDevice.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPDevice.cpp index 62c39454bf..e9fdc0dfd4 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPDevice.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPDevice.cpp @@ -5,7 +5,7 @@ /*! \class KPPPDevice \brief Represents a device at the lowest level of the communcation stack. - + A device may be, for example: Modem, PPPoE, PPTP. \n It encapsulates the packet and sends it over a line to the other end. The device is the first layer that receives a packet. @@ -14,13 +14,12 @@ #include #include -#include #include /*! \brief Initializes the device. - + \param name The device's type name (e.g.: PPPoE). \param overhead Length of the header that is prepended to each packet. \param interface Owning interface. @@ -46,12 +45,13 @@ KPPPDevice::~KPPPDevice() /*! \brief Allows private extensions. - + If you override this method you must call the parent's method for unknown ops. */ status_t KPPPDevice::Control(uint32 op, void *data, size_t length) { + dprintf("KPPPDevice::Control\n"); switch (op) { case PPPC_GET_DEVICE_INFO: { @@ -89,7 +89,7 @@ KPPPDevice::IsAllowedToSend() const //! This method is never used. status_t -KPPPDevice::Receive(struct mbuf *packet, uint16 protocolNumber) +KPPPDevice::Receive(net_buffer *packet, uint16 protocolNumber) { // let the interface handle the packet if (protocolNumber == 0) @@ -100,10 +100,10 @@ KPPPDevice::Receive(struct mbuf *packet, uint16 protocolNumber) /*! \brief Report that device is going up. - + Called by Up(). \n From now on, the connection attempt can may be aborted by calling Down(). - + \return - \c true: You are allowed to connect. - \c false: You should abort immediately. Down() will \e not be called! @@ -112,15 +112,15 @@ bool KPPPDevice::UpStarted() { fConnectionPhase = PPP_ESTABLISHMENT_PHASE; - + return Interface().StateMachine().TLSNotify(); } /*! \brief Report that device is going down. - + Called by Down(). - + \return - \c true: You are allowed to disconnect. - \c false: You must not disconnect! @@ -129,7 +129,7 @@ bool KPPPDevice::DownStarted() { fConnectionPhase = PPP_TERMINATION_PHASE; - + return Interface().StateMachine().TLFNotify(); } @@ -139,7 +139,7 @@ void KPPPDevice::UpFailedEvent() { fConnectionPhase = PPP_DOWN_PHASE; - + Interface().StateMachine().UpFailedEvent(); } @@ -149,7 +149,7 @@ void KPPPDevice::UpEvent() { fConnectionPhase = PPP_ESTABLISHED_PHASE; - + Interface().StateMachine().UpEvent(); } @@ -159,6 +159,6 @@ void KPPPDevice::DownEvent() { fConnectionPhase = PPP_DOWN_PHASE; - + Interface().StateMachine().DownEvent(); } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp index db04a6358d..99a2516f47 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp @@ -5,7 +5,7 @@ /*! \class KPPPInterface \brief The kernel representation of a PPP interface. - + This class is never created by the programmer directly. Instead, the PPP manager kernel module should be used. \n KPPPInterface handles all interface-specific commands from userspace and it @@ -23,7 +23,11 @@ // void (KernelExport.h) and once with int (stdio.h). #include #include -#include + +#include +#include +#include +#include // now our headers... #include @@ -38,7 +42,8 @@ #include // general helper classes not only belonging to us -#include +// #include +// #include // 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 @@ -69,7 +77,7 @@ status_t interface_deleter_thread(void *data); /*! \brief Creates a new interface. - + \param name Name of the PPP interface description file. \param entry The PPP manager passes an internal structure to the constructor. \param ID The interface's ID. @@ -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), @@ -110,30 +118,30 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, fDeleteCounter(0) { entry->interface = this; - + if (name) { // load settings from description file char path[B_PATH_NAME_LENGTH]; sprintf(path, "ptpnet/%s", name); // XXX: TODO: change base path to "/etc/ptpnet" - + void *handle = load_driver_settings(path); if (!handle) { fInitStatus = B_ERROR; return; } - + fSettings = dup_driver_settings(get_driver_settings(handle)); unload_driver_settings(handle); } else fSettings = dup_driver_settings(settings); // use the given settings - + if (!fSettings) { fInitStatus = B_ERROR; return; } - + // add internal modules // LCP if (!AddProtocol(&LCP())) { @@ -162,48 +170,48 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, ERROR("KPPPInterface: Could not add PFC handler!\n"); delete pfcHandler; } - + // set up connect delays fConnectRetryDelay = 3000; // 3s delay between each new attempt to reconnect fReconnectDelay = 1000; // 1s delay between lost connection and reconnect - + if (get_module(PPP_INTERFACE_MODULE_NAME, (module_info**) &fManager) != B_OK) ERROR("KPPPInterface: Manager module not found!\n"); - + // are we a multilink subinterface? if (parent && parent->IsMultilink()) { fParent = parent; fParent->AddChild(this); fIsMultilink = true; } - + RegisterInterface(); - + if (!fSettings) { fInitStatus = B_ERROR; return; } - + const char *value; - + // get login value = get_settings_value(PPP_USERNAME_KEY, fSettings); fUsername = value ? strdup(value) : strdup(""); value = get_settings_value(PPP_PASSWORD_KEY, fSettings); fPassword = value ? strdup(value) : strdup(""); - + // get DisonnectAfterIdleSince settings value = get_settings_value(PPP_DISONNECT_AFTER_IDLE_SINCE_KEY, fSettings); if (!value) fDisconnectAfterIdleSince = 0; else fDisconnectAfterIdleSince = atoi(value) * 1000; - + if (fDisconnectAfterIdleSince < 0) fDisconnectAfterIdleSince = 0; - + // get mode settings value = get_settings_value(PPP_MODE_KEY, fSettings); if (value && !strcasecmp(value, PPP_SERVER_MODE_VALUE)) @@ -211,17 +219,17 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, else fMode = PPP_CLIENT_MODE; // we are a client by default - + SetAutoReconnect( get_boolean_value( get_settings_value(PPP_AUTO_RECONNECT_KEY, fSettings), false) ); // auto reconnect is disabled by default - + fAskBeforeConnecting = get_boolean_value( get_settings_value(PPP_ASK_BEFORE_CONNECTING_KEY, fSettings), false); - + // load all protocols and the device if (!LoadModules(fSettings, 0, fSettings->parameter_count)) { ERROR("KPPPInterface: Error loading modules!\n"); @@ -234,41 +242,42 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, KPPPInterface::~KPPPInterface() { TRACE("KPPPInterface: Destructor\n"); - + // tell protocols to uninit (remove routes, etc.) KPPPProtocol *protocol = FirstProtocol(); for (; protocol; protocol = protocol->NextProtocol()) protocol->Uninit(); - + // make sure we are not accessible by any thread before we continue UnregisterInterface(); - + if (fManager) fManager->RemoveInterface(ID()); - + // Call Down() until we get a lock on an interface that is down. // This lock is not released until we are actually deleted. while (true) { Down(); - fLock.Lock(); - if (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) - break; - fLock.Unlock(); + { + MutexLocker (fLock); + if (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) + break; + } } - + Report(PPP_DESTRUCTION_REPORT, 0, &fID, sizeof(ppp_interface_id)); // tell all listeners that we are being destroyed - + int32 tmp; send_data_with_timeout(fReconnectThread, 0, NULL, 0, 200); // tell thread that we are being destroyed (200ms timeout) wait_for_thread(fReconnectThread, &tmp); - + while (CountChildren()) delete ChildAt(0); - + delete Device(); - + while (FirstProtocol()) { if (FirstProtocol() == &LCP()) fFirstProtocol = fFirstProtocol->NextProtocol(); @@ -276,17 +285,17 @@ KPPPInterface::~KPPPInterface() delete FirstProtocol(); // destructor removes protocol from list } - + for (int32 index = 0; index < fModules.CountItems(); index++) { put_module(fModules.ItemAt(index)); delete[] fModules.ItemAt(index); } - + free_driver_settings(fSettings); - + if (Parent()) Parent()->RemoveChild(this); - + if (fManager) put_module(PPP_INTERFACE_MODULE_NAME); } @@ -296,14 +305,16 @@ 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; // only one thread should delete us! - + fDeleteCounter = 1; - + fManager->DeleteInterface(ID()); // This will mark us for deletion. // Any subsequent calls to delete_interface() will do nothing. @@ -316,17 +327,17 @@ KPPPInterface::InitCheck() const { if (fInitStatus != B_OK) return fInitStatus; - + if (!fSettings || !fManager) return B_ERROR; - + // sub-interfaces should have a device if (IsMultilink()) { if (Parent() && !fDevice) return B_ERROR; } else if (!fDevice) return B_ERROR; - + return B_OK; } @@ -338,7 +349,7 @@ KPPPInterface::Username() const // this data is not available before we authenticate if (Phase() < PPP_AUTHENTICATION_PHASE) return NULL; - + return fUsername; } @@ -350,7 +361,7 @@ KPPPInterface::Password() const // this data is not available before we authenticate if (Phase() < PPP_AUTHENTICATION_PHASE) return NULL; - + return fPassword; } @@ -360,16 +371,18 @@ bool KPPPInterface::SetMRU(uint32 MRU) { TRACE("KPPPInterface: SetMRU(%ld)\n", 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; - + CalculateInterfaceMTU(); - + return true; } @@ -379,22 +392,22 @@ uint32 KPPPInterface::PacketOverhead() const { uint32 overhead = fHeaderLength + 2; - + if (Device()) overhead += Device()->Overhead(); - + return overhead; } /*! \brief Allows accessing additional functions. - + This is normally called by userland apps to get information about the interface. - + \param op The op value (see ppp_control_ops enum). \param data (Optional): Additional data may be needed for this op. \param length Length of data. - + \return - \c B_OK: \c Control() was successful. - \c B_ERROR: Either \a length is too small or data is NULL. @@ -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; @@ -470,12 +774,12 @@ 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; - + free(fPassword); fPassword = data ? strdup((const char*) data) : strdup(""); break; @@ -505,7 +809,7 @@ KPPPInterface::Control(uint32 op, void *data, size_t length) case PPPC_SET_AUTO_RECONNECT: if (length < sizeof(uint32) || !data) return B_ERROR; - + SetAutoReconnect(*((uint32*)data)); break; @@ -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) { @@ -562,7 +866,7 @@ KPPPInterface::Control(uint32 op, void *data, size_t length) { if (length < sizeof(ppp_control_info) || !data) return B_ERROR; - + ppp_control_info *control = (ppp_control_info*) data; if (control->index != 0 || !Device()) return B_BAD_INDEX; @@ -574,12 +878,12 @@ KPPPInterface::Control(uint32 op, void *data, size_t length) { if (length < sizeof(ppp_control_info) || !data) return B_ERROR; - + ppp_control_info *control = (ppp_control_info*) data; KPPPProtocol *protocol = ProtocolAt(control->index); if (!protocol) return B_BAD_INDEX; - + return protocol->Control(control->op, control->data, control->length); } @@ -597,7 +901,7 @@ KPPPInterface::Control(uint32 op, void *data, size_t length) control->length); } - case PPPC_CONTROL_LCP_EXTENSION: + case PPPC_CONTROL_LCP_EXTENSION: { if (length < sizeof(ppp_control_info) || !data) return B_ERROR; @@ -625,22 +929,23 @@ KPPPInterface::Control(uint32 op, void *data, size_t length) } default: + dprintf("bad ppp_interface_control!\n"); return B_BAD_VALUE; } - + return B_OK; } /*! \brief Sets a new device for this interface. - + A device add-on should call this method to register itself. The best place to do this is in your module's \c add_to() function. - + \param device The device object. - + \return \c true if successful or \c false otherwise. - + \sa KPPPDevice \sa kppp_module_info */ @@ -648,46 +953,46 @@ bool KPPPInterface::SetDevice(KPPPDevice *device) { TRACE("KPPPInterface: SetDevice(%p)\n", device); - + if (device && &device->Interface() != this) return false; - + if (IsMultilink() && !Parent()) return false; // main interfaces do not have devices - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + if (Phase() != PPP_DOWN_PHASE) return false; // a running connection may not change - + if (fDevice && (IsUp() || fDevice->IsUp())) Down(); - + fDevice = device; SetNext(device); - + if (fDevice) fMRU = fDevice->MTU() - 2; - + CalculateInterfaceMTU(); CalculateBaudRate(); - + return true; } /*! \brief Adds a new protocol to this interface. - + NOTE: You can only add protocols in \c PPP_DOWN_PHASE. \n A protocol add-on should call this method to register itself. The best place to do this is in your module's \c add_to() function. - + \param protocol The protocol object. - + \return \c true if successful or \c false otherwise. - + \sa KPPPProtocol \sa kppp_module_info */ @@ -696,36 +1001,36 @@ KPPPInterface::AddProtocol(KPPPProtocol *protocol) { // Find insert position after the last protocol // with the same level. - + TRACE("KPPPInterface: AddProtocol(%X)\n", protocol ? protocol->ProtocolNumber() : 0); - + if (!protocol || &protocol->Interface() != this || protocol->Level() == PPP_INTERFACE_LEVEL) return false; - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + if (Phase() != PPP_DOWN_PHASE) return false; // a running connection may not change - + KPPPProtocol *current = fFirstProtocol, *previous = NULL; - + while (current) { if (current->Level() < protocol->Level()) break; - + previous = current; current = current->NextProtocol(); } - + if (!current) { if (!previous) fFirstProtocol = protocol; else previous->SetNextProtocol(protocol); - + // set up the last protocol in the chain protocol->SetNextProtocol(NULL); // this also sets next to NULL @@ -733,33 +1038,33 @@ KPPPInterface::AddProtocol(KPPPProtocol *protocol) // we need to set us as the next layer for the last protocol } else { protocol->SetNextProtocol(current); - + if (!previous) fFirstProtocol = protocol; else previous->SetNextProtocol(protocol); } - + if (protocol->Level() < PPP_PROTOCOL_LEVEL) CalculateInterfaceMTU(); - + if (IsUp() || Phase() >= protocol->ActivationPhase()) protocol->Up(); - + return true; } /*! \brief Removes a protocol from this interface. - + NOTE: You can only remove protocols in \c PPP_DOWN_PHASE. \n A protocol add-on should call this method to remove itself explicitly from the interface. \n Normally, this method is called in KPPPProtocol's destructor. Do not call it yourself unless you know what you do! - + \param protocol The protocol object. - + \return \c true if successful or \c false otherwise. */ bool @@ -767,40 +1072,40 @@ 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; // a running connection may not change - + KPPPProtocol *current = fFirstProtocol, *previous = NULL; - + while (current) { if (current == protocol) { if (!protocol->IsDown()) protocol->Down(); - + if (previous) { previous->SetNextProtocol(current->NextProtocol()); - + // set us as next layer if needed if (!previous->Next()) previous->SetNext(this); } else fFirstProtocol = current->NextProtocol(); - + current->SetNextProtocol(NULL); - + CalculateInterfaceMTU(); - + return true; } - + previous = current; current = current->NextProtocol(); } - + return false; } @@ -809,14 +1114,14 @@ KPPPInterface::RemoveProtocol(KPPPProtocol *protocol) int32 KPPPInterface::CountProtocols() const { - LockerHelper locker(fLock); - + MutexLocker locker(fLock); + KPPPProtocol *protocol = FirstProtocol(); - + int32 count = 0; for (; protocol; protocol = protocol->NextProtocol()) ++count; - + return count; } @@ -825,34 +1130,35 @@ KPPPInterface::CountProtocols() const KPPPProtocol* KPPPInterface::ProtocolAt(int32 index) const { - LockerHelper locker(fLock); - + MutexLocker locker(fLock); + KPPPProtocol *protocol = FirstProtocol(); - + int32 currentIndex = 0; for (; protocol && currentIndex != index; protocol = protocol->NextProtocol()) ++currentIndex; - + return protocol; } /*! \brief Returns the protocol object responsible for a given protocol number. - + \param protocolNumber The protocol number that the object should handle. \param start (Optional): Start with this protocol. Can be used for iteration. - + \return Either the object that was found or \c NULL. */ KPPPProtocol* 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(); - + for (; current; current = current->NextProtocol()) { if (current->ProtocolNumber() == protocolNumber || (current->Flags() & PPP_INCLUDES_NCP @@ -860,7 +1166,7 @@ KPPPInterface::ProtocolFor(uint16 protocolNumber, KPPPProtocol *start) const == (protocolNumber & 0x7FFF))) return current; } - + return NULL; } @@ -870,17 +1176,17 @@ bool KPPPInterface::AddChild(KPPPInterface *child) { TRACE("KPPPInterface: AddChild(%lX)\n", child ? child->ID() : 0); - + if (!child) return false; - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + if (fChildren.HasItem(child) || !fChildren.AddItem(child)) return false; - + child->SetParent(this); - + return true; } @@ -890,18 +1196,18 @@ bool 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; - + child->SetParent(NULL); - + // parents cannot exist without their children if (CountChildren() == 0 && fManager && Ifnet()) Delete(); - + return true; } @@ -911,14 +1217,14 @@ KPPPInterface* KPPPInterface::ChildAt(int32 index) const { TRACE("KPPPInterface: ChildAt(%ld)\n", index); - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + KPPPInterface *child = fChildren.ItemAt(index); - + if (child == fChildren.GetDefaultItem()) return NULL; - + return child; } @@ -928,10 +1234,10 @@ void KPPPInterface::SetAutoReconnect(bool autoReconnect) { TRACE("KPPPInterface: SetAutoReconnect(%s)\n", autoReconnect ? "true" : "false"); - + if (Mode() != PPP_CLIENT_MODE) return; - + fAutoReconnect = autoReconnect; } @@ -942,11 +1248,11 @@ KPPPInterface::SetConnectOnDemand(bool connectOnDemand) { // All protocols must check if ConnectOnDemand was enabled/disabled after this // interface went down. This is the only situation where a change is relevant. - + TRACE("KPPPInterface: SetConnectOnDemand(%s)\n", connectOnDemand ? "true" : "false"); - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + // Only clients support ConnectOnDemand. if (Mode() != PPP_CLIENT_MODE) { TRACE("KPPPInterface::SetConnectOnDemand(): Wrong mode!\n"); @@ -954,9 +1260,9 @@ KPPPInterface::SetConnectOnDemand(bool connectOnDemand) return; } else if (DoesConnectOnDemand() == connectOnDemand) return; - + fConnectOnDemand = connectOnDemand; - + // Do not allow changes when we are disconnected (only main interfaces). // This would make no sense because // - enabling: this cannot happen because hidden interfaces are deleted if they @@ -966,17 +1272,17 @@ KPPPInterface::SetConnectOnDemand(bool connectOnDemand) if (!connectOnDemand) Delete(); // as long as the protocols were not configured we can just delete us - + return; } - + // 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(); } } @@ -1003,65 +1309,65 @@ bool 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; - + fPFCOptions = pfcOptions; return true; } /*! \brief Brings this interface up. - + \c Down() overrides all \c Up() requests. \n This method runs an asynchronous process (it returns immediately). - + \return \c false on error. */ bool KPPPInterface::Up() { TRACE("KPPPInterface: Up()\n"); - + if (InitCheck() != B_OK || Phase() == PPP_TERMINATION_PHASE) return false; - + if (IsUp()) return true; - - LockerHelper locker(fLock); + + MutexLocker locker(fLock); StateMachine().OpenEvent(); - + return true; } /*! \brief Brings this interface down. - + \c Down() overrides all \c Up() requests. \n This method runs an asynchronous process (it returns immediately). - + \return \c false on error. */ bool KPPPInterface::Down() { TRACE("KPPPInterface: Down()\n"); - + if (InitCheck() != B_OK) return false; else if (State() == PPP_INITIAL_STATE && Phase() == PPP_DOWN_PHASE) return true; - + 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; } @@ -1071,58 +1377,65 @@ bool KPPPInterface::WaitForConnection() { TRACE("KPPPInterface: WaitForConnection()\n"); - + 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; thread_id sender; bool successful = false; while (true) { if (receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE) continue; - + if (report.type == PPP_DESTRUCTION_REPORT) break; else if (report.type != PPP_CONNECTION_REPORT) continue; - + if (report.code == PPP_REPORT_UP_SUCCESSFUL) { successful = true; break; } else if (report.code == PPP_REPORT_DOWN_SUCCESSFUL) break; } - + ReportManager().DisableReports(PPP_CONNECTION_REPORT, find_thread(NULL)); + dprintf("KPPPInterface: WaitForConnection():%s\n", successful ? "True" : "False"); return successful; } /*! \brief Loads modules specified in the settings structure. - + \param settings PPP interface description file format settings. \param start Index of driver_parameter to start with. \param count Number of driver_parameters to look at. - + \return \c true if successful or \c false otherwise. */ bool KPPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count) { TRACE("KPPPInterface: LoadModules()\n"); - + if (Phase() != PPP_DOWN_PHASE) return false; // a running connection may not change - + ppp_module_key_type type; // which type key was used for loading this module? - + const char *name = NULL; - + // multilink handling for (int32 index = start; index < settings->parameter_count && index < (start + count); index++) { @@ -1134,7 +1447,7 @@ KPPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count) break; } } - + // are we a multilink main interface? if (IsMultilink() && !Parent()) { // main interfaces only load the multilink module @@ -1142,13 +1455,13 @@ KPPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count) fManager->CreateInterface(settings, ID()); return true; } - + for (int32 index = start; index < settings->parameter_count && index < start + count; index++) { type = PPP_UNDEFINED_KEY_TYPE; - + name = settings->parameters[index].name; - + if (!strcasecmp(name, PPP_LOAD_MODULE_KEY)) type = PPP_LOAD_MODULE_KEY_TYPE; else if (!strcasecmp(name, PPP_DEVICE_KEY)) @@ -1157,7 +1470,7 @@ KPPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count) type = PPP_PROTOCOL_KEY_TYPE; else if (!strcasecmp(name, PPP_AUTHENTICATOR_KEY)) type = PPP_AUTHENTICATOR_KEY_TYPE; - + if (type >= 0) for (int32 value_id = 0; value_id < settings->parameters[index].value_count; value_id++) @@ -1165,17 +1478,17 @@ KPPPInterface::LoadModules(driver_settings *settings, int32 start, int32 count) &settings->parameters[index], type)) return false; } - + return true; } /*! \brief Loads a specific module. - + \param name Name of the module. \param parameter Module settings. \param type Type of module. - + \return \c true if successful or \c false otherwise. */ bool @@ -1183,28 +1496,28 @@ KPPPInterface::LoadModule(const char *name, driver_parameter *parameter, ppp_module_key_type type) { TRACE("KPPPInterface: LoadModule(%s)\n", name ? name : "XXX: NO NAME"); - + if (Phase() != PPP_DOWN_PHASE) return false; // a running connection may not change - + if (!name || strlen(name) > B_FILE_NAME_LENGTH) return false; - + char *moduleName = new char[B_PATH_NAME_LENGTH]; - + sprintf(moduleName, "%s/%s", PPP_MODULES_PATH, name); - + ppp_module_info *module; if (get_module(moduleName, (module_info**) &module) != B_OK) { delete[] moduleName; return false; } - + // add the module to the list of loaded modules // for putting them on our destruction fModules.AddItem(moduleName); - + return module->add_to(Parent() ? *Parent() : *this, this, parameter, type); } @@ -1218,53 +1531,56 @@ KPPPInterface::IsAllowedToSend() const /*! \brief Sends a packet to the device. - + This brings the interface up if connect-on-demand is enabled and we are not connected. \n PFC encoding is handled here. \n NOTE: In order to prevent interface destruction while sending you must either hold a refcount for this interface or make sure it is locked. - + \param packet The packet. \param protocolNumber The packet's protocol number. - + \return - \c B_OK: Sending was successful. - \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); - + if (!packet) return B_ERROR; - + // we must pass the basic tests like: // 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; } - + // find the protocol handler for the current protocol number KPPPProtocol *protocol = ProtocolFor(protocolNumber); while (protocol && !protocol->IsEnabled()) protocol = protocol->NextProtocol() ? ProtocolFor(protocolNumber, protocol->NextProtocol()) : NULL; - + #if DEBUG if (!protocol) TRACE("KPPPInterface::Send(): no protocol found!\n"); @@ -1277,70 +1593,79 @@ KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber) else TRACE("KPPPInterface::Send(): protocol allowed\n"); #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 (packet == NULL) - return B_ERROR; - - uint8 *header = mtod(packet, uint8*); - *header = protocolNumber & 0xFF; + if (UseLocalPFC() && (protocolNumber & 0xFF00) == 0) { + TRACE("%s::%s should not go here\n", __FILE__, __func__); + NetBufferPrepend bufferHeader(packet); + if (bufferHeader.Status() != B_OK) + return bufferHeader.Status(); + + uint8 &header = bufferHeader.Data(); + + // memcpy(header.destination, ether_pppoe_ppp_header, 1); + header = (protocolNumber & 0x00FF); + // bufferHeader.Sync(); + } else { - M_PREPEND(packet, 2); - - if (packet == NULL) - return B_ERROR; - + NetBufferPrepend bufferHeader(packet); + if (bufferHeader.Status() != B_OK) + return bufferHeader.Status(); + + 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; } } /*! \brief Receives a packet. - + Encapsulation protocols may use this method to pass encapsulated packets to the PPP interface. Packets will be handled as if they were raw packets that came directly from the device via \c ReceiveFromDevice(). \n If no handler could be found in this interface the parent's \c Receive() method is called. - + \param packet The packet. \param protocolNumber The packet's protocol number. - + \return - \c B_OK: Receiving was successful. - \c B_ERROR: Some error occured. @@ -1348,26 +1673,38 @@ 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 // the handler might be upped by this packet. @@ -1377,26 +1714,26 @@ KPPPInterface::Receive(struct mbuf *packet, uint16 protocolNumber) protocol = protocol->NextProtocol() ? ProtocolFor(protocolNumber, protocol->NextProtocol()) : NULL) { TRACE("KPPPInterface::Receive(): trying protocol\n"); - + if (!protocol->IsEnabled() || !IsProtocolAllowed(*protocol)) continue; // skip handler if disabled or not allowed - + result = protocol->Receive(packet, protocolNumber); if (result == PPP_UNHANDLED) continue; - + return result; } - + TRACE("KPPPInterface::Receive(): trying parent\n"); - + // maybe the parent interface can handle the packet if (Parent()) return Parent()->Receive(packet, protocolNumber); - + if (result == PPP_UNHANDLED) { - m_freem(packet); + gBufferModule->free(packet); return PPP_DISCARDED; } else { StateMachine().RUCEvent(packet, protocolNumber); @@ -1406,12 +1743,12 @@ KPPPInterface::Receive(struct mbuf *packet, uint16 protocolNumber) /*! \brief Receives a base PPP packet from the device. - + KPPPDevice should call this method when it receives a packet. \n PFC decoding is handled here. - + \param packet The packet. - + \return - \c B_OK: Receiving was successful. - \c B_ERROR: Some error occured. @@ -1419,30 +1756,47 @@ 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"); - + if (!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 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 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); atomic_add64(&fStatistics.packetsReceived, 1); return Receive(packet, protocolNumber); @@ -1453,21 +1807,21 @@ KPPPInterface::ReceiveFromDevice(struct mbuf *packet) void KPPPInterface::Pulse() { - LockerHelper locker(fLock); - + MutexLocker locker(fLock); + if (Device()) Device()->Pulse(); - + KPPPProtocol *protocol = FirstProtocol(); for (; protocol; protocol = protocol->NextProtocol()) protocol->Pulse(); - + uint32 currentTime = real_time_clock(); if (fUpdateIdleSince) { fIdleSince = currentTime; fUpdateIdleSince = false; } - + // check our idle time and disconnect if needed if (fDisconnectAfterIdleSince > 0 && fIdleSince != 0 && fIdleSince - currentTime >= fDisconnectAfterIdleSince) @@ -1480,31 +1834,33 @@ bool KPPPInterface::RegisterInterface() { TRACE("KPPPInterface: RegisterInterface()\n"); - + if (fIfnet) return true; // we are already registered - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + // only MainInterfaces get an ifnet if (IsMultilink() && Parent() && Parent()->RegisterInterface()) return true; - + if (!fManager) return false; - + 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(); - + return true; } @@ -1514,24 +1870,24 @@ bool KPPPInterface::UnregisterInterface() { TRACE("KPPPInterface: UnregisterInterface()\n"); - + if (!fIfnet) return true; // we are already unregistered - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + // only MainInterfaces get an ifnet if (IsMultilink() && Parent()) return true; - + if (!fManager) return false; - + fManager->UnregisterInterface(ID()); // this will delete fIfnet, so do not access it anymore! fIfnet = NULL; - + return true; } @@ -1541,12 +1897,12 @@ status_t KPPPInterface::StackControl(uint32 op, void *data) { TRACE("KPPPInterface: StackControl(0x%lX)\n", op); - + switch (op) { default: return StackControlEachHandler(op, data); } - + return B_OK; } @@ -1574,7 +1930,7 @@ class CallStackControl { }; /*! \brief This calls Control() with the given parameters for each add-on. - + \return - \c B_OK: All handlers returned B_OK. - \c B_BAD_VALUE: No handler was found. @@ -1584,11 +1940,11 @@ status_t KPPPInterface::StackControlEachHandler(uint32 op, void *data) { TRACE("KPPPInterface: StackControlEachHandler(0x%lX)\n", op); - + status_t result = B_BAD_VALUE, tmp; - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + KPPPProtocol *protocol = FirstProtocol(); for (; protocol; protocol = protocol->NextProtocol()) { tmp = protocol->StackControl(op, data); @@ -1597,12 +1953,12 @@ KPPPInterface::StackControlEachHandler(uint32 op, void *data) else if (tmp != B_BAD_VALUE) result = tmp; } - + ForEachItem(LCP().fLCPExtensions, CallStackControl(op, data, result)); ForEachItem(LCP().fOptionHandlers, CallStackControl(op, data, result)); - + return result; } @@ -1612,26 +1968,29 @@ void 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; - + // sum all headers (the protocol field is not counted) KPPPProtocol *protocol = FirstProtocol(); for (; protocol; protocol = protocol->NextProtocol()) { if (protocol->Level() < PPP_PROTOCOL_LEVEL) fHeaderLength += protocol->Overhead(); } - + fInterfaceMTU -= fHeaderLength; - + if (Ifnet()) { - Ifnet()->if_mtu = fInterfaceMTU; - Ifnet()->if_hdrlen = fHeaderLength; + Ifnet()->mtu = fInterfaceMTU; + Ifnet()->header_length = fHeaderLength; + return; } - + if (Parent()) Parent()->CalculateInterfaceMTU(); } @@ -1642,20 +2001,21 @@ void 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(), - Device()->OutputTransferRate()); + 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; } } @@ -1665,25 +2025,25 @@ void KPPPInterface::Reconnect(uint32 delay) { TRACE("KPPPInterface: Reconnect(%ld)\n", delay); - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + if (fReconnectThread != -1) return; - + ++fConnectAttempt; - + // start a new thread that calls our Up() method reconnect_info info; info.interface = this; info.thread = &fReconnectThread; info.delay = delay; - + fReconnectThread = spawn_kernel_thread(reconnect_thread, "KPPPInterface: reconnect_thread", B_NORMAL_PRIORITY, NULL); - + resume_thread(fReconnectThread); - + send_data(fReconnectThread, 0, &info, sizeof(reconnect_info)); } @@ -1694,17 +2054,17 @@ reconnect_thread(void *data) reconnect_info info; thread_id sender; int32 code; - + receive_data(&sender, &info, sizeof(reconnect_info)); - + // we try to receive data instead of snooze, so we can quit on destruction if (receive_data_with_timeout(&sender, &code, NULL, 0, info.delay) == B_OK) { *info.thread = -1; return B_OK; } - + info.interface->Up(); *info.thread = -1; - + return B_OK; } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCP.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCP.cpp index d84a0728cb..0191a90266 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCP.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCP.cpp @@ -5,7 +5,7 @@ /*! \class KPPPLCP \brief The LCP protocol. - + Every PPP interface \e must have an LCP protocol. It is used for establishing and terminating connections. \n When establishing a connecition the LCP protocol determines connection-specific @@ -20,9 +20,12 @@ #include #include -#include + +#include #include +extern net_buffer_module_info *gBufferModule; + //! Creates a new LCP protocol for the given interface. KPPPLCP::KPPPLCP(KPPPInterface& interface) @@ -48,7 +51,7 @@ KPPPLCP::~KPPPLCP() /*! \brief Adds a new option handler. - + NOTE: You can only add option handlers in \c PPP_DOWN_PHASE. \n There may only be one handler per option type! */ @@ -57,19 +60,19 @@ KPPPLCP::AddOptionHandler(KPPPOptionHandler *optionHandler) { if (!optionHandler || &optionHandler->Interface() != &Interface()) return false; - + if (Interface().Phase() != PPP_DOWN_PHASE || OptionHandlerFor(optionHandler->Type())) return false; // a running connection may not change and there may only be // one handler per option type - + return fOptionHandlers.AddItem(optionHandler); } /*! \brief Removes an option handler, but does not delete it. - + NOTE: You can only remove option handlers in \c PPP_DOWN_PHASE. */ bool @@ -78,7 +81,7 @@ KPPPLCP::RemoveOptionHandler(KPPPOptionHandler *optionHandler) if (Interface().Phase() != PPP_DOWN_PHASE) return false; // a running connection may not change - + return fOptionHandlers.RemoveItem(optionHandler); } @@ -87,11 +90,12 @@ KPPPLCP::RemoveOptionHandler(KPPPOptionHandler *optionHandler) KPPPOptionHandler* KPPPLCP::OptionHandlerAt(int32 index) const { + dprintf("total optionhandler count %ld\n", CountOptionHandlers()); KPPPOptionHandler *optionHandler = fOptionHandlers.ItemAt(index); - + if (optionHandler == fOptionHandlers.GetDefaultItem()) return NULL; - + return optionHandler; } @@ -103,14 +107,14 @@ KPPPLCP::OptionHandlerFor(uint8 type, int32 *start) const // The iteration style in this method is strange C/C++. // Explanation: I use this style because it makes extending all XXXFor // methods simpler as that they look very similar, now. - + int32 index = start ? *start : 0; - + if (index < 0) return NULL; - + KPPPOptionHandler *current = OptionHandlerAt(index); - + for (; current; current = OptionHandlerAt(++index)) { if (current->Type() == type) { if (start) @@ -118,13 +122,13 @@ KPPPLCP::OptionHandlerFor(uint8 type, int32 *start) const return current; } } - + return NULL; } /*! \brief Adds a new LCP extension. - + NOTE: You can only add LCP extensions in \c PPP_DOWN_PHASE. */ bool @@ -132,17 +136,17 @@ KPPPLCP::AddLCPExtension(KPPPLCPExtension *lcpExtension) { if (!lcpExtension || &lcpExtension->Interface() != &Interface()) return false; - + if (Interface().Phase() != PPP_DOWN_PHASE) return false; // a running connection may not change - + return fLCPExtensions.AddItem(lcpExtension); } /*! \brief Removes an LCP extension, but does not delete it. - + NOTE: You can only remove LCP extensions in \c PPP_DOWN_PHASE. */ bool @@ -151,7 +155,7 @@ KPPPLCP::RemoveLCPExtension(KPPPLCPExtension *lcpExtension) if (Interface().Phase() != PPP_DOWN_PHASE) return false; // a running connection may not change - + return fLCPExtensions.RemoveItem(lcpExtension); } @@ -160,11 +164,12 @@ KPPPLCP::RemoveLCPExtension(KPPPLCPExtension *lcpExtension) KPPPLCPExtension* KPPPLCP::LCPExtensionAt(int32 index) const { + dprintf("LCPExtension count %ld\n", CountLCPExtensions()); KPPPLCPExtension *lcpExtension = fLCPExtensions.ItemAt(index); - + if (lcpExtension == fLCPExtensions.GetDefaultItem()) return NULL; - + return lcpExtension; } @@ -176,14 +181,14 @@ KPPPLCP::LCPExtensionFor(uint8 code, int32 *start) const // The iteration style in this method is strange C/C++. // Explanation: I use this style because it makes extending all XXXFor // methods simpler as that they look very similar, now. - + int32 index = start ? *start : 0; - + if (index < 0) return NULL; - + KPPPLCPExtension *current = LCPExtensionAt(index); - + for (; current; current = LCPExtensionAt(++index)) { if (current->Code() == code) { if (start) @@ -191,27 +196,11 @@ KPPPLCP::LCPExtensionFor(uint8 code, int32 *start) const return current; } } - + return NULL; } -//! Returns the interface, target, and device overhead. -uint32 -KPPPLCP::AdditionalOverhead() const -{ - uint32 overhead = Interface().Overhead(); - - if (Target()) - overhead += Target()->Overhead(); - - if (Interface().Device()) - overhead += Interface().Device()->Overhead(); - - return overhead; -} - - //! Always returns \c true. bool KPPPLCP::Up() @@ -230,7 +219,7 @@ KPPPLCP::Down() //! Sends a packet to the target (if there is one) or to the interface. status_t -KPPPLCP::Send(struct mbuf *packet, uint16 protocolNumber) +KPPPLCP::Send(net_buffer *packet, uint16 protocolNumber) { if (Target()) return Target()->Send(packet, PPP_LCP_PROTOCOL); @@ -241,39 +230,32 @@ KPPPLCP::Send(struct mbuf *packet, uint16 protocolNumber) //! Decodes the LCP packet and passes it to the KPPPStateMachine or an LCP extension. status_t -KPPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber) +KPPPLCP::Receive(net_buffer *packet, uint16 protocolNumber) { if (!packet) return B_ERROR; - + if (protocolNumber != PPP_LCP_PROTOCOL) { ERROR("KPPPLCP::Receive(): wrong protocol number!\n"); return PPP_UNHANDLED; } - - ppp_lcp_packet *data = mtod(packet, ppp_lcp_packet*); - + + NetBufferHeaderReader bufferHeader(packet); + if (bufferHeader.Status() < B_OK) + return bufferHeader.Status(); + + ppp_lcp_packet &data = bufferHeader.Data(); + // remove padding - int32 length = packet->m_len; - if (packet->m_flags & M_PKTHDR) - length = packet->m_pkthdr.len; - length -= ntohs(data->length); - if (length) - m_adj(packet, -length); - - struct mbuf *copy = m_gethdr(MT_DATA); - if (copy) { - copy->m_data += AdditionalOverhead(); - copy->m_pkthdr.len = copy->m_len = packet->m_len; - memcpy(copy->m_data, packet->m_data, copy->m_len); - } - - if (ntohs(data->length) < 4) + + net_buffer *copy = gBufferModule->duplicate(packet); + + if (ntohs(data.length) < 4) return B_ERROR; bool handled = true; - switch (data->code) { + switch (data.code) { case PPP_CONFIGURE_REQUEST: StateMachine().RCREvent(packet); break; @@ -310,43 +292,43 @@ KPPPLCP::Receive(struct mbuf *packet, uint16 protocolNumber) break; default: - m_freem(packet); + // gBufferModule->free(packet); handled = false; } - + packet = copy; - + if (!packet) return handled ? B_OK : B_ERROR; - + status_t result = B_OK; - + // Try to find LCP extensions that can handle this code. // We must duplicate the packet in order to ask all handlers. int32 index = 0; - KPPPLCPExtension *lcpExtension = LCPExtensionFor(data->code, &index); - for (; lcpExtension; lcpExtension = LCPExtensionFor(data->code, &(++index))) { + KPPPLCPExtension *lcpExtension = LCPExtensionFor(data.code, &index); + for (; lcpExtension; lcpExtension = LCPExtensionFor(data.code, &(++index))) { if (!lcpExtension->IsEnabled()) continue; - - result = lcpExtension->Receive(packet, data->code); - + + result = lcpExtension->Receive(packet, data.code); + // check return value and return it on error if (result == B_OK) handled = true; else if (result != PPP_UNHANDLED) { - m_freem(packet); + gBufferModule->free(packet); return result; } } - + if (!handled) { StateMachine().RUCEvent(packet, PPP_LCP_PROTOCOL, PPP_CODE_REJECT); return PPP_REJECTED; } - - m_freem(packet); - + + gBufferModule->free(packet); + return result; } @@ -356,7 +338,7 @@ void KPPPLCP::Pulse() { StateMachine().TimerEvent(); - + for (int32 index = 0; index < CountLCPExtensions(); index++) LCPExtensionAt(index)->Pulse(); } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCPExtension.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCPExtension.cpp index e3165459a4..61f978ea47 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCPExtension.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCPExtension.cpp @@ -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: { diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLayer.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLayer.cpp index b967e220d7..11894c2b90 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLayer.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLayer.cpp @@ -5,7 +5,7 @@ /*! \class KPPPLayer \brief An abstract layer that can encapsulate/send and receive packets. - + All packet handlers should derive from this class. It does not define a protocol number like KPPPProtocol does. It only has a header overhead and an encapsulation level that is used to determine the order at which the packets get encapsulated @@ -19,13 +19,15 @@ #include +#include + #include #include -#include +extern net_buffer_module_info *gBufferModule; /*! \brief Creates a new layer. - + If an error occurs in the constructor you should set \c fInitStatus. */ KPPPLayer::KPPPLayer(const char *name, ppp_level level, uint32 overhead) @@ -56,11 +58,11 @@ KPPPLayer::InitCheck() const //! Sends a packet to the next layer in the chain. status_t -KPPPLayer::SendToNext(struct mbuf *packet, uint16 protocolNumber) const +KPPPLayer::SendToNext(net_buffer *packet, uint16 protocolNumber) const { if (!packet) return B_ERROR; - + // Find the next possible handler for this packet. // Normal protocols (Level() >= PPP_PROTOCOL_LEVEL) do not encapsulate anything. if (Next()) { @@ -70,14 +72,14 @@ KPPPLayer::SendToNext(struct mbuf *packet, uint16 protocolNumber) const return Next()->SendToNext(packet, protocolNumber); } else { ERROR("KPPPLayer: SendToNext() failed because there is no next handler!\n"); - m_freem(packet); + gBufferModule->free(packet); return B_ERROR; } } /*! \brief You may override this for periodic tasks. - + This method gets called every \c PPP_PULSE_RATE microseconds. */ void @@ -92,7 +94,7 @@ void KPPPLayer::SetName(const char *name) { free(fName); - + if (name) fName = strdup(name); else diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPOptionHandler.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPOptionHandler.cpp index 19522cf320..3325eaa179 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPOptionHandler.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPOptionHandler.cpp @@ -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: { diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPReportManager.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPReportManager.cpp index 17acd2bf35..98892c795b 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPReportManager.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPReportManager.cpp @@ -9,7 +9,9 @@ #include -#include +#include +#include + #include @@ -30,10 +32,10 @@ report_sender_thread(void *data) /*! \brief Constructor. - + \param lock The BLocker that should be used by this report manager. */ -KPPPReportManager::KPPPReportManager(BLocker& lock) +KPPPReportManager::KPPPReportManager(mutex& lock) : fLock(lock) { } @@ -48,10 +50,10 @@ KPPPReportManager::~KPPPReportManager() /*! \brief Send the given report message to the given thread. - + \param thread The report receiver. \param report The report message. - + \return \c false on error. */ bool @@ -59,7 +61,7 @@ KPPPReportManager::SendReport(thread_id thread, const ppp_report_packet *report) { if (!report) return false; - + if (thread == find_thread(NULL)) { report_sender_info *info = new report_sender_info; info->thread = thread; @@ -68,7 +70,7 @@ KPPPReportManager::SendReport(thread_id thread, const ppp_report_packet *report) B_NORMAL_PRIORITY, info)); return true; } - + send_data_with_timeout(thread, PPP_REPORT_CODE, &report, sizeof(report), PPP_REPORT_TIMEOUT); return true; @@ -76,7 +78,7 @@ KPPPReportManager::SendReport(thread_id thread, const ppp_report_packet *report) /*! \brief Requests report messages of a given \a type. - + \param type The type of report. \param thread The receiver thread. \param flags Optional report flags. See \c ppp_report_flags for more information. @@ -87,14 +89,14 @@ KPPPReportManager::EnableReports(ppp_report_type type, thread_id thread, { if (thread < 0 || type == PPP_ALL_REPORTS) return; - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + ppp_report_request *request = new ppp_report_request; request->type = type; request->thread = thread; request->flags = flags; - + fReportRequests.AddItem(request); } @@ -105,21 +107,21 @@ KPPPReportManager::DisableReports(ppp_report_type type, thread_id thread) { if (thread < 0) return; - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + ppp_report_request *request; - + for (int32 i = 0; i < fReportRequests.CountItems(); i++) { request = fReportRequests.ItemAt(i); - + if (request->thread != thread) continue; - + if (request->type == type || type == PPP_ALL_REPORTS) fReportRequests.RemoveItem(request); } - + // empty message queue while (has_data(thread)) { thread_id sender; @@ -134,32 +136,32 @@ KPPPReportManager::DoesReport(ppp_report_type type, thread_id thread) { if (thread < 0) return false; - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + ppp_report_request *request; - + for (int32 i = 0; i < fReportRequests.CountItems(); i++) { request = fReportRequests.ItemAt(i); - + if (request->thread == thread && request->type == type) return true; } - + return false; } /*! \brief Send out report messages to all requestors. - + You may append additional data to the report messages. The data length may not be greater than \c PPP_REPORT_DATA_LIMIT. - + \param type The report type. \param code The report code belonging to the report type. \param data Additional data. \param length Length of the data. - + \return \c false on error. */ bool @@ -167,44 +169,44 @@ KPPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 le { TRACE("KPPPReportManager: Report(type=%d code=%ld length=%ld) to %ld receivers\n", type, code, length, fReportRequests.CountItems()); - + if (length > PPP_REPORT_DATA_LIMIT) return false; - + if (fReportRequests.CountItems() == 0) return true; - + if (!data) length = 0; - - LockerHelper locker(fLock); - + + MutexLocker locker(fLock); + status_t result; thread_id me = find_thread(NULL); - + ppp_report_packet report; report.type = type; report.code = code; report.length = length; memcpy(report.data, data, length); - + ppp_report_request *request; - + for (int32 index = 0; index < fReportRequests.CountItems(); index++) { request = fReportRequests.ItemAt(index); - + // do not send to yourself if (request->thread == me) continue; - + result = send_data_with_timeout(request->thread, PPP_REPORT_CODE, &report, sizeof(report), PPP_REPORT_TIMEOUT); - + #if DEBUG if (result == B_TIMED_OUT) TRACE("KPPPReportManager::Report(): timed out sending\n"); #endif - + if (result == B_BAD_THREAD_ID || result == B_NO_MEMORY || request->flags & PPP_REMOVE_AFTER_REPORT) { fReportRequests.RemoveItem(request); @@ -212,6 +214,6 @@ KPPPReportManager::Report(ppp_report_type type, int32 code, void *data, int32 le continue; } } - + return true; } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp index 06f30baf9d..181110ce58 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp @@ -5,9 +5,9 @@ /*! \class KPPPStateMachine \brief PPP state machine belonging to the LCP protocol - + The state machine is responsible for handling events and state changes. - + \sa KPPPLCP */ @@ -22,8 +22,12 @@ #include #include -#include +#include +#include +#include + +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"); } @@ -71,7 +76,7 @@ KPPPStateMachine::NextID() /*! \brief Changes the current state. - + Remember: NewState() must always be called \e after IllegalEvent() because IllegalEvent() also looks at the current state. */ @@ -79,20 +84,20 @@ void KPPPStateMachine::NewState(ppp_state next) { TRACE("KPPPSM: NewState(%d) state=%d\n", next, State()); - + // maybe we do not need the timer anymore if (next < PPP_CLOSING_STATE || next == PPP_OPENED_STATE) fNextTimeout = 0; - + if (State() == PPP_OPENED_STATE && next != State()) ResetLCPHandlers(); - + fState = next; } /*! \brief Changes the current phase. - + This method is responsible for setting the \c if_flags and sending the \c PPP_REPORT_UP_SUCCESSFUL report message. */ @@ -103,33 +108,33 @@ KPPPStateMachine::NewPhase(ppp_phase next) if (next <= PPP_ESTABLISHMENT_PHASE || next == PPP_ESTABLISHED_PHASE) TRACE("KPPPSM: NewPhase(%d) phase=%d\n", next, Phase()); #endif - + // there is nothing after established phase and nothing before down phase if (next > PPP_ESTABLISHED_PHASE) next = PPP_ESTABLISHED_PHASE; else if (next < PPP_DOWN_PHASE) next = PPP_DOWN_PHASE; - + // Report a down event to parent if we are not usable anymore. // 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()) Interface().Parent()->StateMachine().DownEvent(Interface()); } - + fPhase = next; - + if (Phase() == PPP_ESTABLISHED_PHASE) { 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) send_data_with_timeout(Interface().fReconnectThread, 0, NULL, 0, 200); @@ -148,17 +153,17 @@ bool KPPPStateMachine::Reconfigure() { TRACE("KPPPSM: Reconfigure() state=%d phase=%d\n", State(), Phase()); - + if (State() < PPP_REQ_SENT_STATE) return false; - + NewState(PPP_REQ_SENT_STATE); NewPhase(PPP_ESTABLISHMENT_PHASE); // indicates to handlers that we are reconfiguring - + DownProtocols(); ResetLCPHandlers(); - + return SendConfigureRequest(); } @@ -168,25 +173,37 @@ bool KPPPStateMachine::SendEchoRequest() { TRACE("KPPPSM: SendEchoRequest() state=%d phase=%d\n", State(), Phase()); - + 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 - - 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)); - + + void *data; + status_t status = gBufferModule->append_size(packet, 1492, &data); + if (status == B_OK && data == NULL) { + gBufferModule->free(packet); + return false; + } + + // 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; } @@ -196,24 +213,35 @@ bool 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 - - 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)); - + // 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; + + 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; } @@ -221,7 +249,7 @@ KPPPStateMachine::SendDiscardRequest() // authentication events /*! Notification that local authentication is requested. - + NOTE: This must be called \e after \c KPPPProtocol::Up(). */ void @@ -229,12 +257,12 @@ KPPPStateMachine::LocalAuthenticationRequested() { TRACE("KPPPSM: LocalAuthenticationRequested() state=%d phase=%d\n", State(), Phase()); - + fLastConnectionReportCode = PPP_REPORT_AUTHENTICATION_REQUESTED; Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_REQUESTED, &fInterface.fID, sizeof(ppp_interface_id)); - + fLocalAuthenticationStatus = PPP_AUTHENTICATING; free(fLocalAuthenticationName); fLocalAuthenticationName = NULL; @@ -242,9 +270,9 @@ KPPPStateMachine::LocalAuthenticationRequested() /*! \brief Notification that local authentication was accepted. - + NOTE: This must be called \e before \c UpEvent(). - + \param name The username/login that was accepted. */ void @@ -252,7 +280,7 @@ KPPPStateMachine::LocalAuthenticationAccepted(const char *name) { TRACE("KPPPSM: LocalAuthenticationAccepted() state=%d phase=%d\n", State(), Phase()); - + fLocalAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; free(fLocalAuthenticationName); if (name) @@ -263,23 +291,23 @@ KPPPStateMachine::LocalAuthenticationAccepted(const char *name) /*! \brief Notification that local authentication was denied. - + NOTE: This must be called \e before \c UpFailedEvent(). - + \param name The username/login that was denied. */ void KPPPStateMachine::LocalAuthenticationDenied(const char *name) { TRACE("KPPPSM: LocalAuthenticationDenied() state=%d phase=%d\n", State(), Phase()); - + fLocalAuthenticationStatus = PPP_AUTHENTICATION_FAILED; free(fLocalAuthenticationName); if (name) fLocalAuthenticationName = strdup(name); else fLocalAuthenticationName = NULL; - + // the report will be sent in DownEvent() } @@ -290,12 +318,12 @@ KPPPStateMachine::PeerAuthenticationRequested() { TRACE("KPPPSM: PeerAuthenticationRequested() state=%d phase=%d\n", State(), Phase()); - + fLastConnectionReportCode = PPP_REPORT_AUTHENTICATION_REQUESTED; Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_REQUESTED, &fInterface.fID, sizeof(ppp_interface_id)); - + fPeerAuthenticationStatus = PPP_AUTHENTICATING; free(fPeerAuthenticationName); fPeerAuthenticationName = NULL; @@ -303,9 +331,9 @@ KPPPStateMachine::PeerAuthenticationRequested() /*! \brief Notification that peer authentication was accepted. - + NOTE: This must be called \e before \c UpEvent(). - + \param name The username/login that was accepted. */ void @@ -313,7 +341,7 @@ KPPPStateMachine::PeerAuthenticationAccepted(const char *name) { TRACE("KPPPSM: PeerAuthenticationAccepted() state=%d phase=%d\n", State(), Phase()); - + fPeerAuthenticationStatus = PPP_AUTHENTICATION_SUCCESSFUL; free(fPeerAuthenticationName); if (name) @@ -324,25 +352,25 @@ KPPPStateMachine::PeerAuthenticationAccepted(const char *name) /*! \brief Notification that peer authentication was denied. - + NOTE: This must be called \e before \c UpFailedEvent(). - + \param name The username/login that was denied. */ void KPPPStateMachine::PeerAuthenticationDenied(const char *name) { TRACE("KPPPSM: PeerAuthenticationDenied() state=%d phase=%d\n", State(), Phase()); - + fPeerAuthenticationStatus = PPP_AUTHENTICATION_FAILED; free(fPeerAuthenticationName); if (name) fPeerAuthenticationName = strdup(name); else fPeerAuthenticationName = NULL; - + CloseEvent(); - + // the report will be sent in DownEvent() } @@ -352,7 +380,7 @@ void KPPPStateMachine::UpFailedEvent(KPPPInterface& interface) { TRACE("KPPPSM: UpFailedEvent(interface) state=%d phase=%d\n", State(), Phase()); - + // TODO: // log that an interface did not go up } @@ -363,14 +391,14 @@ void KPPPStateMachine::UpEvent(KPPPInterface& interface) { TRACE("KPPPSM: UpEvent(interface) state=%d phase=%d\n", State(), Phase()); - + if (Phase() <= PPP_TERMINATION_PHASE) { interface.StateMachine().CloseEvent(); return; } - + Interface().CalculateBaudRate(); - + if (Phase() == PPP_ESTABLISHMENT_PHASE) { // this is the first interface that went up Interface().SetMRU(interface.MRU()); @@ -378,7 +406,7 @@ KPPPStateMachine::UpEvent(KPPPInterface& interface) } else if (Interface().MRU() > interface.MRU()) Interface().SetMRU(interface.MRU()); // MRU should always be the smallest value of all children - + NewState(PPP_OPENED_STATE); } @@ -388,35 +416,35 @@ void KPPPStateMachine::DownEvent(KPPPInterface& interface) { TRACE("KPPPSM: DownEvent(interface) state=%d phase=%d\n", State(), Phase()); - + uint32 MRU = 0; // the new MRU - + Interface().CalculateBaudRate(); - + // when all children are down we should not be running if (Interface().IsMultilink() && !Interface().Parent()) { uint32 count = 0; KPPPInterface *child; for (int32 index = 0; index < Interface().CountChildren(); index++) { child = Interface().ChildAt(index); - + if (child && child->IsUp()) { // set MRU to the smallest value of all children if (MRU == 0) MRU = child->MRU(); else if (MRU > child->MRU()) MRU = child->MRU(); - + ++count; } } - + if (MRU == 0) Interface().SetMRU(1500); else Interface().SetMRU(MRU); - + if (count == 0) DownEvent(); } @@ -424,7 +452,7 @@ KPPPStateMachine::DownEvent(KPPPInterface& interface) /*! \brief Notification that a protocol failed to go up. - + NOTE FOR AUTHENTICATORS: This \e must be called \e after an authentication notification method like \c LocalAuthenticationFailed(). */ @@ -432,7 +460,7 @@ void KPPPStateMachine::UpFailedEvent(KPPPProtocol *protocol) { TRACE("KPPPSM: UpFailedEvent(protocol) state=%d phase=%d\n", State(), Phase()); - + if ((protocol->Flags() & PPP_NOT_IMPORTANT) == 0) { if (Interface().Mode() == PPP_CLIENT_MODE) { // pretend we lost connection @@ -451,7 +479,7 @@ KPPPStateMachine::UpFailedEvent(KPPPProtocol *protocol) /*! \brief Notification that a protocol went up successfully. - + NOTE FOR AUTHENTICATORS: This \e must be called \e after an authentication notification method like \c LocalAuthenticationSuccessful(). */ @@ -459,14 +487,14 @@ void KPPPStateMachine::UpEvent(KPPPProtocol *protocol) { TRACE("KPPPSM: UpEvent(protocol) state=%d phase=%d\n", State(), Phase()); - + if (Phase() >= PPP_ESTABLISHMENT_PHASE) BringProtocolsUp(); } /*! \brief Notification that a protocol went down. - + NOTE FOR AUTHENTICATORS: This \e must be called \e after an authentication notification method like \c LocalAuthenticationFailed(). */ @@ -478,9 +506,9 @@ KPPPStateMachine::DownEvent(KPPPProtocol *protocol) /*! \brief Notification that the device entered establishment phase. - + We can use \c Device::Down() to abort establishment until \c UpEvent() is called. - + \return - \c true: We are waiting for an \c UpEvent() - \c false: The device should immediately abort its attempt to connect. @@ -489,22 +517,22 @@ bool KPPPStateMachine::TLSNotify() { TRACE("KPPPSM: TLSNotify() state=%d phase=%d\n", State(), Phase()); - + if (State() == PPP_STARTING_STATE) { if (Phase() == PPP_DOWN_PHASE) NewPhase(PPP_ESTABLISHMENT_PHASE); // this says that the device is going up return true; } - + return false; } /*! \brief Notification that the device entered termination phase. - + A \c Device::Up() should wait until the device went down. - + \return - \c true: Continue terminating. - \c false: We want to stay connected, though we called \c Device::Down(). @@ -513,10 +541,10 @@ bool KPPPStateMachine::TLFNotify() { TRACE("KPPPSM: TLFNotify() state=%d phase=%d\n", State(), Phase()); - + NewPhase(PPP_TERMINATION_PHASE); // tell DownEvent() that it may create a connection-lost-report - + return true; } @@ -526,7 +554,7 @@ void KPPPStateMachine::UpFailedEvent() { TRACE("KPPPSM: UpFailedEvent() state=%d phase=%d\n", State(), Phase()); - + switch (State()) { case PPP_STARTING_STATE: fLastConnectionReportCode = PPP_REPORT_DEVICE_UP_FAILED; @@ -534,12 +562,12 @@ KPPPStateMachine::UpFailedEvent() &fInterface.fID, sizeof(ppp_interface_id)); if (Interface().Parent()) Interface().Parent()->StateMachine().UpFailedEvent(Interface()); - + NewPhase(PPP_DOWN_PHASE); // tell DownEvent() that it should not create a connection-lost-report DownEvent(); break; - + default: IllegalEvent(PPP_UP_FAILED_EVENT); } @@ -551,16 +579,16 @@ void KPPPStateMachine::UpEvent() { TRACE("KPPPSM: UpEvent() state=%d phase=%d\n", State(), Phase()); - + // This call is public, thus, it might not only be called by the device. // We must recognize these attempts to fool us and handle them correctly. - + if (!Interface().Device() || !Interface().Device()->IsUp()) return; // it is not our device that went up... - + Interface().CalculateBaudRate(); - + switch (State()) { case PPP_INITIAL_STATE: if (Interface().Mode() != PPP_SERVER_MODE @@ -570,16 +598,16 @@ KPPPStateMachine::UpEvent() IllegalEvent(PPP_UP_EVENT); NewState(PPP_CLOSED_STATE); ThisLayerFinished(); - + return; } - + // TODO: handle server-up! (maybe already done correctly) NewState(PPP_REQ_SENT_STATE); InitializeRestartCount(); SendConfigureRequest(); break; - + case PPP_STARTING_STATE: // we must have called TLS() which sets establishment phase if (Phase() != PPP_ESTABLISHMENT_PHASE) { @@ -591,12 +619,12 @@ KPPPStateMachine::UpEvent() ThisLayerFinished(); break; } - + NewState(PPP_REQ_SENT_STATE); InitializeRestartCount(); SendConfigureRequest(); break; - + default: IllegalEvent(PPP_UP_EVENT); } @@ -604,7 +632,7 @@ KPPPStateMachine::UpEvent() /*! \brief Notification that the device went down. - + If this is called without a prior \c TLFNotify() the state machine will assume that we lost our connection. */ @@ -612,33 +640,33 @@ void KPPPStateMachine::DownEvent() { TRACE("KPPPSM: DownEvent() state=%d phase=%d\n", State(), Phase()); - + if (Interface().Device() && Interface().Device()->IsUp()) return; // it is not our device that went down... - + Interface().CalculateBaudRate(); - + // reset IdleSince Interface().fIdleSince = 0; - + switch (State()) { // XXX: this does not belong to the standard, but may happen in our // implementation case PPP_STARTING_STATE: break; - + case PPP_CLOSED_STATE: case PPP_CLOSING_STATE: NewState(PPP_INITIAL_STATE); break; - + case PPP_STOPPED_STATE: // The RFC says we should reconnect, but our implementation // will only do this if auto-reconnect is enabled (only clients). NewState(PPP_STARTING_STATE); break; - + case PPP_STOPPING_STATE: case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: @@ -646,20 +674,20 @@ KPPPStateMachine::DownEvent() case PPP_OPENED_STATE: NewState(PPP_STARTING_STATE); break; - + default: IllegalEvent(PPP_DOWN_EVENT); } - + ppp_phase oldPhase = Phase(); NewPhase(PPP_DOWN_PHASE); - + DownProtocols(); - + // maybe we need to reconnect if (State() == PPP_STARTING_STATE) { bool deleteInterface = false, retry = false; - + // we do not try to reconnect if authentication failed if (fLocalAuthenticationStatus == PPP_AUTHENTICATION_FAILED || fLocalAuthenticationStatus == PPP_AUTHENTICATING @@ -673,7 +701,7 @@ KPPPStateMachine::DownEvent() } else { if (Interface().fConnectAttempt > (Interface().fConnectRetriesLimit + 1)) deleteInterface = true; - + if (oldPhase == PPP_DOWN_PHASE) { // failed to bring device up (UpFailedEvent() was called) retry = true; @@ -685,12 +713,12 @@ KPPPStateMachine::DownEvent() &fInterface.fID, sizeof(ppp_interface_id)); } } - + if (Interface().Parent()) Interface().Parent()->StateMachine().UpFailedEvent(Interface()); - + NewState(PPP_INITIAL_STATE); - + if (!deleteInterface && (retry || Interface().DoesAutoReconnect())) Interface().Reconnect(Interface().ReconnectDelay()); else @@ -701,7 +729,7 @@ KPPPStateMachine::DownEvent() &fInterface.fID, sizeof(ppp_interface_id)); Interface().Delete(); } - + fLocalAuthenticationStatus = PPP_NOT_AUTHENTICATED; fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED; } @@ -712,49 +740,49 @@ void KPPPStateMachine::OpenEvent() { TRACE("KPPPSM: OpenEvent() state=%d phase=%d\n", State(), Phase()); - + // reset all handlers if (Phase() != PPP_ESTABLISHED_PHASE) { DownProtocols(); ResetLCPHandlers(); } - + switch (State()) { case PPP_INITIAL_STATE: fLastConnectionReportCode = PPP_REPORT_GOING_UP; Interface().Report(PPP_CONNECTION_REPORT, PPP_REPORT_GOING_UP, &fInterface.fID, sizeof(ppp_interface_id)); - + if (Interface().Mode() == PPP_SERVER_MODE) { NewPhase(PPP_ESTABLISHMENT_PHASE); - + if (Interface().Device() && !Interface().Device()->Up()) { Interface().Device()->UpFailedEvent(); return; } } else NewState(PPP_STARTING_STATE); - + if (Interface().fAskBeforeConnecting == false) ContinueOpenEvent(); break; - + case PPP_CLOSED_STATE: if (Phase() == PPP_DOWN_PHASE) { // the device is already going down return; } - + NewState(PPP_REQ_SENT_STATE); NewPhase(PPP_ESTABLISHMENT_PHASE); InitializeRestartCount(); SendConfigureRequest(); break; - + case PPP_CLOSING_STATE: NewState(PPP_STOPPING_STATE); break; - + default: ; } @@ -765,7 +793,7 @@ void KPPPStateMachine::ContinueOpenEvent() { TRACE("KPPPSM: ContinueOpenEvent() state=%d phase=%d\n", State(), Phase()); - + if (Interface().IsMultilink() && !Interface().Parent()) { NewPhase(PPP_ESTABLISHMENT_PHASE); for (int32 index = 0; index < Interface().CountChildren(); index++) @@ -780,21 +808,21 @@ void KPPPStateMachine::CloseEvent() { TRACE("KPPPSM: CloseEvent() state=%d phase=%d\n", State(), Phase()); - + if (Interface().IsMultilink() && !Interface().Parent()) { NewState(PPP_INITIAL_STATE); - + if (Phase() != PPP_DOWN_PHASE) NewPhase(PPP_TERMINATION_PHASE); - + ThisLayerDown(); - + for (int32 index = 0; index < Interface().CountChildren(); index++) Interface().ChildAt(index)->StateMachine().CloseEvent(); - + return; } - + switch (State()) { case PPP_OPENED_STATE: case PPP_REQ_SENT_STATE: @@ -808,10 +836,10 @@ KPPPStateMachine::CloseEvent() ThisLayerDown(); SendTerminateRequest(); break; - + case PPP_STARTING_STATE: NewState(PPP_INITIAL_STATE); - + // TLSNotify() will know that we were faster because we // are in PPP_INITIAL_STATE now if (Phase() == PPP_ESTABLISHMENT_PHASE) { @@ -822,15 +850,15 @@ KPPPStateMachine::CloseEvent() ThisLayerFinished(); } break; - + case PPP_STOPPING_STATE: NewState(PPP_CLOSING_STATE); break; - + case PPP_STOPPED_STATE: NewState(PPP_STOPPED_STATE); break; - + default: ; } @@ -842,21 +870,21 @@ void KPPPStateMachine::TOGoodEvent() { TRACE("KPPPSM: TOGoodEvent() state=%d phase=%d\n", State(), Phase()); - + switch (State()) { case PPP_CLOSING_STATE: case PPP_STOPPING_STATE: SendTerminateRequest(); break; - + case PPP_ACK_RCVD_STATE: NewState(PPP_REQ_SENT_STATE); - + case PPP_REQ_SENT_STATE: case PPP_ACK_SENT_STATE: SendConfigureRequest(); break; - + default: IllegalEvent(PPP_TO_GOOD_EVENT); } @@ -868,14 +896,14 @@ void KPPPStateMachine::TOBadEvent() { TRACE("KPPPSM: TOBadEvent() state=%d phase=%d\n", State(), Phase()); - + switch (State()) { case PPP_CLOSING_STATE: NewState(PPP_CLOSED_STATE); NewPhase(PPP_TERMINATION_PHASE); ThisLayerFinished(); break; - + case PPP_STOPPING_STATE: case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: @@ -884,7 +912,7 @@ KPPPStateMachine::TOBadEvent() NewPhase(PPP_TERMINATION_PHASE); ThisLayerFinished(); break; - + default: IllegalEvent(PPP_TO_BAD_EVENT); } @@ -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 @@ -936,120 +971,145 @@ KPPPStateMachine::RCRGoodEvent(struct mbuf *packet) SendConfigureRequest(); SendConfigureAck(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: IllegalEvent(PPP_RCR_BAD_EVENT); break; - + case PPP_CLOSED_STATE: SendTerminateAck(); break; - + case PPP_STOPPED_STATE: // irc,scr,scn/6 // XXX: should we do nothing and wait for DownEvent()? break; - + case PPP_OPENED_STATE: NewState(PPP_REQ_SENT_STATE); NewPhase(PPP_ESTABLISHMENT_PHASE); // indicates to handlers that we are reconfiguring ThisLayerDown(); SendConfigureRequest(); - + case PPP_ACK_SENT_STATE: if (State() == PPP_ACK_SENT_STATE) NewState(PPP_REQ_SENT_STATE); // OPENED_STATE might have set this already - + case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: - if (nak && ntohs(mtod(nak, ppp_lcp_packet*)->length) > 3) + if (nak) { + NetBufferHeaderReader nakBufferHeader(nak); + if (nakBufferHeader.Status() < B_OK) + break; + ppp_lcp_packet &nakHeader = nakBufferHeader.Data(); + lenNak = nakHeader.length; + } + + if (reject) { + NetBufferHeaderReader 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 - + default: ; } - + 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 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; } - + // let the option handlers parse this ack KPPPConfigurePacket ack(packet); KPPPOptionHandler *optionHandler; 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; } } - + switch (State()) { case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RCA_EVENT); break; - + case PPP_CLOSED_STATE: case PPP_STOPPED_STATE: SendTerminateAck(); break; - + case PPP_REQ_SENT_STATE: NewState(PPP_ACK_RCVD_STATE); InitializeRestartCount(); break; - + case PPP_ACK_RCVD_STATE: NewState(PPP_REQ_SENT_STATE); SendConfigureRequest(); break; - + case PPP_ACK_SENT_STATE: NewState(PPP_OPENED_STATE); InitializeRestartCount(); ThisLayerUp(); break; - + case PPP_OPENED_STATE: NewState(PPP_REQ_SENT_STATE); NewPhase(PPP_ESTABLISHMENT_PHASE); @@ -1057,72 +1117,77 @@ KPPPStateMachine::RCAEvent(struct mbuf *packet) ThisLayerDown(); SendConfigureRequest(); break; - + default: ; } - - 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 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; } - + // let the option handlers parse this nak/reject KPPPConfigurePacket nak_reject(packet); KPPPOptionHandler *optionHandler; for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) { optionHandler = LCP().OptionHandlerAt(index); - + 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; } } } - + switch (State()) { case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RCN_EVENT); break; - + case PPP_CLOSED_STATE: case PPP_STOPPED_STATE: SendTerminateAck(); break; - + case PPP_REQ_SENT_STATE: case PPP_ACK_SENT_STATE: InitializeRestartCount(); - + case PPP_ACK_RCVD_STATE: if (State() == PPP_ACK_RCVD_STATE) NewState(PPP_REQ_SENT_STATE); SendConfigureRequest(); break; - + case PPP_OPENED_STATE: NewState(PPP_REQ_SENT_STATE); NewPhase(PPP_ESTABLISHMENT_PHASE); @@ -1130,35 +1195,40 @@ KPPPStateMachine::RCNEvent(struct mbuf *packet) ThisLayerDown(); SendConfigureRequest(); break; - + default: ; } - - 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 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; fPeerAuthenticationStatus = PPP_NOT_AUTHENTICATED; - + switch (State()) { case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RTR_EVENT); - m_freem(packet); + gBufferModule->free(packet); break; - + case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: NewState(PPP_REQ_SENT_STATE); @@ -1166,7 +1236,7 @@ KPPPStateMachine::RTREvent(struct mbuf *packet) // indicates to handlers that we are terminating SendTerminateAck(packet); break; - + case PPP_OPENED_STATE: NewState(PPP_STOPPING_STATE); NewPhase(PPP_TERMINATION_PHASE); @@ -1175,7 +1245,7 @@ KPPPStateMachine::RTREvent(struct mbuf *packet) ThisLayerDown(); SendTerminateAck(packet); break; - + default: NewPhase(PPP_TERMINATION_PHASE); // indicates to handlers that we are terminating @@ -1186,39 +1256,44 @@ 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 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; } - + switch (State()) { case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RTA_EVENT); break; - + case PPP_CLOSING_STATE: NewState(PPP_CLOSED_STATE); ThisLayerFinished(); break; - + case PPP_STOPPING_STATE: NewState(PPP_STOPPED_STATE); ThisLayerFinished(); break; - + case PPP_ACK_RCVD_STATE: NewState(PPP_REQ_SENT_STATE); break; - + case PPP_OPENED_STATE: NewState(PPP_REQ_SENT_STATE); NewPhase(PPP_ESTABLISHMENT_PHASE); @@ -1226,29 +1301,29 @@ KPPPStateMachine::RTAEvent(struct mbuf *packet) ThisLayerDown(); SendConfigureRequest(); break; - + default: ; } - - 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()); - + switch (State()) { case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RUC_EVENT); - m_freem(packet); + gBufferModule->free(packet); break; - + default: SendCodeReject(packet, protocolNumber, code); } @@ -1257,23 +1332,23 @@ 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()); - + // This method does not m_freem(packet) because the acceptable rejects are // also passed to the parent. RXJEvent() will m_freem(packet) when needed. - + switch (State()) { case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RXJ_GOOD_EVENT); break; - + case PPP_ACK_RCVD_STATE: NewState(PPP_REQ_SENT_STATE); break; - + default: ; } @@ -1282,35 +1357,35 @@ 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()); - + switch (State()) { case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RXJ_BAD_EVENT); break; - + case PPP_CLOSING_STATE: NewState(PPP_CLOSED_STATE); - + case PPP_CLOSED_STATE: ThisLayerFinished(); break; - + case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: NewState(PPP_STOPPED_STATE); - + case PPP_STOPPING_STATE: NewPhase(PPP_TERMINATION_PHASE); - + case PPP_STOPPED_STATE: ThisLayerFinished(); break; - + case PPP_OPENED_STATE: NewState(PPP_STOPPING_STATE); NewPhase(PPP_TERMINATION_PHASE); @@ -1320,41 +1395,44 @@ KPPPStateMachine::RXJBadEvent(struct mbuf *packet) SendTerminateRequest(); 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*); - - if (echo->code == PPP_ECHO_REPLY && echo->id != fEchoID) { + + NetBufferHeaderReader bufferHeader(packet); + if (bufferHeader.Status() < B_OK) + return; + ppp_lcp_packet &echo = bufferHeader.Data(); + + if (echo.code == PPP_ECHO_REPLY && echo.id != fEchoID) { // TODO: // log that we got a reply, but no request was sent } - + switch (State()) { case PPP_INITIAL_STATE: case PPP_STARTING_STATE: IllegalEvent(PPP_RXR_EVENT); 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 - + default: ; } - - m_freem(packet); + + gBufferModule->free(packet); } @@ -1366,12 +1444,12 @@ KPPPStateMachine::TimerEvent() if (fNextTimeout != 0) TRACE("KPPPSM: TimerEvent()\n"); #endif - + if (fNextTimeout == 0 || fNextTimeout > system_time()) return; - + fNextTimeout = 0; - + switch (State()) { case PPP_CLOSING_STATE: case PPP_STOPPING_STATE: @@ -1380,7 +1458,7 @@ KPPPStateMachine::TimerEvent() else TOGoodEvent(); break; - + case PPP_REQ_SENT_STATE: case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: @@ -1389,7 +1467,7 @@ KPPPStateMachine::TimerEvent() else TOGoodEvent(); break; - + default: ; } @@ -1397,56 +1475,76 @@ 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 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()); - + // each handler should add unacceptable values for each item status_t result; // the return value of ParseRequest() KPPPOptionHandler *optionHandler; for (int32 index = 0; index < request.CountItems(); index++) { optionHandler = LCP().OptionHandlerFor(request.ItemAt(index)->type); - + if (!optionHandler || !optionHandler->IsEnabled()) { - ERROR("KPPPSM::RCREvent():unknown type:%d\n", request.ItemAt(index)->type); - // unhandled items should be added to the reject - reject.AddItem(request.ItemAt(index)); - continue; + 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"); result = optionHandler->ParseRequest(request, index, nak, reject); - + 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; } } - + // Additional values may be appended. // If we sent too many naks we should not append additional values. if (fNakCounter > 0) { @@ -1455,25 +1553,27 @@ KPPPStateMachine::RCREvent(struct mbuf *packet) if (optionHandler && optionHandler->IsEnabled()) { result = optionHandler->ParseRequest(request, request.CountItems(), nak, reject); - + 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 append error!\n"); - m_freem(packet); + gBufferModule->free(packet); CloseEvent(); return; } } } } - + 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,49 +1583,52 @@ 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*); - - if (reject->code == PPP_CODE_REJECT) { - uint8 rejectedCode = reject->data[0]; - + + NetBufferHeaderReader 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]; + // 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); - + return; } - + // find the LCP extension and disable it KPPPLCPExtension *lcpExtension; for (int32 index = 0; index < LCP().CountLCPExtensions(); index++) { lcpExtension = LCP().LCPExtensionAt(index); - + if (lcpExtension->Code() == rejectedCode) 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) { // LCP must not be rejected! RXJBadEvent(packet); return; } - + // disable protocols with the rejected protocol number KPPPProtocol *protocol = Interface().FirstProtocol(); for (; protocol; protocol = protocol->NextProtocol()) { @@ -1533,15 +1636,15 @@ KPPPStateMachine::RXJEvent(struct mbuf *packet) protocol->SetEnabled(false); // disable protocol } - + RXJGoodEvent(packet); // this event handler does not m_freem(packet)!!! - + // notify parent, too 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()); } @@ -1561,16 +1664,16 @@ void KPPPStateMachine::ThisLayerUp() { TRACE("KPPPSM: ThisLayerUp() state=%d phase=%d\n", State(), Phase()); - + // We begin with authentication phase and wait until each phase is done. // We stop when we reach established phase. - + // Do not forget to check if we are going down. if (Phase() != PPP_ESTABLISHMENT_PHASE) return; - + NewPhase(PPP_AUTHENTICATION_PHASE); - + BringProtocolsUp(); } @@ -1579,7 +1682,7 @@ void KPPPStateMachine::ThisLayerDown() { TRACE("KPPPSM: ThisLayerDown() state=%d phase=%d\n", State(), Phase()); - + // KPPPProtocol::Down() should block if needed. DownProtocols(); } @@ -1589,7 +1692,7 @@ void KPPPStateMachine::ThisLayerStarted() { TRACE("KPPPSM: ThisLayerStarted() state=%d phase=%d\n", State(), Phase()); - + if (Interface().Device() && !Interface().Device()->Up()) Interface().Device()->UpFailedEvent(); } @@ -1599,7 +1702,7 @@ void KPPPStateMachine::ThisLayerFinished() { TRACE("KPPPSM: ThisLayerFinished() state=%d phase=%d\n", State(), Phase()); - + if (Interface().Device()) Interface().Device()->Down(); } @@ -1627,14 +1730,14 @@ bool KPPPStateMachine::SendConfigureRequest() { TRACE("KPPPSM: SendConfigureRequest() state=%d phase=%d\n", State(), Phase()); - + --fRequestCounter; fNextTimeout = system_time() + kPPPStateMachineTimeout; - + KPPPConfigurePacket request(PPP_CONFIGURE_REQUEST); request.SetID(NextID()); fRequestID = request.ID(); - + for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) { // add all items if (LCP().OptionHandlerAt(index)->AddToRequest(request) != B_OK) { @@ -1642,53 +1745,65 @@ KPPPStateMachine::SendConfigureRequest() return false; } } - - 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 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 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; } - + return LCP().Send(packet) == B_OK; } @@ -1697,120 +1812,113 @@ bool KPPPStateMachine::SendTerminateRequest() { TRACE("KPPPSM: SendTerminateRequest() state=%d phase=%d\n", State(), Phase()); - + --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; - - // reserve some space for other protocols - packet->m_data += LCP().AdditionalOverhead(); - - 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; + + packet->code = PPP_TERMINATE_REQUEST; + packet->id = fTerminateID = NextID(); + packet->length = htons(4); + + status = gBufferModule->trim(buffer, 4); + if (status < B_OK) { + gBufferModule->free(buffer); + return false; + } + + 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; - - ppp_lcp_packet *ack; - + + net_buffer *reply = request; + + NetBufferHeaderReader 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; - - 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.length = htons(4); + ack.id = NextID(); + } + + 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()); - + if (!packet) return false; - + int32 length; // additional space needed for this reject if (code == PPP_PROTOCOL_REJECT) length = 6; else length = 4; - - M_PREPEND(packet, length); - // add some space for the header - - // 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); - + + NetBufferHeaderReader bufferHeader(packet); + if (bufferHeader.Status() < B_OK) + return false; + ppp_lcp_packet &reject = bufferHeader.Data(); + + 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 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; } @@ -1823,7 +1931,7 @@ KPPPStateMachine::BringProtocolsUp() while (Phase() <= PPP_ESTABLISHED_PHASE && Phase() >= PPP_AUTHENTICATION_PHASE) { if (BringPhaseUp() > 0) break; - + if (Phase() < PPP_AUTHENTICATION_PHASE) return; // phase was changed by another event @@ -1843,11 +1951,11 @@ KPPPStateMachine::BringPhaseUp() { // Servers do not need to bring all protocols up. // The client specifies which protocols he wants to go up. - + // check for phase change if (Phase() < PPP_AUTHENTICATION_PHASE) return 0; - + uint32 count = 0; KPPPProtocol *protocol = Interface().FirstProtocol(); for (; protocol; protocol = protocol->NextProtocol()) { @@ -1857,18 +1965,18 @@ KPPPStateMachine::BringPhaseUp() else if (protocol->IsDown() && protocol->IsUpRequested()) { if (Interface().Mode() == PPP_CLIENT_MODE) ++count; - + protocol->Up(); } } } - + // We only wait until authentication is complete. if (Interface().Mode() == PPP_SERVER_MODE && (LocalAuthenticationStatus() == PPP_AUTHENTICATING || PeerAuthenticationStatus() == PPP_AUTHENTICATING)) ++count; - + return count; } @@ -1877,7 +1985,7 @@ void KPPPStateMachine::DownProtocols() { KPPPProtocol *protocol = Interface().FirstProtocol(); - + for (; protocol; protocol = protocol->NextProtocol()) if (protocol->IsEnabled()) protocol->Down(); @@ -1889,7 +1997,7 @@ KPPPStateMachine::ResetLCPHandlers() { for (int32 index = 0; index < LCP().CountOptionHandlers(); index++) LCP().OptionHandlerAt(index)->Reset(); - + for (int32 index = 0; index < LCP().CountLCPExtensions(); index++) LCP().LCPExtensionAt(index)->Reset(); } diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPConfigurePacket.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPConfigurePacket.h index 408dabc15d..61a78897bd 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPConfigurePacket.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPConfigurePacket.h @@ -7,8 +7,7 @@ #define _K_PPP_CONFIGURE_PACKET__H #include - -struct mbuf; +#include //! 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; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPDevice.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPDevice.h index e2cd97170e..a6917345d8 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPDevice.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPDevice.h @@ -9,6 +9,8 @@ #include #include +#include + #ifndef _K_PPP_INTERFACE__H #include #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). diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h index a2c22e50d7..a1c92d82ab 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPInterface.h @@ -30,6 +30,12 @@ #include +#include +#include + +#include +#include + class KPPPDevice; class KPPPProtocol; class KPPPOptionHandler; @@ -48,6 +54,8 @@ class KPPPInterface : public KPPPLayer { KPPPInterface(const KPPPInterface& copy); KPPPInterface& operator= (const KPPPInterface& copy); + public: + // we should set to private after finishing test // only PPPManager may construct us! KPPPInterface(const char *name, ppp_interface_entry *entry, ppp_interface_id ID, const driver_settings *settings, @@ -75,8 +83,8 @@ class KPPPInterface : public KPPPLayer { { return fLCP; } //! Returns the interfac's ifnet structure that is exported to the netstack. - struct ifnet *Ifnet() const - { return fIfnet; } + net_device *Ifnet() const + { return fIfnet; } const char *Username() const; const char *Password() const; @@ -220,11 +228,11 @@ class KPPPInterface : public KPPPLayer { virtual bool IsAllowedToSend() const; // always returns true - virtual status_t Send(struct mbuf *packet, uint16 protocolNumber); + virtual status_t Send(net_buffer *packet, uint16 protocolNumber); // sends the packet to the next handler (normally the device) - virtual status_t Receive(struct mbuf *packet, uint16 protocolNumber); + virtual status_t Receive(net_buffer *packet, uint16 protocolNumber); - status_t ReceiveFromDevice(struct mbuf *packet); + status_t ReceiveFromDevice(net_buffer *packet); // This must not block KPPPDevice::Send()! void Pulse(); @@ -255,7 +263,7 @@ class KPPPInterface : public KPPPLayer { ppp_interface_id fID; // the manager assigns an ID to every interface driver_settings *fSettings; - struct ifnet *fIfnet; + net_device *fIfnet; char *fUsername, *fPassword; @@ -288,7 +296,7 @@ class KPPPInterface : public KPPPLayer { KPPPStateMachine fStateMachine; KPPPLCP fLCP; KPPPReportManager fReportManager; - BLocker& fLock; + mutex& fLock; int32 fDeleteCounter; }; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLCP.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLCP.h index 5919911ddd..04f966c454 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLCP.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLCP.h @@ -20,6 +20,9 @@ #include #endif +#include +#include + 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(); diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLCPExtension.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLCPExtension.h index 8d21c7b180..828a0a1b82 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLCPExtension.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLCPExtension.h @@ -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(); diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLayer.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLayer.h index 4aba95d118..98731b8e99 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLayer.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPLayer.h @@ -8,6 +8,7 @@ #include +#include 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(); diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPManager.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPManager.h index dd92c8fda2..347e0aa474 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPManager.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPManager.h @@ -6,12 +6,12 @@ #ifndef _K_PPP_MANAGER__H #define _K_PPP_MANAGER__H -#include "net_module.h" +#include +#include #include #include - -#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, diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPProtocol.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPProtocol.h index 824fd91d1b..bc1a8a085d 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPProtocol.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPProtocol.h @@ -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. diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPReportManager.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPReportManager.h index 1d5f1eac63..91bf6370ce 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPReportManager.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPReportManager.h @@ -13,10 +13,13 @@ #include +#include +#include + 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 fReportRequests; }; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPStateMachine.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPStateMachine.h index d281e0de73..a0cac1bd43 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPStateMachine.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPStateMachine.h @@ -14,7 +14,8 @@ class KPPPProtocol; #include #endif -#include +#include +#include class PPPManager; class KPPPInterface; @@ -30,7 +31,7 @@ class KPPPStateMachine { // may only be constructed/destructed by KPPPInterface KPPPStateMachine(KPPPInterface& interface); ~KPPPStateMachine(); - + // copies are not allowed! KPPPStateMachine(const KPPPStateMachine& copy); KPPPStateMachine& operator= (const KPPPStateMachine& copy); @@ -42,28 +43,28 @@ class KPPPStateMachine { //! Returns the LCP protocol object belonging to this state machine. KPPPLCP& LCP() const { return fLCP; } - + //! Returns the current state as defined in RFC 1661. ppp_state State() const { return fState; } //! Returns the internal phase. ppp_phase Phase() const { return fPhase; } - + uint8 NextID(); - + //! Sets our packets' magic number. Used by Link-Quality-Monitoring. void SetMagicNumber(uint32 magicNumber) { fMagicNumber = magicNumber; } //! Returns our packets' magic number. uint32 MagicNumber() const { return fMagicNumber; } - + // public actions bool Reconfigure(); bool SendEchoRequest(); bool SendDiscardRequest(); - + // public events: // NOTE: Local/PeerAuthenticationAccepted/Denied MUST be called before // Up(Failed)/DownEvent in order to allow changing the configuration of @@ -77,7 +78,7 @@ class KPPPStateMachine { //! Returns our local authentication status. ppp_authentication_status LocalAuthenticationStatus() const { return fLocalAuthenticationStatus; } - + void PeerAuthenticationRequested(); void PeerAuthenticationAccepted(const char *name); void PeerAuthenticationDenied(const char *name); @@ -87,17 +88,17 @@ class KPPPStateMachine { //! Returns the peer's authentication status. ppp_authentication_status PeerAuthenticationStatus() const { return fPeerAuthenticationStatus; } - + // sub-interface events void UpFailedEvent(KPPPInterface& interface); void UpEvent(KPPPInterface& interface); void DownEvent(KPPPInterface& interface); - + // protocol events void UpFailedEvent(KPPPProtocol *protocol); void UpEvent(KPPPProtocol *protocol); void DownEvent(KPPPProtocol *protocol); - + // device events bool TLSNotify(); bool TLFNotify(); @@ -109,30 +110,30 @@ class KPPPStateMachine { // private StateMachine methods void NewState(ppp_state next); void NewPhase(ppp_phase next); - + // private events void OpenEvent(); void ContinueOpenEvent(); void CloseEvent(); void TOGoodEvent(); void TOBadEvent(); - void RCRGoodEvent(struct mbuf *packet); - void RCRBadEvent(struct mbuf *nak, struct mbuf *reject); - void RCAEvent(struct mbuf *packet); - void RCNEvent(struct mbuf *packet); - void RTREvent(struct mbuf *packet); - void RTAEvent(struct mbuf *packet); - void RUCEvent(struct mbuf *packet, uint16 protocolNumber, + void RCRGoodEvent(net_buffer *packet); + void RCRBadEvent(net_buffer *nak, net_buffer *reject); + void RCAEvent(net_buffer *packet); + void RCNEvent(net_buffer *packet); + void RTREvent(net_buffer *packet); + void RTAEvent(net_buffer *packet); + void RUCEvent(net_buffer *packet, uint16 protocolNumber, uint8 code = PPP_PROTOCOL_REJECT); - void RXJGoodEvent(struct mbuf *packet); - void RXJBadEvent(struct mbuf *packet); - void RXREvent(struct mbuf *packet); - + void RXJGoodEvent(net_buffer *packet); + void RXJBadEvent(net_buffer *packet); + void RXREvent(net_buffer *packet); + // general events (for Good/Bad events) void TimerEvent(); - void RCREvent(struct mbuf *packet); - void RXJEvent(struct mbuf *packet); - + void RCREvent(net_buffer *packet); + void RXJEvent(net_buffer *packet); + // actions void IllegalEvent(ppp_event event); void ThisLayerUp(); @@ -142,42 +143,42 @@ class KPPPStateMachine { void InitializeRestartCount(); void ZeroRestartCount(); bool SendConfigureRequest(); - bool SendConfigureAck(struct mbuf *packet); - bool SendConfigureNak(struct mbuf *packet); + bool SendConfigureAck(net_buffer *packet); + bool SendConfigureNak(net_buffer *packet); bool SendTerminateRequest(); - bool SendTerminateAck(struct mbuf *request = NULL); - bool SendCodeReject(struct mbuf *packet, uint16 protocolNumber, uint8 code); - bool SendEchoReply(struct mbuf *request); - + bool SendTerminateAck(net_buffer *request = NULL); + bool SendCodeReject(net_buffer *packet, uint16 protocolNumber, uint8 code); + bool SendEchoReply(net_buffer *request); + void BringProtocolsUp(); uint32 BringPhaseUp(); - + void DownProtocols(); void ResetLCPHandlers(); private: KPPPInterface& fInterface; KPPPLCP& fLCP; - + ppp_state fState; ppp_phase fPhase; - - vint32 fID; + + int32 fID; uint32 fMagicNumber; int32 fLastConnectionReportCode; - + ppp_authentication_status fLocalAuthenticationStatus, fPeerAuthenticationStatus; char *fLocalAuthenticationName, *fPeerAuthenticationName; - + // counters and timers int32 fMaxRequest, fMaxTerminate, fMaxNak; int32 fRequestCounter, fTerminateCounter, fNakCounter; uint8 fRequestID, fTerminateID, fEchoID; // the ID we used for the last configure/terminate/echo request bigtime_t fNextTimeout; - - BLocker fLock; + + mutex fLock; }; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPControl.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPControl.h index cb731571c7..ca5c536d8c 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPControl.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPControl.h @@ -11,6 +11,76 @@ #include +#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 diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPDefs.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPDefs.h index afa85d1a43..58be01fae7 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPDefs.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/PPPDefs.h @@ -10,8 +10,6 @@ #include -#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 diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/ppp_device.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/ppp_device.h new file mode 100644 index 0000000000..7e70e0c08b --- /dev/null +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/ppp_device.h @@ -0,0 +1,18 @@ +#ifndef __PPP_DEV_H +#define __PPP_DEV_H +#include +#include + +#include + +#include +#include +#include + +struct ppp_device : net_device, DoublyLinkedListLinkImpl { + KPPPInterface * KPPP_Interface; + uint32 frame_size; + net_fifo ppp_fifo; +}; + +#endif diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/Jamfile b/src/add-ons/kernel/network/ppp/shared/libppp/Jamfile index 4d658b0afd..1f720cdc88 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/Jamfile +++ b/src/add-ons/kernel/network/ppp/shared/libppp/Jamfile @@ -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 ] ; diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp b/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp index 5a4118c1c3..2977bd2a8d 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp @@ -13,13 +13,20 @@ #include "PPPInterface.h" #include +#include +#include +#include #include -#include "_libppputils.h" #include #include #include +#include + +#include +#include + /*! \brief Sets the interface to \a ID. @@ -27,7 +34,9 @@ */ PPPInterface::PPPInterface(ppp_interface_id ID) { - fFD = open(get_stack_driver_path(), O_RDWR); + // printf("direct constructor\n"); + int family = AF_INET; + fFD = socket(family, SOCK_DGRAM, 0); SetTo(ID); } @@ -36,7 +45,10 @@ PPPInterface::PPPInterface(ppp_interface_id ID) //! Copy constructor. PPPInterface::PPPInterface(const PPPInterface& copy) { - fFD = open(get_stack_driver_path(), O_RDWR); + // printf("Copy constructor\n"); + // fFD = open(get_stack_driver_path(), O_RDWR); + int family = AF_INET; + fFD = socket(family, SOCK_DGRAM, 0); SetTo(copy.ID()); } @@ -45,6 +57,7 @@ PPPInterface::PPPInterface(const PPPInterface& copy) //! Destructor. PPPInterface::~PPPInterface() { + // printf("Destructor\n"); if (fFD >= 0) close(fFD); } @@ -64,6 +77,7 @@ PPPInterface::InitCheck() const { if (fFD < 0) return B_ERROR; + if (fID == PPP_UNDEFINED_INTERFACE_ID) return B_BAD_INDEX; @@ -87,19 +101,29 @@ PPPInterface::InitCheck() const status_t PPPInterface::SetTo(ppp_interface_id ID) { - if (fFD < 0) + // printf("Set To %ld begin=============================\n", ID); + if (fFD < 0) { + printf("No fFD\n"); return B_ERROR; + } + + fID = ID; ppp_interface_info_t info; + // printf("SetTo info:%p\n", &info); if (GetInterfaceInfo(&info)) { fName = info.info.name; fID = ID; + // printf("%s fine: name:%s, fID:%ld\n", __func__, info.info.name, fID); } else { fName = ""; fID = PPP_UNDEFINED_INTERFACE_ID; + // printf("%s fail: name:%s, fID:%ld\n", __func__, "", fID); return B_ERROR; } + // printf("Set To %ld end =============================\n", ID); + return B_OK; } @@ -119,23 +143,32 @@ PPPInterface::SetTo(ppp_interface_id ID) status_t PPPInterface::Control(uint32 op, void *data, size_t length) const { - if (InitCheck() != B_OK) + if (InitCheck() != B_OK) { + printf("%s:InitCheck fail\n", __func__); return InitCheck(); - - ppp_control_info control; + } + + ppp_control_info info; control_net_module_args args; - + + sprintf(args.ifr_name, "%s", "ppp1"); args.name = PPP_INTERFACE_MODULE_NAME; args.op = PPPC_CONTROL_INTERFACE; - args.data = &control; - args.length = sizeof(control); - - control.index = ID(); - control.op = op; - control.data = data; - control.length = length; - - return ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args); + args.data = &info; + args.length = sizeof(ppp_control_info); + + info.index = ID(); + info.op = op; + info.data = data; + info.length = length; + + printf("PPPInterface::Control: ppp_control_info %p control_net_module_args %p data %p \n", &info, &args, data); + + status_t status = ioctl(fFD, NET_STACK_CONTROL_NET_MODULE, &args); + if (status != B_OK) + printf("%s:%s: fail\n", __FILE__, __func__); + + return status; } @@ -143,6 +176,7 @@ PPPInterface::Control(uint32 op, void *data, size_t length) const bool PPPInterface::SetUsername(const char *username) const { + printf("PPPInterface::SetUsername\n"); if (InitCheck() != B_OK || !username) return false; @@ -155,6 +189,7 @@ PPPInterface::SetUsername(const char *username) const bool PPPInterface::SetPassword(const char *password) const { + printf("PPPInterface::SetPassword\n"); if (InitCheck() != B_OK || !password) return false; @@ -167,6 +202,7 @@ PPPInterface::SetPassword(const char *password) const bool PPPInterface::SetAskBeforeConnecting(bool askBeforeConnecting) const { + printf("PPPInterface::SetAskBeforeConnecting\n"); if (InitCheck() != B_OK) return false; @@ -188,6 +224,7 @@ PPPInterface::SetAskBeforeConnecting(bool askBeforeConnecting) const status_t PPPInterface::GetSettingsEntry(BEntry *entry) const { + printf("PPPInterface::GetSettingsEntry\n"); if (InitCheck() != B_OK) return InitCheck(); else if (!entry || strlen(Name()) == 0) @@ -205,10 +242,103 @@ PPPInterface::GetSettingsEntry(BEntry *entry) const bool PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const { + // printf("%s info at:%p", __func__, info); + if (InitCheck() != B_OK || !info) { + // printf("InitCheck fail %s info at:%p", __func__, info); + return false; + } + + return Control(PPPC_GET_INTERFACE_INFO, info, sizeof(ppp_interface_info_t)) + == B_OK; +} + + +bool +PPPInterface::ControlDevice(ppp_device_info_t *info) const +{ + // printf("%s info at:%p", __func__, info); if (InitCheck() != B_OK || !info) return false; - - return Control(PPPC_GET_INTERFACE_INFO, &info, sizeof(ppp_interface_info_t)) + + ppp_control_info controlInfo; + controlInfo.op = PPPC_GET_DEVICE_INFO; + controlInfo.index = 0; + controlInfo.data = info; + controlInfo.length = sizeof(ppp_device_info_t); + + return Control(PPPC_CONTROL_DEVICE, &controlInfo, sizeof(ppp_control_info)) + == B_OK; +} + + +bool +PPPInterface::ControlOptionHandler(ppp_simple_handler_info_t *info, uint32 handlerindex, uint32 handlerOP) const +{ + // printf("%s info at:%p", __func__, info); + if (InitCheck() != B_OK || !info) + return false; + + ppp_control_info controlInfo; + controlInfo.index = handlerindex; + controlInfo.op = handlerOP; + controlInfo.data = info; + controlInfo.length = sizeof(ppp_simple_handler_info_t); + + return Control(PPPC_CONTROL_OPTION_HANDLER, &controlInfo, sizeof(ppp_control_info)) + == B_OK; +} + + +bool +PPPInterface::ControlChild(void *info, uint32 childindex, uint32 childOP) const +{ + // printf("%s info at:%p", __func__, info); + if (InitCheck() != B_OK || !info) + return false; + + ppp_control_info controlInfo; + controlInfo.index = childindex; + controlInfo.op = childOP; + controlInfo.data = info; + // controlInfo.length = sizeof(ppp_simple_handler_info_t); + + return Control(PPPC_CONTROL_CHILD, &controlInfo, sizeof(ppp_control_info)) + == B_OK; +} + + +bool +PPPInterface::ControlLCPExtension(ppp_simple_handler_info_t *info, uint32 LCPExtensionindex, uint32 LCPExtensionOP) const +{ + // printf("%s info at:%p", __func__, info); + if (InitCheck() != B_OK || !info) + return false; + + ppp_control_info controlInfo; + controlInfo.index = LCPExtensionindex; + controlInfo.op = LCPExtensionOP; + controlInfo.data = info; + controlInfo.length = sizeof(ppp_simple_handler_info_t); + + return Control(PPPC_CONTROL_LCP_EXTENSION, &controlInfo, sizeof(ppp_control_info)) + == B_OK; +} + + +bool +PPPInterface::ControlProtocol(ppp_protocol_info_t *info, uint32 protocolindex, uint32 protocolOP) const +{ + // printf("%s info at:%p", __func__, info); + if (InitCheck() != B_OK || !info) + return false; + + ppp_control_info controlInfo; + controlInfo.index = protocolindex; + controlInfo.op = protocolOP; + controlInfo.data = info; + controlInfo.length = sizeof(ppp_protocol_info_t); + + return Control(PPPC_CONTROL_PROTOCOL, &controlInfo, sizeof(ppp_control_info)) == B_OK; } @@ -222,6 +352,7 @@ PPPInterface::GetInterfaceInfo(ppp_interface_info_t *info) const bool PPPInterface::GetStatistics(ppp_statistics *statistics) const { + printf("PPPInterface::GetStatistics\n"); if (!statistics) return false; @@ -233,6 +364,7 @@ PPPInterface::GetStatistics(ppp_statistics *statistics) const bool PPPInterface::HasSettings(const driver_settings *settings) const { + printf("PPPInterface::HasSettings\n"); if (InitCheck() != B_OK || !settings) return false; @@ -250,9 +382,24 @@ PPPInterface::Up() const { if (InitCheck() != B_OK) return false; - + + BNetworkInterface interface(Name()); + if (!interface.Exists()) + return false; + + int32 currentFlags = interface.Flags(); + currentFlags |= IFF_UP; + + status_t status = interface.SetFlags(currentFlags); + + if (status != B_OK) + return false; + + return true; + int32 id = ID(); control_net_module_args args; + sprintf(args.ifr_name, "%s", "ppp1"); args.name = PPP_INTERFACE_MODULE_NAME; args.op = PPPC_BRING_INTERFACE_UP; args.data = &id; @@ -268,9 +415,24 @@ PPPInterface::Down() const { if (InitCheck() != B_OK) return false; - + + BNetworkInterface interface(Name()); + if (!interface.Exists()) + return false; + + int32 currentFlags = interface.Flags(); + currentFlags &= ~IFF_UP; + + status_t status = interface.SetFlags(currentFlags); + + if (status != B_OK) + return false; + + return true; + int32 id = ID(); control_net_module_args args; + sprintf(args.ifr_name, "%s", "ppp1"); args.name = PPP_INTERFACE_MODULE_NAME; args.op = PPPC_BRING_INTERFACE_DOWN; args.data = &id; @@ -292,6 +454,7 @@ bool PPPInterface::EnableReports(ppp_report_type type, thread_id thread, int32 flags) const { + printf("PPPInterface::EnableReports\n"); ppp_report_request request; request.type = type; request.thread = thread; @@ -311,6 +474,7 @@ PPPInterface::EnableReports(ppp_report_type type, thread_id thread, bool PPPInterface::DisableReports(ppp_report_type type, thread_id thread) const { + printf("PPPInterface::DisableReports\n"); ppp_report_request request; request.type = type; request.thread = thread; diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp b/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp index 3ca8c5a453..7ccc4c61a7 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libppp/PPPManager.cpp @@ -20,16 +20,49 @@ #include #include +#include #include #include #include -#include "_libppputils.h" +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include //! Constructor. Does nothing special. PPPManager::PPPManager() { - fFD = open(get_stack_driver_path(), O_RDWR); + // fFD = open(get_stack_driver_path(), O_RDWR); + int family = AF_INET; + + fFD = socket(family, SOCK_DGRAM, 0); + + // FileDescriptorCloser closer(socket); + + // ifaliasreq request; + // strlcpy(request.ifra_name, name, IF_NAMESIZE); + // request.ifra_index = address.Index(); + // request.ifra_flags = address.Flags(); + + // memcpy(&request.ifra_addr, &address.Address().SockAddr(), + // address.Address().Length()); + // memcpy(&request.ifra_mask, &address.Mask().SockAddr(), + // address.Mask().Length()); + // memcpy(&request.ifra_broadaddr, &address.Broadcast().SockAddr(), + // address.Broadcast().Length()); + + // if (ioctl(socket, option, &request, sizeof(struct ifaliasreq)) < 0) + // return errno; + } @@ -133,6 +166,7 @@ PPPManager::Control(uint32 op, void *data, size_t length) const return B_ERROR; control_net_module_args args; + sprintf(args.ifr_name, "%s", "ppp1"); args.name = PPP_INTERFACE_MODULE_NAME; args.op = op; args.data = data; @@ -169,6 +203,7 @@ PPPManager::ControlModule(const char *name, uint32 op, void *data, return B_ERROR; control_net_module_args args; + sprintf(args.ifr_name, "%s", "ppp1"); args.name = name; args.op = op; args.data = data; @@ -207,13 +242,72 @@ PPPManager::CreateInterface(const driver_settings *settings) const ppp_interface_id PPPManager::CreateInterfaceWithName(const char *name) const { - ppp_interface_description_info info; - info.u.name = name; + ppp_interface_id ID = InterfaceWithName(name); + + if (ID != PPP_UNDEFINED_INTERFACE_ID) + return ID; + + BNetworkInterface interface(name); + if (!interface.Exists()) { + // the interface does not exist yet, we have to add it first + BNetworkRoster& roster = BNetworkRoster::Default(); + + status_t status = roster.AddInterface(interface); + if (status != B_OK) { + fprintf(stderr, "PPPManager::CreateInterfaceWithName: Could not add interface: %s\n", + strerror(status)); + return PPP_UNDEFINED_INTERFACE_ID; + } + + return InterfaceWithName(name); + } + + return PPP_UNDEFINED_INTERFACE_ID; + +// ppp_interface_description_info info; +// info.u.name = name; +// +// if (Control(PPPC_CREATE_INTERFACE_WITH_NAME, &info, sizeof(info)) != B_OK) +// return PPP_UNDEFINED_INTERFACE_ID; +// else +// return info.interface; + +} + + +/*! It will remove the complete interface with all + of its addresses. +*/ +bool +delete_interface(const char* name) +{ + BNetworkInterface interface(name); + + // Delete interface + BNetworkRoster& roster = BNetworkRoster::Default(); + + status_t status = roster.RemoveInterface(interface); + if (status != B_OK) { + fprintf(stderr, "delete_interface: Could not delete interface %s\n", + name); + return false; + } + + return true; +} + + +//! Deletes the interface with the given \a name. +bool +PPPManager::DeleteInterface(const char* name) const +{ + ppp_interface_id ID = InterfaceWithName(name); + + if (ID == PPP_UNDEFINED_INTERFACE_ID) + return false; + + return delete_interface(name); - if (Control(PPPC_CREATE_INTERFACE_WITH_NAME, &info, sizeof(info)) != B_OK) - return PPP_UNDEFINED_INTERFACE_ID; - else - return info.interface; } @@ -253,18 +347,22 @@ PPPManager::Interfaces(int32 *count, // loop until we get all interfaces while (true) { requestCount = *count = CountInterfaces(filter); - if (*count == -1) + if (*count <= 0) { + printf("No interface, count, first round:%ld\n", *count); return NULL; + } requestCount += 10; // request some more interfaces in case some are added in the mean time interfaces = new ppp_interface_id[requestCount]; + // printf("interfaces addr: %p\n, requestCount: %ld", interfaces, requestCount); *count = GetInterfaces(interfaces, requestCount, filter); - if (*count == -1) { + if (*count <= 0) { + printf("No interface, count second round:%ld\n", *count); delete interfaces; return NULL; } - + if (*count < requestCount) break; @@ -345,12 +443,17 @@ PPPManager::InterfaceWithName(const char *name) const int32 count; ppp_interface_id *interfaces = Interfaces(&count, PPP_REGISTERED_INTERFACES); - if (!interfaces) + if (!interfaces || count <= 0) { + printf("ERROR: Could not get ppp name:%s\n", name); return PPP_UNDEFINED_INTERFACE_ID; - + } + + // printf("first ID:%ld count:%ld\n", interfaces[0], count); + ppp_interface_id id = PPP_UNDEFINED_INTERFACE_ID; PPPInterface interface; ppp_interface_info_t info; + // printf("internal info is at: %p\n", &info); for (int32 index = 0; index < count; index++) { interface.SetTo(interfaces[index]); @@ -374,11 +477,79 @@ PPPManager::InterfaceWithName(const char *name) const } +//! Returns the number of existing interfaces or a negative value on error. +bool +is_ppp_interface(const char* name) +{ + // size_t length = strlen(name); + // if (length < 8) + // putchar('\t'); + // else + // printf("\n\t"); + + // get link level interface for this interface + + BNetworkInterface interface(name); + BNetworkAddress linkAddress; + status_t status = interface.GetHardwareAddress(linkAddress); + if (status == B_OK) { + // const char *type = "unknown"; + switch (linkAddress.LinkLevelType()) { + case IFT_ETHER: + // type = "Ethernet"; + // printf("%s\n", type); + break; + case IFT_LOOP: + // type = "Local Loopback"; + // printf("%s\n", type); + break; + case IFT_MODEM: + // type = "Modem"; + // printf("%s\n", type); + break; + case IFT_PPP: + // type = "PPP"; + // printf("%s\n", type); + return true; + break; + default: + // printf("%s\n", type); + ; + + } + + } + return false; +} + + +//! Returns the number of ppp interfaces +int32 +count_ppp_interface(void) +{ + int32 count = 0; + + // get a list of all ppp interfaces + BNetworkRoster& roster = BNetworkRoster::Default(); + + BNetworkInterface interface; + uint32 cookie = 0; + + while (roster.GetNextInterface(&cookie, interface) == B_OK) { + if (is_ppp_interface(interface.Name())) + count++; + } + + return count; +} + + //! Returns the number of existing interfaces or a negative value on error. int32 PPPManager::CountInterfaces(ppp_interface_filter filter) const { - return Control(PPPC_COUNT_INTERFACES, &filter, sizeof(filter)); + // return Control(PPPC_COUNT_INTERFACES, &filter, sizeof(filter)); + return count_ppp_interface(); } diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/_libppputils.cpp b/src/add-ons/kernel/network/ppp/shared/libppp/_libppputils.cpp deleted file mode 100644 index b81c10fde2..0000000000 --- a/src/add-ons/kernel/network/ppp/shared/libppp/_libppputils.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2003-2007, Waldemar Kornewald - * Distributed under the terms of the MIT License. - */ - -#include -#include "_libppputils.h" -#include -#include - - -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; -} diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/_libppputils.h b/src/add-ons/kernel/network/ppp/shared/libppp/_libppputils.h deleted file mode 100644 index db72c1aaca..0000000000 --- a/src/add-ons/kernel/network/ppp/shared/libppp/_libppputils.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2003-2007, Waldemar Kornewald - * Distributed under the terms of the MIT License. - */ - -#ifndef __libppputils__h -#define __libppputils__h - -#include - - -char *get_stack_driver_path(); - - -#endif diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPInterface.h b/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPInterface.h index 5ab2261dfd..7d2c3c9bb1 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPInterface.h +++ b/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPInterface.h @@ -39,6 +39,12 @@ class PPPInterface { bool GetInterfaceInfo(ppp_interface_info_t *info) const; bool GetStatistics(ppp_statistics *statistics) const; bool HasSettings(const driver_settings *settings) const; + + bool ControlDevice(ppp_device_info_t *info) const; + bool ControlProtocol(ppp_protocol_info_t *info, uint32 protocolindex, uint32 procotolOP) const; + bool ControlOptionHandler(ppp_simple_handler_info_t *info, uint32 handlerindex, uint32 handlerOP) const; + bool ControlLCPExtension(ppp_simple_handler_info_t *info, uint32 LCPExtensionindex, uint32 LCPExtensionOP) const; + bool ControlChild(void *info, uint32 childindex, uint32 childOP) const; bool Up() const; bool Down() const; diff --git a/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPManager.h b/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPManager.h index b3ae547202..9cb7664aeb 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPManager.h +++ b/src/add-ons/kernel/network/ppp/shared/libppp/headers/PPPManager.h @@ -6,6 +6,7 @@ #ifndef _PPP_MANAGER__H #define _PPP_MANAGER__H +#include #include #include @@ -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; diff --git a/src/add-ons/kernel/network/stack/stack.cpp b/src/add-ons/kernel/network/stack/stack.cpp index 7151ace2ba..d70f0d2677 100644 --- a/src/add-ons/kernel/network/stack/stack.cpp +++ b/src/add-ons/kernel/network/stack/stack.cpp @@ -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, diff --git a/src/bin/network/Jamfile b/src/bin/network/Jamfile index ea4fffd975..06e6a79b9d 100644 --- a/src/bin/network/Jamfile +++ b/src/bin/network/Jamfile @@ -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 ; diff --git a/src/bin/network/ppp_up/Jamfile b/src/bin/network/ppp_up/Jamfile index 69a6dc5b34..b028a65185 100644 --- a/src/bin/network/ppp_up/Jamfile +++ b/src/bin/network/ppp_up/Jamfile @@ -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 diff --git a/src/bin/network/ppp_up/PPPStatusView.h b/src/bin/network/ppp_up/PPPStatusView.h index 8463f5c244..f103724b81 100644 --- a/src/bin/network/ppp_up/PPPStatusView.h +++ b/src/bin/network/ppp_up/PPPStatusView.h @@ -6,8 +6,9 @@ #ifndef STATUS_VIEW__H #define STATUS_VIEW__H -#include +#include #include +#include class PPPStatusView : public BView { diff --git a/src/bin/network/pppconfig/Jamfile b/src/bin/network/pppconfig/Jamfile index e51f5d0041..b0dec8cde0 100644 --- a/src/bin/network/pppconfig/Jamfile +++ b/src/bin/network/pppconfig/Jamfile @@ -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 diff --git a/src/bin/network/pppconfig/pppconfig.cpp b/src/bin/network/pppconfig/pppconfig.cpp index db35b97a05..1df352561d 100644 --- a/src/bin/network/pppconfig/pppconfig.cpp +++ b/src/bin/network/pppconfig/pppconfig.cpp @@ -40,33 +40,35 @@ status_t show(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES) { PPPManager manager; - if(manager.InitCheck() != B_OK) { + if (manager.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not load interface manager!\n"); return -1; } - int32 count; + int32 count = 0; ppp_interface_id *interfaces = manager.Interfaces(&count, filter); - if(!interfaces) { + if (!interfaces || count <= 0) { fprintf(stderr, "Error: Could not get interfaces information!\n"); return -1; } - + + fprintf(stderr, "Get %ld ppp interfaces, first is %ld!\n", count, interfaces[0]); + ppp_interface_info_t info; PPPInterface interface; printf("Listing PPP interfaces:\n"); // print out information for each interface - for(int32 index = 0; index < count; index++) { + for (int32 index = 0; index < count; index++) { interface.SetTo(interfaces[index]); - if(interface.InitCheck() == B_OK) { + if (interface.InitCheck() == B_OK) { interface.GetInterfaceInfo(&info); printf("\n"); // type and unit (if it has one) - if(info.info.if_unit >= 0) { + if (info.info.if_unit >= 0) { printf("Type: Visible\n"); printf("\tInterface: ppp%ld\n", info.info.if_unit); } else @@ -79,9 +81,9 @@ show(ppp_interface_filter filter = PPP_REGISTERED_INTERFACES) // mode printf("\tMode: "); - if(info.info.mode == PPP_CLIENT_MODE) + if (info.info.mode == PPP_CLIENT_MODE) printf("Client\n"); - else if(info.info.mode == PPP_SERVER_MODE) + else if (info.info.mode == PPP_SERVER_MODE) printf("Server\n"); else printf("Unknown\n"); @@ -118,13 +120,13 @@ status_t create(const char *name, bool bringUp = true) { PPPManager manager; - if(manager.InitCheck() != B_OK) { + if (manager.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not load interface manager!\n"); return -1; } PPPInterface interface(manager.CreateInterfaceWithName(name)); - if(interface.InitCheck() != B_OK) { + if (interface.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not create interface: %s!\n", name); return -1; } @@ -134,13 +136,13 @@ create(const char *name, bool bringUp = true) ppp_interface_info_t info; interface.GetInterfaceInfo(&info); - if(info.info.if_unit >= 0) + if (info.info.if_unit >= 0) printf("Interface: ppp%ld\n", info.info.if_unit); else printf("This interface is hidden! You can delete it by typing:\n" "pppconfig delete %ld\n", interface.ID()); - if(bringUp) { + if (bringUp) { interface.Up(); printf("Connecting in background...\n"); } @@ -153,22 +155,22 @@ static status_t connect(const char *name) { - if(!name || strlen(name) == 0) + if (!name || strlen(name) == 0) return -1; PPPManager manager; - if(manager.InitCheck() != B_OK) { + if (manager.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not load interface manager!\n"); return -1; } PPPInterface interface(manager.InterfaceWithName(name)); - if(interface.InitCheck() != B_OK) { + if (interface.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not find interface: %s!\n", name); return -1; } - if(!interface.Up()) { + if (!interface.Up()) { fprintf(stderr, "Error: Could not connect!\n"); return -1; } @@ -181,24 +183,435 @@ connect(const char *name) static status_t -disconnect(const char *name) +setuser(const char *name, const char* user) { - if(!name || strlen(name) == 0) + if (!name || strlen(name) == 0) return -1; + if (!user || strlen(user) == 0) + return -1; + PPPManager manager; - if(manager.InitCheck() != B_OK) { + if (manager.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not load interface manager!\n"); return -1; } PPPInterface interface(manager.InterfaceWithName(name)); - if(interface.InitCheck() != B_OK) { + if (interface.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not find interface: %s!\n", name); return -1; } - if(!interface.Down()) { + if (!interface.SetUsername(user)) { + fprintf(stderr, "Error: Could not SetUsername %s!\n", user); + return -1; + } + + return 0; +} + + +static +status_t +setpass(const char *name, const char* pass) +{ + if (!name || strlen(name) == 0) + return -1; + + if (!pass || strlen(pass) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + if (!interface.SetPassword(pass)) { + fprintf(stderr, "Error: Could not SetUsername %s!\n", pass); + return -1; + } + + return 0; +} + + +static +status_t +setaskbeforeconnect(const char *name, const char* connect) +{ + if (!name || strlen(name) == 0) + return -1; + + bool askBeforeConnecting = false; + if (connect || !strcmp(connect, "true") || !strcmp(connect, "ask") || + !strcmp(connect, "yes") || !strcmp(connect, "y")) + askBeforeConnecting = true; + + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + if (!interface.SetAskBeforeConnecting(askBeforeConnecting)) { + fprintf(stderr, "Error: Could not connect %s!\n", connect); + return -1; + } + + return 0; +} + + +static +status_t +getstatistics(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + ppp_statistics pppStatistics; + if (interface.GetStatistics(&pppStatistics) != B_OK) { + fprintf(stderr, "Error: Could not getstatistics: %s!\n", name); + return -1; + } + + return 0; +} + + +static +status_t +hassettings(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + driver_settings settings; + if (interface.HasSettings(&settings) != B_OK) { + fprintf(stderr, "Error: Could not getstatistics: %s!\n", name); + return -1; + } + + return 0; +} + + +static +status_t +enablereports(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + ppp_report_type type = PPP_ALL_REPORTS; + thread_id thread = 0; + int32 flags = 0; + + if (interface.EnableReports(type, thread, flags) != true) { + fprintf(stderr, "Error: Could not EnableReports: %s!\n", name); + return -1; + } + + return 0; +} + + +static +status_t +disablereports(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + ppp_report_type type = PPP_ALL_REPORTS; + thread_id thread = 0; + + if (interface.DisableReports(type, thread) != true) { + fprintf(stderr, "Error: Could not EnableReports: %s!\n", name); + return -1; + } + + return 0; +} + + +static +status_t +controlchild(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + ppp_simple_handler_info_t info; + + if (interface.ControlChild(&info, 0, PPPC_GET_SIMPLE_HANDLER_INFO) != true) { + fprintf(stderr, "Error: Could not PPPC_GET_SIMPLE_HANDLER_INFO: %s!\n", name); + return -1; + } + + printf("LCPExtensionHandler: %s\n", info.info.name); + printf("isEnabled: %d\n", info.info.isEnabled); + + if (interface.ControlChild(&info, 0, PPPC_ENABLE) != true) { + fprintf(stderr, "Error: Could not PPPC_ENABLE: %s!\n", name); + return -1; + } + return 0; +} + + +static +status_t +controllcpextension(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + ppp_simple_handler_info_t info; + + if (interface.ControlLCPExtension(&info, 1, PPPC_GET_SIMPLE_HANDLER_INFO) != true) { + fprintf(stderr, "Error: Could not PPPC_GET_SIMPLE_HANDLER_INFO: %s!\n", name); + return -1; + } + + printf("LCPExtensionHandler: %s\n", info.info.name); + printf("isEnabled: %d\n", info.info.isEnabled); + + if (interface.ControlLCPExtension(&info, 1, PPPC_ENABLE) != true) { + fprintf(stderr, "Error: Could not PPPC_ENABLE: %s!\n", name); + return -1; + } + return 0; +} + + +static +status_t +controloptionhandler(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + ppp_simple_handler_info_t info; + + if (interface.ControlOptionHandler(&info, 0, PPPC_GET_SIMPLE_HANDLER_INFO) != true) { + fprintf(stderr, "Error: Could not PPPC_GET_SIMPLE_HANDLER_INFO: %s!\n", name); + return -1; + } + + printf("protocol: %s\n", info.info.name); + printf("isEnabled: %d\n", info.info.isEnabled); + + if (interface.ControlOptionHandler(&info, 0, PPPC_ENABLE) != true) { + fprintf(stderr, "Error: Could not PPPC_ENABLE: %s!\n", name); + return -1; + } + return 0; +} + + +static +status_t +controlprotocol(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + ppp_protocol_info_t info; + + if (interface.ControlProtocol(&info, 0, PPPC_GET_PROTOCOL_INFO) != true) { + fprintf(stderr, "Error: Could not PPPC_GET_PROTOCOL_INFO: %s!\n", name); + return -1; + } + + printf("protocol: %s\n", info.info.name); + printf("type: %s\n", info.info.type); + printf("activationPhase: %d\n", info.info.activationPhase); + printf("addressFamily: %ld\n", info.info.addressFamily); + printf("flags: %ld\n", info.info.flags); + printf("side: %d\n", info.info.side); + printf("level: %d\n", info.info.level); + printf("connectionPhase: %d\n", info.info.connectionPhase); + printf("protocolNumber: %d\n", info.info.protocolNumber); + printf("isEnabled: %d\n", info.info.isEnabled); + printf("isUpRequested: %d\n", info.info.isUpRequested); + + if (interface.ControlProtocol(&info, 0, PPPC_ENABLE) != true) { + fprintf(stderr, "Error: Could not PPPC_ENABLE: %s!\n", name); + return -1; + } + return 0; +} + + +static +status_t +controldevice(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + ppp_device_info_t info; + + if (interface.ControlDevice(&info) != true) { + fprintf(stderr, "Error: Could not ControlDevice: %s!\n", name); + return -1; + } + + printf("name: %s\n", info.info.name); + printf("MTU: %ld\n", info.info.MTU); + printf("inputTransferRate: %ld\n", info.info.inputTransferRate); + printf("outputTransferRate: %ld\n", info.info.outputTransferRate); + printf("outputBytesCount: %ld\n", info.info.outputBytesCount); + printf("isUp: %d\n", info.info.isUp); + + return 0; +} + + +static +status_t +disconnect(const char *name) +{ + if (!name || strlen(name) == 0) + return -1; + + PPPManager manager; + if (manager.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not load interface manager!\n"); + return -1; + } + + PPPInterface interface(manager.InterfaceWithName(name)); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface: %s!\n", name); + return -1; + } + + if (!interface.Down()) { fprintf(stderr, "Error: Could not disconnect!\n"); return -1; } @@ -211,16 +624,16 @@ static status_t delete_interface(const char *name) { - if(!name || strlen(name) == 0) + if (!name || strlen(name) == 0) return -1; PPPManager manager; - if(manager.InitCheck() != B_OK) { + if (manager.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not load interface manager!\n"); return -1; } - if(!manager.DeleteInterface(manager.InterfaceWithName(name))) { + if (!manager.DeleteInterface(name)) { fprintf(stderr, "Error: Could not delete interface!\n"); return -1; } @@ -233,26 +646,33 @@ static status_t show_details(const char *name) { - if(!name || strlen(name) == 0) + if (!name || strlen(name) == 0) return -1; PPPManager manager; - if(manager.InitCheck() != B_OK) { + if (manager.InitCheck() != B_OK) { fprintf(stderr, "Error: Could not load interface manager!\n"); return -1; } - PPPInterface interface(manager.InterfaceWithName(name)); - if(interface.InitCheck() != B_OK) { + ppp_interface_id ID = manager.InterfaceWithName(name); + if (ID <= 0) { fprintf(stderr, "Error: Could not find interface: %s!\n", name); return -1; } + + PPPInterface interface(ID); + if (interface.InitCheck() != B_OK) { + fprintf(stderr, "Error: Could not find interface ID: %ld!\n", ID); + return -1; + } ppp_interface_info_t info; + // printf("ppp_interface_info_t addr:%p\n", &info); interface.GetInterfaceInfo(&info); // type and name (if it has one) - if(info.info.if_unit >= 0) { + if (info.info.if_unit >= 0) { printf("Type: Visible\n"); printf("Interface: ppp%ld\n", info.info.if_unit); } else @@ -277,9 +697,9 @@ show_details(const char *name) // mode printf("Mode: "); - if(info.info.mode == PPP_CLIENT_MODE) + if (info.info.mode == PPP_CLIENT_MODE) printf("Client\n"); - else if(info.info.mode == PPP_SERVER_MODE) + else if (info.info.mode == PPP_SERVER_MODE) printf("Server\n"); else printf("Unknown\n"); @@ -310,24 +730,51 @@ show_details(const char *name) int main(int argc, char *argv[]) { - if(argc == 2) { - if(!strcmp(argv[1], "show") || !strcmp(argv[1], "-a")) + if (argc == 2) { + if (!strcmp(argv[1], "show") || !strcmp(argv[1], "-a")) return show(PPP_ALL_INTERFACES); else return print_help(); - }if(argc == 3) { - if(!strcmp(argv[1], "init")) + }if (argc == 3) { + if (!strcmp(argv[1], "init")) return create(argv[2], false); - else if(!strcmp(argv[1], "create")) + else if (!strcmp(argv[1], "create")) return create(argv[2], true); - else if(!strcmp(argv[1], "connect")) + else if (!strcmp(argv[1], "connect")) return connect(argv[2]); - else if(!strcmp(argv[1], "disconnect")) + else if (!strcmp(argv[1], "disconnect")) return disconnect(argv[2]); - else if(!strcmp(argv[1], "delete")) + else if (!strcmp(argv[1], "delete")) return delete_interface(argv[2]); - else if(!strcmp(argv[1], "details")) + else if (!strcmp(argv[1], "details")) return show_details(argv[2]); + else if (!strcmp(argv[1], "getstatistics")) + return getstatistics(argv[2]); + else if (!strcmp(argv[1], "hassettings")) + return hassettings(argv[2]); + else if (!strcmp(argv[1], "enablereports")) + return enablereports(argv[2]); + else if (!strcmp(argv[1], "disablereports")) + return disablereports(argv[2]); + else if (!strcmp(argv[1], "controldevice")) + return controldevice(argv[2]); + else if (!strcmp(argv[1], "controlprotocol")) + return controlprotocol(argv[2]); + else if (!strcmp(argv[1], "controloptionhandler")) + return controloptionhandler(argv[2]); + else if (!strcmp(argv[1], "controllcpextension")) + return controllcpextension(argv[2]); + else if (!strcmp(argv[1], "controlchild")) + return controlchild(argv[2]); + else + return print_help(); + } if (argc == 4) { + if (!strcmp(argv[1], "setuser")) + return setuser(argv[2], argv[3]); + else if (!strcmp(argv[1], "setpass")) + return setpass(argv[2], argv[3]); + else if (!strcmp(argv[1], "setaskbeforeconnect")) + return setaskbeforeconnect(argv[2], argv[3]); else return print_help(); } else