More work on UDI, Added more Login VTerms
[tpg/acess2.git] / Modules / IPStack / arp.c
1 /*
2  * Acess2 IP Stack
3  * - Address Resolution Protocol
4  */
5 #include "ipstack.h"
6 #include "arp.h"
7 #include "link.h"
8
9 #define ARP_CACHE_SIZE  64
10
11 // === IMPORTS ===
12 extern tInterface       *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
13 extern tInterface       *IPv6_GetInterface(tAdapter *Adapter, tIPv6 Address, int Broadcast);
14
15 // === PROTOTYPES ===
16  int    ARP_Initialise();
17  int    ARP_int_Resolve4(tInterface *Interface, tIPv4 Address);
18 void    ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffer);
19
20 // === GLOBALS ===
21 struct sARP_Cache {
22         tMacAddr        MAC;
23         tIPv4   IP4;
24         tIPv6   IP6;
25         Sint64  LastUpdate;
26 }       *gaARP_Cache;
27  int    giARP_CacheSpace;
28
29 // === CODE ===
30 /**
31  * \fn int ARP_Initialise()
32  * \brief Initalise the ARP section
33  */
34 int ARP_Initialise()
35 {
36         gaARP_Cache = malloc( ARP_CACHE_SIZE * sizeof(*gaARP_Cache) );
37         memset( gaARP_Cache, 0, ARP_CACHE_SIZE * sizeof(*gaARP_Cache) );
38         giARP_CacheSpace = ARP_CACHE_SIZE;
39         
40         Link_RegisterType(0x0806, ARP_int_GetPacket);
41         return 1;
42 }
43
44 /**
45  * \fn int ARP_int_Resolve4(tInterface *Interface, tIPv4 Address)
46  * \brief Request the network to resolve an IPv4 Address
47  * \return Boolean Success
48  */
49 int ARP_int_Resolve4(tInterface *Interface, tIPv4 Address)
50 {
51         struct sArpRequest4     req;
52         
53         req.HWType = htons(0x100);      // Ethernet
54         req.Type   = htons(0x0800);
55         req.HWSize = 6;
56         req.SWSize = 4;
57         req.Request = htons(1);
58         req.SourceMac = Interface->Adapter->MacAddr;
59         req.SourceIP = Interface->IP4.Address;
60         req.DestMac = cMAC_BROADCAST;
61         req.DestIP = Address;
62         
63         Link_SendPacket(Interface->Adapter, 0x0806, req.DestMac, sizeof(struct sArpRequest4), &req);
64         
65         return 0;
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          int    i, free = -1;
75          int    oldest = 0;
76         tArpRequest4    *req4 = Buffer;
77         tArpRequest6    *req6 = Buffer;
78         tInterface      *iface;
79         
80         // Sanity Check Packet
81         if( Length < sizeof(tArpRequest4) ) {
82                 Log("[ARP  ] Recieved undersized packet");
83                 return ;
84         }
85         if( ntohs(req4->Type) != 0x0800 ) {
86                 Log("[ARP  ] Recieved a packet with a bad type 0x%x", ntohs(req4->Type));
87                 return ;
88         }
89         if( req4->HWSize != 6 ) {
90                 Log("[ARP  ] Recieved a packet with HWSize != 6 (%i)", req4->HWSize);
91                 return;
92         }
93         if( !MAC_EQU(req4->SourceMac, From) ) {
94                 Log("[ARP  ] ARP spoofing detected", req4->HWSize);
95                 return;
96         }
97         
98         Log("[ARP  ] Request ID %i", ntohs(req4->Request));
99         
100         switch( ntohs(req4->Request) )
101         {
102         case 1: // You want my IP?
103                 Log("[ARP  ] ARP Request Address class %i", req4->SWSize);
104                 // Check what type of IP it is
105                 switch( req4->SWSize )
106                 {
107                 case 4:
108                         Log("[ARP  ] From MAC %02x:%02x:%02x:%02x:%02x:%02x",
109                                 req4->SourceMac.B[0], req4->SourceMac.B[1],
110                                 req4->SourceMac.B[2], req4->SourceMac.B[3],
111                                 req4->SourceMac.B[4], req4->SourceMac.B[5]);
112                         Log("[ARP  ] to MAC %02x:%02x:%02x:%02x:%02x:%02x",
113                                 req4->DestMac.B[0], req4->DestMac.B[1],
114                                 req4->DestMac.B[2], req4->DestMac.B[3],
115                                 req4->DestMac.B[4], req4->DestMac.B[5]);
116                         Log("[ARP  ] ARP Request IPv4 Address %i.%i.%i.%i",
117                                 req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2],
118                                 req4->DestIP.B[3]);
119                         Log("[ARP  ] from %i.%i.%i.%i",
120                                 req4->SourceIP.B[0], req4->SourceIP.B[1],
121                                 req4->SourceIP.B[2], req4->SourceIP.B[3]);
122                         iface = IPv4_GetInterface(Adapter, req4->DestIP, 0);
123                         if( iface )
124                         {
125                                 req4->DestIP = req4->SourceIP;
126                                 req4->DestMac = req4->SourceMac;
127                                 req4->SourceIP = iface->IP4.Address;
128                                 req4->SourceMac = Adapter->MacAddr;
129                                 req4->Request = htons(2);
130                                 Log("[ARP  ] Hey, That's us!");
131                                 Log("[ARP  ] Sending back %02x:%02x:%02x:%02x:%02x:%02x",
132                                         req4->SourceMac.B[0], req4->SourceMac.B[1],
133                                         req4->SourceMac.B[2], req4->SourceMac.B[3],
134                                         req4->SourceMac.B[4], req4->SourceMac.B[5]);
135                                 Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4);
136                         }
137                         break;
138                 case 6:
139                         if( Length < sizeof(tArpRequest6) ) {
140                                 Log("[ARP  ] Recieved undersized packet (IPv6)");
141                                 return ;
142                         }
143                         iface = IPv6_GetInterface(Adapter, req6->DestIP, 0);
144                         if( iface )
145                         {
146                                 req6->DestIP = req6->SourceIP;
147                                 req6->DestMac = req6->SourceMac;
148                                 req6->SourceIP = iface->IP6.Address;
149                                 req6->SourceMac = Adapter->MacAddr;
150                                 req6->Request = htons(2);
151                                 Link_SendPacket(Adapter, 0x0806, req6->DestMac, sizeof(tArpRequest6), req6);
152                         }
153                         break;
154                 default:
155                         Log("[ARP  ] Unknown Protocol Address size (%i)", req4->SWSize);
156                         return ;
157                 }
158                 
159                 break;
160         
161         case 2: // Ooh! A response!
162                 // Find an entry for the MAC address in the cache
163                 for( i = giARP_CacheSpace; i--; )
164                 {
165                         if(gaARP_Cache[oldest].LastUpdate > gaARP_Cache[i].LastUpdate) {
166                                 oldest = i;
167                         }
168                         if( MAC_EQU(gaARP_Cache[i].MAC, From) ) break;
169                         if( gaARP_Cache[i].LastUpdate == 0 && free==-1 )        free = i;
170                 }
171                 if(i + 1 == 0) {
172                         if(free != -1)
173                                 i = free;
174                         else
175                                 i = oldest;
176                 }
177                 
178                 // Check what type of IP it is
179                 switch( req4->SWSize )
180                 {
181                 case 4:
182                         gaARP_Cache[i].IP4 = req4->SourceIP;
183                         break;
184                 case 6:
185                         if( Length < sizeof(tArpRequest6) ) {
186                                 Log("[ARP  ] Recieved undersized packet (IPv6)");
187                                 return ;
188                         }
189                         gaARP_Cache[i].IP6 = req6->SourceIP;
190                         break;
191                 default:
192                         Log("[ARP  ] Unknown Protocol Address size (%i)", req4->SWSize);
193                         return ;
194                 }
195                 
196                 gaARP_Cache[i].LastUpdate = now();
197                 break;
198         }
199 }

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