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:
Sun Apr 16 14:21:55 2017 +0000
Revision:
10:f0854784e960
Child:
11:c051adb70c5a
MDNS and LLMNR now working.

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