2 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
6 #include <boot/net/IP.h>
9 #include <KernelExport.h>
11 #include <boot/net/ARP.h>
12 #include <boot/net/ChainBuffer.h>
17 # define TRACE(x) dprintf x
23 // #pragma mark - IPSubService
26 IPSubService::IPSubService(const char *serviceName
)
27 : NetService(serviceName
)
32 IPSubService::~IPSubService()
37 // #pragma mark - IPService
40 IPService::IPService(EthernetService
*ethernet
, ARPService
*arpService
)
41 : EthernetSubService(kIPServiceName
),
43 fARPService(arpService
)
48 IPService::~IPService()
51 fEthernet
->UnregisterEthernetSubService(this);
60 if (!fEthernet
->RegisterEthernetSubService(this))
67 IPService::IPAddress() const
69 return (fEthernet
? fEthernet
->IPAddress() : INADDR_ANY
);
74 IPService::EthernetProtocol() const
79 // HandleEthernetPacket
81 IPService::HandleEthernetPacket(EthernetService
*ethernet
,
82 const mac_addr_t
&targetAddress
, const void *data
, size_t size
)
84 TRACE(("IPService::HandleEthernetPacket(): %lu - %lu bytes\n", size
,
87 if (!data
|| size
< sizeof(ip_header
))
91 const ip_header
*header
= (const ip_header
*)data
;
93 int headerLength
= header
->header_length
* 4;
94 if (headerLength
< 20 || headerLength
> (int)size
96 || header
->version
!= IP_PROTOCOL_VERSION_4
98 || ntohs(header
->total_length
) > size
99 // broadcast or our IP?
100 || (header
->destination
!= htonl(INADDR_BROADCAST
)
101 && (fEthernet
->IPAddress() == INADDR_ANY
102 || header
->destination
!= htonl(fEthernet
->IPAddress())))
104 || _Checksum(*header
) != 0) {
108 // find a service handling this kind of packet
109 int serviceCount
= fServices
.Count();
110 for (int i
= 0; i
< serviceCount
; i
++) {
111 IPSubService
*service
= fServices
.ElementAt(i
);
112 if (service
->IPProtocol() == header
->protocol
) {
113 service
->HandleIPPacket(this, ntohl(header
->source
),
114 ntohl(header
->destination
),
115 (uint8
*)data
+ headerLength
,
116 ntohs(header
->total_length
) - headerLength
);
124 IPService::Send(ip_addr_t destination
, uint8 protocol
, ChainBuffer
*buffer
)
126 TRACE(("IPService::Send(to: %08lx, proto: %lu, %lu bytes)\n", destination
,
127 (uint32
)protocol
, (buffer
? buffer
->TotalSize() : 0)));
132 if (!fEthernet
|| !fARPService
)
137 ChainBuffer
headerBuffer(&header
, sizeof(header
), buffer
);
138 header
.header_length
= 5; // 5 32 bit words, no options
139 header
.version
= IP_PROTOCOL_VERSION_4
;
140 header
.type_of_service
= 0;
141 header
.total_length
= htons(headerBuffer
.TotalSize());
142 header
.identifier
= 0;
143 header
.fragment_offset
= htons(IP_DONT_FRAGMENT
);
144 header
.time_to_live
= IP_DEFAULT_TIME_TO_LIVE
;
145 header
.protocol
= protocol
;
147 header
.source
= htonl(fEthernet
->IPAddress());
148 header
.destination
= htonl(destination
);
151 header
.checksum
= htons(_Checksum(header
));
153 // get target MAC address
154 mac_addr_t targetMAC
;
155 status_t error
= fARPService
->GetMACForIP(destination
, targetMAC
);
160 return fEthernet
->Send(targetMAC
, ETHERTYPE_IP
, &headerBuffer
);
163 // ProcessIncomingPackets
165 IPService::ProcessIncomingPackets()
168 fEthernet
->ProcessIncomingPackets();
171 // RegisterIPSubService
173 IPService::RegisterIPSubService(IPSubService
*service
)
175 return (service
&& fServices
.Add(service
) == B_OK
);
178 // UnregisterIPSubService
180 IPService::UnregisterIPSubService(IPSubService
*service
)
182 return (service
&& fServices
.Remove(service
) >= 0);
185 // CountSubNetServices
187 IPService::CountSubNetServices() const
189 return fServices
.Count();
194 IPService::SubNetServiceAt(int index
) const
196 return fServices
.ElementAt(index
);
201 IPService::_Checksum(const ip_header
&header
)
203 ChainBuffer
buffer((void*)&header
, header
.header_length
* 4);
204 return ip_checksum(&buffer
);
212 ip_checksum(ChainBuffer
*buffer
)
214 // ChainBuffer iterator returning a stream of uint16 (big endian).
216 Iterator(ChainBuffer
*buffer
)
230 uint16 byte
= _NextByte();
231 return (byte
<< 8) | _NextByte();
239 if (fOffset
< (int)fBuffer
->Size())
243 fBuffer
= fBuffer
->Next();
249 uint8 byte
= (fBuffer
? ((uint8
*)fBuffer
->Data())[fOffset
] : 0);
254 ChainBuffer
*fBuffer
;
261 while (it
.HasNext()) {
262 checksum
+= it
.Next();
263 while (checksum
>> 16)
264 checksum
= (checksum
& 0xffff) + (checksum
>> 16);
272 ip_parse_address(const char *string
)
274 ip_addr_t address
= 0;
277 // TODO: Handles only IPv4 addresses for now.
278 while (components
< 4) {
279 address
|= strtol(string
, NULL
, 0) << ((4 - components
- 1) * 8);
281 const char *dot
= strchr(string
, '.');