1 //----------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 // 5 // Copyright (c) 2003-2004 Waldemar Kornewald, Waldemar.Kornewald@web.de 6 //----------------------------------------------------------------------- 7 8 #include <KernelExport.h> 9 #include <driver_settings.h> 10 #include <core_funcs.h> 11 #include <net_module.h> 12 13 #include <ethernet_module.h> 14 15 #include <KPPPInterface.h> 16 #include <KPPPModule.h> 17 #include <LockerHelper.h> 18 19 #include "PPPoEDevice.h" 20 #include "DiscoveryPacket.h" 21 22 23 #define PPPoE_MODULE_NAME NETWORK_MODULES_ROOT "ppp/pppoe" 24 25 struct core_module_info *core = NULL; 26 static struct ethernet_module_info *sEthernet; 27 static int32 sHostUniq = 0; 28 status_t std_ops(int32 op, ...); 29 30 static BLocker sLock; 31 static TemplateList<PPPoEDevice*> *sDevices; 32 33 34 uint32 35 NewHostUniq() 36 { 37 return (uint32) atomic_add(&sHostUniq, 1); 38 } 39 40 41 void 42 add_device(PPPoEDevice *device) 43 { 44 #if DEBUG 45 dprintf("PPPoE: add_device()\n"); 46 #endif 47 48 LockerHelper locker(sLock); 49 sDevices->AddItem(device); 50 } 51 52 53 void 54 remove_device(PPPoEDevice *device) 55 { 56 #if DEBUG 57 dprintf("PPPoE: remove_device()\n"); 58 #endif 59 60 LockerHelper locker(sLock); 61 sDevices->RemoveItem(device); 62 } 63 64 65 static 66 void 67 pppoe_input(struct mbuf *packet) 68 { 69 if(!packet) 70 return; 71 72 ifnet *sourceIfnet = packet->m_pkthdr.rcvif; 73 complete_pppoe_header *header = mtod(packet, complete_pppoe_header*); 74 PPPoEDevice *device; 75 76 LockerHelper locker(sLock); 77 78 for(int32 index = 0; index < sDevices->CountItems(); index++) { 79 device = sDevices->ItemAt(index); 80 81 if(device && device->EthernetIfnet() == sourceIfnet) { 82 if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOE 83 && header->pppoeHeader.sessionID == device->SessionID()) { 84 #if DEBUG 85 dprintf("PPPoE: session packet\n"); 86 #endif 87 device->Receive(packet); 88 return; 89 } else if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC 90 && header->pppoeHeader.code != PADI 91 && header->pppoeHeader.code != PADR 92 && !device->IsDown()) { 93 #if DEBUG 94 dprintf("PPPoE: discovery packet\n"); 95 #endif 96 DiscoveryPacket discovery(packet, ETHER_HDR_LEN); 97 if(discovery.InitCheck() != B_OK) { 98 dprintf("PPPoE: received corrupted discovery packet!\n"); 99 return; 100 } 101 102 pppoe_tag *tag = discovery.TagWithType(HOST_UNIQ); 103 if(header->pppoeHeader.code == PADT || (tag && tag->length == 4 104 && *((uint32*)tag->data) == device->HostUniq())) { 105 device->Receive(packet); 106 return; 107 } 108 } 109 } 110 } 111 112 dprintf("PPPoE: No device found for packet from: %s\n", sourceIfnet->if_name); 113 m_freem(packet); 114 } 115 116 117 static 118 bool 119 add_to(KPPPInterface& mainInterface, KPPPInterface *subInterface, 120 driver_parameter *settings, ppp_module_key_type type) 121 { 122 if(mainInterface.Mode() != PPP_CLIENT_MODE || type != PPP_DEVICE_KEY_TYPE) 123 return B_ERROR; 124 125 PPPoEDevice *device; 126 bool success; 127 if(subInterface) { 128 device = new PPPoEDevice(*subInterface, settings); 129 success = subInterface->SetDevice(device); 130 } else { 131 device = new PPPoEDevice(mainInterface, settings); 132 success = mainInterface.SetDevice(device); 133 } 134 135 #if DEBUG 136 dprintf("PPPoE: add_to(): %s\n", 137 success && device && device->InitCheck() == B_OK ? "OK" : "ERROR"); 138 #endif 139 140 return success && device && device->InitCheck() == B_OK; 141 } 142 143 144 static ppp_module_info pppoe_module = { 145 { 146 PPPoE_MODULE_NAME, 147 0, 148 std_ops 149 }, 150 NULL, 151 add_to 152 }; 153 154 155 _EXPORT 156 status_t 157 std_ops(int32 op, ...) 158 { 159 switch(op) { 160 case B_MODULE_INIT: 161 if(get_module(NET_CORE_MODULE_NAME, (module_info**)&core) != B_OK) 162 return B_ERROR; 163 164 if(get_module(NET_ETHERNET_MODULE_NAME, 165 (module_info**) &sEthernet) != B_OK) { 166 put_module(NET_CORE_MODULE_NAME); 167 return B_ERROR; 168 } 169 170 sDevices = new TemplateList<PPPoEDevice*>; 171 172 sEthernet->set_pppoe_receiver(pppoe_input); 173 174 #if DEBUG 175 dprintf("PPPoE: Registered PPPoE receiver.\n"); 176 #endif 177 return B_OK; 178 179 case B_MODULE_UNINIT: 180 delete sDevices; 181 sEthernet->unset_pppoe_receiver(); 182 #if DEBUG 183 dprintf("PPPoE: Unregistered PPPoE receiver.\n"); 184 #endif 185 put_module(NET_CORE_MODULE_NAME); 186 put_module(NET_ETHERNET_MODULE_NAME); 187 break; 188 189 default: 190 return B_ERROR; 191 } 192 193 return B_OK; 194 } 195 196 197 _EXPORT 198 module_info *modules[] = { 199 (module_info*) &pppoe_module, 200 NULL 201 }; 202