3 * - IPv6 Protcol Handling
11 extern tInterface *gIP_Interfaces;
12 extern Uint32 IPv4_Netmask(int FixedBits);
15 int IPv6_Initialise();
16 int IPv6_RegisterCallback(int ID, tIPCallback Callback);
17 void IPv6_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
18 tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
21 tIPCallback gaIPv6_Callbacks[256];
25 * \brief Initialise the IPv6 handling code
29 Link_RegisterType(IPV6_ETHERNET_ID, IPv6_int_GetPacket);
34 * \brief Registers a callback
35 * \param ID 8-bit packet type ID
36 * \param Callback Callback function
38 int IPv6_RegisterCallback(int ID, tIPCallback Callback)
40 if( ID < 0 || ID > 255 ) return 0;
41 if( gaIPv6_Callbacks[ID] ) return 0;
42 gaIPv6_Callbacks[ID] = Callback;
47 * \brief Creates and sends an IPv6 Packet
48 * \param Iface Interface
49 * \param Destination Destination IP
50 * \param Protocol Protocol ID
51 * \param Length Data Length
52 * \param Data Packet Data
53 * \return Boolean Success
55 int IPv6_SendPacket(tInterface *Iface, tIPv6 Destination, int Protocol, size_t Length, const void *Data)
61 * \fn void IPv6_int_GetPacket(tInterface *Interface, tMacAddr From, int Length, void *Buffer)
62 * \brief Process an IPv6 Packet
63 * \param Interface Input interface
64 * \param From Source MAC address
65 * \param Length Packet length
66 * \param Buffer Packet data
68 void IPv6_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
71 tIPv6Header *hdr = Buffer;
76 if(Length < sizeof(tIPv6Header)) return;
78 hdr->Head = ntohl(hdr->Head);
80 //if( ((hdr->Head >> (20+8)) & 0xF) != 6 )
81 if( hdr->Version != 6 )
85 Log_Debug("IPv6", "hdr = {");
86 Log_Debug("IPv6", " .Version = %i", hdr->Version );
87 Log_Debug("IPv6", " .TrafficClass = %i", hdr->TrafficClass );
88 Log_Debug("IPv6", " .FlowLabel = %i", hdr->FlowLabel );
89 Log_Debug("IPv6", " .PayloadLength = 0x%04x", ntohs(hdr->PayloadLength) );
90 Log_Debug("IPv6", " .NextHeader = 0x%02x", hdr->NextHeader );
91 Log_Debug("IPv6", " .HopLimit = 0x%02x", hdr->HopLimit );
92 Log_Debug("IPv6", " .Source = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Source );
93 Log_Debug("IPv6", " .Destination = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Destination );
94 Log_Debug("IPv6", "}");
97 // No checksum in IPv6
99 // Check Packet length
100 if( ntohs(hdr->PayloadLength)+sizeof(tIPv6Header) > Length) {
101 Log_Log("IPv6", "hdr->PayloadLength(%i) > Length(%i)", ntohs(hdr->PayloadLength), Length);
106 nextHeader = hdr->NextHeader;
108 dataLength = hdr->PayloadLength;
113 Uint8 Length; // In 8-byte chunks, with 0 being 8 bytes long
116 optionHdr = (void*)dataPtr;
117 // Hop-by-hop options
120 // TODO: Parse the options (actually, RFC2460 doesn't specify any)
123 else if(nextHeader == 43)
125 // TODO: Routing Header options
129 break; // Unknown, pass on
131 nextHeader = optionHdr->NextHeader;
132 dataPtr += (optionHdr->Length + 1) * 8; // 8-octet length (0 = 8 bytes long)
135 // Get Interface (allowing broadcasts)
136 iface = IPv6_GetInterface(Adapter, hdr->Destination, 1);
141 ret = IPTables_TestChain("INPUT",
142 6, &hdr->Source, &hdr->Destination,
144 hdr->PayloadLength, hdr->Data
149 ret = IPTables_TestChain("FORWARD",
150 6, &hdr->Source, &hdr->Destination,
152 hdr->PayloadLength, hdr->Data
162 Log_Debug("IPv6", "Silently dropping packet");
164 // Unknown, silent drop
176 Log_Debug("IPv6", "Route the packet");
177 // Drop the packet if the TTL is zero
178 if( hdr->HopLimit == 0 ) {
179 Log_Warning("IPv6", "TODO: Sent ICMP-Timeout when TTL exceeded");
185 rt = IPStack_FindRoute(6, NULL, &hdr->Destination); // Get the route (gets the interface)
186 to = ICMP6_ResolveHWAddr(rt->Interface, hdr->Destination); // Resolve address
189 Log_Log("IPv6", "Forwarding packet");
190 Link_SendPacket(rt->Interface->Adapter, IPV6_ETHERNET_ID, to, Length, Buffer);
197 if( !gaIPv6_Callbacks[hdr->NextHeader] ) {
198 Log_Log("IPv6", "Unknown Protocol %i", hdr->NextHeader);
202 gaIPv6_Callbacks[hdr->NextHeader]( iface, &hdr->Source, hdr->PayloadLength, hdr->Data );
206 * \fn tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address)
207 * \brief Searches an adapter for a matching address
208 * \param Adapter Source adapter
209 * \param Address Destination Address
210 * \param Broadcast Allow broadcast?
212 tInterface *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast)
215 tInterface *iface = NULL;
218 for( iface = gIP_Interfaces; iface; iface = iface->Next)
222 // Check for this adapter
223 if( iface->Adapter != Adapter ) continue;
225 // Skip non-IPv6 Interfaces
226 if( iface->Type != 6 ) continue;
228 thisAddr = (tIPv6*)iface->Address;
229 // If the address is a perfect match, return this interface
230 if( IP6_EQU(Address, *thisAddr) ) return iface;
232 // Check if we want to match broadcast addresses
233 if( !Broadcast ) continue;
235 // Check for broadcast
236 // - Check first DWORDs
237 if( iface->SubnetBits > 32 && Address.L[0] != thisAddr->L[0] )
239 if( iface->SubnetBits > 64 && Address.L[1] != thisAddr->L[1] )
241 if( iface->SubnetBits > 96 && Address.L[2] != thisAddr->L[2] )
245 j = iface->SubnetBits / 32;
246 i = iface->SubnetBits % 32;
247 netmask = IPv4_Netmask( iface->SubnetBits % 32 );
249 // Check the last bit of the netmask
250 if( (Address.L[j] >> i) != (thisAddr->L[j] >> i) ) continue;
252 // Check that the host portion is one
253 if( (Address.L[j] & ~netmask) != (0xFFFFFFFF & ~netmask) ) continue;
254 if( j >= 2 && Address.L[3] != 0xFFFFFFFF) continue;
255 if( j >= 1 && Address.L[2] != 0xFFFFFFFF) continue;
256 if( j >= 0 && Address.L[1] != 0xFFFFFFFF) continue;