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 Oct 26 14:50:24 2017 +0000
Revision:
47:73af5c0b0dc2
Parent:
44:83ce5ace337b
Child:
48:952dddb74b8b
Replaced a number of temporary buffers with direct writes to the Log or HTTP.

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 43:bc028d5a6424 7 #include "ar.h"
andrewboyson 43:bc028d5a6424 8 #include "nr.h"
andrewboyson 43:bc028d5a6424 9 #include "dhcp.h"
andrewboyson 43:bc028d5a6424 10 #include "eth.h"
andrewboyson 43:bc028d5a6424 11 #include "ip.h"
andrewboyson 43:bc028d5a6424 12 #include "ip4.h"
andrewboyson 43:bc028d5a6424 13 #include "ntp.h"
andrewboyson 43:bc028d5a6424 14 #include "mac.h"
andrewboyson 47:73af5c0b0dc2 15 #include "http-reply.h"
andrewboyson 10:f0854784e960 16
andrewboyson 37:793b39683406 17 #define SHOW_FILTERED true
andrewboyson 10:f0854784e960 18
andrewboyson 11:c051adb70c5a 19 #define IP4_BROADCAST_ADDRESS 0xFFFFFFFF
andrewboyson 11:c051adb70c5a 20 #define IP4_MULTICAST_ALL_HOSTS 0x010000E0
andrewboyson 11:c051adb70c5a 21 #define IP4_MULTICAST_ALL_ROUTERS 0x020000E0
andrewboyson 11:c051adb70c5a 22 #define IP4_MULTICAST_DNS_ADDRESS 0xFB0000E0
andrewboyson 11:c051adb70c5a 23 #define IP4_MULTICAST_LLMNR_ADDRESS 0xFC0000E0
andrewboyson 11:c051adb70c5a 24
andrewboyson 14:e75a59c1123d 25 int Ip4AddressToString(uint32_t ip, int size, char* text)
andrewboyson 14:e75a59c1123d 26 {
andrewboyson 14:e75a59c1123d 27 int a0 = (ip & 0xFF000000) >> 24;
andrewboyson 14:e75a59c1123d 28 int a1 = (ip & 0x00FF0000) >> 16;
andrewboyson 14:e75a59c1123d 29 int a2 = (ip & 0x0000FF00) >> 8;
andrewboyson 14:e75a59c1123d 30 int a3 = (ip & 0x000000FF);
andrewboyson 14:e75a59c1123d 31 return snprintf(text, size, "%d.%d.%d.%d", a3, a2, a1, a0);
andrewboyson 14:e75a59c1123d 32 }
andrewboyson 47:73af5c0b0dc2 33 int Ip4AddressLog(uint32_t ip)
andrewboyson 47:73af5c0b0dc2 34 {
andrewboyson 47:73af5c0b0dc2 35 int a0 = (ip & 0xFF000000) >> 24;
andrewboyson 47:73af5c0b0dc2 36 int a1 = (ip & 0x00FF0000) >> 16;
andrewboyson 47:73af5c0b0dc2 37 int a2 = (ip & 0x0000FF00) >> 8;
andrewboyson 47:73af5c0b0dc2 38 int a3 = (ip & 0x000000FF);
andrewboyson 47:73af5c0b0dc2 39 return LogF("%d.%d.%d.%d", a3, a2, a1, a0);
andrewboyson 47:73af5c0b0dc2 40 }
andrewboyson 47:73af5c0b0dc2 41 int Ip4AddressHttp(uint32_t ip)
andrewboyson 47:73af5c0b0dc2 42 {
andrewboyson 47:73af5c0b0dc2 43 int a0 = (ip & 0xFF000000) >> 24;
andrewboyson 47:73af5c0b0dc2 44 int a1 = (ip & 0x00FF0000) >> 16;
andrewboyson 47:73af5c0b0dc2 45 int a2 = (ip & 0x0000FF00) >> 8;
andrewboyson 47:73af5c0b0dc2 46 int a3 = (ip & 0x000000FF);
andrewboyson 47:73af5c0b0dc2 47 return HttpReplyAddF("%d.%d.%d.%d", a3, a2, a1, a0);
andrewboyson 47:73af5c0b0dc2 48 }
andrewboyson 14:e75a59c1123d 49
andrewboyson 18:accfcb80d9c3 50 uint32_t Ip4Parse(char* text)
andrewboyson 18:accfcb80d9c3 51 {
andrewboyson 18:accfcb80d9c3 52 int ints[4];
andrewboyson 18:accfcb80d9c3 53 sscanf(text, "%d.%d.%d.%d", &ints[3], &ints[2], &ints[1], &ints[0]);
andrewboyson 18:accfcb80d9c3 54 return (ints[0] << 24) + (ints[1] << 16) + (ints[2] << 8) + ints[3];
andrewboyson 18:accfcb80d9c3 55 }
andrewboyson 18:accfcb80d9c3 56
andrewboyson 47:73af5c0b0dc2 57 void Ip4DstIpFromDest(int dest, uint32_t* pDstIp)
andrewboyson 11:c051adb70c5a 58 {
andrewboyson 37:793b39683406 59 switch (dest)
andrewboyson 11:c051adb70c5a 60 {
andrewboyson 11:c051adb70c5a 61 case UNICAST: break;
andrewboyson 11:c051adb70c5a 62 case UNICAST_DNS: *pDstIp = DhcpDnsServer; break;
andrewboyson 11:c051adb70c5a 63 case UNICAST_DHCP: *pDstIp = DhcpServer; break;
andrewboyson 22:914b970356f0 64 case UNICAST_NTP: *pDstIp = NtpServerIp4; break;
andrewboyson 11:c051adb70c5a 65 case MULTICAST_NODE: *pDstIp = IP4_MULTICAST_ALL_HOSTS; break;
andrewboyson 11:c051adb70c5a 66 case MULTICAST_ROUTER: *pDstIp = IP4_MULTICAST_ALL_ROUTERS; break;
andrewboyson 11:c051adb70c5a 67 case MULTICAST_MDNS: *pDstIp = IP4_MULTICAST_DNS_ADDRESS; break;
andrewboyson 11:c051adb70c5a 68 case MULTICAST_LLMNR: *pDstIp = IP4_MULTICAST_LLMNR_ADDRESS; break;
andrewboyson 11:c051adb70c5a 69 case BROADCAST: *pDstIp = IP4_BROADCAST_ADDRESS; break;
andrewboyson 11:c051adb70c5a 70 default:
andrewboyson 37:793b39683406 71 LogTimeF("Ip4DestIpFromDest unknown destination %d\r\n", dest);
andrewboyson 11:c051adb70c5a 72 break;
andrewboyson 11:c051adb70c5a 73 }
andrewboyson 11:c051adb70c5a 74 }
andrewboyson 11:c051adb70c5a 75
andrewboyson 10:f0854784e960 76 #define HEADER_LENGTH 20
andrewboyson 10:f0854784e960 77
andrewboyson 10:f0854784e960 78 __packed struct header
andrewboyson 10:f0854784e960 79 {
andrewboyson 10:f0854784e960 80 uint8_t versionIhl;
andrewboyson 10:f0854784e960 81 uint8_t tos;
andrewboyson 10:f0854784e960 82 uint16_t length;
andrewboyson 10:f0854784e960 83 uint16_t id;
andrewboyson 10:f0854784e960 84 uint16_t flagsOffset;
andrewboyson 10:f0854784e960 85 uint8_t ttl;
andrewboyson 10:f0854784e960 86 uint8_t protocol;
andrewboyson 10:f0854784e960 87 uint16_t checksum;
andrewboyson 10:f0854784e960 88 uint32_t src;
andrewboyson 10:f0854784e960 89 uint32_t dst;
andrewboyson 10:f0854784e960 90 };
andrewboyson 10:f0854784e960 91
andrewboyson 10:f0854784e960 92 //Header variables
andrewboyson 10:f0854784e960 93 static uint8_t version;
andrewboyson 10:f0854784e960 94 static int headerLength;
andrewboyson 10:f0854784e960 95 static uint8_t tos;
andrewboyson 10:f0854784e960 96 static uint16_t id;
andrewboyson 10:f0854784e960 97 static bool dontFragment;
andrewboyson 10:f0854784e960 98 static bool moreFragments;
andrewboyson 10:f0854784e960 99 static uint16_t offset;
andrewboyson 10:f0854784e960 100 static uint8_t ttl;
andrewboyson 10:f0854784e960 101 static uint8_t protocol;
andrewboyson 10:f0854784e960 102 static uint16_t checksum;
andrewboyson 10:f0854784e960 103 static uint16_t calcsum;
andrewboyson 35:93c39d260a83 104 static uint32_t srcIp;
andrewboyson 35:93c39d260a83 105 static uint32_t dstIp;
andrewboyson 10:f0854784e960 106 static void* pData;
andrewboyson 10:f0854784e960 107 static int dataLength;
andrewboyson 10:f0854784e960 108
andrewboyson 10:f0854784e960 109 void readHeader(struct header * pHeader)
andrewboyson 10:f0854784e960 110 {
andrewboyson 10:f0854784e960 111 version = pHeader->versionIhl >> 4;
andrewboyson 10:f0854784e960 112 uint8_t ihl = pHeader->versionIhl & 0xF;
andrewboyson 10:f0854784e960 113 headerLength = ihl * 4;
andrewboyson 10:f0854784e960 114 tos = pHeader->tos;
andrewboyson 10:f0854784e960 115 uint16_t totalLength = NetToHost16(pHeader->length);
andrewboyson 10:f0854784e960 116 id = NetToHost16(pHeader->id);
andrewboyson 10:f0854784e960 117 uint16_t flagsOffset = NetToHost16(pHeader->flagsOffset);
andrewboyson 10:f0854784e960 118 dontFragment = flagsOffset & 0x4000;
andrewboyson 10:f0854784e960 119 moreFragments = flagsOffset & 0x8000;
andrewboyson 10:f0854784e960 120 offset = flagsOffset & 0x1FFF;
andrewboyson 10:f0854784e960 121 ttl = pHeader->ttl;
andrewboyson 10:f0854784e960 122 protocol = pHeader->protocol;
andrewboyson 10:f0854784e960 123 checksum = NetToHost16(pHeader->checksum);
andrewboyson 10:f0854784e960 124 calcsum = NetCheckSum(headerLength, pHeader);
andrewboyson 35:93c39d260a83 125 srcIp = pHeader->src;
andrewboyson 35:93c39d260a83 126 dstIp = pHeader->dst;
andrewboyson 10:f0854784e960 127 pData = (char*)pHeader + headerLength;
andrewboyson 10:f0854784e960 128 dataLength = totalLength - headerLength;
andrewboyson 10:f0854784e960 129 }
andrewboyson 10:f0854784e960 130 void writeHeader(struct header * pHeader)
andrewboyson 10:f0854784e960 131 {
andrewboyson 10:f0854784e960 132 uint16_t flagsOffset = offset;
andrewboyson 10:f0854784e960 133 if (dontFragment) flagsOffset |= 0x4000;
andrewboyson 10:f0854784e960 134 if (moreFragments) flagsOffset |= 0x8000;
andrewboyson 10:f0854784e960 135
andrewboyson 10:f0854784e960 136 uint8_t ihl = headerLength >> 2;
andrewboyson 10:f0854784e960 137 pHeader->versionIhl = (version << 4) + ihl;
andrewboyson 10:f0854784e960 138 pHeader->tos = tos;
andrewboyson 10:f0854784e960 139 pHeader->id = NetToHost16(id);
andrewboyson 10:f0854784e960 140 pHeader->flagsOffset = NetToHost16(flagsOffset);
andrewboyson 10:f0854784e960 141 pHeader->ttl = ttl;
andrewboyson 10:f0854784e960 142 pHeader->protocol = protocol;
andrewboyson 10:f0854784e960 143
andrewboyson 35:93c39d260a83 144 pHeader->dst = dstIp;
andrewboyson 35:93c39d260a83 145 pHeader->src = srcIp;
andrewboyson 10:f0854784e960 146 pHeader->length = NetToHost16(headerLength + dataLength);
andrewboyson 10:f0854784e960 147 pHeader->checksum = 0;
andrewboyson 10:f0854784e960 148 pHeader->checksum = NetCheckSum(headerLength, pHeader);
andrewboyson 10:f0854784e960 149 calcsum = 0;
andrewboyson 10:f0854784e960 150 }
andrewboyson 11:c051adb70c5a 151
andrewboyson 37:793b39683406 152 static void logHeader()
andrewboyson 11:c051adb70c5a 153 {
andrewboyson 43:bc028d5a6424 154 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 155 {
andrewboyson 44:83ce5ace337b 156 Log ("IP4 header\r\n");
andrewboyson 43:bc028d5a6424 157 LogF(" Version %d\r\n", version);
andrewboyson 43:bc028d5a6424 158 LogF(" Header length %d\r\n", headerLength);
andrewboyson 43:bc028d5a6424 159 LogF(" Type of service %d\r\n", tos);
andrewboyson 43:bc028d5a6424 160 LogF(" Data length %d\r\n", dataLength);
andrewboyson 43:bc028d5a6424 161 LogF(" Identification %d\r\n", id);
andrewboyson 43:bc028d5a6424 162 if (dontFragment) LogF(" Don't fragment\r\n");
andrewboyson 43:bc028d5a6424 163 else LogF(" Do fragment\r\n");
andrewboyson 43:bc028d5a6424 164 if (moreFragments) LogF(" More fragments\r\n");
andrewboyson 43:bc028d5a6424 165 else LogF(" No more fragments\r\n");
andrewboyson 43:bc028d5a6424 166 LogF(" Offset %d\r\n", offset);
andrewboyson 43:bc028d5a6424 167 LogF(" Time to live %d\r\n", ttl);
andrewboyson 47:73af5c0b0dc2 168 LogF(" Protocol "); IpProtocolLog(protocol); Log("\r\n");
andrewboyson 43:bc028d5a6424 169 LogF(" Checksum (hex) %04hX\r\n", checksum);
andrewboyson 43:bc028d5a6424 170 LogF(" Calculated (hex) %04hX\r\n", calcsum);
andrewboyson 47:73af5c0b0dc2 171 LogF(" Source IP "); Ip4AddressLog(srcIp); Log("\r\n");
andrewboyson 47:73af5c0b0dc2 172 LogF(" Destination IP "); Ip4AddressLog(dstIp); Log("\r\n");
andrewboyson 43:bc028d5a6424 173 }
andrewboyson 43:bc028d5a6424 174 else
andrewboyson 43:bc028d5a6424 175 {
andrewboyson 44:83ce5ace337b 176 Log ("IP4 header ");
andrewboyson 47:73af5c0b0dc2 177 IpProtocolLog(protocol);
andrewboyson 43:bc028d5a6424 178 Log(" ");
andrewboyson 47:73af5c0b0dc2 179 Ip4AddressLog(srcIp);
andrewboyson 43:bc028d5a6424 180 Log(" >>> ");
andrewboyson 47:73af5c0b0dc2 181 Ip4AddressLog(dstIp);
andrewboyson 43:bc028d5a6424 182 Log("\r\n");
andrewboyson 43:bc028d5a6424 183 }
andrewboyson 11:c051adb70c5a 184 }
andrewboyson 37:793b39683406 185 static void (*pTraceBack)(void);
andrewboyson 37:793b39683406 186 static void trace()
andrewboyson 10:f0854784e960 187 {
andrewboyson 37:793b39683406 188 pTraceBack();
andrewboyson 37:793b39683406 189 logHeader();
andrewboyson 37:793b39683406 190 }
andrewboyson 37:793b39683406 191 int Ip4HandleReceivedPacket(void (*traceback)(void), char* pSrcMac, void* pPacket, int* pSize, char* pDstMac)
andrewboyson 37:793b39683406 192 {
andrewboyson 37:793b39683406 193 pTraceBack = traceback;
andrewboyson 10:f0854784e960 194 struct header * pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 195 readHeader(pHeader);
andrewboyson 10:f0854784e960 196
andrewboyson 37:793b39683406 197 bool isMe = dstIp == DhcpLocalIp;
andrewboyson 35:93c39d260a83 198 bool isLocalBroadcast = dstIp == DhcpLocalIp | 0xFF000000;
andrewboyson 37:793b39683406 199 bool isBroadcast = dstIp == IP4_BROADCAST_ADDRESS;
andrewboyson 37:793b39683406 200 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 201
andrewboyson 15:6ca6778168b1 202 bool doIt = isMe || isLocalBroadcast || isBroadcast || isMulticast;
andrewboyson 15:6ca6778168b1 203 if (!doIt)
andrewboyson 15:6ca6778168b1 204 {
andrewboyson 37:793b39683406 205 if (SHOW_FILTERED)
andrewboyson 15:6ca6778168b1 206 {
andrewboyson 47:73af5c0b0dc2 207 LogTimeF("IP4 filtered out ip "); Ip4AddressLog(dstIp);
andrewboyson 47:73af5c0b0dc2 208 Log(" from ");
andrewboyson 47:73af5c0b0dc2 209 Ip4AddressLog(srcIp);
andrewboyson 47:73af5c0b0dc2 210 Log("\r\n");
andrewboyson 15:6ca6778168b1 211 }
andrewboyson 15:6ca6778168b1 212 return DO_NOTHING;
andrewboyson 15:6ca6778168b1 213 }
andrewboyson 10:f0854784e960 214
andrewboyson 35:93c39d260a83 215 ArAddIp4Record(pSrcMac, srcIp);
andrewboyson 35:93c39d260a83 216 NrMakeRequestForNameFromIp4(srcIp);
andrewboyson 10:f0854784e960 217
andrewboyson 10:f0854784e960 218 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 219 switch (protocol)
andrewboyson 10:f0854784e960 220 {
andrewboyson 43:bc028d5a6424 221 case ICMP: action = Icmp4HandleReceivedPacket(trace, &srcIp, &dstIp, &dataLength, pData); break;
andrewboyson 44:83ce5ace337b 222 case IGMP: break;
andrewboyson 43:bc028d5a6424 223 case UDP: action = Udp4HandleReceivedPacket(trace, &srcIp, &dstIp, &dataLength, pData); break;
andrewboyson 43:bc028d5a6424 224 case TCP: action = Tcp4HandleReceivedPacket(trace, &srcIp, &dstIp, &dataLength, pData); break;
andrewboyson 44:83ce5ace337b 225 case IP6IN4: break;
andrewboyson 10:f0854784e960 226 default:
andrewboyson 37:793b39683406 227 LogTimeF("IP4 received packet unknown protocol %d\r\n");
andrewboyson 10:f0854784e960 228 return DO_NOTHING;
andrewboyson 10:f0854784e960 229 }
andrewboyson 11:c051adb70c5a 230 if (!action) return DO_NOTHING;
andrewboyson 10:f0854784e960 231
andrewboyson 44:83ce5ace337b 232 if (DhcpIpNeedsToBeRouted(dstIp)) ArIpToMac4(DhcpRouter, pDstMac); //Send back to the router
andrewboyson 44:83ce5ace337b 233 else MacCopy(pDstMac, pSrcMac); //Send back to the source
andrewboyson 37:793b39683406 234
andrewboyson 10:f0854784e960 235 writeHeader(pHeader);
andrewboyson 10:f0854784e960 236
andrewboyson 10:f0854784e960 237 *pSize = headerLength + dataLength;
andrewboyson 10:f0854784e960 238
andrewboyson 37:793b39683406 239 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 240
andrewboyson 10:f0854784e960 241 return action;
andrewboyson 10:f0854784e960 242 }
andrewboyson 10:f0854784e960 243 int Ip4PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
andrewboyson 10:f0854784e960 244 {
andrewboyson 11:c051adb70c5a 245 headerLength = HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 246 pData = (char*)pPacket + headerLength;
andrewboyson 11:c051adb70c5a 247 dataLength = 0;
andrewboyson 10:f0854784e960 248 version = 4;
andrewboyson 10:f0854784e960 249 tos = 0;
andrewboyson 10:f0854784e960 250 id = 0;
andrewboyson 10:f0854784e960 251 dontFragment = true;
andrewboyson 10:f0854784e960 252 moreFragments = false;
andrewboyson 10:f0854784e960 253 offset = 0;
andrewboyson 10:f0854784e960 254 ttl = 255;
andrewboyson 10:f0854784e960 255 protocol = UDP;
andrewboyson 10:f0854784e960 256
andrewboyson 11:c051adb70c5a 257 int action = DO_NOTHING;
andrewboyson 35:93c39d260a83 258 if (!action) action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp);
andrewboyson 11:c051adb70c5a 259 if (!action) return DO_NOTHING;
andrewboyson 42:222a4f45f916 260 int dest = ActionGetDestPart(action);
andrewboyson 42:222a4f45f916 261 switch (dest)
andrewboyson 11:c051adb70c5a 262 {
andrewboyson 11:c051adb70c5a 263 case UNICAST:
andrewboyson 11:c051adb70c5a 264 case UNICAST_DNS:
andrewboyson 11:c051adb70c5a 265 case UNICAST_DHCP:
andrewboyson 22:914b970356f0 266 case UNICAST_NTP:
andrewboyson 44:83ce5ace337b 267 if (DhcpIpNeedsToBeRouted(dstIp)) ArIpToMac4(DhcpRouter, pDstMac); //send via router
andrewboyson 44:83ce5ace337b 268 else ArIpToMac4(dstIp, pDstMac); //Send direct
andrewboyson 11:c051adb70c5a 269 break;
andrewboyson 42:222a4f45f916 270 case MULTICAST_NODE:
andrewboyson 42:222a4f45f916 271 case MULTICAST_ROUTER:
andrewboyson 42:222a4f45f916 272 case MULTICAST_MDNS:
andrewboyson 42:222a4f45f916 273 case MULTICAST_LLMNR:
andrewboyson 22:914b970356f0 274 case BROADCAST:
andrewboyson 22:914b970356f0 275 break;
andrewboyson 22:914b970356f0 276 default:
andrewboyson 42:222a4f45f916 277 LogTimeF("Ip4PollForPacketToSend - undefined destination %d\r\n", dest);
andrewboyson 22:914b970356f0 278 break;
andrewboyson 11:c051adb70c5a 279 }
andrewboyson 10:f0854784e960 280
andrewboyson 11:c051adb70c5a 281 writeHeader((header*)pPacket);
andrewboyson 10:f0854784e960 282
andrewboyson 10:f0854784e960 283 *pSize = headerLength + dataLength;
andrewboyson 10:f0854784e960 284
andrewboyson 37:793b39683406 285 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 286
andrewboyson 10:f0854784e960 287 return action;
andrewboyson 10:f0854784e960 288 }