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