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 *ethernet; 34 static int32 host_uniq = 0; 35 status_t std_ops(int32 op, ...); 36 37 static BLocker lock; 38 static List<PPPoEDevice*> *devices; 39 40 41 uint32 42 NewHostUniq() 43 { 44 return (uint32) atomic_add(&host_uniq, 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(lock); 56 devices->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(lock); 68 devices->RemoveItem(device); 69 } 70 71 72 static 73 void 74 pppoe_input(struct mbuf *packet) 75 { 76 if(!packet) 77 return; 78 79 #if DEBUG 80 // dump_packet(packet); 81 #endif 82 83 ifnet *sourceIfnet = packet->m_pkthdr.rcvif; 84 complete_pppoe_header *header = mtod(packet, complete_pppoe_header*); 85 PPPoEDevice *device; 86 87 LockerHelper locker(lock); 88 89 for(int32 index = 0; index < devices->CountItems(); index++) { 90 device = devices->ItemAt(index); 91 92 if(device && device->EthernetIfnet() == sourceIfnet) { 93 if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOE 94 && header->pppoeHeader.sessionID == device->SessionID()) { 95 #if DEBUG 96 printf("PPPoE: session packet\n"); 97 #endif 98 device->Receive(packet); 99 return; 100 } else if(header->ethernetHeader.ether_type == ETHERTYPE_PPPOEDISC 101 && header->pppoeHeader.code != PADI 102 && header->pppoeHeader.code != PADR 103 && !device->IsDown()) { 104 #if DEBUG 105 printf("PPPoE: discovery packet\n"); 106 #endif 107 DiscoveryPacket discovery(packet, ETHER_HDR_LEN); 108 if(discovery.InitCheck() != B_OK) { 109 printf("PPPoE: received corrupted discovery packet!\n"); 110 return; 111 } 112 113 pppoe_tag *tag = discovery.TagWithType(HOST_UNIQ); 114 if(header->pppoeHeader.code == PADT || (tag && tag->length == 4 115 && *((uint32*)tag->data) == device->HostUniq())) { 116 device->Receive(packet); 117 return; 118 } 119 } 120 } 121 } 122 123 printf("PPPoE: No device found for packet from: %s\n", sourceIfnet->if_name); 124 m_freem(packet); 125 } 126 127 128 static 129 bool 130 add_to(PPPInterface& mainInterface, PPPInterface *subInterface, 131 driver_parameter *settings, ppp_module_key_type type) 132 { 133 if(type != PPP_DEVICE_KEY_TYPE) 134 return B_ERROR; 135 136 PPPoEDevice *device; 137 bool success; 138 if(subInterface) { 139 device = new PPPoEDevice(*subInterface, settings); 140 success = subInterface->SetDevice(device); 141 } else { 142 device = new PPPoEDevice(mainInterface, settings); 143 success = mainInterface.SetDevice(device); 144 } 145 146 #if DEBUG 147 printf("PPPoE: add_to(): %s\n", 148 success && device && device->InitCheck() == B_OK ? "OK" : "ERROR"); 149 #endif 150 151 return success && device && device->InitCheck() == B_OK; 152 } 153 154 155 static ppp_module_info pppoe_module = { 156 { 157 PPPoE_MODULE_NAME, 158 0, 159 std_ops 160 }, 161 NULL, 162 add_to 163 }; 164 165 166 _EXPORT 167 status_t 168 std_ops(int32 op, ...) 169 { 170 switch(op) { 171 case B_MODULE_INIT: 172 if(get_module(NET_CORE_MODULE_NAME, (module_info**)&core) != B_OK) 173 return B_ERROR; 174 175 if(get_module(NET_ETHERNET_MODULE_NAME, 176 (module_info**) ðernet) != B_OK) { 177 put_module(NET_CORE_MODULE_NAME); 178 return B_ERROR; 179 } 180 181 devices = new List<PPPoEDevice*>; 182 183 ethernet->set_pppoe_receiver(pppoe_input); 184 185 #if DEBUG 186 printf("PPPoE: Registered PPPoE receiver.\n"); 187 #endif 188 return B_OK; 189 190 case B_MODULE_UNINIT: 191 delete devices; 192 ethernet->unset_pppoe_receiver(); 193 #if DEBUG 194 printf("PPPoE: Unregistered PPPoE receiver.\n"); 195 #endif 196 put_module(NET_CORE_MODULE_NAME); 197 put_module(NET_ETHERNET_MODULE_NAME); 198 break; 199 200 default: 201 return B_ERROR; 202 } 203 204 return B_OK; 205 } 206 207 208 _EXPORT 209 module_info *modules[] = { 210 (module_info*) &pppoe_module, 211 NULL 212 }; 213