Usermode/libc - Fix strchr and strrchr behavior
[tpg/acess2.git] / KernelLand / Modules / IPStack / arp.c
1 /*
2  * Acess2 IP Stack
3  * - Address Resolution Protocol
4  * - Part of the IPv4 protocol
5  */
6 #define DEBUG   0
7 #include "ipstack.h"
8 #include "arp.h"
9 #include "link.h"
10 #include "ipv4.h"       // For IPv4_Netmask
11 #include "include/adapters_int.h"       // for MAC addr
12 #include <semaphore.h>
13 #include <timers.h>
14 #include "hwaddr_cache.h"
15
16 #define ARPv6   0
17 #define ARP_CACHE_SIZE  128
18 #define ARP_MAX_AGE             (60*60*1000)    // 1Hr
19
20 // === IMPORTS ===
21 extern tInterface       *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
22 #if ARPv6
23 extern tInterface       *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
24 #endif
25
26 // === PROTOTYPES ===
27  int    ARP_Initialise();
28 void    ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer);
29
30 // === GLOBALS ===
31
32 // === CODE ===
33 /**
34  * \fn int ARP_Initialise()
35  * \brief Initalise the ARP section
36  */
37 int ARP_Initialise()
38 {
39         Link_RegisterType(0x0806, ARP_int_GetPacket);
40         return 1;
41 }
42
43 void ARP_Request4(tInterface *Interface, tIPv4 Address)
44 {
45         struct sArpRequest4     req;
46         // Create request
47         Log_Log("ARP4", "Asking for address %i.%i.%i.%i",
48                 Address.B[0], Address.B[1], Address.B[2], Address.B[3]
49                 );
50         req.HWType = htons(0x0001);     // Ethernet
51         req.Type   = htons(0x0800);
52         req.HWSize = 6;
53         req.SWSize = 4;
54         req.Request = htons(1);
55         memcpy(&req.SourceMac, Interface->Adapter->HWAddr, 6);  // TODO: Remove hard size
56         req.SourceIP = *(tIPv4*)Interface->Address;
57         req.DestMac = cMAC_BROADCAST;
58         req.DestIP = Address;
59
60         // Assumes only a header and footer at link layer
61         tIPStackBuffer  *buffer = IPStack_Buffer_CreateBuffer(3);
62         IPStack_Buffer_AppendSubBuffer(buffer, sizeof(struct sArpRequest4), 0, &req, NULL, NULL);
63
64         // Send Request
65         Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, buffer);
66 }
67
68 /**
69  * \fn void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
70  * \brief Called when an ARP packet is recieved
71  */
72 void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer)
73 {
74         tArpRequest4    *req4 = Buffer;
75         #if ARPv6
76         tArpRequest6    *req6 = Buffer;
77         #endif
78         tInterface      *iface;
79         
80         // Sanity Check Packet
81         if( Length < (int)sizeof(tArpRequest4) ) {
82                 Log_Log("ARP", "Recieved undersized packet");
83                 return ;
84         }
85         if( ntohs(req4->Type) != 0x0800 ) {
86                 Log_Log("ARP", "Recieved a packet with a bad type (0x%x)", ntohs(req4->Type));
87                 return ;
88         }
89         if( req4->HWSize != 6 ) {
90                 Log_Log("ARP", "Recieved a packet with HWSize != 6 (%i)", req4->HWSize);
91                 return;
92         }
93         #if ARP_DETECT_SPOOFS
94         if( !MAC_EQU(req4->SourceMac, From) ) {
95                 Log_Log("ARP", "ARP spoofing detected "
96                         "(%02x%02x:%02x%02x:%02x%02x != %02x%02x:%02x%02x:%02x%02x)",
97                         req4->SourceMac.B[0], req4->SourceMac.B[1], req4->SourceMac.B[2],
98                         req4->SourceMac.B[3], req4->SourceMac.B[4], req4->SourceMac.B[5],
99                         From.B[0], From.B[1], From.B[2],
100                         From.B[3], From.B[4], From.B[5]
101                         );
102                 return;
103         }
104         #endif
105         
106         switch( ntohs(req4->Request) )
107         {
108         case 1: // You want my IP?
109                 // Check what type of IP it is
110                 switch( req4->SWSize )
111                 {
112                 case 4:
113                         iface = IPv4_GetInterface(Adapter, req4->DestIP, 0);
114                         if( iface )
115                         {
116                                 Log_Debug("ARP", "ARP Request IPv4 Address %i.%i.%i.%i from %i.%i.%i.%i"
117                                         " (%02x:%02x:%02x:%02x:%02x:%02x)",
118                                         req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2],
119                                         req4->DestIP.B[3],
120                                         req4->SourceIP.B[0], req4->SourceIP.B[1],
121                                         req4->SourceIP.B[2], req4->SourceIP.B[3],
122                                         req4->SourceMac.B[0], req4->SourceMac.B[1],
123                                         req4->SourceMac.B[2], req4->SourceMac.B[3],
124                                         req4->SourceMac.B[4], req4->SourceMac.B[5]);
125                                 // Someone has ARPed us, let's cache them
126                                 HWCache_Set(Adapter, 4, &req4->SourceIP, &req4->SourceMac);
127                                 
128                                 req4->DestIP = req4->SourceIP;
129                                 req4->DestMac = req4->SourceMac;
130                                 req4->SourceIP = *(tIPv4*)iface->Address;;
131                                 memcpy(&req4->SourceMac, Adapter->HWAddr, 6);   // TODO: Remove hard size
132                                 req4->Request = htons(2);
133                                 Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)",
134                                         req4->SourceMac.B[0], req4->SourceMac.B[1],
135                                         req4->SourceMac.B[2], req4->SourceMac.B[3],
136                                         req4->SourceMac.B[4], req4->SourceMac.B[5]);
137                                 
138                                 // Assumes only a header and footer at link layer
139                                 tIPStackBuffer  *buffer = IPStack_Buffer_CreateBuffer(3);
140                                 IPStack_Buffer_AppendSubBuffer(buffer,
141                                         sizeof(struct sArpRequest4), 0, req4,
142                                         NULL, NULL);
143                                 Link_SendPacket(Adapter, 0x0806, req4->DestMac, buffer);
144                         }
145                         break;
146                 #if ARPv6
147                 case 6:
148                         if( Length < (int)sizeof(tArpRequest6) ) {
149                                 Log_Log("ARP", "Recieved undersized packet (IPv6)");
150                                 return ;
151                         }
152                         Log_Debug("ARP", "ARP Request IPv6 Address %08x:%08x:%08x:%08x",
153                                 ntohl(req6->DestIP.L[0]), ntohl(req6->DestIP.L[1]),
154                                 ntohl(req6->DestIP.L[2]), ntohl(req6->DestIP.L[3])
155                                 );
156                         iface = IPv6_GetInterface(Adapter, req6->DestIP, 0);
157                         if( iface )
158                         {
159                                 req6->DestIP = req6->SourceIP;
160                                 req6->DestMac = req6->SourceMac;
161                                 req6->SourceIP = *(tIPv6*)iface->Address;
162                                 req6->SourceMac = Adapter->MacAddr;
163                                 req6->Request = htons(2);
164                                 Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)",
165                                         req4->SourceMac.B[0], req4->SourceMac.B[1],
166                                         req4->SourceMac.B[2], req4->SourceMac.B[3],
167                                         req4->SourceMac.B[4], req4->SourceMac.B[5]);
168                                 Link_SendPacket(Adapter, 0x0806, req6->DestMac, sizeof(tArpRequest6), req6);
169                         }
170                         break;
171                 #endif
172                 default:
173                         Log_Debug("ARP", "Unknown Protocol Address size (%i)", req4->SWSize);
174                         return ;
175                 }
176                 
177                 break;
178         
179         case 2: // Ooh! A response!             
180                 // Check what type of IP it is
181                 switch( req4->SWSize )
182                 {
183                 case 4:
184                         HWCache_Set(Adapter, 4, &req4->SourceIP, &From);
185                         break;
186                 #if ARPv6
187                 case 6:
188                         if( Length < (int)sizeof(tArpRequest6) ) {
189                                 Log_Debug("ARP", "Recieved undersized packet (IPv6)");
190                                 return ;
191                         }
192                         HWCache_Set(Adapter, 6, &req6->SourceIP, &From );
193                         break;
194                 #endif
195                 default:
196                         Log_Debug("ARP", "Unknown Protocol Address size (%i)", req4->SWSize);
197                         return ;
198                 }
199                 
200                 break;
201         
202         default:
203                 Log_Warning("ARP", "Unknown Request ID %i", ntohs(req4->Request));
204                 break;
205         }
206 }

UCC git Repository :: git.ucc.asn.au