A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Dec 14 20:55:40 2017 +0000
Revision:
59:e0e556c8bd46
Parent:
57:e0fb648acf48
Added buffer length to help avoid over runs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 43:bc028d5a6424 1 #include "mbed.h"
andrewboyson 43:bc028d5a6424 2 #include "log.h"
andrewboyson 43:bc028d5a6424 3 #include "net.h"
andrewboyson 43:bc028d5a6424 4 #include "action.h"
andrewboyson 43:bc028d5a6424 5 #include "icmp4.h"
andrewboyson 10:f0854784e960 6 #include "udptcp4.h"
andrewboyson 48:952dddb74b8b 7 #include "ar4.h"
andrewboyson 50:492f2d2954e4 8 #include "nr4.h"
andrewboyson 43:bc028d5a6424 9 #include "dhcp.h"
andrewboyson 43:bc028d5a6424 10 #include "eth.h"
andrewboyson 43:bc028d5a6424 11 #include "ip.h"
andrewboyson 49:1a6336f2b3f9 12 #include "ip4addr.h"
andrewboyson 43:bc028d5a6424 13 #include "ntp.h"
andrewboyson 43:bc028d5a6424 14 #include "mac.h"
andrewboyson 10:f0854784e960 15
andrewboyson 48:952dddb74b8b 16 bool Ip4Trace = true;
andrewboyson 10:f0854784e960 17
andrewboyson 53:77f8a49adf89 18 #define OFF_LINK_TTL 64
andrewboyson 53:77f8a49adf89 19
andrewboyson 10:f0854784e960 20 __packed struct header
andrewboyson 10:f0854784e960 21 {
andrewboyson 10:f0854784e960 22 uint8_t versionIhl;
andrewboyson 10:f0854784e960 23 uint8_t tos;
andrewboyson 10:f0854784e960 24 uint16_t length;
andrewboyson 10:f0854784e960 25 uint16_t id;
andrewboyson 10:f0854784e960 26 uint16_t flagsOffset;
andrewboyson 10:f0854784e960 27 uint8_t ttl;
andrewboyson 10:f0854784e960 28 uint8_t protocol;
andrewboyson 10:f0854784e960 29 uint16_t checksum;
andrewboyson 10:f0854784e960 30 uint32_t src;
andrewboyson 10:f0854784e960 31 uint32_t dst;
andrewboyson 10:f0854784e960 32 };
andrewboyson 10:f0854784e960 33
andrewboyson 10:f0854784e960 34 //Header variables
andrewboyson 10:f0854784e960 35 static uint8_t version;
andrewboyson 10:f0854784e960 36 static int headerLength;
andrewboyson 10:f0854784e960 37 static uint8_t tos;
andrewboyson 59:e0e556c8bd46 38 static uint16_t totalLength;
andrewboyson 10:f0854784e960 39 static uint16_t id;
andrewboyson 10:f0854784e960 40 static bool dontFragment;
andrewboyson 10:f0854784e960 41 static bool moreFragments;
andrewboyson 10:f0854784e960 42 static uint16_t offset;
andrewboyson 10:f0854784e960 43 static uint8_t ttl;
andrewboyson 10:f0854784e960 44 static uint8_t protocol;
andrewboyson 10:f0854784e960 45 static uint16_t checksum;
andrewboyson 10:f0854784e960 46 static uint16_t calcsum;
andrewboyson 35:93c39d260a83 47 static uint32_t srcIp;
andrewboyson 35:93c39d260a83 48 static uint32_t dstIp;
andrewboyson 10:f0854784e960 49
andrewboyson 59:e0e556c8bd46 50 static void readHeader(struct header * pHeader)
andrewboyson 10:f0854784e960 51 {
andrewboyson 10:f0854784e960 52 version = pHeader->versionIhl >> 4;
andrewboyson 10:f0854784e960 53 uint8_t ihl = pHeader->versionIhl & 0xF;
andrewboyson 10:f0854784e960 54 headerLength = ihl * 4;
andrewboyson 10:f0854784e960 55 tos = pHeader->tos;
andrewboyson 59:e0e556c8bd46 56 totalLength = NetToHost16(pHeader->length);
andrewboyson 10:f0854784e960 57 id = NetToHost16(pHeader->id);
andrewboyson 10:f0854784e960 58 uint16_t flagsOffset = NetToHost16(pHeader->flagsOffset);
andrewboyson 10:f0854784e960 59 dontFragment = flagsOffset & 0x4000;
andrewboyson 10:f0854784e960 60 moreFragments = flagsOffset & 0x8000;
andrewboyson 10:f0854784e960 61 offset = flagsOffset & 0x1FFF;
andrewboyson 10:f0854784e960 62 ttl = pHeader->ttl;
andrewboyson 10:f0854784e960 63 protocol = pHeader->protocol;
andrewboyson 10:f0854784e960 64 checksum = NetToHost16(pHeader->checksum);
andrewboyson 10:f0854784e960 65 calcsum = NetCheckSum(headerLength, pHeader);
andrewboyson 35:93c39d260a83 66 srcIp = pHeader->src;
andrewboyson 35:93c39d260a83 67 dstIp = pHeader->dst;
andrewboyson 10:f0854784e960 68 }
andrewboyson 59:e0e556c8bd46 69 static void writeHeader(struct header * pHeader)
andrewboyson 10:f0854784e960 70 {
andrewboyson 10:f0854784e960 71 uint16_t flagsOffset = offset;
andrewboyson 10:f0854784e960 72 if (dontFragment) flagsOffset |= 0x4000;
andrewboyson 10:f0854784e960 73 if (moreFragments) flagsOffset |= 0x8000;
andrewboyson 10:f0854784e960 74
andrewboyson 10:f0854784e960 75 uint8_t ihl = headerLength >> 2;
andrewboyson 10:f0854784e960 76 pHeader->versionIhl = (version << 4) + ihl;
andrewboyson 10:f0854784e960 77 pHeader->tos = tos;
andrewboyson 10:f0854784e960 78 pHeader->id = NetToHost16(id);
andrewboyson 10:f0854784e960 79 pHeader->flagsOffset = NetToHost16(flagsOffset);
andrewboyson 10:f0854784e960 80 pHeader->ttl = ttl;
andrewboyson 10:f0854784e960 81 pHeader->protocol = protocol;
andrewboyson 10:f0854784e960 82
andrewboyson 35:93c39d260a83 83 pHeader->dst = dstIp;
andrewboyson 35:93c39d260a83 84 pHeader->src = srcIp;
andrewboyson 59:e0e556c8bd46 85 pHeader->length = NetToHost16(totalLength);
andrewboyson 10:f0854784e960 86 pHeader->checksum = 0;
andrewboyson 10:f0854784e960 87 pHeader->checksum = NetCheckSum(headerLength, pHeader);
andrewboyson 10:f0854784e960 88 calcsum = 0;
andrewboyson 10:f0854784e960 89 }
andrewboyson 11:c051adb70c5a 90
andrewboyson 37:793b39683406 91 static void logHeader()
andrewboyson 11:c051adb70c5a 92 {
andrewboyson 43:bc028d5a6424 93 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 94 {
andrewboyson 44:83ce5ace337b 95 Log ("IP4 header\r\n");
andrewboyson 43:bc028d5a6424 96 LogF(" Version %d\r\n", version);
andrewboyson 43:bc028d5a6424 97 LogF(" Header length %d\r\n", headerLength);
andrewboyson 43:bc028d5a6424 98 LogF(" Type of service %d\r\n", tos);
andrewboyson 59:e0e556c8bd46 99 LogF(" Total length %d\r\n", totalLength);
andrewboyson 43:bc028d5a6424 100 LogF(" Identification %d\r\n", id);
andrewboyson 43:bc028d5a6424 101 if (dontFragment) LogF(" Don't fragment\r\n");
andrewboyson 43:bc028d5a6424 102 else LogF(" Do fragment\r\n");
andrewboyson 43:bc028d5a6424 103 if (moreFragments) LogF(" More fragments\r\n");
andrewboyson 43:bc028d5a6424 104 else LogF(" No more fragments\r\n");
andrewboyson 43:bc028d5a6424 105 LogF(" Offset %d\r\n", offset);
andrewboyson 43:bc028d5a6424 106 LogF(" Time to live %d\r\n", ttl);
andrewboyson 47:73af5c0b0dc2 107 LogF(" Protocol "); IpProtocolLog(protocol); Log("\r\n");
andrewboyson 43:bc028d5a6424 108 LogF(" Checksum (hex) %04hX\r\n", checksum);
andrewboyson 43:bc028d5a6424 109 LogF(" Calculated (hex) %04hX\r\n", calcsum);
andrewboyson 47:73af5c0b0dc2 110 LogF(" Source IP "); Ip4AddressLog(srcIp); Log("\r\n");
andrewboyson 47:73af5c0b0dc2 111 LogF(" Destination IP "); Ip4AddressLog(dstIp); Log("\r\n");
andrewboyson 43:bc028d5a6424 112 }
andrewboyson 43:bc028d5a6424 113 else
andrewboyson 43:bc028d5a6424 114 {
andrewboyson 44:83ce5ace337b 115 Log ("IP4 header ");
andrewboyson 47:73af5c0b0dc2 116 IpProtocolLog(protocol);
andrewboyson 43:bc028d5a6424 117 Log(" ");
andrewboyson 47:73af5c0b0dc2 118 Ip4AddressLog(srcIp);
andrewboyson 43:bc028d5a6424 119 Log(" >>> ");
andrewboyson 47:73af5c0b0dc2 120 Ip4AddressLog(dstIp);
andrewboyson 43:bc028d5a6424 121 Log("\r\n");
andrewboyson 43:bc028d5a6424 122 }
andrewboyson 11:c051adb70c5a 123 }
andrewboyson 37:793b39683406 124 static void (*pTraceBack)(void);
andrewboyson 37:793b39683406 125 static void trace()
andrewboyson 10:f0854784e960 126 {
andrewboyson 37:793b39683406 127 pTraceBack();
andrewboyson 37:793b39683406 128 logHeader();
andrewboyson 37:793b39683406 129 }
andrewboyson 59:e0e556c8bd46 130 int Ip4HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* macRemote)
andrewboyson 37:793b39683406 131 {
andrewboyson 37:793b39683406 132 pTraceBack = traceback;
andrewboyson 59:e0e556c8bd46 133 struct header * pHeaderRx = (header*)pPacketRx;
andrewboyson 59:e0e556c8bd46 134 struct header * pHeaderTx = (header*)pPacketTx;
andrewboyson 59:e0e556c8bd46 135
andrewboyson 59:e0e556c8bd46 136 char* pDataRx = (char*)pHeaderRx + headerLength;
andrewboyson 59:e0e556c8bd46 137 char* pDataTx = (char*)pHeaderTx + headerLength;
andrewboyson 59:e0e556c8bd46 138
andrewboyson 59:e0e556c8bd46 139 readHeader(pHeaderRx);
andrewboyson 59:e0e556c8bd46 140 if (totalLength < sizeRx) sizeRx = totalLength;
andrewboyson 59:e0e556c8bd46 141 int dataLengthRx = sizeRx - headerLength;
andrewboyson 59:e0e556c8bd46 142 int dataLengthTx = *pSizeTx - sizeof(header);
andrewboyson 10:f0854784e960 143
andrewboyson 37:793b39683406 144 bool isMe = dstIp == DhcpLocalIp;
andrewboyson 35:93c39d260a83 145 bool isLocalBroadcast = dstIp == DhcpLocalIp | 0xFF000000;
andrewboyson 37:793b39683406 146 bool isBroadcast = dstIp == IP4_BROADCAST_ADDRESS;
andrewboyson 37:793b39683406 147 bool isMulticast = (dstIp & 0xE0) == 0xE0; //224.x.x.x == 1110 0000 == E0.xx.xx.xx == xx.xx.xx.E0 in little endian
andrewboyson 10:f0854784e960 148
andrewboyson 15:6ca6778168b1 149 bool doIt = isMe || isLocalBroadcast || isBroadcast || isMulticast;
andrewboyson 15:6ca6778168b1 150 if (!doIt)
andrewboyson 15:6ca6778168b1 151 {
andrewboyson 48:952dddb74b8b 152 if (Ip4Trace);
andrewboyson 15:6ca6778168b1 153 {
andrewboyson 47:73af5c0b0dc2 154 LogTimeF("IP4 filtered out ip "); Ip4AddressLog(dstIp);
andrewboyson 47:73af5c0b0dc2 155 Log(" from ");
andrewboyson 47:73af5c0b0dc2 156 Ip4AddressLog(srcIp);
andrewboyson 47:73af5c0b0dc2 157 Log("\r\n");
andrewboyson 15:6ca6778168b1 158 }
andrewboyson 15:6ca6778168b1 159 return DO_NOTHING;
andrewboyson 15:6ca6778168b1 160 }
andrewboyson 10:f0854784e960 161
andrewboyson 50:492f2d2954e4 162 if (srcIp)
andrewboyson 50:492f2d2954e4 163 {
andrewboyson 59:e0e556c8bd46 164 Ar4AddIpRecord(trace, macRemote, srcIp);
andrewboyson 50:492f2d2954e4 165 Nr4MakeRequestForNameFromIp(srcIp);
andrewboyson 50:492f2d2954e4 166 }
andrewboyson 59:e0e556c8bd46 167
andrewboyson 10:f0854784e960 168 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 169 switch (protocol)
andrewboyson 10:f0854784e960 170 {
andrewboyson 59:e0e556c8bd46 171 case ICMP: action = Icmp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break;
andrewboyson 59:e0e556c8bd46 172 case IGMP: break;
andrewboyson 59:e0e556c8bd46 173 case UDP: action = Udp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break;
andrewboyson 59:e0e556c8bd46 174 case TCP: action = Tcp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break;
andrewboyson 59:e0e556c8bd46 175 case IP6IN4: break;
andrewboyson 10:f0854784e960 176 default:
andrewboyson 37:793b39683406 177 LogTimeF("IP4 received packet unknown protocol %d\r\n");
andrewboyson 10:f0854784e960 178 return DO_NOTHING;
andrewboyson 10:f0854784e960 179 }
andrewboyson 11:c051adb70c5a 180 if (!action) return DO_NOTHING;
andrewboyson 10:f0854784e960 181
andrewboyson 53:77f8a49adf89 182 if (DhcpIpNeedsToBeRouted(dstIp))
andrewboyson 53:77f8a49adf89 183 {
andrewboyson 59:e0e556c8bd46 184 Ar4IpToMac(DhcpRouter, macRemote); //Send back to the router
andrewboyson 53:77f8a49adf89 185 ttl = OFF_LINK_TTL;
andrewboyson 53:77f8a49adf89 186 }
andrewboyson 53:77f8a49adf89 187 else
andrewboyson 53:77f8a49adf89 188 {
andrewboyson 53:77f8a49adf89 189 ttl = 255;
andrewboyson 53:77f8a49adf89 190 }
andrewboyson 59:e0e556c8bd46 191
andrewboyson 59:e0e556c8bd46 192 totalLength = sizeof(header) + dataLengthTx;
andrewboyson 59:e0e556c8bd46 193 headerLength = sizeof(header);
andrewboyson 59:e0e556c8bd46 194
andrewboyson 59:e0e556c8bd46 195 writeHeader(pHeaderTx);
andrewboyson 53:77f8a49adf89 196
andrewboyson 59:e0e556c8bd46 197 *pSizeTx = totalLength;
andrewboyson 10:f0854784e960 198
andrewboyson 37:793b39683406 199 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 200
andrewboyson 10:f0854784e960 201 return action;
andrewboyson 10:f0854784e960 202 }
andrewboyson 10:f0854784e960 203 int Ip4PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
andrewboyson 59:e0e556c8bd46 204 {
andrewboyson 59:e0e556c8bd46 205 headerLength = sizeof(header);
andrewboyson 59:e0e556c8bd46 206 char* pData = (char*)pPacket + headerLength;
andrewboyson 10:f0854784e960 207 version = 4;
andrewboyson 10:f0854784e960 208 tos = 0;
andrewboyson 10:f0854784e960 209 id = 0;
andrewboyson 10:f0854784e960 210 dontFragment = true;
andrewboyson 10:f0854784e960 211 moreFragments = false;
andrewboyson 10:f0854784e960 212 offset = 0;
andrewboyson 10:f0854784e960 213 protocol = UDP;
andrewboyson 10:f0854784e960 214
andrewboyson 59:e0e556c8bd46 215 int dataLength = *pSize - sizeof(header);
andrewboyson 59:e0e556c8bd46 216
andrewboyson 11:c051adb70c5a 217 int action = DO_NOTHING;
andrewboyson 35:93c39d260a83 218 if (!action) action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp);
andrewboyson 11:c051adb70c5a 219 if (!action) return DO_NOTHING;
andrewboyson 42:222a4f45f916 220 int dest = ActionGetDestPart(action);
andrewboyson 42:222a4f45f916 221 switch (dest)
andrewboyson 11:c051adb70c5a 222 {
andrewboyson 11:c051adb70c5a 223 case UNICAST:
andrewboyson 11:c051adb70c5a 224 case UNICAST_DNS:
andrewboyson 11:c051adb70c5a 225 case UNICAST_DHCP:
andrewboyson 22:914b970356f0 226 case UNICAST_NTP:
andrewboyson 57:e0fb648acf48 227 case UNICAST_TFTP:
andrewboyson 53:77f8a49adf89 228 if (DhcpIpNeedsToBeRouted(dstIp))
andrewboyson 53:77f8a49adf89 229 {
andrewboyson 53:77f8a49adf89 230 Ar4IpToMac(DhcpRouter, pDstMac); //send via router
andrewboyson 53:77f8a49adf89 231 ttl = OFF_LINK_TTL;
andrewboyson 53:77f8a49adf89 232 }
andrewboyson 53:77f8a49adf89 233 else
andrewboyson 53:77f8a49adf89 234 {
andrewboyson 53:77f8a49adf89 235 Ar4IpToMac(dstIp, pDstMac); //Send direct
andrewboyson 53:77f8a49adf89 236 ttl = 255;
andrewboyson 53:77f8a49adf89 237 }
andrewboyson 11:c051adb70c5a 238 break;
andrewboyson 42:222a4f45f916 239 case MULTICAST_NODE:
andrewboyson 42:222a4f45f916 240 case MULTICAST_ROUTER:
andrewboyson 42:222a4f45f916 241 case MULTICAST_MDNS:
andrewboyson 42:222a4f45f916 242 case MULTICAST_LLMNR:
andrewboyson 22:914b970356f0 243 case BROADCAST:
andrewboyson 53:77f8a49adf89 244 ttl = 255;
andrewboyson 22:914b970356f0 245 break;
andrewboyson 22:914b970356f0 246 default:
andrewboyson 42:222a4f45f916 247 LogTimeF("Ip4PollForPacketToSend - undefined destination %d\r\n", dest);
andrewboyson 53:77f8a49adf89 248 return DO_NOTHING;
andrewboyson 11:c051adb70c5a 249 }
andrewboyson 10:f0854784e960 250
andrewboyson 59:e0e556c8bd46 251 struct header* pHeader = (struct header*)pPacket;
andrewboyson 59:e0e556c8bd46 252
andrewboyson 59:e0e556c8bd46 253 totalLength = sizeof(header) + dataLength;
andrewboyson 59:e0e556c8bd46 254 headerLength = sizeof(header);
andrewboyson 59:e0e556c8bd46 255
andrewboyson 59:e0e556c8bd46 256 writeHeader(pHeader);
andrewboyson 10:f0854784e960 257
andrewboyson 59:e0e556c8bd46 258 *pSize = totalLength;
andrewboyson 10:f0854784e960 259
andrewboyson 37:793b39683406 260 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 261
andrewboyson 10:f0854784e960 262 return action;
andrewboyson 10:f0854784e960 263 }