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 Oct 22 17:19:17 2017 +0000
Revision:
44:83ce5ace337b
Parent:
43:bc028d5a6424
Child:
46:40d33e9037e4
Fixed DnsServer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 30:e34173b7585c 1 #include "mbed.h"
andrewboyson 30:e34173b7585c 2 #include "log.h"
andrewboyson 30:e34173b7585c 3 #include "net.h"
andrewboyson 37:793b39683406 4 #include "action.h"
andrewboyson 30:e34173b7585c 5 #include "icmp6.h"
andrewboyson 30:e34173b7585c 6 #include "udptcp6.h"
andrewboyson 30:e34173b7585c 7 #include "ar.h"
andrewboyson 35:93c39d260a83 8 #include "nr.h"
andrewboyson 30:e34173b7585c 9 #include "slaac.h"
andrewboyson 30:e34173b7585c 10 #include "eth.h"
andrewboyson 30:e34173b7585c 11 #include "ip.h"
andrewboyson 30:e34173b7585c 12 #include "ip6.h"
andrewboyson 30:e34173b7585c 13 #include "ra.h"
andrewboyson 30:e34173b7585c 14 #include "io.h"
andrewboyson 35:93c39d260a83 15 #include "ntp.h"
andrewboyson 36:900e24b27bfb 16 #include "mac.h"
andrewboyson 11:c051adb70c5a 17
andrewboyson 34:e3a7bff69bfc 18 #define SHOW_FILTERED true
andrewboyson 11:c051adb70c5a 19
andrewboyson 36:900e24b27bfb 20 void Ip6Clear(char* ip)
andrewboyson 36:900e24b27bfb 21 {
andrewboyson 36:900e24b27bfb 22 *ip = 0;
andrewboyson 36:900e24b27bfb 23 }
andrewboyson 36:900e24b27bfb 24 bool Ip6IsEmpty(char* ip)
andrewboyson 36:900e24b27bfb 25 {
andrewboyson 36:900e24b27bfb 26 return !*ip; //Just check for the first byte being non zero
andrewboyson 36:900e24b27bfb 27 }
andrewboyson 14:e75a59c1123d 28 static void addHexNibble(bool* pAdded, int number, int index, char** pp)
andrewboyson 14:e75a59c1123d 29 {
andrewboyson 14:e75a59c1123d 30 int nibble = number;
andrewboyson 14:e75a59c1123d 31 if (index) nibble >>= 4;
andrewboyson 14:e75a59c1123d 32 nibble &= 0xF;
andrewboyson 14:e75a59c1123d 33
andrewboyson 14:e75a59c1123d 34 if (nibble || *pAdded)
andrewboyson 14:e75a59c1123d 35 {
andrewboyson 14:e75a59c1123d 36 **pp = nibble < 10 ? nibble + '0' : nibble - 10 + 'a';
andrewboyson 14:e75a59c1123d 37 *pp += 1;
andrewboyson 14:e75a59c1123d 38 *pAdded = true;
andrewboyson 14:e75a59c1123d 39 }
andrewboyson 14:e75a59c1123d 40 }
andrewboyson 14:e75a59c1123d 41 int Ip6AddressToString(char* pIp, int size, char* pText)
andrewboyson 14:e75a59c1123d 42 {
andrewboyson 14:e75a59c1123d 43 char* pIpE = pIp + 16;
andrewboyson 14:e75a59c1123d 44 char* p = pText;
andrewboyson 14:e75a59c1123d 45 while (true)
andrewboyson 14:e75a59c1123d 46 {
andrewboyson 14:e75a59c1123d 47 bool added = false;
andrewboyson 14:e75a59c1123d 48 if (*pIp || *(pIp + 1))
andrewboyson 14:e75a59c1123d 49 {
andrewboyson 14:e75a59c1123d 50 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 1, &p);
andrewboyson 14:e75a59c1123d 51 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 0, &p);
andrewboyson 14:e75a59c1123d 52 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 1, &p);
andrewboyson 14:e75a59c1123d 53 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 0, &p);
andrewboyson 14:e75a59c1123d 54 }
andrewboyson 14:e75a59c1123d 55
andrewboyson 14:e75a59c1123d 56 pIp += 2;
andrewboyson 14:e75a59c1123d 57 if (pIp >= pIpE) break;
andrewboyson 14:e75a59c1123d 58
andrewboyson 14:e75a59c1123d 59 if (p > pText + size - 2) break; *p++ = ':';
andrewboyson 14:e75a59c1123d 60 }
andrewboyson 14:e75a59c1123d 61 *p = 0;
andrewboyson 14:e75a59c1123d 62 return p - pText;
andrewboyson 14:e75a59c1123d 63 }
andrewboyson 35:93c39d260a83 64 bool Ip6IsSame(char* ipA, char* ipB)
andrewboyson 35:93c39d260a83 65 {
andrewboyson 35:93c39d260a83 66 return memcmp(ipA, ipB, 16) == 0;
andrewboyson 35:93c39d260a83 67 }
andrewboyson 36:900e24b27bfb 68 void Ip6Copy(char* ipTo, char* ipFrom)
andrewboyson 35:93c39d260a83 69 {
andrewboyson 35:93c39d260a83 70 memcpy(ipTo, ipFrom, 16);
andrewboyson 35:93c39d260a83 71 }
andrewboyson 14:e75a59c1123d 72
andrewboyson 11:c051adb70c5a 73 char Ip6AllNodes [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
andrewboyson 11:c051adb70c5a 74 char Ip6AllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
andrewboyson 11:c051adb70c5a 75 char Ip6Mdns [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb};
andrewboyson 11:c051adb70c5a 76 char Ip6Llmnr [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03};
andrewboyson 11:c051adb70c5a 77
andrewboyson 44:83ce5ace337b 78 void Ip6DstIpFromDest(int dest, char* pDstIp)
andrewboyson 11:c051adb70c5a 79 {
andrewboyson 37:793b39683406 80 switch (dest)
andrewboyson 11:c051adb70c5a 81 {
andrewboyson 36:900e24b27bfb 82 case UNICAST: break;
andrewboyson 36:900e24b27bfb 83 case UNICAST_DNS: Ip6Copy(pDstIp, RaDnsServer ); break;
andrewboyson 36:900e24b27bfb 84 case UNICAST_NTP: Ip6Copy(pDstIp, NtpServerIp6 ); break;
andrewboyson 36:900e24b27bfb 85 case MULTICAST_NODE: Ip6Copy(pDstIp, Ip6AllNodes ); break;
andrewboyson 36:900e24b27bfb 86 case MULTICAST_ROUTER: Ip6Copy(pDstIp, Ip6AllRouters); break;
andrewboyson 36:900e24b27bfb 87 case MULTICAST_MDNS: Ip6Copy(pDstIp, Ip6Mdns ); break;
andrewboyson 36:900e24b27bfb 88 case MULTICAST_LLMNR: Ip6Copy(pDstIp, Ip6Llmnr ); break;
andrewboyson 11:c051adb70c5a 89 default:
andrewboyson 37:793b39683406 90 LogTimeF("Ip6DestIpFromDest unknown destination %d\r\n", dest);
andrewboyson 11:c051adb70c5a 91 break;
andrewboyson 11:c051adb70c5a 92 }
andrewboyson 11:c051adb70c5a 93 }
andrewboyson 44:83ce5ace337b 94 void Ip6SrcIpFromScope(int scope, char* pSrcIp)
andrewboyson 44:83ce5ace337b 95 {
andrewboyson 44:83ce5ace337b 96 if (scope == SCOPE_GLOBAL) Ip6Copy(pSrcIp, SlaacGlobalIp );
andrewboyson 44:83ce5ace337b 97 else Ip6Copy(pSrcIp, SlaacLinkLocalIp);
andrewboyson 44:83ce5ace337b 98 //Note that scope could be SCOPE_NONE if source was multicast in which case should return the link local ip.
andrewboyson 44:83ce5ace337b 99 }
andrewboyson 10:f0854784e960 100
andrewboyson 10:f0854784e960 101 #define HEADER_LENGTH 40
andrewboyson 10:f0854784e960 102 __packed struct header
andrewboyson 10:f0854784e960 103 {
andrewboyson 10:f0854784e960 104 uint32_t versionTrafficFlow;
andrewboyson 10:f0854784e960 105 uint16_t dataLength;
andrewboyson 10:f0854784e960 106 uint8_t protocol;
andrewboyson 10:f0854784e960 107 uint8_t hoplimit;
andrewboyson 10:f0854784e960 108 char src[16];
andrewboyson 10:f0854784e960 109 char dst[16];
andrewboyson 10:f0854784e960 110 };
andrewboyson 11:c051adb70c5a 111
andrewboyson 11:c051adb70c5a 112 static uint8_t version;
andrewboyson 11:c051adb70c5a 113 static int dataLength;
andrewboyson 11:c051adb70c5a 114 static uint8_t protocol;
andrewboyson 11:c051adb70c5a 115 static uint8_t hoplimit;
andrewboyson 35:93c39d260a83 116 static char srcIp[16];
andrewboyson 35:93c39d260a83 117 static char dstIp[16];
andrewboyson 11:c051adb70c5a 118 static void* pData;
andrewboyson 11:c051adb70c5a 119
andrewboyson 11:c051adb70c5a 120 static void readHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 121 {
andrewboyson 11:c051adb70c5a 122 version = (pHeader->versionTrafficFlow >> 4) & 0xF;
andrewboyson 11:c051adb70c5a 123 dataLength = NetToHost16(pHeader->dataLength);
andrewboyson 11:c051adb70c5a 124 protocol = pHeader->protocol;
andrewboyson 11:c051adb70c5a 125 hoplimit = pHeader->hoplimit;
andrewboyson 36:900e24b27bfb 126 Ip6Copy(srcIp, pHeader->src);
andrewboyson 36:900e24b27bfb 127 Ip6Copy(dstIp, pHeader->dst);
andrewboyson 11:c051adb70c5a 128 pData = (char*)pHeader + HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 129 }
andrewboyson 11:c051adb70c5a 130 static void writeHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 131 {
andrewboyson 36:900e24b27bfb 132 pHeader->versionTrafficFlow = version << 4;
andrewboyson 36:900e24b27bfb 133 pHeader->protocol = protocol;
andrewboyson 44:83ce5ace337b 134 pHeader->hoplimit = hoplimit;
andrewboyson 36:900e24b27bfb 135 Ip6Copy(pHeader->dst, dstIp);
andrewboyson 36:900e24b27bfb 136 Ip6Copy(pHeader->src, srcIp);
andrewboyson 36:900e24b27bfb 137 pHeader->dataLength = NetToHost16(dataLength);
andrewboyson 11:c051adb70c5a 138 }
andrewboyson 11:c051adb70c5a 139
andrewboyson 37:793b39683406 140 static void logHeader()
andrewboyson 11:c051adb70c5a 141 {
andrewboyson 11:c051adb70c5a 142 char text[100];
andrewboyson 43:bc028d5a6424 143 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 144 {
andrewboyson 43:bc028d5a6424 145 Log("IP6 header\r\n");
andrewboyson 43:bc028d5a6424 146 LogF(" Version %d\r\n", version);
andrewboyson 43:bc028d5a6424 147 LogF(" Payload length %d\r\n", dataLength);
andrewboyson 43:bc028d5a6424 148 LogF(" Hop limit %d\r\n", hoplimit);
andrewboyson 43:bc028d5a6424 149 IpProtocolToString(protocol, sizeof(text), text);
andrewboyson 43:bc028d5a6424 150 LogF(" Protocol %s\r\n", text);
andrewboyson 43:bc028d5a6424 151 Ip6AddressToString(srcIp, sizeof(text), text);
andrewboyson 43:bc028d5a6424 152 LogF(" Source IP %s\r\n", text);
andrewboyson 43:bc028d5a6424 153 Ip6AddressToString(dstIp, sizeof(text), text);
andrewboyson 43:bc028d5a6424 154 LogF(" Destination IP %s\r\n", text);
andrewboyson 43:bc028d5a6424 155 }
andrewboyson 43:bc028d5a6424 156 else
andrewboyson 43:bc028d5a6424 157 {
andrewboyson 44:83ce5ace337b 158 Log("IP6 header ");
andrewboyson 43:bc028d5a6424 159 IpProtocolToString(protocol, sizeof(text), text);
andrewboyson 43:bc028d5a6424 160 Log(text);
andrewboyson 43:bc028d5a6424 161 Log(" ");
andrewboyson 43:bc028d5a6424 162 Ip6AddressToString(srcIp, sizeof(text), text);
andrewboyson 43:bc028d5a6424 163 Log(text);
andrewboyson 43:bc028d5a6424 164 Log(" >>> ");
andrewboyson 43:bc028d5a6424 165 Ip6AddressToString(dstIp, sizeof(text), text);
andrewboyson 43:bc028d5a6424 166 Log(text);
andrewboyson 43:bc028d5a6424 167 Log("\r\n");
andrewboyson 43:bc028d5a6424 168 }
andrewboyson 11:c051adb70c5a 169 }
andrewboyson 11:c051adb70c5a 170
andrewboyson 10:f0854784e960 171 static bool getIsSolicited(char* p)
andrewboyson 10:f0854784e960 172 {
andrewboyson 10:f0854784e960 173 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 174 if (*p++ != 0x02) return false;
andrewboyson 10:f0854784e960 175
andrewboyson 10:f0854784e960 176 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 177 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 178
andrewboyson 10:f0854784e960 179 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 180 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 181
andrewboyson 10:f0854784e960 182 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 183 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 184
andrewboyson 10:f0854784e960 185 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 186 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 187
andrewboyson 10:f0854784e960 188 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 189 if (*p++ != 0x01) return false;
andrewboyson 10:f0854784e960 190
andrewboyson 10:f0854784e960 191 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 192
andrewboyson 10:f0854784e960 193 return true;
andrewboyson 10:f0854784e960 194 }
andrewboyson 10:f0854784e960 195 static bool getIsSameGroup(char* pA, char* pB)
andrewboyson 10:f0854784e960 196 {
andrewboyson 10:f0854784e960 197 pA += 13;
andrewboyson 10:f0854784e960 198 pB += 13;
andrewboyson 10:f0854784e960 199 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 200 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 201 return *pA == *pB;
andrewboyson 10:f0854784e960 202 }
andrewboyson 37:793b39683406 203 static void (*pTraceBack)(void);
andrewboyson 37:793b39683406 204 static void trace()
andrewboyson 10:f0854784e960 205 {
andrewboyson 37:793b39683406 206 pTraceBack();
andrewboyson 37:793b39683406 207 logHeader();
andrewboyson 37:793b39683406 208 }
andrewboyson 37:793b39683406 209 int Ip6HandleReceivedPacket(void (*traceback)(void), char* pSrcMac, void* pPacket, int* pSize, char* pDstMac)
andrewboyson 37:793b39683406 210 {
andrewboyson 37:793b39683406 211 pTraceBack = traceback;
andrewboyson 37:793b39683406 212
andrewboyson 10:f0854784e960 213 struct header * pHeader = (header*)pPacket;
andrewboyson 11:c051adb70c5a 214 readHeader(pHeader);
andrewboyson 10:f0854784e960 215
andrewboyson 44:83ce5ace337b 216 int scope = SlaacScope(dstIp);
andrewboyson 35:93c39d260a83 217 bool isMulticast = dstIp[0] == 0xFF;
andrewboyson 35:93c39d260a83 218 bool isSolicited = getIsSolicited(dstIp);
andrewboyson 35:93c39d260a83 219 bool isGroup = getIsSameGroup(dstIp, SlaacLinkLocalIp);
andrewboyson 10:f0854784e960 220
andrewboyson 44:83ce5ace337b 221 bool doIt = scope || (isMulticast && !isSolicited) || (isGroup && isSolicited);
andrewboyson 10:f0854784e960 222
andrewboyson 14:e75a59c1123d 223 if (!doIt)
andrewboyson 14:e75a59c1123d 224 {
andrewboyson 37:793b39683406 225 if (SHOW_FILTERED)
andrewboyson 15:6ca6778168b1 226 {
andrewboyson 15:6ca6778168b1 227 char text[100];
andrewboyson 35:93c39d260a83 228 Ip6AddressToString(dstIp, sizeof(text), text);
andrewboyson 15:6ca6778168b1 229 LogTimeF("IP6 filtered out ip %s ", text);
andrewboyson 35:93c39d260a83 230 Ip6AddressToString(srcIp, sizeof(text), text);
andrewboyson 15:6ca6778168b1 231 LogF("from %s \r\n", text);
andrewboyson 15:6ca6778168b1 232 }
andrewboyson 14:e75a59c1123d 233 return DO_NOTHING;
andrewboyson 14:e75a59c1123d 234 }
andrewboyson 10:f0854784e960 235
andrewboyson 35:93c39d260a83 236 ArAddIp6Record(pSrcMac, srcIp);
andrewboyson 35:93c39d260a83 237 NrMakeRequestForNameFromIp6(srcIp);
andrewboyson 11:c051adb70c5a 238
andrewboyson 10:f0854784e960 239 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 240 switch (protocol)
andrewboyson 10:f0854784e960 241 {
andrewboyson 44:83ce5ace337b 242 case HOPOPT: action = DO_NOTHING; break;
andrewboyson 44:83ce5ace337b 243 case ICMP6: action = Icmp6HandleReceivedPacket(trace, scope, srcIp, dstIp, &dataLength, pData); break;
andrewboyson 44:83ce5ace337b 244 case UDP: action = Udp6HandleReceivedPacket(trace, scope, srcIp, dstIp, &dataLength, pData); break;
andrewboyson 44:83ce5ace337b 245 case TCP: action = Tcp6HandleReceivedPacket(trace, scope, srcIp, dstIp, &dataLength, pData); break;
andrewboyson 10:f0854784e960 246 default:
andrewboyson 37:793b39683406 247 LogTimeF("IP6 protocol %d unhandled\r\n", protocol);
andrewboyson 10:f0854784e960 248 return DO_NOTHING;
andrewboyson 10:f0854784e960 249 }
andrewboyson 11:c051adb70c5a 250 if (!action) return DO_NOTHING;
andrewboyson 11:c051adb70c5a 251
andrewboyson 44:83ce5ace337b 252 if (RaIpNeedsToBeRouted(dstIp)) MacCopy(pDstMac, RaRouterMac); //Send to the router MAC
andrewboyson 44:83ce5ace337b 253 else MacCopy(pDstMac, pSrcMac); //Send back to the source
andrewboyson 10:f0854784e960 254
andrewboyson 11:c051adb70c5a 255 writeHeader(pHeader);
andrewboyson 11:c051adb70c5a 256
andrewboyson 10:f0854784e960 257 *pSize = HEADER_LENGTH + dataLength;
andrewboyson 10:f0854784e960 258
andrewboyson 37:793b39683406 259 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 260
andrewboyson 10:f0854784e960 261 return action;
andrewboyson 10:f0854784e960 262 }
andrewboyson 10:f0854784e960 263 int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
andrewboyson 10:f0854784e960 264 {
andrewboyson 11:c051adb70c5a 265 pData = (char*)pPacket + HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 266 dataLength = 0;
andrewboyson 11:c051adb70c5a 267 version = 6;
andrewboyson 11:c051adb70c5a 268 hoplimit = 255;
andrewboyson 10:f0854784e960 269
andrewboyson 10:f0854784e960 270 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 271 if (action == DO_NOTHING)
andrewboyson 10:f0854784e960 272 {
andrewboyson 35:93c39d260a83 273 action = Icmp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
andrewboyson 10:f0854784e960 274 protocol = ICMP6;
andrewboyson 10:f0854784e960 275 }
andrewboyson 10:f0854784e960 276
andrewboyson 10:f0854784e960 277 if (action == DO_NOTHING)
andrewboyson 10:f0854784e960 278 {
andrewboyson 35:93c39d260a83 279 action = Udp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
andrewboyson 10:f0854784e960 280 protocol = UDP;
andrewboyson 10:f0854784e960 281 }
andrewboyson 11:c051adb70c5a 282 if (!action) return DO_NOTHING;
andrewboyson 37:793b39683406 283
andrewboyson 37:793b39683406 284 int dest = ActionGetDestPart(action);
andrewboyson 37:793b39683406 285 switch (dest)
andrewboyson 11:c051adb70c5a 286 {
andrewboyson 11:c051adb70c5a 287 case UNICAST:
andrewboyson 11:c051adb70c5a 288 case UNICAST_DNS:
andrewboyson 11:c051adb70c5a 289 case UNICAST_DHCP:
andrewboyson 22:914b970356f0 290 case UNICAST_NTP:
andrewboyson 44:83ce5ace337b 291 if (RaIpNeedsToBeRouted(dstIp)) MacCopy(pDstMac, RaRouterMac); //Send to the router MAC
andrewboyson 44:83ce5ace337b 292 else ArIpToMac6(dstIp, pDstMac); //Make the remote MAC from NP
andrewboyson 11:c051adb70c5a 293 break;
andrewboyson 22:914b970356f0 294 case MULTICAST_NODE:
andrewboyson 22:914b970356f0 295 case MULTICAST_ROUTER:
andrewboyson 22:914b970356f0 296 case MULTICAST_MDNS:
andrewboyson 22:914b970356f0 297 case MULTICAST_LLMNR:
andrewboyson 22:914b970356f0 298 case SOLICITED_NODE:
andrewboyson 22:914b970356f0 299 break;
andrewboyson 22:914b970356f0 300 default:
andrewboyson 37:793b39683406 301 LogTimeF("Ip6PollForPacketToSend - undefined destination %d\r\n", dest);
andrewboyson 22:914b970356f0 302 break;
andrewboyson 11:c051adb70c5a 303 }
andrewboyson 10:f0854784e960 304
andrewboyson 11:c051adb70c5a 305 writeHeader((header*)pPacket);
andrewboyson 11:c051adb70c5a 306
andrewboyson 10:f0854784e960 307 *pSize = HEADER_LENGTH + dataLength;
andrewboyson 10:f0854784e960 308
andrewboyson 37:793b39683406 309 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 310
andrewboyson 10:f0854784e960 311 return action;
andrewboyson 10:f0854784e960 312 }