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 Dec 14 20:55:40 2017 +0000
Revision:
59:e0e556c8bd46
Parent:
57:e0fb648acf48
Added buffer length to help avoid over runs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 57:e0fb648acf48 1 #include "mbed.h"
andrewboyson 57:e0fb648acf48 2 #include "log.h"
andrewboyson 57:e0fb648acf48 3 #include "net.h"
andrewboyson 57:e0fb648acf48 4 #include "action.h"
andrewboyson 57:e0fb648acf48 5 #include "ns.h"
andrewboyson 57:e0fb648acf48 6 #include "ra.h"
andrewboyson 57:e0fb648acf48 7 #include "rs.h"
andrewboyson 57:e0fb648acf48 8 #include "ip.h"
andrewboyson 49:1a6336f2b3f9 9 #include "ip6addr.h"
andrewboyson 57:e0fb648acf48 10 #include "slaac.h"
andrewboyson 57:e0fb648acf48 11 #include "echo6.h"
andrewboyson 57:e0fb648acf48 12 #include "dest6.h"
andrewboyson 43:bc028d5a6424 13
andrewboyson 43:bc028d5a6424 14 __packed struct header
andrewboyson 43:bc028d5a6424 15 {
andrewboyson 43:bc028d5a6424 16 uint8_t type;
andrewboyson 43:bc028d5a6424 17 uint8_t code;
andrewboyson 43:bc028d5a6424 18 uint16_t checksum;
andrewboyson 43:bc028d5a6424 19 };
andrewboyson 43:bc028d5a6424 20 static uint8_t type;
andrewboyson 43:bc028d5a6424 21 static uint8_t code;
andrewboyson 43:bc028d5a6424 22 static uint16_t checksum;
andrewboyson 43:bc028d5a6424 23 static uint16_t calculatedChecksum;
andrewboyson 43:bc028d5a6424 24
andrewboyson 47:73af5c0b0dc2 25 static void logType(uint8_t type)
andrewboyson 43:bc028d5a6424 26 {
andrewboyson 43:bc028d5a6424 27 switch (type)
andrewboyson 43:bc028d5a6424 28 {
andrewboyson 49:1a6336f2b3f9 29 case 1: Log ("Destination unreacheable" ); break;
andrewboyson 49:1a6336f2b3f9 30 case 128: Log ("Echo Request" ); break;
andrewboyson 49:1a6336f2b3f9 31 case 129: Log ("Echo Reply" ); break;
andrewboyson 57:e0fb648acf48 32 case 133: Log ("Router solicit" ); break;
andrewboyson 57:e0fb648acf48 33 case 134: Log ("Router advertisement" ); break;
andrewboyson 57:e0fb648acf48 34 case 135: Log ("Neighbour solicit" ); break;
andrewboyson 57:e0fb648acf48 35 case 136: Log ("Neighbour advertisement" ); break;
andrewboyson 57:e0fb648acf48 36 case 137: Log ("Redirect" ); break;
andrewboyson 57:e0fb648acf48 37 default: LogF("Unknown type %u", type ); break;
andrewboyson 43:bc028d5a6424 38 }
andrewboyson 43:bc028d5a6424 39 }
andrewboyson 43:bc028d5a6424 40 static uint16_t calculateChecksum(char* pSrcIp, char* pDstIp, int size, void* pPacket)
andrewboyson 43:bc028d5a6424 41 {
andrewboyson 43:bc028d5a6424 42 __packed struct pseudo
andrewboyson 43:bc028d5a6424 43 {
andrewboyson 43:bc028d5a6424 44 char src[16];
andrewboyson 43:bc028d5a6424 45 char dst[16];
andrewboyson 43:bc028d5a6424 46 uint32_t len;
andrewboyson 43:bc028d5a6424 47 uint8_t zer[3];
andrewboyson 43:bc028d5a6424 48 uint8_t pro;
andrewboyson 43:bc028d5a6424 49 } pseudo;
andrewboyson 43:bc028d5a6424 50
andrewboyson 49:1a6336f2b3f9 51 Ip6AddressCopy(pseudo.src, pSrcIp);
andrewboyson 49:1a6336f2b3f9 52 Ip6AddressCopy(pseudo.dst, pDstIp);
andrewboyson 43:bc028d5a6424 53 pseudo.len = NetToHost32(size);
andrewboyson 43:bc028d5a6424 54 pseudo.zer[0] = 0;
andrewboyson 43:bc028d5a6424 55 pseudo.zer[1] = 0;
andrewboyson 43:bc028d5a6424 56 pseudo.zer[2] = 0;
andrewboyson 43:bc028d5a6424 57 pseudo.pro = ICMP6;
andrewboyson 43:bc028d5a6424 58
andrewboyson 43:bc028d5a6424 59 return NetCheckSumTwo(sizeof(pseudo), &pseudo, size, pPacket);
andrewboyson 43:bc028d5a6424 60 }
andrewboyson 43:bc028d5a6424 61 static void logHeader()
andrewboyson 43:bc028d5a6424 62 {
andrewboyson 43:bc028d5a6424 63 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 64 {
andrewboyson 43:bc028d5a6424 65 Log ("ICMP6 header\r\n");
andrewboyson 47:73af5c0b0dc2 66 Log (" Type "); logType(type); Log("\r\n");
andrewboyson 43:bc028d5a6424 67 LogF(" Code %u\r\n", code);
andrewboyson 43:bc028d5a6424 68 LogF(" Checksum (hex) %04hX\r\n", checksum);
andrewboyson 43:bc028d5a6424 69 LogF(" Calculated %04hX\r\n", calculatedChecksum);
andrewboyson 43:bc028d5a6424 70 }
andrewboyson 43:bc028d5a6424 71 else
andrewboyson 43:bc028d5a6424 72 {
andrewboyson 43:bc028d5a6424 73 Log ("ICMP6 header ");
andrewboyson 47:73af5c0b0dc2 74 logType(type);
andrewboyson 43:bc028d5a6424 75 Log("\r\n");
andrewboyson 43:bc028d5a6424 76 }
andrewboyson 43:bc028d5a6424 77 }
andrewboyson 43:bc028d5a6424 78 static void readHeader(char* pSrcIp, char* pDstIp, void* pPacket, int size)
andrewboyson 43:bc028d5a6424 79 {
andrewboyson 43:bc028d5a6424 80 struct header* pHeader = (header*)pPacket;
andrewboyson 43:bc028d5a6424 81 type = pHeader->type;
andrewboyson 43:bc028d5a6424 82 code = pHeader->code;
andrewboyson 43:bc028d5a6424 83 checksum = NetToHost16(pHeader->checksum);
andrewboyson 43:bc028d5a6424 84 calculatedChecksum = calculateChecksum(pSrcIp, pDstIp, size, pPacket);
andrewboyson 43:bc028d5a6424 85 }
andrewboyson 43:bc028d5a6424 86 static void writeHeader(void* pPacket, int size, char* pSrcIp, char* pDstIp)
andrewboyson 43:bc028d5a6424 87 {
andrewboyson 43:bc028d5a6424 88 struct header* pHeader = (header*)pPacket;
andrewboyson 43:bc028d5a6424 89 pHeader->type = type;
andrewboyson 43:bc028d5a6424 90 pHeader->code = code;
andrewboyson 43:bc028d5a6424 91 pHeader->checksum = 0;
andrewboyson 47:73af5c0b0dc2 92 checksum = calculateChecksum(pSrcIp, pDstIp, size, pPacket);
andrewboyson 47:73af5c0b0dc2 93 pHeader->checksum = checksum;
andrewboyson 43:bc028d5a6424 94 calculatedChecksum = 0;
andrewboyson 43:bc028d5a6424 95 }
andrewboyson 43:bc028d5a6424 96 static void (*pTraceBack)(void);
andrewboyson 43:bc028d5a6424 97 static void trace()
andrewboyson 43:bc028d5a6424 98 {
andrewboyson 43:bc028d5a6424 99 pTraceBack();
andrewboyson 43:bc028d5a6424 100 logHeader();
andrewboyson 43:bc028d5a6424 101 }
andrewboyson 59:e0e556c8bd46 102 int Icmp6HandleReceivedPacket(void (*traceback)(void), int scope, void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* pSrcIp, char* pDstIp)
andrewboyson 43:bc028d5a6424 103 {
andrewboyson 43:bc028d5a6424 104 pTraceBack = traceback;
andrewboyson 59:e0e556c8bd46 105
andrewboyson 59:e0e556c8bd46 106 readHeader(pSrcIp, pDstIp, pPacketRx, sizeRx);
andrewboyson 43:bc028d5a6424 107
andrewboyson 59:e0e556c8bd46 108 int dataLengthRx = sizeRx - sizeof(header);
andrewboyson 59:e0e556c8bd46 109 int dataLengthTx = *pSizeTx - sizeof(header);
andrewboyson 59:e0e556c8bd46 110 char* pPayloadRx = (char*)pPacketRx + sizeof(header);
andrewboyson 59:e0e556c8bd46 111 char* pPayloadTx = (char*)pPacketTx + sizeof(header);
andrewboyson 43:bc028d5a6424 112
andrewboyson 43:bc028d5a6424 113 int action = DO_NOTHING;
andrewboyson 43:bc028d5a6424 114 switch (type)
andrewboyson 43:bc028d5a6424 115 {
andrewboyson 57:e0fb648acf48 116 case 1: //Destination unreacheable
andrewboyson 57:e0fb648acf48 117 action = Dest6HandleRequest(trace, &type, &code);
andrewboyson 57:e0fb648acf48 118 break;
andrewboyson 43:bc028d5a6424 119 case 128: //Echo request - Ping
andrewboyson 59:e0e556c8bd46 120 action = Echo6HandleRequest(trace, &type, &code, pPayloadRx, dataLengthRx, pPayloadTx, &dataLengthTx);
andrewboyson 43:bc028d5a6424 121 break;
andrewboyson 43:bc028d5a6424 122 case 133: //Router solicit
andrewboyson 43:bc028d5a6424 123 return DO_NOTHING; //We are not a router so quietly drop this
andrewboyson 43:bc028d5a6424 124 case 134: //Router advertisement
andrewboyson 59:e0e556c8bd46 125 action = RaHandleReceivedAdvertisement(trace, pPayloadRx, &dataLengthRx);
andrewboyson 43:bc028d5a6424 126 break;
andrewboyson 43:bc028d5a6424 127 case 135: //Neighbour solicit
andrewboyson 59:e0e556c8bd46 128 action = NsHandleReceivedSolicitation(trace, &type, &code, pPayloadRx, dataLengthRx, pPayloadTx, &dataLengthTx);
andrewboyson 43:bc028d5a6424 129 break;
andrewboyson 43:bc028d5a6424 130 case 136: //Neighbour advertisement
andrewboyson 59:e0e556c8bd46 131 action = NsHandleReceivedAdvertisement(trace, pPayloadRx, &dataLengthRx);
andrewboyson 43:bc028d5a6424 132 break;
andrewboyson 43:bc028d5a6424 133 default:
andrewboyson 48:952dddb74b8b 134 LogTimeF("ICMP6 unknown packet type %d\r\n", type);
andrewboyson 43:bc028d5a6424 135 return DO_NOTHING;
andrewboyson 43:bc028d5a6424 136 }
andrewboyson 43:bc028d5a6424 137 if (!action) return DO_NOTHING;
andrewboyson 43:bc028d5a6424 138
andrewboyson 49:1a6336f2b3f9 139 Ip6AddressCopy(pDstIp, pSrcIp);
andrewboyson 49:1a6336f2b3f9 140 SlaacAddressFromScope(scope, pSrcIp);
andrewboyson 49:1a6336f2b3f9 141 Ip6AddressFromDest (ActionGetDestPart(action), pDstIp);
andrewboyson 43:bc028d5a6424 142
andrewboyson 59:e0e556c8bd46 143 *pSizeTx = sizeof(header) + dataLengthTx;
andrewboyson 43:bc028d5a6424 144
andrewboyson 59:e0e556c8bd46 145 writeHeader(pPacketTx, *pSizeTx, pSrcIp, pDstIp);
andrewboyson 43:bc028d5a6424 146
andrewboyson 43:bc028d5a6424 147 if (ActionGetTracePart(action)) logHeader();
andrewboyson 43:bc028d5a6424 148
andrewboyson 43:bc028d5a6424 149 return action;
andrewboyson 43:bc028d5a6424 150 }
andrewboyson 43:bc028d5a6424 151 int Icmp6PollForPacketToSend(void* pPacket, int* pSize, char* pSrcIp, char* pDstIp)
andrewboyson 43:bc028d5a6424 152 {
andrewboyson 59:e0e556c8bd46 153 char* pData = (char*)pPacket + sizeof(header);
andrewboyson 59:e0e556c8bd46 154 int dataLength = *pSize - sizeof(header);
andrewboyson 43:bc028d5a6424 155 int action = DO_NOTHING;
andrewboyson 46:40d33e9037e4 156 if (!action) action = RsGetWaitingSolicitation(pData, &dataLength, &type, &code);
andrewboyson 43:bc028d5a6424 157 if (!action) action = NsGetWaitingSolicitation(pData, &dataLength, &type, &code);
andrewboyson 43:bc028d5a6424 158 if (!action) return DO_NOTHING;
andrewboyson 43:bc028d5a6424 159
andrewboyson 44:83ce5ace337b 160 int scope = SCOPE_LOCAL;
andrewboyson 49:1a6336f2b3f9 161 SlaacAddressFromScope(scope, pSrcIp);
andrewboyson 49:1a6336f2b3f9 162 Ip6AddressFromDest (ActionGetDestPart(action), pDstIp);
andrewboyson 43:bc028d5a6424 163
andrewboyson 59:e0e556c8bd46 164 *pSize = sizeof(header) + dataLength;
andrewboyson 43:bc028d5a6424 165
andrewboyson 43:bc028d5a6424 166 writeHeader(pPacket, *pSize, pSrcIp, pDstIp);
andrewboyson 43:bc028d5a6424 167
andrewboyson 43:bc028d5a6424 168 if (ActionGetTracePart(action)) logHeader();
andrewboyson 43:bc028d5a6424 169
andrewboyson 43:bc028d5a6424 170 return action;
andrewboyson 43:bc028d5a6424 171
andrewboyson 43:bc028d5a6424 172 }