Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Tue Oct 23 06:46:50 2018 +0000
Revision:
73:43e3d7fb3d60
Child:
74:c3756bfa960e
Separated the TCP header into its own module

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 73:43e3d7fb3d60 4 #include "log.h"
andrewboyson 73:43e3d7fb3d60 5 #include "net.h"
andrewboyson 73:43e3d7fb3d60 6
andrewboyson 73:43e3d7fb3d60 7 __packed struct header
andrewboyson 73:43e3d7fb3d60 8 {
andrewboyson 73:43e3d7fb3d60 9 uint16_t srcPort;
andrewboyson 73:43e3d7fb3d60 10 uint16_t dstPort;
andrewboyson 73:43e3d7fb3d60 11 uint32_t seqnum;
andrewboyson 73:43e3d7fb3d60 12 uint32_t acknum;
andrewboyson 73:43e3d7fb3d60 13 uint8_t dataOffset;
andrewboyson 73:43e3d7fb3d60 14 uint8_t flags;
andrewboyson 73:43e3d7fb3d60 15 uint16_t window;
andrewboyson 73:43e3d7fb3d60 16 uint16_t checksum;
andrewboyson 73:43e3d7fb3d60 17 uint16_t urgent;
andrewboyson 73:43e3d7fb3d60 18 };
andrewboyson 73:43e3d7fb3d60 19
andrewboyson 73:43e3d7fb3d60 20 //Header variables
andrewboyson 73:43e3d7fb3d60 21 uint16_t TcpHdrSrcPort;
andrewboyson 73:43e3d7fb3d60 22 uint16_t TcpHdrDstPort;
andrewboyson 73:43e3d7fb3d60 23 uint32_t TcpHdrSeqNum;
andrewboyson 73:43e3d7fb3d60 24 uint32_t TcpHdrAckNum;
andrewboyson 73:43e3d7fb3d60 25 int TcpHdrSize;
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 73:43e3d7fb3d60 36 //Option variables
andrewboyson 73:43e3d7fb3d60 37 uint16_t TcpHdrMss;
andrewboyson 73:43e3d7fb3d60 38
andrewboyson 73:43e3d7fb3d60 39 void TcpHdrRead(void* pPacket)
andrewboyson 73:43e3d7fb3d60 40 {
andrewboyson 73:43e3d7fb3d60 41 struct header* pHeader = (struct header*)pPacket;
andrewboyson 73:43e3d7fb3d60 42
andrewboyson 73:43e3d7fb3d60 43 TcpHdrSrcPort = NetToHost16(pHeader->srcPort);
andrewboyson 73:43e3d7fb3d60 44 TcpHdrDstPort = NetToHost16(pHeader->dstPort);
andrewboyson 73:43e3d7fb3d60 45 TcpHdrSeqNum = NetToHost32(pHeader->seqnum);
andrewboyson 73:43e3d7fb3d60 46 TcpHdrAckNum = NetToHost32(pHeader->acknum);
andrewboyson 73:43e3d7fb3d60 47 TcpHdrSize = (pHeader->dataOffset >> 2) & 0xFC; //Same as right shifting by 4 bits and multiplying by 4
andrewboyson 73:43e3d7fb3d60 48 uint8_t flags = pHeader->flags;
andrewboyson 73:43e3d7fb3d60 49 TcpHdrURG = flags & 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 73:43e3d7fb3d60 50 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 51 TcpHdrPSH = flags & 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 73:43e3d7fb3d60 52 TcpHdrRST = flags & 0x04; //Reset the connection
andrewboyson 73:43e3d7fb3d60 53 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 54 TcpHdrFIN = flags & 0x01; //No more data from sender
andrewboyson 73:43e3d7fb3d60 55 TcpHdrWindow = NetToHost16(pHeader->window);
andrewboyson 73:43e3d7fb3d60 56 TcpHdrChecksum = NetToHost16(pHeader->checksum);
andrewboyson 73:43e3d7fb3d60 57 TcpHdrUrgent = NetToHost16(pHeader->urgent);
andrewboyson 73:43e3d7fb3d60 58 }
andrewboyson 73:43e3d7fb3d60 59
andrewboyson 73:43e3d7fb3d60 60 static void logFlags()
andrewboyson 73:43e3d7fb3d60 61 {
andrewboyson 73:43e3d7fb3d60 62 if (TcpHdrURG) Log(" URG");
andrewboyson 73:43e3d7fb3d60 63 if (TcpHdrACK) Log(" ACK");
andrewboyson 73:43e3d7fb3d60 64 if (TcpHdrPSH) Log(" PSH");
andrewboyson 73:43e3d7fb3d60 65 if (TcpHdrRST) Log(" RST");
andrewboyson 73:43e3d7fb3d60 66 if (TcpHdrSYN) Log(" SYN");
andrewboyson 73:43e3d7fb3d60 67 if (TcpHdrFIN) Log(" FIN");
andrewboyson 73:43e3d7fb3d60 68 }
andrewboyson 73:43e3d7fb3d60 69 void TcpHdrLog(uint16_t calculatedChecksum)
andrewboyson 73:43e3d7fb3d60 70 {
andrewboyson 73:43e3d7fb3d60 71 if (NetTraceVerbose)
andrewboyson 73:43e3d7fb3d60 72 {
andrewboyson 73:43e3d7fb3d60 73 Log("TCP header\r\n");
andrewboyson 73:43e3d7fb3d60 74 Log(" Source port "); LogF("%hu", TcpHdrSrcPort ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 75 Log(" Destination port "); LogF("%hu", TcpHdrDstPort ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 76 Log(" Seq number "); LogF("%u", TcpHdrSeqNum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 77 Log(" Ack number "); LogF("%u", TcpHdrAckNum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 78 Log(" Header size "); LogF("%u", TcpHdrSize ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 79 Log(" Flags " ); logFlags( ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 80 Log(" Window "); LogF("%hu", TcpHdrWindow ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 81 Log(" Checksum (hex) "); LogF("%04hX", TcpHdrChecksum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 82 Log(" Calculated (hex) "); LogF("%04hX", calculatedChecksum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 83 Log(" Urgent pointer "); LogF("%hu", TcpHdrUrgent ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 84
andrewboyson 73:43e3d7fb3d60 85 }
andrewboyson 73:43e3d7fb3d60 86 else
andrewboyson 73:43e3d7fb3d60 87 {
andrewboyson 73:43e3d7fb3d60 88 LogF("TCP header %hu >>> %hu", TcpHdrSrcPort, TcpHdrDstPort);
andrewboyson 73:43e3d7fb3d60 89 logFlags();
andrewboyson 73:43e3d7fb3d60 90 Log("\r\n");
andrewboyson 73:43e3d7fb3d60 91 }
andrewboyson 73:43e3d7fb3d60 92 }
andrewboyson 73:43e3d7fb3d60 93 void TcpHdrAddChecksum(void* pPacket, uint16_t checksum)
andrewboyson 73:43e3d7fb3d60 94 {
andrewboyson 73:43e3d7fb3d60 95 struct header* pHeader = (struct header*)pPacket;
andrewboyson 73:43e3d7fb3d60 96 pHeader->checksum = checksum;
andrewboyson 73:43e3d7fb3d60 97 }
andrewboyson 73:43e3d7fb3d60 98 void TcpHdrReadOptions(void* pPacket)
andrewboyson 73:43e3d7fb3d60 99 {
andrewboyson 73:43e3d7fb3d60 100 char* pOptions = (char*)pPacket + sizeof(struct header);
andrewboyson 73:43e3d7fb3d60 101 int optionLength = TcpHdrSize - sizeof(struct header);
andrewboyson 73:43e3d7fb3d60 102
andrewboyson 73:43e3d7fb3d60 103 TcpHdrMss = 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)];
andrewboyson 73:43e3d7fb3d60 104 for (char* p = pOptions; p < pOptions + optionLength; p++)
andrewboyson 73:43e3d7fb3d60 105 {
andrewboyson 73:43e3d7fb3d60 106 switch (*p)
andrewboyson 73:43e3d7fb3d60 107 {
andrewboyson 73:43e3d7fb3d60 108 case 0: break; //End of options - used to pad to 32 bit boundary
andrewboyson 73:43e3d7fb3d60 109 case 1: break; //NOP, padding - optional
andrewboyson 73:43e3d7fb3d60 110 case 2:
andrewboyson 73:43e3d7fb3d60 111 p++;
andrewboyson 73:43e3d7fb3d60 112 if (*p != 4) LogTimeF("MSS option width %d when expected 4\r\n", *p);
andrewboyson 73:43e3d7fb3d60 113 p++;
andrewboyson 73:43e3d7fb3d60 114 TcpHdrMss = ((uint16_t)*p) << 8;
andrewboyson 73:43e3d7fb3d60 115 p++;
andrewboyson 73:43e3d7fb3d60 116 TcpHdrMss += *p;
andrewboyson 73:43e3d7fb3d60 117 return;
andrewboyson 73:43e3d7fb3d60 118 default: LogTimeF("Unrecognised TCP option %d\r\n", *p);
andrewboyson 73:43e3d7fb3d60 119 }
andrewboyson 73:43e3d7fb3d60 120 }
andrewboyson 73:43e3d7fb3d60 121 }
andrewboyson 73:43e3d7fb3d60 122 void TcpHdrWriteOptions(void* pPacket)
andrewboyson 73:43e3d7fb3d60 123 {
andrewboyson 73:43e3d7fb3d60 124 char* pOptions = (char*)pPacket + sizeof(struct header);
andrewboyson 73:43e3d7fb3d60 125 pOptions[0] = 2;
andrewboyson 73:43e3d7fb3d60 126 pOptions[1] = 4;
andrewboyson 73:43e3d7fb3d60 127 pOptions[2] = TcpHdrMss >> 8;
andrewboyson 73:43e3d7fb3d60 128 pOptions[3] = TcpHdrMss & 0xFF;
andrewboyson 73:43e3d7fb3d60 129 TcpHdrSize += sizeof(struct header) + 4;
andrewboyson 73:43e3d7fb3d60 130 }
andrewboyson 73:43e3d7fb3d60 131 void TcpHdrClearOptions()
andrewboyson 73:43e3d7fb3d60 132 {
andrewboyson 73:43e3d7fb3d60 133 TcpHdrSize = sizeof(struct header);
andrewboyson 73:43e3d7fb3d60 134 }
andrewboyson 73:43e3d7fb3d60 135
andrewboyson 73:43e3d7fb3d60 136 void TcpHdrWrite(int size, void* pPacket)
andrewboyson 73:43e3d7fb3d60 137 {
andrewboyson 73:43e3d7fb3d60 138 struct header* pHeader = (struct header*)pPacket;
andrewboyson 73:43e3d7fb3d60 139
andrewboyson 73:43e3d7fb3d60 140 pHeader->dstPort = NetToHost16(TcpHdrDstPort);
andrewboyson 73:43e3d7fb3d60 141 pHeader->srcPort = NetToHost16(TcpHdrSrcPort);
andrewboyson 73:43e3d7fb3d60 142 pHeader->seqnum = NetToHost32(TcpHdrSeqNum); //This is the sequence number of the first byte of this message
andrewboyson 73:43e3d7fb3d60 143 pHeader->acknum = NetToHost32(TcpHdrAckNum); //This is the sequence number we expect in the next message
andrewboyson 73:43e3d7fb3d60 144 pHeader->dataOffset = TcpHdrSize << 2; //Same as dividing by 4 to get bytes and left shifting by 4 bits
andrewboyson 73:43e3d7fb3d60 145 uint8_t flags = 0;
andrewboyson 73:43e3d7fb3d60 146 if (TcpHdrURG) flags |= 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 73:43e3d7fb3d60 147 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 148 if (TcpHdrPSH) flags |= 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 73:43e3d7fb3d60 149 if (TcpHdrRST) flags |= 0x04; //Reset the connection
andrewboyson 73:43e3d7fb3d60 150 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 151 if (TcpHdrFIN) flags |= 0x01; //No more data from sender
andrewboyson 73:43e3d7fb3d60 152 pHeader->flags = flags;
andrewboyson 73:43e3d7fb3d60 153 pHeader->window = NetToHost16(TcpHdrWindow);
andrewboyson 73:43e3d7fb3d60 154 pHeader->urgent = NetToHost16(TcpHdrUrgent);
andrewboyson 73:43e3d7fb3d60 155
andrewboyson 73:43e3d7fb3d60 156 pHeader->checksum = 0;
andrewboyson 73:43e3d7fb3d60 157 }