Adding several modules to the Tree, plus some files that escaped earlier
[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         switch( req4->Request )
99         {
100         case 1: // You want my IP?
101                 // Check what type of IP it is
102                 switch( req4->SWSize )
103                 {
104                 case 4:
105                         iface = IPv4_GetInterface(Adapter, req4->DestIP, 0);
106                         if( iface )
107                         {
108                                 IP4_SET(req4->DestIP, req4->SourceIP);
109                                 req4->DestMac = req4->SourceMac;
110                                 req4->SourceIP = iface->IP4.Address;
111                                 req4->SourceMac = Adapter->MacAddr;
112                                 req4->Request = htons(2);
113                                 Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4);
114                         }
115                         break;
116                 case 6:
117                         if( Length < sizeof(tArpRequest6) ) {
118                                 Log("[ARP  ] Recieved undersized packet (IPv6)");
119                                 return ;
120                         }
121                         iface = IPv6_GetInterface(Adapter, req6->DestIP, 0);
122                         if( iface )
123                         {
124                                 req6->DestIP = req6->SourceIP;
125                                 req6->DestMac = req6->SourceMac;
126                                 req6->SourceIP = iface->IP6.Address;
127                                 req6->SourceMac = Adapter->MacAddr;
128                                 req6->Request = htons(2);
129                                 Link_SendPacket(Adapter, 0x0806, req6->DestMac, sizeof(tArpRequest6), req6);
130                         }
131                         break;
132                 default:
133                         Log("[ARP  ] Unknown Protocol Address size (%i)", req4->SWSize);
134                         return ;
135                 }
136                 
137                 break;
138         
139         case 2: // Ooh! A response!
140                 // Find an entry for the MAC address in the cache
141                 for( i = giARP_CacheSpace; i--; )
142                 {
143                         if(gaARP_Cache[oldest].LastUpdate > gaARP_Cache[i].LastUpdate) {
144                                 oldest = i;
145                         }
146                         if( MAC_EQU(gaARP_Cache[i].MAC, From) ) break;
147                         if( gaARP_Cache[i].LastUpdate == 0 && free==-1 )        free = i;
148                 }
149                 if(i + 1 == 0) {
150                         if(free != -1)
151                                 i = free;
152                         else
153                                 i = oldest;
154                 }
155                 
156                 // Check what type of IP it is
157                 switch( req4->SWSize )
158                 {
159                 case 4:
160                         gaARP_Cache[i].IP4 = req4->SourceIP;
161                         break;
162                 case 6:
163                         if( Length < sizeof(tArpRequest6) ) {
164                                 Log("[ARP  ] Recieved undersized packet (IPv6)");
165                                 return ;
166                         }
167                         gaARP_Cache[i].IP6 = req6->SourceIP;
168                         break;
169                 default:
170                         Log("[ARP  ] Unknown Protocol Address size (%i)", req4->SWSize);
171                         return ;
172                 }
173                 
174                 gaARP_Cache[i].LastUpdate = now();
175                 break;
176         }
177 }

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