5 * - Internet Control Message Protocol v6
9 #include "ipv4.h" // For the IP Checksum
12 #include "hwaddr_cache.h"
13 #include "include/adapters_int.h"
16 void ICMPv6_GetPacket(tInterface *Interface, void *Address, int Length, const void *Buffer);
17 int ICMPv6_ND_GetOpt(size_t Length, const void *Buffer, Uint8 OptID, const void **Ptr);
20 void ICMPv6_Initialise(void)
25 void ICMPv6_GetPacket(tInterface *Interface, void *Address, int Length, const void *Buffer)
27 if( Length < sizeof(tICMPv6_Header))
29 const tICMPv6_Header *hdr = Buffer;
32 if( IPv4_Checksum(Buffer, Length) != 0 )
35 if( hdr->Type == ICMPV6_INFO_NEIGHBOUR_ADVERTISMENT )
37 if( Length < sizeof(tICMPv6_Header) + sizeof(tICMPv6_NA) )
39 // TODO: Check that IP.HopLimt == 255
40 const tICMPv6_NA *na = (const void*)(hdr+1);
41 if( !(na->Flags & (1 << 1)) ) {
45 if( na->Flags & (1 << 2) ) {
46 // Override, force update
48 const tICMPv6_Opt_LinkAddr *la = NULL;
49 if( ICMPv6_ND_GetOpt(Length-sizeof(*hdr)+sizeof(*na), na+1, ICMPV6_OPTION_SRCLINK, (const void**)&la) )
52 LOG("No link address on neighbor advertisement");
56 HWCache_Set(Interface->Adapter, 6, Address, (const tMacAddr*)la->Address);
64 case ICMPV6_INFO_ROUTER_SOLICITATION:
65 // TODO: If routing is active, send out RA
67 case ICMPV6_INFO_ROUTER_ADVERTISEMENT: {
68 // TODO: If routing INACTIVE, and interface is ::/0, set address
70 case ICMPV6_INFO_NEIGHBOUR_SOLICITATION:
71 if( Length < sizeof(tICMPv6_Header) + sizeof(tICMPv6_NS) )
73 // TODO: Check that IP.HopLimt == 255
75 case ICMPV6_INFO_NEIGHBOUR_ADVERTISMENT:
76 //HWCache_Set(Interface->Adapter,
81 int ICMPv6_ND_GetOpt(size_t Length, const void *Buffer, Uint8 OptID, const void **Ptr)
90 while( Length >= sizeof(*opts))
92 if( opts->Length == 0 )
94 if( opts->Length * 8 > Length )
97 if( opts->Type == OptID ) {
101 opts += opts->Length;
106 void ICMPv6_SendNS(tInterface *Interface, const void *Address)
108 const Uint8 *addr8 = Address;
113 tICMPv6_Opt_LinkAddr linkaddr;
116 // Custom-crafted IPv6 header
118 pkt.ip.TrafficClass = 0;
119 pkt.ip.FlowLabel = 0;
120 pkt.ip.Head = htonl(pkt.ip.Head);
121 pkt.ip.PayloadLength = htons(sizeof(pkt)-sizeof(pkt.ip));
122 pkt.ip.NextHeader = IPV6PROT_ICMPV6;
123 pkt.ip.HopLimit = 255; // Max value
124 pkt.ip.Source = *(tIPv6*)Interface->Address;
125 pkt.ip.Destination = (tIPv6){.B={0xFF,0x02, 0,0, 0,0, 0,0, 0,0, 0,1,0xFF,addr8[13], addr8[14],addr8[15]}};
127 pkt.icmp.Type = ICMPV6_INFO_NEIGHBOUR_SOLICITATION;
129 pkt.icmp.Checksum = 0; // populated later
132 pkt.ns.TargetAddress = *(const tIPv6*)Address;
134 pkt.linkaddr.Type = ICMPV6_OPTION_SRCLINK;
135 pkt.linkaddr.Length = 1; // 1 * 8 bytes
136 memcpy(pkt.our_mac, Interface->Adapter->HWAddr, 6);
138 pkt.icmp.Checksum = IPv4_Checksum(&pkt, sizeof(pkt));
141 tMacAddr to = {.B={0x33, 0x33, addr8[12], addr8[13], addr8[14], addr8[15]}};
143 tIPStackBuffer *buffer = IPStack_Buffer_CreateBuffer(2);
144 IPStack_Buffer_AppendSubBuffer(buffer, sizeof(pkt), 0, &pkt, NULL, NULL);
145 Link_SendPacket(Interface->Adapter, IPV6_ETHERNET_ID, to, buffer);
146 IPStack_Buffer_DestroyBuffer(buffer);