diff --git a/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp b/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp index d2115b12f0..085c86080b 100644 --- a/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp +++ b/src/add-ons/kernel/network/interfaces/ppp/PPPManager.cpp @@ -9,9 +9,12 @@ #include "PPPManager.h" #include +#include #include #include +#include + #include #include @@ -272,22 +275,7 @@ PPPManager::CreateInterfaceWithName(const char *name, if(!name) return PPP_UNDEFINED_INTERFACE_ID; - char path[B_PATH_NAME_LENGTH]; - sprintf(path, "pppidf/%s", name); - // XXX: TODO: change base path to "/etc/ppp" when settings API supports it - - void *handle = load_driver_settings(path); - if(!handle) - return PPP_UNDEFINED_INTERFACE_ID; - - const driver_settings *settings = get_driver_settings(handle); - if(!settings) { - unload_driver_settings(handle); - return PPP_UNDEFINED_INTERFACE_ID; - } - - ppp_interface_id result = _CreateInterface(name, settings, profile, parentID); - unload_driver_settings(handle); + ppp_interface_id result = _CreateInterface(name, NULL, profile, parentID); return result; } @@ -422,8 +410,24 @@ PPPManager::Control(uint32 op, void *data, size_t length) // this method is intended for use by userland applications switch(op) { -// case PPPC_CONTROL_MODULE: { -// } break; + case PPPC_CONTROL_MODULE: { + if(length < sizeof(control_net_module_args) || !data) + return B_ERROR; + + control_net_module_args *args = (control_net_module_args*) data; + if(!args->name) + return B_ERROR; + + char name[B_PATH_NAME_LENGTH]; + strcpy(name, PPP_MODULES_PATH); + strcat(name, args->name); + ppp_module_info *module; + if(get_module(name, (module_info**) &module) != B_OK + || !module->control) + return B_ERROR; + + return module->control(args->op, args->data, args->length); + } break; case PPPC_CREATE_INTERFACE: { if(length < sizeof(ppp_interface_description_info) || !data) @@ -776,11 +780,11 @@ PPPManager::_CreateInterface(const char *name, const driver_settings *settings, entry->accessing = 1; entry->deleting = false; fEntries.AddItem(entry); - // nothing bad can happen because we are in a locked section here + // nothing bad can happen because we are in a locked section new KPPPInterface(name, entry, id, settings, profile, parentEntry ? parentEntry->interface : NULL); - // KPPPInterface will add itself to the entry (no need to do it here) + // KPPPInterface will add itself to the entry (no need to do it here) if(entry->interface->InitCheck() != B_OK) { delete entry->interface; delete entry; @@ -788,7 +792,7 @@ PPPManager::_CreateInterface(const char *name, const driver_settings *settings, } locker.UnlockNow(); - // it is safe to access the manager from userland + // it is safe to access the manager from userland now if(!Report(PPP_MANAGER_REPORT, PPP_REPORT_INTERFACE_CREATED, &id, sizeof(ppp_interface_id))) { diff --git a/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp b/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp index 8cf7601d4c..cf8a8670c8 100644 --- a/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp +++ b/src/add-ons/kernel/network/ppp/ipcp/Protocol.cpp @@ -37,20 +37,7 @@ IPCP::IPCP(KPPPInterface& interface, driver_parameter *settings) fTerminateID(0), fNextTimeout(0) { - // 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 - const driver_parameter *profile - = Interface().Profile().SettingsFor("protocol", "ipcp"); - ParseSideRequests(get_parameter_with_name("Local", profile), PPP_LOCAL_SIDE); - ParseSideRequests(get_parameter_with_name("Peer", profile), PPP_PEER_SIDE); + ProfileChanged(); } @@ -92,6 +79,26 @@ IPCP::StackControl(uint32 op, void *data) } +void +IPCP::ProfileChanged() +{ + // 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 + const driver_parameter *profile + = Interface().Profile().SettingsFor("protocol", "ipcp"); + ParseSideRequests(get_parameter_with_name("Local", profile), PPP_LOCAL_SIDE); + ParseSideRequests(get_parameter_with_name("Peer", profile), PPP_PEER_SIDE); +} + + bool IPCP::Up() { diff --git a/src/add-ons/kernel/network/ppp/ipcp/Protocol.h b/src/add-ons/kernel/network/ppp/ipcp/Protocol.h index 7c7e2f4806..27fec59ed5 100644 --- a/src/add-ons/kernel/network/ppp/ipcp/Protocol.h +++ b/src/add-ons/kernel/network/ppp/ipcp/Protocol.h @@ -68,6 +68,8 @@ class IPCP : public KPPPProtocol { virtual status_t StackControl(uint32 op, void *data); + virtual void ProfileChanged(); + virtual bool Up(); virtual bool Down(); diff --git a/src/add-ons/kernel/network/ppp/pap/Protocol.cpp b/src/add-ons/kernel/network/ppp/pap/Protocol.cpp index 55ba991118..0b18e5635c 100644 --- a/src/add-ons/kernel/network/ppp/pap/Protocol.cpp +++ b/src/add-ons/kernel/network/ppp/pap/Protocol.cpp @@ -120,9 +120,7 @@ PAP::PAP(KPPPInterface& interface, driver_parameter *settings) fRequestID(0), fNextTimeout(0) { - fUser[0] = fPassword[0] = 0; - - ParseSettings(Interface().Profile().SettingsFor("authenticator", "pap")); + ProfileChanged(); } @@ -141,6 +139,13 @@ PAP::InitCheck() const } +void +PAP::ProfileChanged() +{ + ParseSettings(Interface().Profile().SettingsFor("authenticator", "pap")); +} + + bool PAP::Up() { diff --git a/src/add-ons/kernel/network/ppp/pap/Protocol.h b/src/add-ons/kernel/network/ppp/pap/Protocol.h index eeedd55509..e3122bf85d 100644 --- a/src/add-ons/kernel/network/ppp/pap/Protocol.h +++ b/src/add-ons/kernel/network/ppp/pap/Protocol.h @@ -63,6 +63,8 @@ class PAP : public KPPPProtocol { pap_state State() const { return fState; } + virtual void ProfileChanged(); + virtual bool Up(); virtual bool Down(); diff --git a/src/add-ons/kernel/network/ppp/pppoe/PPPoE.h b/src/add-ons/kernel/network/ppp/pppoe/PPPoE.h index 0817a223b1..2637e60e13 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/PPPoE.h +++ b/src/add-ons/kernel/network/ppp/pppoe/PPPoE.h @@ -15,6 +15,10 @@ class PPPoEDevice; +#define PPPoE_QUERY_REPORT_SIZE 2048 +#define PPPoE_QUERY_REPORT 'PoEQ' + // the code value used for query reports + #define PPPoE_HEADER_SIZE 6 // without ethernet header #define PPPoE_TIMEOUT 3000000 @@ -29,6 +33,16 @@ class PPPoEDevice; #define PPPoE_AC_NAME_KEY "ACName" #define PPPoE_SERVICE_NAME_KEY "ServiceName" +enum pppoe_ops { + PPPoE_GET_INTERFACES, + PPPoE_QUERY_SERVICES +}; + +typedef struct pppoe_query_request { + const char *interfaceName; + thread_id receiver; +} pppoe_query_request; + extern struct core_module_info *core; @@ -48,6 +62,7 @@ typedef struct complete_pppoe_header { // defined in pppoe.cpp +ifnet *FindPPPoEInterface(const char *name); uint32 NewHostUniq(); void add_device(PPPoEDevice *device); void remove_device(PPPoEDevice *device); diff --git a/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp b/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp index db1d13f246..2f7fa44775 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp +++ b/src/add-ons/kernel/network/ppp/pppoe/PPPoEDevice.cpp @@ -49,6 +49,8 @@ PPPoEDevice::PPPoEDevice(KPPPInterface& interface, driver_parameter *settings) fEthernetIfnet(NULL), fSessionID(0), fHostUniq(NewHostUniq()), + fACName(NULL), + fServiceName(NULL), fAttempts(0), fNextTimeout(0), fState(INITIAL) @@ -74,14 +76,7 @@ PPPoEDevice::PPPoEDevice(KPPPInterface& interface, driver_parameter *settings) fACName = get_parameter_value(PPPoE_AC_NAME_KEY, settings); fServiceName = get_parameter_value(PPPoE_SERVICE_NAME_KEY, settings); - ifnet *current = get_interfaces(); - for(; current; current = current->if_next) { - if(current->if_type == IFT_ETHER && current->if_name - && !strcmp(current->if_name, interfaceName)) { - fEthernetIfnet = current; - break; - } - } + fEthernetIfnet = FindPPPoEInterface(interfaceName); #if DEBUG if(!fEthernetIfnet) @@ -312,6 +307,9 @@ PPPoEDevice::Send(struct mbuf *packet, uint16 protocolNumber = 0) locker.UnlockNow(); + if(!packet) + dprintf("PPPoEDevice::Send(): packet is NULL!\n"); + if(EthernetIfnet()->output(EthernetIfnet(), packet, &destination, NULL) != B_OK) { dprintf("PPPoEDevice::Send(): EthernetIfnet()->output() failed!\n"); DownEvent(); @@ -385,6 +383,9 @@ PPPoEDevice::Receive(struct mbuf *packet, uint16 protocolNumber = 0) DiscoveryPacket reply(PADR); for(int32 index = 0; index < discovery.CountTags(); index++) { tag = discovery.TagAt(index); + if(!tag) + continue; + switch(tag->type) { case SERVICE_NAME: if(!hasServiceName && (!ServiceName() diff --git a/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp b/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp index 0039a325bd..071bc7405a 100644 --- a/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp +++ b/src/add-ons/kernel/network/ppp/pppoe/pppoe.cpp @@ -14,12 +14,19 @@ #include #include +#include #include #include "PPPoEDevice.h" #include "DiscoveryPacket.h" +typedef struct pppoe_query { + ifnet *ethernetIfnet; + uint32 hostUniq; + thread_id receiver; +} pppoe_query; + #define PPPoE_MODULE_NAME NETWORK_MODULES_ROOT "ppp/pppoe" struct core_module_info *core = NULL; @@ -29,8 +36,64 @@ status_t std_ops(int32 op, ...); static BLocker sLock; static TemplateList *sDevices; +static TemplateList *sQueries; +static +void +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) + 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++) { + tag = discovery.TagAt(index); + 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* +FindPPPoEInterface(const char *name) +{ + if(!name) + return NULL; + + ifnet *current = get_interfaces(); + for(; current; current = current->if_next) { + if(current->if_type == IFT_ETHER && current->if_name + && !strcmp(current->if_name, name)) + return current; + } + + return NULL; +} + uint32 NewHostUniq() { @@ -72,9 +135,36 @@ pppoe_input(struct mbuf *packet) ifnet *sourceIfnet = packet->m_pkthdr.rcvif; complete_pppoe_header *header = mtod(packet, complete_pppoe_header*); 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++) { + query = sQueries->ItemAt(index); + + if(query && query->ethernetIfnet == sourceIfnet) { + if(header->pppoeHeader.code == PADO) { + DiscoveryPacket discovery(packet, ETHER_HDR_LEN); + if(discovery.InitCheck() != B_OK) { + dprintf("PPPoE: received corrupted discovery packet!\n"); + m_freem(packet); + return; + } + + pppoe_tag *hostTag = discovery.TagWithType(HOST_UNIQ); + if(hostTag && hostTag->length == 4 + && *((uint32*)hostTag->data) == query->hostUniq) { + SendQueryPacket(query, discovery); + m_freem(packet); + return; + } + } + } + } + } + for(int32 index = 0; index < sDevices->CountItems(); index++) { device = sDevices->ItemAt(index); @@ -96,6 +186,7 @@ pppoe_input(struct mbuf *packet) DiscoveryPacket discovery(packet, ETHER_HDR_LEN); if(discovery.InitCheck() != B_OK) { dprintf("PPPoE: received corrupted discovery packet!\n"); + m_freem(packet); return; } @@ -145,7 +236,59 @@ static status_t control(uint32 op, void *data, size_t length) { - return B_ERROR; + 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->name) { + if(position + strlen(current->name) + 1 > length) + return B_NO_MEMORY; + + strcpy(names + position, current->name); + position += strlen(current->name) + 1; + ++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)) + return B_ERROR; + + pppoe_query_request *request = (pppoe_query_request*) data; + + pppoe_query query; + query.ethernetIfnet = FindPPPoEInterface(request->interfaceName); + if(!query.ethernetIfnet) + return B_BAD_VALUE; + + query.hostUniq = NewHostUniq(); + query.receiver = request->receiver; + + sLock.Lock(); + sQueries->AddItem(&query); + sLock.Unlock(); + + snooze(2000000); + // wait two seconds for results + + sLock.Lock(); + sQueries->RemoveItem(&query); + sLock.Unlock(); + } break; + + default: + return B_ERROR; + } + + return B_OK; } @@ -176,9 +319,8 @@ std_ops(int32 op, ...) } set_max_linkhdr(PPPoE_HEADER_SIZE + ETHER_HDR_LEN); - sDevices = new TemplateList; - + sQueries = new TemplateList; sEthernet->set_pppoe_receiver(pppoe_input); #if DEBUG 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 3bb134a6dd..d429b9dd63 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPDevice.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPDevice.cpp @@ -41,7 +41,8 @@ KPPPDevice::Control(uint32 op, void *data, size_t length) ppp_device_info *info = (ppp_device_info*) data; memset(info, 0, sizeof(ppp_device_info_t)); - strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); + if(Name()) + strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); info->MTU = MTU(); info->inputTransferRate = InputTransferRate(); info->outputTransferRate = OutputTransferRate(); 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 00109468e6..45a999b95f 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPInterface.cpp @@ -93,7 +93,28 @@ KPPPInterface::KPPPInterface(const char *name, ppp_interface_entry *entry, { entry->interface = this; - fSettings = dup_driver_settings(settings); + if(name) { + // load settings from description file + char path[B_PATH_NAME_LENGTH]; + sprintf(path, "pppidf/%s", name); + // XXX: TODO: change base path to "/etc/ppp" when settings API supports it + + 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; + } fProfile.LoadSettings(profile, fSettings); // add internal modules @@ -235,11 +256,12 @@ KPPPInterface::~KPPPInterface() fFirstProtocol = fFirstProtocol->NextProtocol(); else delete FirstProtocol(); + // destructor removes protocol from list } for(int32 index = 0; index < fModules.CountItems(); index++) { put_module(fModules.ItemAt(index)); - free(fModules.ItemAt(index)); + delete[] fModules.ItemAt(index); } free_driver_settings(fSettings); @@ -336,7 +358,8 @@ KPPPInterface::Control(uint32 op, void *data, size_t length) ppp_interface_info *info = (ppp_interface_info*) data; memset(info, 0, sizeof(ppp_interface_info_t)); - strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); + if(Name()) + strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); if(Ifnet()) info->if_unit = Ifnet()->if_unit; else @@ -418,6 +441,16 @@ KPPPInterface::Control(uint32 op, void *data, size_t length) ReportManager().DisableReports(request->type, request->thread); } break; + case PPPC_SET_PROFILE: { + if(!data) + return B_ERROR; + + driver_settings *profile = (driver_settings*) data; + fProfile.LoadSettings(profile, fSettings); + + UpdateProfile(); + } break; + case PPPC_CONTROL_DEVICE: { if(length < sizeof(ppp_control_info) || !data) return B_ERROR; @@ -1155,17 +1188,19 @@ KPPPInterface::LoadModule(const char *name, driver_parameter *parameter, if(!name || strlen(name) > B_FILE_NAME_LENGTH) return false; - char *module_name = (char*) malloc(B_PATH_NAME_LENGTH); + char *moduleName = new char[B_PATH_NAME_LENGTH]; - sprintf(module_name, "%s/%s", PPP_MODULES_PATH, name); + sprintf(moduleName, "%s/%s", PPP_MODULES_PATH, name); ppp_module_info *module; - if(get_module(module_name, (module_info**) &module) != B_OK) + 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(module_name); + fModules.AddItem(moduleName); return module->add_to(Parent() ? *Parent() : *this, this, parameter, type); } @@ -1191,7 +1226,7 @@ KPPPInterface::Send(struct mbuf *packet, uint16 protocolNumber) // we must pass the basic tests like: // do we have a device? // did we load all modules? - if(InitCheck() != B_OK || !Device()) { + if(InitCheck() != B_OK) { m_freem(packet); return B_ERROR; } @@ -1444,6 +1479,16 @@ KPPPInterface::UnregisterInterface() } +// called when profile changes +void +KPPPInterface::UpdateProfile() +{ + KPPPLayer *layer = FirstProtocol(); + for(; layer; layer = layer->Next()) + layer->ProfileChanged(); +} + + // called by KPPPManager: manager routes stack ioctls to interface status_t KPPPInterface::StackControl(uint32 op, void *data) 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 b72a68c7a0..4bd0e8c06c 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCP.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCP.cpp @@ -187,6 +187,26 @@ KPPPLCP::AdditionalOverhead() const } +void +KPPPLCP::ProfileChanged() +{ + KPPPLCPExtension *extension; + KPPPOptionHandler *handler; + + for(int32 index = 0; index < CountLCPExtensions(); index++) { + extension = LCPExtensionAt(index); + if(extension) + extension->ProfileChanged(); + } + + for(int32 index = 0; index < CountOptionHandlers(); index++) { + handler = OptionHandlerAt(index); + if(handler) + handler->ProfileChanged(); + } +} + + bool KPPPLCP::Up() { 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 b5a58cc53b..cf23cd329a 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCPExtension.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLCPExtension.cpp @@ -20,7 +20,7 @@ KPPPLCPExtension::KPPPLCPExtension(const char *name, uint8 code, KPPPInterface& if(name) fName = strdup(name); else - fName = strdup("Unknown"); + fName = NULL; } @@ -49,7 +49,8 @@ KPPPLCPExtension::Control(uint32 op, void *data, size_t length) ppp_simple_handler_info *info = (ppp_simple_handler_info*) data; memset(info, 0, sizeof(ppp_simple_handler_info_t)); - strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); + if(Name()) + strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); info->isEnabled = IsEnabled(); } break; @@ -80,6 +81,13 @@ KPPPLCPExtension::StackControl(uint32 op, void *data) } +void +KPPPLCPExtension::ProfileChanged() +{ + // do nothing by default +} + + void KPPPLCPExtension::Reset() { 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 fa1d6b729e..9556398e21 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLayer.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPLayer.cpp @@ -19,8 +19,8 @@ KPPPLayer::KPPPLayer(const char *name, ppp_level level, uint32 overhead) : fInitStatus(B_OK), fOverhead(overhead), - fLevel(level), fName(NULL), + fLevel(level), fNext(NULL) { SetName(name); @@ -40,6 +40,13 @@ KPPPLayer::InitCheck() const } +void +KPPPLayer::ProfileChanged() +{ + // do nothing by default +} + + status_t KPPPLayer::SendToNext(struct mbuf *packet, uint16 protocolNumber) const { @@ -76,5 +83,5 @@ KPPPLayer::SetName(const char *name) if(name) fName = strdup(name); else - fName = strdup("Unknown"); + fName = NULL; } 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 2cce49d1b5..6d65d5cc61 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPOptionHandler.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPOptionHandler.cpp @@ -21,7 +21,7 @@ KPPPOptionHandler::KPPPOptionHandler(const char *name, uint8 type, if(name) fName = strdup(name); else - fName = strdup("Unknown"); + fName = NULL; } @@ -50,7 +50,8 @@ KPPPOptionHandler::Control(uint32 op, void *data, size_t length) ppp_simple_handler_info *info = (ppp_simple_handler_info*) data; memset(info, 0, sizeof(ppp_simple_handler_info_t)); - strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); + if(Name()) + strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); info->isEnabled = IsEnabled(); } break; @@ -79,3 +80,10 @@ KPPPOptionHandler::StackControl(uint32 op, void *data) return B_OK; } + + +void +KPPPOptionHandler::ProfileChanged() +{ + // do nothing by default +} diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProfile.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProfile.cpp index d1971967c6..e025808600 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProfile.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProfile.cpp @@ -55,6 +55,9 @@ void KPPPProfile::LoadSettings(const driver_settings *profile, driver_settings *interfaceSettings) { + if(fSettings != Interface().Settings()) + free_driver_settings(fSettings); + // ----------------------------- // given profile // ----------------------------- diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProtocol.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProtocol.cpp index 0e8b9315fc..38802f3a89 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProtocol.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPProtocol.cpp @@ -34,7 +34,7 @@ KPPPProtocol::KPPPProtocol(const char *name, ppp_phase activationPhase, if(type) fType = strdup(type); else - fType = strdup("Unknown"); + fType = NULL; const char *sideString = get_parameter_value("side", settings); if(sideString) @@ -66,8 +66,10 @@ KPPPProtocol::Control(uint32 op, void *data, size_t length) ppp_protocol_info *info = (ppp_protocol_info*) data; memset(info, 0, sizeof(ppp_protocol_info_t)); - strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); - strncpy(info->type, Type(), PPP_HANDLER_NAME_LENGTH_LIMIT); + if(Name()) + strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); + if(Type()) + strncpy(info->type, Type(), PPP_HANDLER_NAME_LENGTH_LIMIT); info->activationPhase = ActivationPhase(); info->addressFamily = AddressFamily(); info->flags = Flags(); 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 c751c16fc5..249b7c731c 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/KPPPStateMachine.cpp @@ -1538,7 +1538,8 @@ KPPPStateMachine::RCREvent(struct mbuf *packet) } #if DEBUG - dprintf("KPPPSM::RCREvent(): OH=%s\n", optionHandler->Name()); + dprintf("KPPPSM::RCREvent(): OH=%s\n", + optionHandler->Name() ? optionHandler->Name() : "Unknown"); #endif result = optionHandler->ParseRequest(request, index, nak, reject); diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/_KPPPAuthenticationHandler.cpp b/src/add-ons/kernel/network/ppp/shared/libkernelppp/_KPPPAuthenticationHandler.cpp index 30fbe2e7b2..ecf2ee4577 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/_KPPPAuthenticationHandler.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/_KPPPAuthenticationHandler.cpp @@ -42,7 +42,7 @@ _KPPPAuthenticationHandler::NextAuthenticator(const KPPPProtocol *start, KPPPProtocol *current = start ? start->NextProtocol() : Interface().FirstProtocol(); for(; current; current = current->NextProtocol()) { - if(!strcasecmp(current->Type(), AUTHENTICATOR_TYPE_STRING) + if(current->Type() && !strcasecmp(current->Type(), AUTHENTICATOR_TYPE_STRING) && current->OptionHandler() && current->Side() == side) return current; } @@ -136,7 +136,7 @@ _KPPPAuthenticationHandler::ParseNak(const KPPPConfigurePacket& nak) fPeerAuthenticatorRejected = true; KPPPProtocol *authenticator = Interface().ProtocolFor(ntohs(item->protocolNumber)); - if(authenticator + if(authenticator && authenticator->Type() && !strcasecmp(authenticator->Type(), AUTHENTICATOR_TYPE_STRING) && authenticator->OptionHandler()) fSuggestedPeerAuthenticator = authenticator; @@ -199,8 +199,8 @@ _KPPPAuthenticationHandler::ParseRequest(const KPPPConfigurePacket& request, // try to find the requested protocol fLocalAuthenticator = Interface().ProtocolFor(ntohs(item->protocolNumber)); - if(fLocalAuthenticator && - !strcasecmp(fLocalAuthenticator->Type(), AUTHENTICATOR_TYPE_STRING) + if(fLocalAuthenticator && fLocalAuthenticator->Type() + && !strcasecmp(fLocalAuthenticator->Type(), AUTHENTICATOR_TYPE_STRING) && fLocalAuthenticator->OptionHandler()) return fLocalAuthenticator->OptionHandler()->ParseRequest(request, index, nak, reject); 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 0e694139a1..2ea5d46526 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 @@ -194,7 +194,7 @@ class KPPPInterface : public KPPPLayer { // saves the returned ifnet structure bool UnregisterInterface(); - void SetName(const char *name); + void UpdateProfile(); status_t StackControl(uint32 op, void *data); // stack routes ioctls to interface 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 db13934b95..96f74a9cbe 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 @@ -74,6 +74,8 @@ class KPPPLCP : public KPPPProtocol { uint32 AdditionalOverhead() const; // the overhead caused by the target, the device, and the interface + virtual void ProfileChanged(); + virtual bool Up(); virtual bool Down(); 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 d4f49c0c92..22d28711c6 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 @@ -46,6 +46,8 @@ class KPPPLCPExtension { virtual status_t StackControl(uint32 op, void *data); // called by netstack (forwarded by KPPPInterface) + virtual void ProfileChanged(); + virtual status_t Receive(struct mbuf *packet, uint8 code) = 0; virtual void Reset(); 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 9539671dcb..b888e48c18 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 @@ -34,6 +34,8 @@ class KPPPLayer { KPPPLayer *Next() const { return fNext; } + virtual void ProfileChanged(); + virtual bool Up() = 0; virtual bool Down() = 0; 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 2072dd9e39..1db5b39258 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 @@ -16,7 +16,7 @@ #define PPP_INTERFACE_MODULE_NAME NETWORK_MODULES_ROOT "interfaces/ppp" #define PPP_UNDEFINED_INTERFACE_ID 0 - // create_interface() returns this value on failure + // CreateInterface() returns this value on failure class KPPPInterface; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPOptionHandler.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPOptionHandler.h index 44e68361a9..9fa5f562e9 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPOptionHandler.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPOptionHandler.h @@ -48,6 +48,8 @@ class KPPPOptionHandler { virtual status_t StackControl(uint32 op, void *data); // called by netstack (forwarded by KPPPInterface) + virtual void ProfileChanged(); + // we want to send a configure request or we received a reply virtual status_t AddToRequest(KPPPConfigurePacket& request) = 0; virtual status_t ParseNak(const KPPPConfigurePacket& nak) = 0; diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPUtils.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPUtils.h index dc47fc5985..daf6bd41cb 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPUtils.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/KPPPUtils.h @@ -18,7 +18,7 @@ class KPPPProtocol; // helper functions -bool IsProtocolAllowed(const KPPPProtocol& protocol); +extern bool IsProtocolAllowed(const KPPPProtocol& protocol); // the list template does not support iterating over each item :( // this template iterates over each item in an indexed list @@ -35,10 +35,10 @@ ForEachItem(_LIST& list, _FUNCTION function) // These are very simple send/receive_data functions with a timeout // and there is a race condition beween has_data() and send/receive_data(). // Timeouts in ms. -status_t send_data_with_timeout(thread_id thread, int32 code, void *buffer, - size_t buffer_size, uint32 timeout); -status_t receive_data_with_timeout(thread_id *sender, int32 *code, void *buffer, +extern status_t send_data_with_timeout(thread_id thread, int32 code, void *buffer, size_t buffer_size, uint32 timeout); +extern status_t receive_data_with_timeout(thread_id *sender, int32 *code, + void *buffer, size_t buffer_size, uint32 timeout); #endif 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 45d7153599..cb7053812a 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 @@ -52,9 +52,10 @@ enum ppp_control_ops { PPPC_SET_DIAL_ON_DEMAND, PPPC_SET_AUTO_REDIAL, PPPC_HAS_INTERFACE_SETTINGS, + PPPC_SET_PROFILE, // handler access - PPPC_CONTROL_DEVICE, + PPPC_CONTROL_DEVICE = PPP_INTERFACE_OPS_START + 0xFF, PPPC_CONTROL_PROTOCOL, PPPC_CONTROL_OPTION_HANDLER, PPPC_CONTROL_LCP_EXTENSION, diff --git a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/settings_tools.h b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/settings_tools.h index 028e4a6385..42dd243892 100644 --- a/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/settings_tools.h +++ b/src/add-ons/kernel/network/ppp/shared/libkernelppp/headers/settings_tools.h @@ -12,19 +12,23 @@ // TODO: remove this as soon as we get the extended driver_settings API -driver_settings *dup_driver_settings(const driver_settings *settings); -void free_driver_settings(driver_settings *settings); +extern driver_settings *dup_driver_settings(const driver_settings *settings); +extern void free_driver_settings(driver_settings *settings); -bool equal_driver_settings(const driver_settings *lhs, const driver_settings *rhs); -bool equal_driver_parameters(const driver_parameter *lhs, const driver_parameter *rhs); -bool equal_interface_settings(const driver_settings *lhs, const driver_settings *rhs); +extern bool equal_driver_settings(const driver_settings *lhs, + const driver_settings *rhs); +extern bool equal_driver_parameters(const driver_parameter *lhs, + const driver_parameter *rhs); +extern bool equal_interface_settings(const driver_settings *lhs, + const driver_settings *rhs); // this compares only the relevant parts of the interface settings -ppp_side get_side_string_value(const char *sideString, ppp_side unknownValue); -bool get_boolean_value(const char *string, bool unknownValue); -const driver_parameter *get_parameter_with_name(const char *name, +extern ppp_side get_side_string_value(const char *sideString, ppp_side unknownValue); +extern bool get_boolean_value(const char *string, bool unknownValue); +extern const driver_parameter *get_parameter_with_name(const char *name, + const driver_settings *settings); +extern const char *get_settings_value(const char *name, const driver_settings *settings); -const char *get_settings_value(const char *name, const driver_settings *settings); inline 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 b09c22f5b9..9fdba0aaea 100644 --- a/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp +++ b/src/add-ons/kernel/network/ppp/shared/libppp/PPPInterface.cpp @@ -134,6 +134,16 @@ PPPInterface::HasSettings(const driver_settings *settings) const } +void +PPPInterface::SetProfile(const driver_settings *profile) const +{ + if(InitCheck() != B_OK || !profile) + return; + + Control(PPPC_SET_PROFILE, const_cast(profile), 0); +} + + bool PPPInterface::Up() const { 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 c935336887..32b5aea111 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 @@ -36,6 +36,8 @@ class PPPInterface { bool GetInterfaceInfo(ppp_interface_info_t *info) const; bool HasSettings(const driver_settings *settings) const; + void SetProfile(const driver_settings *profile) const; + bool Up() const; bool Down() const;