1 /* 2 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 #include <boot/net/Ethernet.h> 7 8 #include <stdio.h> 9 #include <KernelExport.h> 10 11 #include <boot/net/ChainBuffer.h> 12 13 14 //#define TRACE_ETHERNET 15 #ifdef TRACE_ETHERNET 16 # define TRACE(x) dprintf x 17 #else 18 # define TRACE(x) ; 19 #endif 20 21 22 // #pragma mark - EthernetInterface 23 24 // constructor 25 EthernetInterface::EthernetInterface() 26 : fIPAddress(INADDR_ANY) 27 { 28 } 29 30 // destructor 31 EthernetInterface::~EthernetInterface() 32 { 33 } 34 35 // IPAddress 36 ip_addr_t 37 EthernetInterface::IPAddress() const 38 { 39 return fIPAddress; 40 } 41 42 // SetIPAddress 43 void 44 EthernetInterface::SetIPAddress(ip_addr_t ipAddress) 45 { 46 fIPAddress = ipAddress; 47 } 48 49 50 // #pragma mark - EthernetSubService 51 52 // constructor 53 EthernetSubService::EthernetSubService(const char *serviceName) 54 : NetService(serviceName) 55 { 56 } 57 58 // destructor 59 EthernetSubService::~EthernetSubService() 60 { 61 } 62 63 64 // #pragma mark - EthernetService 65 66 // constructor 67 EthernetService::EthernetService() 68 : NetService(kEthernetServiceName), 69 fInterface(NULL), 70 fSendBuffer(NULL), 71 fReceiveBuffer(NULL) 72 { 73 } 74 75 // destructor 76 EthernetService::~EthernetService() 77 { 78 if (fSendBuffer) 79 fInterface->FreeSendReceiveBuffer(fSendBuffer); 80 } 81 82 // Init 83 status_t 84 EthernetService::Init(EthernetInterface *interface) 85 { 86 if (!interface) 87 return B_BAD_VALUE; 88 89 fInterface = interface; 90 91 fSendBuffer = fInterface->AllocateSendReceiveBuffer( 92 SEND_BUFFER_SIZE + RECEIVE_BUFFER_SIZE); 93 if (!fSendBuffer) 94 return B_NO_MEMORY; 95 fReceiveBuffer = (uint8*)fSendBuffer + SEND_BUFFER_SIZE; 96 97 return B_OK; 98 } 99 100 // MACAddress 101 mac_addr_t 102 EthernetService::MACAddress() const 103 { 104 return fInterface->MACAddress(); 105 } 106 107 // IPAddress 108 ip_addr_t 109 EthernetService::IPAddress() const 110 { 111 return fInterface->IPAddress(); 112 } 113 114 // SetIPAddress 115 void 116 EthernetService::SetIPAddress(ip_addr_t ipAddress) 117 { 118 fInterface->SetIPAddress(ipAddress); 119 } 120 121 // Send 122 status_t 123 EthernetService::Send(const mac_addr_t &destination, uint16 protocol, 124 ChainBuffer *buffer) 125 { 126 TRACE(("EthernetService::Send(to: %012llx, proto: 0x%hx, %lu bytes)\n", 127 destination.ToUInt64(), protocol, (buffer ? buffer->TotalSize() : 0))); 128 129 if (!fInterface || !fSendBuffer) 130 return B_NO_INIT; 131 132 // sending has time, but we need to handle incoming packets as soon as 133 // possible 134 ProcessIncomingPackets(); 135 136 if (!buffer) 137 return B_BAD_VALUE; 138 139 // data too long? 140 size_t dataSize = buffer->TotalSize(); 141 if (dataSize > ETHER_MAX_TRANSFER_UNIT) 142 return B_BAD_VALUE; 143 144 // prepend ethernet header 145 ether_header header; 146 ChainBuffer headerBuffer(&header, sizeof(header), buffer); 147 header.source = fInterface->MACAddress(); 148 header.destination = destination; 149 header.type = htons(protocol); 150 151 // flatten 152 size_t totalSize = headerBuffer.TotalSize(); 153 headerBuffer.Flatten(fSendBuffer); 154 155 // pad data, if necessary 156 if (dataSize < ETHER_MIN_TRANSFER_UNIT) { 157 size_t paddingSize = ETHER_MIN_TRANSFER_UNIT - dataSize; 158 memset((uint8*)fSendBuffer + totalSize, 0, paddingSize); 159 totalSize += paddingSize; 160 } 161 162 // send 163 ssize_t bytesSent = fInterface->Send(fSendBuffer, totalSize); 164 if (bytesSent < 0) 165 return bytesSent; 166 if (bytesSent != (ssize_t)totalSize) 167 return B_ERROR; 168 169 return B_OK; 170 } 171 172 // ProcessIncomingPackets 173 void 174 EthernetService::ProcessIncomingPackets() 175 { 176 if (!fInterface || !fReceiveBuffer) 177 return; 178 179 for (;;) { 180 // read from the interface 181 ssize_t bytesReceived = fInterface->Receive(fReceiveBuffer, 182 RECEIVE_BUFFER_SIZE); 183 if (bytesReceived < 0) 184 return; 185 186 // basic sanity checks (packet too small/too big) 187 if (bytesReceived 188 < (ssize_t)sizeof(ether_header) + ETHER_MIN_TRANSFER_UNIT 189 || bytesReceived 190 > (ssize_t)sizeof(ether_header) + ETHER_MAX_TRANSFER_UNIT) { 191 continue; 192 } 193 194 // is the packet intended for us? 195 ether_header *header = (ether_header*)fReceiveBuffer; 196 if (header->destination != kBroadcastMACAddress 197 && header->destination != fInterface->MACAddress()) { 198 continue; 199 } 200 201 TRACE(("EthernetService::ProcessIncomingPackets(): received ethernet " 202 "frame: to: %012llx, proto: 0x%hx, %ld bytes\n", 203 header->destination.ToUInt64(), ntohs(header->type), 204 bytesReceived - (ssize_t)sizeof(ether_header))); 205 206 // find a service handling this kind of packet 207 int serviceCount = fServices.Count(); 208 for (int i = 0; i < serviceCount; i++) { 209 EthernetSubService *service = fServices.ElementAt(i); 210 if (service->EthernetProtocol() == ntohs(header->type)) { 211 service->HandleEthernetPacket(this, header->destination, 212 (uint8*)fReceiveBuffer + sizeof(ether_header), 213 bytesReceived - sizeof(ether_header)); 214 break; 215 } 216 } 217 } 218 } 219 220 // RegisterEthernetSubService 221 bool 222 EthernetService::RegisterEthernetSubService(EthernetSubService *service) 223 { 224 return (service && fServices.Add(service) == B_OK); 225 } 226 227 // UnregisterEthernetSubService 228 bool 229 EthernetService::UnregisterEthernetSubService(EthernetSubService *service) 230 { 231 return (service && fServices.Remove(service) >= 0); 232 } 233 234 // CountSubNetServices 235 int 236 EthernetService::CountSubNetServices() const 237 { 238 return fServices.Count(); 239 } 240 241 // SubNetServiceAt 242 NetService * 243 EthernetService::SubNetServiceAt(int index) const 244 { 245 return fServices.ElementAt(index); 246 } 247