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:
Fri Sep 22 13:55:56 2017 +0000
Revision:
35:93c39d260a83
Parent:
33:714a0345e59b
Child:
36:900e24b27bfb
Added name resolution and address resolution

Who changed what in which revision?

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