3 * - IPv6 Protcol Handling
9 #include "hwaddr_cache.h"
12 extern tInterface *gIP_Interfaces;
13 extern Uint32 IPv4_Netmask(int FixedBits);
16 int IPv6_Initialise();
17 // int IPv6_RegisterCallback(int ID, tIPCallback Callback);
18 void IPv6_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
19 tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
22 tIPRxCallback* gaIPv6_Callbacks[256];
26 * \brief Initialise the IPv6 handling code
30 Link_RegisterType(IPV6_ETHERNET_ID, IPv6_int_GetPacket);
35 * \brief Registers a callback
36 * \param ID 8-bit packet type ID
37 * \param Callback Callback function
39 int IPv6_RegisterCallback(int ID, tIPRxCallback* Callback)
41 if( ID < 0 || ID > 255 ) return 0;
42 if( gaIPv6_Callbacks[ID] ) return 0;
43 gaIPv6_Callbacks[ID] = Callback;
48 * \brief Creates and sends an IPv6 Packet
49 * \param Iface Interface
50 * \param Destination Destination IP
51 * \param Protocol Protocol ID
52 * \param Length Data Length
53 * \param Data Packet Data
54 * \return Boolean Success
56 int IPv6_SendPacket(tInterface *Iface, tIPv6 Destination, int Protocol, tIPStackBuffer *Buffer)
58 size_t length = IPStack_Buffer_GetLength(Buffer);
60 // Resolve destination
61 tMacAddr to = HWCache_Resolve(Iface, &Destination);
62 if( MAC_EQU(to, cMAC_ZERO) ) {
72 hdr.Head = htonl(hdr.Head);
73 hdr.PayloadLength = htons(length);
74 hdr.NextHeader = Protocol; // TODO: Routing header?
75 hdr.HopLimit = 64; // TODO: Configurable TTL
76 hdr.Source = *(tIPv6*)Iface->Address;
77 hdr.Destination = Destination;
79 IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(hdr), 0, &hdr, NULL, NULL);
81 Link_SendPacket(Iface->Adapter, IPV6_ETHERNET_ID, to, Buffer);
87 * \fn void IPv6_int_GetPacket(tInterface *Interface, tMacAddr From, int Length, void *Buffer)
88 * \brief Process an IPv6 Packet
89 * \param Interface Input interface
90 * \param From Source MAC address
91 * \param Length Packet length
92 * \param Buffer Packet data
94 void IPv6_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
97 tIPv6Header *hdr = Buffer;
102 if(Length < sizeof(tIPv6Header)) return;
104 hdr->Head = ntohl(hdr->Head);
106 //if( ((hdr->Head >> (20+8)) & 0xF) != 6 )
107 if( hdr->Version != 6 )
111 Log_Debug("IPv6", "hdr = {");
112 Log_Debug("IPv6", " .Version = %i", hdr->Version );
113 Log_Debug("IPv6", " .TrafficClass = %i", hdr->TrafficClass );
114 Log_Debug("IPv6", " .FlowLabel = %i", hdr->FlowLabel );
115 Log_Debug("IPv6", " .PayloadLength = 0x%04x", ntohs(hdr->PayloadLength) );
116 Log_Debug("IPv6", " .NextHeader = 0x%02x", hdr->NextHeader );
117 Log_Debug("IPv6", " .HopLimit = 0x%02x", hdr->HopLimit );
118 Log_Debug("IPv6", " .Source = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Source );
119 Log_Debug("IPv6", " .Destination = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Destination );
120 Log_Debug("IPv6", "}");
123 // No checksum in IPv6
125 // Check Packet length
126 if( ntohs(hdr->PayloadLength)+sizeof(tIPv6Header) > Length) {
127 Log_Log("IPv6", "hdr->PayloadLength(%i) > Length(%i)", ntohs(hdr->PayloadLength), Length);
132 nextHeader = hdr->NextHeader;
138 Uint8 Length; // In 8-byte chunks, with 0 being 8 bytes long
141 optionHdr = (void*)dataPtr;
142 // Hop-by-hop options
145 // TODO: Parse the options (actually, RFC2460 doesn't specify any)
146 // Two Defined: Pad1 and PadN
149 else if(nextHeader == 43)
151 // TODO: Routing Header options
155 break; // Unknown, pass to next layer
157 nextHeader = optionHdr->NextHeader;
158 dataPtr += (optionHdr->Length + 1) * 8; // 8-octet length (0 = 8 bytes long)
161 // Get Interface (allowing broadcasts)
162 iface = IPv6_GetInterface(Adapter, hdr->Destination, 1);
167 ret = IPTables_TestChain("INPUT",
168 6, &hdr->Source, &hdr->Destination,
170 hdr->PayloadLength, hdr->Data
176 // If routing is disabled globally, or if it's disabled for v6 only, drop
181 // TODO: Defer routing of packet
182 LOG("Route the packet");
183 // Drop the packet if the TTL is zero
184 if( hdr->HopLimit == 0 ) {
185 Log_Warning("IPv6", "TODO: Send ICMP-Timeout when TTL exceeded");
190 ret = IPTables_TestChain("FORWARD",
191 6, &hdr->Source, &hdr->Destination,
193 hdr->PayloadLength, hdr->Data
203 Log_Debug("IPv6", "Silently dropping packet");
205 // Unknown, silent drop
213 // TODO: Use tIPStackBuffer instead, for refcounting
214 //IPStack_RoutePacket(6, &hdr->Destination, Length, Buffer);
219 // - TODO: Populate when routing using source address match for iface
220 if( IPStack_CompareAddress(6, &hdr->Source, iface->Address, iface->SubnetBits) )
222 HWCache_Set(Adapter, 6, &hdr->Source, &From);
226 if( !gaIPv6_Callbacks[hdr->NextHeader] ) {
227 Log_Log("IPv6", "Unknown Protocol %i", hdr->NextHeader);
231 gaIPv6_Callbacks[hdr->NextHeader]( iface, &hdr->Source, hdr->PayloadLength, hdr->Data );
235 * \fn tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address)
236 * \brief Searches an adapter for a matching address
237 * \param Adapter Source adapter
238 * \param Address Destination Address
239 * \param Broadcast Allow broadcast?
241 tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast)
244 tInterface *iface = NULL;
247 for( iface = gIP_Interfaces; iface; iface = iface->Next)
251 // Check for this adapter
252 if( iface->Adapter != Adapter ) continue;
254 // Skip non-IPv6 Interfaces
255 if( iface->Type != 6 ) continue;
257 thisAddr = (tIPv6*)iface->Address;
258 // If the address is a perfect match, return this interface
259 if( IP6_EQU(Address, *thisAddr) ) return iface;
261 // Check if we want to match broadcast addresses
262 if( !Broadcast ) continue;
264 // Check for broadcast
265 // - Check first DWORDs
266 if( iface->SubnetBits > 32 && Address.L[0] != thisAddr->L[0] )
268 if( iface->SubnetBits > 64 && Address.L[1] != thisAddr->L[1] )
270 if( iface->SubnetBits > 96 && Address.L[2] != thisAddr->L[2] )
274 j = iface->SubnetBits / 32;
275 i = iface->SubnetBits % 32;
276 netmask = IPv4_Netmask( iface->SubnetBits % 32 );
278 // Check the last bit of the netmask
279 if( (Address.L[j] >> i) != (thisAddr->L[j] >> i) ) continue;
281 // Check that the host portion is one
282 if( (Address.L[j] & ~netmask) != (0xFFFFFFFF & ~netmask) ) continue;
283 if( j >= 2 && Address.L[3] != 0xFFFFFFFF) continue;
284 if( j >= 1 && Address.L[2] != 0xFFFFFFFF) continue;
285 if( j >= 0 && Address.L[1] != 0xFFFFFFFF) continue;