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 May 05 17:44:16 2017 +0000
Revision:
14:e75a59c1123d
Parent:
11:c051adb70c5a
Child:
15:6ca6778168b1
Made IP addresses and ports available to debug messages

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