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 Feb 22 11:26:55 2019 +0000
Revision:
125:8c84daac38ab
Parent:
98:b977424ec7f7
Child:
137:cf6e7db0e985
tidied up ntp data types for calculating ms from clktime.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 73:43e3d7fb3d60 1 #include <stdint.h>
andrewboyson 73:43e3d7fb3d60 2 #include <stdbool.h>
andrewboyson 73:43e3d7fb3d60 3
andrewboyson 98:b977424ec7f7 4 #include "log.h"
andrewboyson 98:b977424ec7f7 5 #include "net.h"
andrewboyson 98:b977424ec7f7 6 #include "fault.h"
andrewboyson 73:43e3d7fb3d60 7
andrewboyson 73:43e3d7fb3d60 8 __packed struct header
andrewboyson 73:43e3d7fb3d60 9 {
andrewboyson 73:43e3d7fb3d60 10 uint16_t srcPort;
andrewboyson 73:43e3d7fb3d60 11 uint16_t dstPort;
andrewboyson 73:43e3d7fb3d60 12 uint32_t seqnum;
andrewboyson 73:43e3d7fb3d60 13 uint32_t acknum;
andrewboyson 73:43e3d7fb3d60 14 uint8_t dataOffset;
andrewboyson 73:43e3d7fb3d60 15 uint8_t flags;
andrewboyson 73:43e3d7fb3d60 16 uint16_t window;
andrewboyson 73:43e3d7fb3d60 17 uint16_t checksum;
andrewboyson 73:43e3d7fb3d60 18 uint16_t urgent;
andrewboyson 73:43e3d7fb3d60 19 };
andrewboyson 73:43e3d7fb3d60 20
andrewboyson 73:43e3d7fb3d60 21 //Header variables
andrewboyson 73:43e3d7fb3d60 22 uint16_t TcpHdrSrcPort;
andrewboyson 73:43e3d7fb3d60 23 uint16_t TcpHdrDstPort;
andrewboyson 73:43e3d7fb3d60 24 uint32_t TcpHdrSeqNum;
andrewboyson 73:43e3d7fb3d60 25 uint32_t TcpHdrAckNum;
andrewboyson 73:43e3d7fb3d60 26 bool TcpHdrURG; //indicates that the Urgent pointer field is significant
andrewboyson 73:43e3d7fb3d60 27 bool TcpHdrACK; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 73:43e3d7fb3d60 28 bool TcpHdrPSH; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 73:43e3d7fb3d60 29 bool TcpHdrRST; //Reset the connection
andrewboyson 73:43e3d7fb3d60 30 bool TcpHdrSYN; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 73:43e3d7fb3d60 31 bool TcpHdrFIN; //No more data from sender
andrewboyson 73:43e3d7fb3d60 32 uint16_t TcpHdrWindow;
andrewboyson 73:43e3d7fb3d60 33 uint16_t TcpHdrChecksum;
andrewboyson 73:43e3d7fb3d60 34 uint16_t TcpHdrUrgent;
andrewboyson 73:43e3d7fb3d60 35
andrewboyson 74:c3756bfa960e 36 //Side effects
andrewboyson 74:c3756bfa960e 37 static int headerSize;
andrewboyson 74:c3756bfa960e 38 int TcpHdrSizeGet() { return headerSize; }
andrewboyson 73:43e3d7fb3d60 39
andrewboyson 74:c3756bfa960e 40 static uint16_t mss = 0;
andrewboyson 74:c3756bfa960e 41 void TcpHdrMssSet(uint16_t value)
andrewboyson 73:43e3d7fb3d60 42 {
andrewboyson 74:c3756bfa960e 43 mss = value;
andrewboyson 74:c3756bfa960e 44 headerSize = sizeof (struct header);
andrewboyson 74:c3756bfa960e 45 if (mss) headerSize += 4;
andrewboyson 73:43e3d7fb3d60 46 }
andrewboyson 74:c3756bfa960e 47 uint16_t TcpHdrMssGet() { return mss; }
andrewboyson 73:43e3d7fb3d60 48
andrewboyson 73:43e3d7fb3d60 49 static void logFlags()
andrewboyson 73:43e3d7fb3d60 50 {
andrewboyson 73:43e3d7fb3d60 51 if (TcpHdrURG) Log(" URG");
andrewboyson 73:43e3d7fb3d60 52 if (TcpHdrACK) Log(" ACK");
andrewboyson 73:43e3d7fb3d60 53 if (TcpHdrPSH) Log(" PSH");
andrewboyson 73:43e3d7fb3d60 54 if (TcpHdrRST) Log(" RST");
andrewboyson 73:43e3d7fb3d60 55 if (TcpHdrSYN) Log(" SYN");
andrewboyson 73:43e3d7fb3d60 56 if (TcpHdrFIN) Log(" FIN");
andrewboyson 73:43e3d7fb3d60 57 }
andrewboyson 73:43e3d7fb3d60 58 void TcpHdrLog(uint16_t calculatedChecksum)
andrewboyson 73:43e3d7fb3d60 59 {
andrewboyson 73:43e3d7fb3d60 60 if (NetTraceVerbose)
andrewboyson 73:43e3d7fb3d60 61 {
andrewboyson 73:43e3d7fb3d60 62 Log("TCP header\r\n");
andrewboyson 73:43e3d7fb3d60 63 Log(" Source port "); LogF("%hu", TcpHdrSrcPort ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 64 Log(" Destination port "); LogF("%hu", TcpHdrDstPort ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 65 Log(" Seq number "); LogF("%u", TcpHdrSeqNum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 66 Log(" Ack number "); LogF("%u", TcpHdrAckNum ); Log("\r\n");
andrewboyson 74:c3756bfa960e 67 Log(" Header size "); LogF("%u", headerSize ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 68 Log(" Flags " ); logFlags( ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 69 Log(" Window "); LogF("%hu", TcpHdrWindow ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 70 Log(" Checksum (hex) "); LogF("%04hX", TcpHdrChecksum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 71 Log(" Calculated (hex) "); LogF("%04hX", calculatedChecksum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 72 Log(" Urgent pointer "); LogF("%hu", TcpHdrUrgent ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 73
andrewboyson 73:43e3d7fb3d60 74 }
andrewboyson 73:43e3d7fb3d60 75 else
andrewboyson 73:43e3d7fb3d60 76 {
andrewboyson 73:43e3d7fb3d60 77 LogF("TCP header %hu >>> %hu", TcpHdrSrcPort, TcpHdrDstPort);
andrewboyson 73:43e3d7fb3d60 78 logFlags();
andrewboyson 73:43e3d7fb3d60 79 Log("\r\n");
andrewboyson 73:43e3d7fb3d60 80 }
andrewboyson 73:43e3d7fb3d60 81 }
andrewboyson 74:c3756bfa960e 82 void TcpHdrReadFromPacket(void* pPacket)
andrewboyson 73:43e3d7fb3d60 83 {
andrewboyson 98:b977424ec7f7 84 int lastFaultPoint = FaultPoint;
andrewboyson 98:b977424ec7f7 85 FaultPoint = FAULT_POINT_TcpHdrReadFromPacket;
andrewboyson 98:b977424ec7f7 86
andrewboyson 73:43e3d7fb3d60 87 struct header* pHeader = (struct header*)pPacket;
andrewboyson 74:c3756bfa960e 88
andrewboyson 74:c3756bfa960e 89 TcpHdrSrcPort = NetToHost16(pHeader->srcPort);
andrewboyson 74:c3756bfa960e 90 TcpHdrDstPort = NetToHost16(pHeader->dstPort);
andrewboyson 74:c3756bfa960e 91 TcpHdrSeqNum = NetToHost32(pHeader->seqnum);
andrewboyson 74:c3756bfa960e 92 TcpHdrAckNum = NetToHost32(pHeader->acknum);
andrewboyson 74:c3756bfa960e 93 headerSize = (pHeader->dataOffset >> 2) & 0xFC; //Same as right shifting by 4 bits and multiplying by 4
andrewboyson 74:c3756bfa960e 94 uint8_t flags = pHeader->flags;
andrewboyson 74:c3756bfa960e 95 TcpHdrURG = flags & 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 74:c3756bfa960e 96 TcpHdrACK = flags & 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 74:c3756bfa960e 97 TcpHdrPSH = flags & 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 74:c3756bfa960e 98 TcpHdrRST = flags & 0x04; //Reset the connection
andrewboyson 74:c3756bfa960e 99 TcpHdrSYN = flags & 0x02; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 74:c3756bfa960e 100 TcpHdrFIN = flags & 0x01; //No more data from sender
andrewboyson 74:c3756bfa960e 101 TcpHdrWindow = NetToHost16(pHeader->window);
andrewboyson 74:c3756bfa960e 102 TcpHdrChecksum = NetToHost16(pHeader->checksum);
andrewboyson 74:c3756bfa960e 103 TcpHdrUrgent = NetToHost16(pHeader->urgent);
andrewboyson 74:c3756bfa960e 104
andrewboyson 73:43e3d7fb3d60 105 char* pOptions = (char*)pPacket + sizeof(struct header);
andrewboyson 74:c3756bfa960e 106 int optionLength = headerSize - sizeof(struct header);
andrewboyson 73:43e3d7fb3d60 107
andrewboyson 74:c3756bfa960e 108 mss = 0;
andrewboyson 88:1ba13e6062a3 109 for (char* p = pOptions; p < pOptions + optionLength; p++) //If the header size is zero then optionLength will be negative and the for loop will do nothing.
andrewboyson 73:43e3d7fb3d60 110 {
andrewboyson 73:43e3d7fb3d60 111 switch (*p)
andrewboyson 73:43e3d7fb3d60 112 {
andrewboyson 98:b977424ec7f7 113 case 0: FaultPoint = lastFaultPoint; return; //End of options so stop
andrewboyson 88:1ba13e6062a3 114 case 1: break; //NOP, padding - optional used to pad to 32 bit boundary
andrewboyson 73:43e3d7fb3d60 115 case 2:
andrewboyson 73:43e3d7fb3d60 116 p++;
andrewboyson 73:43e3d7fb3d60 117 if (*p != 4) LogTimeF("MSS option width %d when expected 4\r\n", *p);
andrewboyson 73:43e3d7fb3d60 118 p++;
andrewboyson 74:c3756bfa960e 119 mss = ((uint16_t)*p) << 8;
andrewboyson 73:43e3d7fb3d60 120 p++;
andrewboyson 74:c3756bfa960e 121 mss += *p;
andrewboyson 98:b977424ec7f7 122 FaultPoint = lastFaultPoint;
andrewboyson 88:1ba13e6062a3 123 return; //Got what we want so stop
andrewboyson 73:43e3d7fb3d60 124 default: LogTimeF("Unrecognised TCP option %d\r\n", *p);
andrewboyson 73:43e3d7fb3d60 125 }
andrewboyson 73:43e3d7fb3d60 126 }
andrewboyson 98:b977424ec7f7 127 FaultPoint = lastFaultPoint;
andrewboyson 73:43e3d7fb3d60 128 }
andrewboyson 73:43e3d7fb3d60 129
andrewboyson 74:c3756bfa960e 130 void TcpHdrWriteToPacket(void* pPacket)
andrewboyson 73:43e3d7fb3d60 131 {
andrewboyson 73:43e3d7fb3d60 132 struct header* pHeader = (struct header*)pPacket;
andrewboyson 73:43e3d7fb3d60 133
andrewboyson 74:c3756bfa960e 134 headerSize = sizeof(struct header);
andrewboyson 74:c3756bfa960e 135 if (TcpHdrMssGet())
andrewboyson 74:c3756bfa960e 136 {
andrewboyson 74:c3756bfa960e 137 char* pOptions = (char*)pPacket + headerSize;
andrewboyson 74:c3756bfa960e 138 pOptions[0] = 2;
andrewboyson 74:c3756bfa960e 139 pOptions[1] = 4;
andrewboyson 74:c3756bfa960e 140 pOptions[2] = mss >> 8;
andrewboyson 74:c3756bfa960e 141 pOptions[3] = mss & 0xFF;
andrewboyson 74:c3756bfa960e 142 headerSize += 4;
andrewboyson 74:c3756bfa960e 143 }
andrewboyson 74:c3756bfa960e 144
andrewboyson 73:43e3d7fb3d60 145 pHeader->dstPort = NetToHost16(TcpHdrDstPort);
andrewboyson 73:43e3d7fb3d60 146 pHeader->srcPort = NetToHost16(TcpHdrSrcPort);
andrewboyson 73:43e3d7fb3d60 147 pHeader->seqnum = NetToHost32(TcpHdrSeqNum); //This is the sequence number of the first byte of this message
andrewboyson 73:43e3d7fb3d60 148 pHeader->acknum = NetToHost32(TcpHdrAckNum); //This is the sequence number we expect in the next message
andrewboyson 74:c3756bfa960e 149 pHeader->dataOffset = headerSize << 2; //Same as dividing by 4 to get bytes and left shifting by 4 bits
andrewboyson 73:43e3d7fb3d60 150 uint8_t flags = 0;
andrewboyson 73:43e3d7fb3d60 151 if (TcpHdrURG) flags |= 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 73:43e3d7fb3d60 152 if (TcpHdrACK) flags |= 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 73:43e3d7fb3d60 153 if (TcpHdrPSH) flags |= 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 73:43e3d7fb3d60 154 if (TcpHdrRST) flags |= 0x04; //Reset the connection
andrewboyson 73:43e3d7fb3d60 155 if (TcpHdrSYN) flags |= 0x02; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 73:43e3d7fb3d60 156 if (TcpHdrFIN) flags |= 0x01; //No more data from sender
andrewboyson 73:43e3d7fb3d60 157 pHeader->flags = flags;
andrewboyson 73:43e3d7fb3d60 158 pHeader->window = NetToHost16(TcpHdrWindow);
andrewboyson 73:43e3d7fb3d60 159 pHeader->urgent = NetToHost16(TcpHdrUrgent);
andrewboyson 73:43e3d7fb3d60 160
andrewboyson 73:43e3d7fb3d60 161 pHeader->checksum = 0;
andrewboyson 74:c3756bfa960e 162 }
andrewboyson 74:c3756bfa960e 163 void TcpHdrAddChecksumToPacket(void* pPacket, uint16_t checksum)
andrewboyson 74:c3756bfa960e 164 {
andrewboyson 74:c3756bfa960e 165 struct header* pHeader = (struct header*)pPacket;
andrewboyson 74:c3756bfa960e 166 pHeader->checksum = checksum;
andrewboyson 74:c3756bfa960e 167 }
andrewboyson 74:c3756bfa960e 168
andrewboyson 74:c3756bfa960e 169 void TcpHdrMakeEmpty()
andrewboyson 74:c3756bfa960e 170 {
andrewboyson 74:c3756bfa960e 171 TcpHdrSrcPort = 0;
andrewboyson 74:c3756bfa960e 172 TcpHdrDstPort = 0;
andrewboyson 74:c3756bfa960e 173 TcpHdrSeqNum = 0;
andrewboyson 74:c3756bfa960e 174 TcpHdrAckNum = 0;
andrewboyson 74:c3756bfa960e 175 headerSize = sizeof(struct header);
andrewboyson 74:c3756bfa960e 176 TcpHdrURG = 0;
andrewboyson 74:c3756bfa960e 177 TcpHdrACK = 0;
andrewboyson 74:c3756bfa960e 178 TcpHdrPSH = 0;
andrewboyson 74:c3756bfa960e 179 TcpHdrRST = 0;
andrewboyson 74:c3756bfa960e 180 TcpHdrSYN = 0;
andrewboyson 74:c3756bfa960e 181 TcpHdrFIN = 0;
andrewboyson 74:c3756bfa960e 182 TcpHdrWindow = 0;
andrewboyson 74:c3756bfa960e 183 TcpHdrChecksum = 0;
andrewboyson 74:c3756bfa960e 184 TcpHdrUrgent = 0;
andrewboyson 74:c3756bfa960e 185 mss = 0;
andrewboyson 74:c3756bfa960e 186
andrewboyson 73:43e3d7fb3d60 187 }