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
EthernetInterface()25 EthernetInterface::EthernetInterface()
26 : fIPAddress(INADDR_ANY)
27 {
28 }
29
30 // destructor
~EthernetInterface()31 EthernetInterface::~EthernetInterface()
32 {
33 }
34
35 // IPAddress
36 ip_addr_t
IPAddress() const37 EthernetInterface::IPAddress() const
38 {
39 return fIPAddress;
40 }
41
42 // SetIPAddress
43 void
SetIPAddress(ip_addr_t ipAddress)44 EthernetInterface::SetIPAddress(ip_addr_t ipAddress)
45 {
46 fIPAddress = ipAddress;
47 }
48
49
50 // #pragma mark - EthernetSubService
51
52 // constructor
EthernetSubService(const char * serviceName)53 EthernetSubService::EthernetSubService(const char *serviceName)
54 : NetService(serviceName)
55 {
56 }
57
58 // destructor
~EthernetSubService()59 EthernetSubService::~EthernetSubService()
60 {
61 }
62
63
64 // #pragma mark - EthernetService
65
66 // constructor
EthernetService()67 EthernetService::EthernetService()
68 : NetService(kEthernetServiceName),
69 fInterface(NULL),
70 fSendBuffer(NULL),
71 fReceiveBuffer(NULL)
72 {
73 }
74
75 // destructor
~EthernetService()76 EthernetService::~EthernetService()
77 {
78 if (fSendBuffer)
79 fInterface->FreeSendReceiveBuffer(fSendBuffer);
80 }
81
82 // Init
83 status_t
Init(EthernetInterface * interface)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
MACAddress() const102 EthernetService::MACAddress() const
103 {
104 return fInterface->MACAddress();
105 }
106
107 // IPAddress
108 ip_addr_t
IPAddress() const109 EthernetService::IPAddress() const
110 {
111 return fInterface->IPAddress();
112 }
113
114 // SetIPAddress
115 void
SetIPAddress(ip_addr_t ipAddress)116 EthernetService::SetIPAddress(ip_addr_t ipAddress)
117 {
118 fInterface->SetIPAddress(ipAddress);
119 }
120
121 // Send
122 status_t
Send(const mac_addr_t & destination,uint16 protocol,ChainBuffer * buffer)123 EthernetService::Send(const mac_addr_t &destination, uint16 protocol,
124 ChainBuffer *buffer)
125 {
126 TRACE(("EthernetService::Send(to: %012" B_PRIx64 ", proto: 0x%hx, %"
127 PRIu32 " bytes)\n",
128 destination.ToUInt64(), protocol, (buffer ? buffer->TotalSize() : 0)));
129
130 if (!fInterface || !fSendBuffer)
131 return B_NO_INIT;
132
133 // sending has time, but we need to handle incoming packets as soon as
134 // possible
135 ProcessIncomingPackets();
136
137 if (!buffer)
138 return B_BAD_VALUE;
139
140 // data too long?
141 size_t dataSize = buffer->TotalSize();
142 if (dataSize > ETHER_MAX_TRANSFER_UNIT)
143 return B_BAD_VALUE;
144
145 // prepend ethernet header
146 ether_header header;
147 ChainBuffer headerBuffer(&header, sizeof(header), buffer);
148 header.source = fInterface->MACAddress();
149 header.destination = destination;
150 header.type = htons(protocol);
151
152 // flatten
153 size_t totalSize = headerBuffer.TotalSize();
154 headerBuffer.Flatten(fSendBuffer);
155
156 // pad data, if necessary
157 if (dataSize < ETHER_MIN_TRANSFER_UNIT) {
158 size_t paddingSize = ETHER_MIN_TRANSFER_UNIT - dataSize;
159 memset((uint8*)fSendBuffer + totalSize, 0, paddingSize);
160 totalSize += paddingSize;
161 }
162
163 // send
164 ssize_t bytesSent = fInterface->Send(fSendBuffer, totalSize);
165 if (bytesSent < 0)
166 return bytesSent;
167 if (bytesSent != (ssize_t)totalSize)
168 return B_ERROR;
169
170 return B_OK;
171 }
172
173 // ProcessIncomingPackets
174 void
ProcessIncomingPackets()175 EthernetService::ProcessIncomingPackets()
176 {
177 if (!fInterface || !fReceiveBuffer)
178 return;
179
180 for (;;) {
181 // read from the interface
182 ssize_t bytesReceived = fInterface->Receive(fReceiveBuffer,
183 RECEIVE_BUFFER_SIZE);
184 if (bytesReceived < 0)
185 return;
186
187 // basic sanity checks (packet too small/too big)
188 if (bytesReceived
189 < (ssize_t)sizeof(ether_header) + ETHER_MIN_TRANSFER_UNIT
190 || bytesReceived
191 > (ssize_t)sizeof(ether_header) + ETHER_MAX_TRANSFER_UNIT) {
192 continue;
193 }
194
195 // is the packet intended for us?
196 ether_header *header = (ether_header*)fReceiveBuffer;
197 if (header->destination != kBroadcastMACAddress
198 && header->destination != fInterface->MACAddress()) {
199 continue;
200 }
201
202 TRACE(("EthernetService::ProcessIncomingPackets(): received ethernet "
203 "frame: to: %012" B_PRIx64 ", proto: 0x%hx, %" B_PRIuSIZE " bytes\n",
204 header->destination.ToUInt64(), ntohs(header->type),
205 bytesReceived - (ssize_t)sizeof(ether_header)));
206
207 // find a service handling this kind of packet
208 int serviceCount = fServices.Count();
209 for (int i = 0; i < serviceCount; i++) {
210 EthernetSubService *service = fServices.ElementAt(i);
211 if (service->EthernetProtocol() == ntohs(header->type)) {
212 service->HandleEthernetPacket(this, header->destination,
213 (uint8*)fReceiveBuffer + sizeof(ether_header),
214 bytesReceived - sizeof(ether_header));
215 break;
216 }
217 }
218 }
219 }
220
221 // RegisterEthernetSubService
222 bool
RegisterEthernetSubService(EthernetSubService * service)223 EthernetService::RegisterEthernetSubService(EthernetSubService *service)
224 {
225 return (service && fServices.Add(service) == B_OK);
226 }
227
228 // UnregisterEthernetSubService
229 bool
UnregisterEthernetSubService(EthernetSubService * service)230 EthernetService::UnregisterEthernetSubService(EthernetSubService *service)
231 {
232 return (service && fServices.Remove(service) >= 0);
233 }
234
235 // CountSubNetServices
236 int
CountSubNetServices() const237 EthernetService::CountSubNetServices() const
238 {
239 return fServices.Count();
240 }
241
242 // SubNetServiceAt
243 NetService *
SubNetServiceAt(int index) const244 EthernetService::SubNetServiceAt(int index) const
245 {
246 return fServices.ElementAt(index);
247 }
248