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 May 20 14:32:52 2021 +0000
Revision:
200:5acbc41bf469
Parent:
195:bd5b123143ca
Increased number of arp entries from 20 to 30 to accommodate the number of WIZ devices plus a few incoming port 80 calls from the internet.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 136:8a65abb0dc63 1
andrewboyson 61:aad055f1b0d1 2 #include <stdint.h>
andrewboyson 61:aad055f1b0d1 3 #include <stdbool.h>
andrewboyson 61:aad055f1b0d1 4
andrewboyson 43:bc028d5a6424 5 #include "log.h"
andrewboyson 43:bc028d5a6424 6 #include "net.h"
andrewboyson 43:bc028d5a6424 7 #include "action.h"
andrewboyson 43:bc028d5a6424 8 #include "icmp4.h"
andrewboyson 10:f0854784e960 9 #include "udptcp4.h"
andrewboyson 48:952dddb74b8b 10 #include "ar4.h"
andrewboyson 172:9bc3c7b2cca1 11 #include "nr.h"
andrewboyson 43:bc028d5a6424 12 #include "dhcp.h"
andrewboyson 43:bc028d5a6424 13 #include "eth.h"
andrewboyson 43:bc028d5a6424 14 #include "ip.h"
andrewboyson 49:1a6336f2b3f9 15 #include "ip4addr.h"
andrewboyson 136:8a65abb0dc63 16 #include "ip4hdr.h"
andrewboyson 43:bc028d5a6424 17 #include "ntp.h"
andrewboyson 43:bc028d5a6424 18 #include "mac.h"
andrewboyson 142:a8c0890a58d1 19 #include "restart.h"
andrewboyson 136:8a65abb0dc63 20 #include "checksum.h"
andrewboyson 10:f0854784e960 21
andrewboyson 195:bd5b123143ca 22 bool Ip4Trace = true;
andrewboyson 195:bd5b123143ca 23 uint32_t Ip4Remote = 0;
andrewboyson 10:f0854784e960 24
andrewboyson 53:77f8a49adf89 25 #define OFF_LINK_TTL 64
andrewboyson 53:77f8a49adf89 26
andrewboyson 136:8a65abb0dc63 27 static void logHeader(char* pPacket)
andrewboyson 11:c051adb70c5a 28 {
andrewboyson 43:bc028d5a6424 29 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 30 {
andrewboyson 44:83ce5ace337b 31 Log ("IP4 header\r\n");
andrewboyson 136:8a65abb0dc63 32 LogF(" Version %d\r\n", Ip4HdrGetVersion (pPacket));
andrewboyson 136:8a65abb0dc63 33 int headerLength = Ip4HdrGetHeaderLen (pPacket);
andrewboyson 43:bc028d5a6424 34 LogF(" Header length %d\r\n", headerLength);
andrewboyson 136:8a65abb0dc63 35 LogF(" Type of service %d\r\n", Ip4HdrGetTos (pPacket));
andrewboyson 136:8a65abb0dc63 36 LogF(" Total length %d\r\n", Ip4HdrGetLength (pPacket));
andrewboyson 136:8a65abb0dc63 37 LogF(" Identification %d\r\n", Ip4HdrGetId (pPacket));
andrewboyson 136:8a65abb0dc63 38 if (Ip4HdrGetDontFrag(pPacket)) LogF(" Don't fragment\r\n");
andrewboyson 136:8a65abb0dc63 39 else LogF(" Do fragment\r\n");
andrewboyson 136:8a65abb0dc63 40 if (Ip4HdrGetMoreFrags(pPacket)) LogF(" More fragments\r\n");
andrewboyson 136:8a65abb0dc63 41 else LogF(" No more fragments\r\n");
andrewboyson 136:8a65abb0dc63 42 LogF(" Frag offset %d\r\n", Ip4HdrGetFragOffset(pPacket));
andrewboyson 136:8a65abb0dc63 43 LogF(" Time to live %d\r\n", Ip4HdrGetTtl (pPacket));
andrewboyson 136:8a65abb0dc63 44 LogF(" Protocol "); IpProtocolLog(Ip4HdrGetProtocol(pPacket)); Log("\r\n");
andrewboyson 136:8a65abb0dc63 45 LogF(" Checksum (hex) %04hX\r\n", Ip4HdrGetChecksum(pPacket));
andrewboyson 136:8a65abb0dc63 46 LogF(" Calculated (hex) %04hX\r\n", CheckSum(headerLength, pPacket));
andrewboyson 187:122fc1996c86 47 LogF(" Source IP "); Ip4AddrLog(Ip4HdrGetSrc(pPacket)); Log("\r\n");
andrewboyson 187:122fc1996c86 48 LogF(" Destination IP "); Ip4AddrLog(Ip4HdrGetDst(pPacket)); Log("\r\n");
andrewboyson 43:bc028d5a6424 49 }
andrewboyson 43:bc028d5a6424 50 else
andrewboyson 43:bc028d5a6424 51 {
andrewboyson 44:83ce5ace337b 52 Log ("IP4 header ");
andrewboyson 136:8a65abb0dc63 53 IpProtocolLog(Ip4HdrGetProtocol(pPacket));
andrewboyson 43:bc028d5a6424 54 Log(" ");
andrewboyson 187:122fc1996c86 55 Ip4AddrLog(Ip4HdrGetSrc(pPacket));
andrewboyson 43:bc028d5a6424 56 Log(" >>> ");
andrewboyson 187:122fc1996c86 57 Ip4AddrLog(Ip4HdrGetDst(pPacket));
andrewboyson 43:bc028d5a6424 58 Log("\r\n");
andrewboyson 43:bc028d5a6424 59 }
andrewboyson 11:c051adb70c5a 60 }
andrewboyson 136:8a65abb0dc63 61 static void makeHeader(char* pPacket, uint16_t totalLength, uint8_t ttl, uint8_t protocol, uint32_t srcIp, uint32_t dstIp)
andrewboyson 136:8a65abb0dc63 62 {
andrewboyson 136:8a65abb0dc63 63 static uint16_t id = 0;
andrewboyson 136:8a65abb0dc63 64 Ip4HdrSetVersion (pPacket, 4 );
andrewboyson 136:8a65abb0dc63 65 Ip4HdrSetHeaderLen(pPacket, IP4_HEADER_LENGTH);
andrewboyson 136:8a65abb0dc63 66 Ip4HdrSetTos (pPacket, 0 );
andrewboyson 136:8a65abb0dc63 67 Ip4HdrSetLength (pPacket, totalLength );
andrewboyson 136:8a65abb0dc63 68 Ip4HdrSetId (pPacket, id++ ); //Used by the recipient for collating packets fragmented in transit; unique per packet sent
andrewboyson 136:8a65abb0dc63 69 Ip4HdrSetFragInfo (pPacket, 0 ); //No flags and no offset
andrewboyson 136:8a65abb0dc63 70 Ip4HdrSetTtl (pPacket, ttl );
andrewboyson 136:8a65abb0dc63 71 Ip4HdrSetProtocol (pPacket, protocol );
andrewboyson 136:8a65abb0dc63 72 Ip4HdrSetSrc (pPacket, srcIp );
andrewboyson 136:8a65abb0dc63 73 Ip4HdrSetDst (pPacket, dstIp );
andrewboyson 136:8a65abb0dc63 74 Ip4HdrSetChecksum (pPacket, 0 );
andrewboyson 136:8a65abb0dc63 75 uint16_t checksum = CheckSum(IP4_HEADER_LENGTH, pPacket);
andrewboyson 136:8a65abb0dc63 76 Ip4HdrSetChecksum (pPacket, checksum );
andrewboyson 136:8a65abb0dc63 77 }
andrewboyson 136:8a65abb0dc63 78 static char* traceHeader;
andrewboyson 37:793b39683406 79 static void (*pTraceBack)(void);
andrewboyson 37:793b39683406 80 static void trace()
andrewboyson 10:f0854784e960 81 {
andrewboyson 37:793b39683406 82 pTraceBack();
andrewboyson 136:8a65abb0dc63 83 logHeader(traceHeader);
andrewboyson 37:793b39683406 84 }
andrewboyson 136:8a65abb0dc63 85
andrewboyson 136:8a65abb0dc63 86 int Ip4HandleReceivedPacket(void (*traceback)(void), char* pPacketRx, int sizeRx, char* pPacketTx, int* pSizeTx, char* macRemote)
andrewboyson 37:793b39683406 87 {
andrewboyson 142:a8c0890a58d1 88 int lastRestartPoint = RestartPoint;
andrewboyson 142:a8c0890a58d1 89 RestartPoint = FAULT_POINT_Ip4HandleReceivedPacket;
andrewboyson 136:8a65abb0dc63 90
andrewboyson 136:8a65abb0dc63 91 traceHeader = pPacketRx;
andrewboyson 37:793b39683406 92 pTraceBack = traceback;
andrewboyson 136:8a65abb0dc63 93
andrewboyson 136:8a65abb0dc63 94 int headerLengthRx = Ip4HdrGetHeaderLen(pPacketRx);
andrewboyson 136:8a65abb0dc63 95 uint16_t totalLengthRx = Ip4HdrGetLength (pPacketRx);
andrewboyson 136:8a65abb0dc63 96 uint8_t protocol = Ip4HdrGetProtocol (pPacketRx);
andrewboyson 136:8a65abb0dc63 97 uint32_t srcIp = Ip4HdrGetSrc (pPacketRx);
andrewboyson 136:8a65abb0dc63 98 uint32_t dstIp = Ip4HdrGetDst (pPacketRx);
andrewboyson 59:e0e556c8bd46 99
andrewboyson 195:bd5b123143ca 100 Ip4Remote = srcIp;
andrewboyson 195:bd5b123143ca 101
andrewboyson 136:8a65abb0dc63 102 char* pDataRx = pPacketRx + headerLengthRx;
andrewboyson 136:8a65abb0dc63 103 char* pDataTx = pPacketTx + IP4_HEADER_LENGTH;
andrewboyson 136:8a65abb0dc63 104
andrewboyson 136:8a65abb0dc63 105 if (sizeRx > totalLengthRx) sizeRx = totalLengthRx;
andrewboyson 136:8a65abb0dc63 106 int dataLengthRx = sizeRx - headerLengthRx;
andrewboyson 136:8a65abb0dc63 107 int dataLengthTx = *pSizeTx - IP4_HEADER_LENGTH;
andrewboyson 136:8a65abb0dc63 108
andrewboyson 61:aad055f1b0d1 109 bool isMe = dstIp == DhcpLocalIp;
andrewboyson 61:aad055f1b0d1 110 bool isLocalBroadcast = dstIp == (DhcpLocalIp | 0xFF000000); // dstIp == 192.168.1.255; '|' is lower precendence than '=='
andrewboyson 61:aad055f1b0d1 111 bool isBroadcast = dstIp == IP4_BROADCAST_ADDRESS; // dstIp == 255.255.255.255
andrewboyson 136:8a65abb0dc63 112 bool isMulticast = (dstIp & 0xE0) == 0xE0; // 224.x.x.x == 1110 0000 == E0.xx.xx.xx == xx.xx.xx.E0 in little endian
andrewboyson 136:8a65abb0dc63 113
andrewboyson 15:6ca6778168b1 114 bool doIt = isMe || isLocalBroadcast || isBroadcast || isMulticast;
andrewboyson 15:6ca6778168b1 115 if (!doIt)
andrewboyson 15:6ca6778168b1 116 {
andrewboyson 160:6a1d1d368f80 117 if (Ip4Trace)
andrewboyson 15:6ca6778168b1 118 {
andrewboyson 187:122fc1996c86 119 LogTimeF("IP4 filtered out ip "); Ip4AddrLog(dstIp);
andrewboyson 47:73af5c0b0dc2 120 Log(" from ");
andrewboyson 187:122fc1996c86 121 Ip4AddrLog(srcIp);
andrewboyson 47:73af5c0b0dc2 122 Log("\r\n");
andrewboyson 15:6ca6778168b1 123 }
andrewboyson 142:a8c0890a58d1 124 RestartPoint = lastRestartPoint;
andrewboyson 15:6ca6778168b1 125 return DO_NOTHING;
andrewboyson 15:6ca6778168b1 126 }
andrewboyson 136:8a65abb0dc63 127
andrewboyson 74:c3756bfa960e 128 int remArIndex = Ar4AddIpRecord(trace, macRemote, srcIp);
andrewboyson 172:9bc3c7b2cca1 129 NrMakeRequestForNameFromAddress4(srcIp);
andrewboyson 136:8a65abb0dc63 130
andrewboyson 10:f0854784e960 131 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 132 switch (protocol)
andrewboyson 10:f0854784e960 133 {
andrewboyson 97:d91f7db00235 134 case ICMP: action = Icmp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break;
andrewboyson 97:d91f7db00235 135 case IGMP: break;
andrewboyson 97:d91f7db00235 136 case UDP: action = Udp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break;
andrewboyson 74:c3756bfa960e 137 case TCP: action = Tcp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp, remArIndex); break;
andrewboyson 97:d91f7db00235 138 case IP6IN4: break;
andrewboyson 10:f0854784e960 139 default:
andrewboyson 136:8a65abb0dc63 140 LogTimeF("IP4 received packet unknown protocol %d\r\n", protocol);
andrewboyson 142:a8c0890a58d1 141 RestartPoint = lastRestartPoint;
andrewboyson 10:f0854784e960 142 return DO_NOTHING;
andrewboyson 10:f0854784e960 143 }
andrewboyson 86:55bc5ddac16c 144 if (!action)
andrewboyson 86:55bc5ddac16c 145 {
andrewboyson 142:a8c0890a58d1 146 RestartPoint = lastRestartPoint;
andrewboyson 86:55bc5ddac16c 147 return DO_NOTHING;
andrewboyson 86:55bc5ddac16c 148 }
andrewboyson 136:8a65abb0dc63 149
andrewboyson 136:8a65abb0dc63 150 uint8_t ttl = 0;
andrewboyson 53:77f8a49adf89 151 if (DhcpIpNeedsToBeRouted(dstIp))
andrewboyson 53:77f8a49adf89 152 {
andrewboyson 116:60521b29e4c9 153 Ar4IpToMac(DhcpRouterIp, macRemote); //Send back to the router
andrewboyson 53:77f8a49adf89 154 ttl = OFF_LINK_TTL;
andrewboyson 53:77f8a49adf89 155 }
andrewboyson 53:77f8a49adf89 156 else
andrewboyson 53:77f8a49adf89 157 {
andrewboyson 53:77f8a49adf89 158 ttl = 255;
andrewboyson 53:77f8a49adf89 159 }
andrewboyson 59:e0e556c8bd46 160
andrewboyson 136:8a65abb0dc63 161 *pSizeTx = IP4_HEADER_LENGTH + dataLengthTx;
andrewboyson 53:77f8a49adf89 162
andrewboyson 136:8a65abb0dc63 163 makeHeader(pPacketTx, *pSizeTx, ttl, protocol, srcIp, dstIp);
andrewboyson 10:f0854784e960 164
andrewboyson 136:8a65abb0dc63 165 if (ActionGetTracePart(action)) logHeader(pPacketTx);
andrewboyson 37:793b39683406 166
andrewboyson 142:a8c0890a58d1 167 RestartPoint = lastRestartPoint;
andrewboyson 10:f0854784e960 168 return action;
andrewboyson 10:f0854784e960 169 }
andrewboyson 136:8a65abb0dc63 170 int Ip4PollForPacketToSend(char* pPacket, int* pSize, char* pDstMac)
andrewboyson 136:8a65abb0dc63 171 {
andrewboyson 136:8a65abb0dc63 172 char* pData = pPacket + IP4_HEADER_LENGTH;
andrewboyson 136:8a65abb0dc63 173 int dataLength = *pSize - IP4_HEADER_LENGTH;
andrewboyson 136:8a65abb0dc63 174
andrewboyson 136:8a65abb0dc63 175 uint8_t protocol = 0;
andrewboyson 136:8a65abb0dc63 176 uint32_t srcIp = 0;
andrewboyson 136:8a65abb0dc63 177 uint32_t dstIp = 0;
andrewboyson 136:8a65abb0dc63 178 int action = DO_NOTHING;
andrewboyson 71:736a5747ade1 179 if (!action) { action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp); protocol = UDP; }
andrewboyson 71:736a5747ade1 180 if (!action) { action = Tcp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp); protocol = TCP; }
andrewboyson 11:c051adb70c5a 181 if (!action) return DO_NOTHING;
andrewboyson 42:222a4f45f916 182 int dest = ActionGetDestPart(action);
andrewboyson 136:8a65abb0dc63 183 uint8_t ttl = 0;
andrewboyson 42:222a4f45f916 184 switch (dest)
andrewboyson 11:c051adb70c5a 185 {
andrewboyson 11:c051adb70c5a 186 case UNICAST:
andrewboyson 11:c051adb70c5a 187 case UNICAST_DNS:
andrewboyson 11:c051adb70c5a 188 case UNICAST_DHCP:
andrewboyson 22:914b970356f0 189 case UNICAST_NTP:
andrewboyson 57:e0fb648acf48 190 case UNICAST_TFTP:
andrewboyson 195:bd5b123143ca 191 case UNICAST_USER:
andrewboyson 53:77f8a49adf89 192 if (DhcpIpNeedsToBeRouted(dstIp))
andrewboyson 53:77f8a49adf89 193 {
andrewboyson 116:60521b29e4c9 194 Ar4IpToMac(DhcpRouterIp, pDstMac); //send via router
andrewboyson 53:77f8a49adf89 195 ttl = OFF_LINK_TTL;
andrewboyson 53:77f8a49adf89 196 }
andrewboyson 53:77f8a49adf89 197 else
andrewboyson 53:77f8a49adf89 198 {
andrewboyson 116:60521b29e4c9 199 Ar4IpToMac(dstIp, pDstMac); //Send direct
andrewboyson 53:77f8a49adf89 200 ttl = 255;
andrewboyson 53:77f8a49adf89 201 }
andrewboyson 11:c051adb70c5a 202 break;
andrewboyson 42:222a4f45f916 203 case MULTICAST_NODE:
andrewboyson 42:222a4f45f916 204 case MULTICAST_ROUTER:
andrewboyson 42:222a4f45f916 205 case MULTICAST_MDNS:
andrewboyson 42:222a4f45f916 206 case MULTICAST_LLMNR:
andrewboyson 112:f8694d0b8858 207 case MULTICAST_NTP:
andrewboyson 22:914b970356f0 208 case BROADCAST:
andrewboyson 53:77f8a49adf89 209 ttl = 255;
andrewboyson 22:914b970356f0 210 break;
andrewboyson 22:914b970356f0 211 default:
andrewboyson 42:222a4f45f916 212 LogTimeF("Ip4PollForPacketToSend - undefined destination %d\r\n", dest);
andrewboyson 53:77f8a49adf89 213 return DO_NOTHING;
andrewboyson 11:c051adb70c5a 214 }
andrewboyson 10:f0854784e960 215
andrewboyson 136:8a65abb0dc63 216 *pSize = IP4_HEADER_LENGTH + dataLength;
andrewboyson 136:8a65abb0dc63 217
andrewboyson 136:8a65abb0dc63 218 makeHeader(pPacket, *pSize, ttl, protocol, srcIp, dstIp);
andrewboyson 59:e0e556c8bd46 219
andrewboyson 136:8a65abb0dc63 220 if (ActionGetTracePart(action)) logHeader(pPacket);
andrewboyson 37:793b39683406 221
andrewboyson 10:f0854784e960 222 return action;
andrewboyson 10:f0854784e960 223 }