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
ip6/icmp/icmp6.c@151:bde6f7da1755, 2019-07-19 (annotated)
- Committer:
- andrewboyson
- Date:
- Fri Jul 19 17:48:06 2019 +0000
- Revision:
- 151:bde6f7da1755
- Parent:
- 138:5ff0c7069300
- Child:
- 172:9bc3c7b2cca1
Removed private key and certificate from semihost storage as found to be unreliable (though secure) and moved it into flash storage (reliable, simple, but visible on mbed.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 61:aad055f1b0d1 | 1 | #include <stdint.h> |
andrewboyson | 61:aad055f1b0d1 | 2 | |
andrewboyson | 57:e0fb648acf48 | 3 | #include "log.h" |
andrewboyson | 57:e0fb648acf48 | 4 | #include "net.h" |
andrewboyson | 57:e0fb648acf48 | 5 | #include "action.h" |
andrewboyson | 57:e0fb648acf48 | 6 | #include "ns.h" |
andrewboyson | 57:e0fb648acf48 | 7 | #include "ra.h" |
andrewboyson | 57:e0fb648acf48 | 8 | #include "rs.h" |
andrewboyson | 57:e0fb648acf48 | 9 | #include "ip.h" |
andrewboyson | 49:1a6336f2b3f9 | 10 | #include "ip6addr.h" |
andrewboyson | 57:e0fb648acf48 | 11 | #include "slaac.h" |
andrewboyson | 57:e0fb648acf48 | 12 | #include "echo6.h" |
andrewboyson | 57:e0fb648acf48 | 13 | #include "dest6.h" |
andrewboyson | 136:8a65abb0dc63 | 14 | #include "checksum.h" |
andrewboyson | 43:bc028d5a6424 | 15 | |
andrewboyson | 138:5ff0c7069300 | 16 | static char* hdrPtrType (char* pPacket) { return pPacket + 0; } //1 |
andrewboyson | 138:5ff0c7069300 | 17 | static char* hdrPtrCode (char* pPacket) { return pPacket + 1; } //1 |
andrewboyson | 138:5ff0c7069300 | 18 | static char* hdrPtrChecksum(char* pPacket) { return pPacket + 2; } //2 |
andrewboyson | 138:5ff0c7069300 | 19 | static const int HEADER_LENGTH = 4; |
andrewboyson | 138:5ff0c7069300 | 20 | |
andrewboyson | 43:bc028d5a6424 | 21 | static uint8_t type; |
andrewboyson | 43:bc028d5a6424 | 22 | static uint8_t code; |
andrewboyson | 43:bc028d5a6424 | 23 | static uint16_t checksum; |
andrewboyson | 43:bc028d5a6424 | 24 | static uint16_t calculatedChecksum; |
andrewboyson | 43:bc028d5a6424 | 25 | |
andrewboyson | 47:73af5c0b0dc2 | 26 | static void logType(uint8_t type) |
andrewboyson | 43:bc028d5a6424 | 27 | { |
andrewboyson | 43:bc028d5a6424 | 28 | switch (type) |
andrewboyson | 43:bc028d5a6424 | 29 | { |
andrewboyson | 49:1a6336f2b3f9 | 30 | case 1: Log ("Destination unreacheable" ); break; |
andrewboyson | 49:1a6336f2b3f9 | 31 | case 128: Log ("Echo Request" ); break; |
andrewboyson | 49:1a6336f2b3f9 | 32 | case 129: Log ("Echo Reply" ); break; |
andrewboyson | 57:e0fb648acf48 | 33 | case 133: Log ("Router solicit" ); break; |
andrewboyson | 57:e0fb648acf48 | 34 | case 134: Log ("Router advertisement" ); break; |
andrewboyson | 57:e0fb648acf48 | 35 | case 135: Log ("Neighbour solicit" ); break; |
andrewboyson | 57:e0fb648acf48 | 36 | case 136: Log ("Neighbour advertisement" ); break; |
andrewboyson | 57:e0fb648acf48 | 37 | case 137: Log ("Redirect" ); break; |
andrewboyson | 57:e0fb648acf48 | 38 | default: LogF("Unknown type %u", type ); break; |
andrewboyson | 43:bc028d5a6424 | 39 | } |
andrewboyson | 43:bc028d5a6424 | 40 | } |
andrewboyson | 138:5ff0c7069300 | 41 | static uint16_t calculateChecksum(char* pSrcIp, char* pDstIp, int size, char* pPacket) |
andrewboyson | 136:8a65abb0dc63 | 42 | { |
andrewboyson | 136:8a65abb0dc63 | 43 | uint32_t sum = 0; |
andrewboyson | 136:8a65abb0dc63 | 44 | uint32_t pro32 = ICMP6; |
andrewboyson | 136:8a65abb0dc63 | 45 | sum = CheckSumAddDirect(sum, 16, pSrcIp ); |
andrewboyson | 136:8a65abb0dc63 | 46 | sum = CheckSumAddDirect(sum, 16, pDstIp ); |
andrewboyson | 136:8a65abb0dc63 | 47 | sum = CheckSumAddInvert(sum, 4, &size ); |
andrewboyson | 136:8a65abb0dc63 | 48 | sum = CheckSumAddInvert(sum, 4, &pro32 ); |
andrewboyson | 136:8a65abb0dc63 | 49 | return CheckSumFinDirect(sum, size, pPacket); |
andrewboyson | 43:bc028d5a6424 | 50 | } |
andrewboyson | 43:bc028d5a6424 | 51 | static void logHeader() |
andrewboyson | 43:bc028d5a6424 | 52 | { |
andrewboyson | 43:bc028d5a6424 | 53 | if (NetTraceVerbose) |
andrewboyson | 43:bc028d5a6424 | 54 | { |
andrewboyson | 43:bc028d5a6424 | 55 | Log ("ICMP6 header\r\n"); |
andrewboyson | 47:73af5c0b0dc2 | 56 | Log (" Type "); logType(type); Log("\r\n"); |
andrewboyson | 43:bc028d5a6424 | 57 | LogF(" Code %u\r\n", code); |
andrewboyson | 43:bc028d5a6424 | 58 | LogF(" Checksum (hex) %04hX\r\n", checksum); |
andrewboyson | 43:bc028d5a6424 | 59 | LogF(" Calculated %04hX\r\n", calculatedChecksum); |
andrewboyson | 43:bc028d5a6424 | 60 | } |
andrewboyson | 43:bc028d5a6424 | 61 | else |
andrewboyson | 43:bc028d5a6424 | 62 | { |
andrewboyson | 43:bc028d5a6424 | 63 | Log ("ICMP6 header "); |
andrewboyson | 47:73af5c0b0dc2 | 64 | logType(type); |
andrewboyson | 43:bc028d5a6424 | 65 | Log("\r\n"); |
andrewboyson | 43:bc028d5a6424 | 66 | } |
andrewboyson | 43:bc028d5a6424 | 67 | } |
andrewboyson | 138:5ff0c7069300 | 68 | static void readHeader(char* pSrcIp, char* pDstIp, char* pPacket, int size) |
andrewboyson | 43:bc028d5a6424 | 69 | { |
andrewboyson | 138:5ff0c7069300 | 70 | type = *hdrPtrType(pPacket); |
andrewboyson | 138:5ff0c7069300 | 71 | code = *hdrPtrCode(pPacket); |
andrewboyson | 138:5ff0c7069300 | 72 | NetDirect16(&checksum, hdrPtrChecksum(pPacket)); |
andrewboyson | 43:bc028d5a6424 | 73 | calculatedChecksum = calculateChecksum(pSrcIp, pDstIp, size, pPacket); |
andrewboyson | 43:bc028d5a6424 | 74 | } |
andrewboyson | 138:5ff0c7069300 | 75 | static void writeHeader(char* pPacket, int size, char* pSrcIp, char* pDstIp) |
andrewboyson | 138:5ff0c7069300 | 76 | { |
andrewboyson | 138:5ff0c7069300 | 77 | *hdrPtrType(pPacket) = type; |
andrewboyson | 138:5ff0c7069300 | 78 | *hdrPtrCode(pPacket) = code; |
andrewboyson | 138:5ff0c7069300 | 79 | checksum = 0; |
andrewboyson | 138:5ff0c7069300 | 80 | NetDirect16(hdrPtrChecksum(pPacket), &checksum); |
andrewboyson | 47:73af5c0b0dc2 | 81 | checksum = calculateChecksum(pSrcIp, pDstIp, size, pPacket); |
andrewboyson | 138:5ff0c7069300 | 82 | NetDirect16(hdrPtrChecksum(pPacket), &checksum); |
andrewboyson | 43:bc028d5a6424 | 83 | calculatedChecksum = 0; |
andrewboyson | 43:bc028d5a6424 | 84 | } |
andrewboyson | 43:bc028d5a6424 | 85 | static void (*pTraceBack)(void); |
andrewboyson | 43:bc028d5a6424 | 86 | static void trace() |
andrewboyson | 43:bc028d5a6424 | 87 | { |
andrewboyson | 43:bc028d5a6424 | 88 | pTraceBack(); |
andrewboyson | 43:bc028d5a6424 | 89 | logHeader(); |
andrewboyson | 43:bc028d5a6424 | 90 | } |
andrewboyson | 138:5ff0c7069300 | 91 | int Icmp6HandleReceivedPacket(void (*traceback)(void), int scope, char* pPacketRx, int sizeRx, char* pPacketTx, int* pSizeTx, char* pSrcIp, char* pDstIp) |
andrewboyson | 43:bc028d5a6424 | 92 | { |
andrewboyson | 43:bc028d5a6424 | 93 | pTraceBack = traceback; |
andrewboyson | 59:e0e556c8bd46 | 94 | |
andrewboyson | 59:e0e556c8bd46 | 95 | readHeader(pSrcIp, pDstIp, pPacketRx, sizeRx); |
andrewboyson | 43:bc028d5a6424 | 96 | |
andrewboyson | 138:5ff0c7069300 | 97 | int dataLengthRx = sizeRx - HEADER_LENGTH; |
andrewboyson | 138:5ff0c7069300 | 98 | int dataLengthTx = *pSizeTx - HEADER_LENGTH; |
andrewboyson | 138:5ff0c7069300 | 99 | char* pPayloadRx = pPacketRx + HEADER_LENGTH; |
andrewboyson | 138:5ff0c7069300 | 100 | char* pPayloadTx = pPacketTx + HEADER_LENGTH; |
andrewboyson | 43:bc028d5a6424 | 101 | |
andrewboyson | 43:bc028d5a6424 | 102 | int action = DO_NOTHING; |
andrewboyson | 43:bc028d5a6424 | 103 | switch (type) |
andrewboyson | 43:bc028d5a6424 | 104 | { |
andrewboyson | 57:e0fb648acf48 | 105 | case 1: //Destination unreacheable |
andrewboyson | 57:e0fb648acf48 | 106 | action = Dest6HandleRequest(trace, &type, &code); |
andrewboyson | 57:e0fb648acf48 | 107 | break; |
andrewboyson | 43:bc028d5a6424 | 108 | case 128: //Echo request - Ping |
andrewboyson | 59:e0e556c8bd46 | 109 | action = Echo6HandleRequest(trace, &type, &code, pPayloadRx, dataLengthRx, pPayloadTx, &dataLengthTx); |
andrewboyson | 43:bc028d5a6424 | 110 | break; |
andrewboyson | 43:bc028d5a6424 | 111 | case 133: //Router solicit |
andrewboyson | 43:bc028d5a6424 | 112 | return DO_NOTHING; //We are not a router so quietly drop this |
andrewboyson | 43:bc028d5a6424 | 113 | case 134: //Router advertisement |
andrewboyson | 59:e0e556c8bd46 | 114 | action = RaHandleReceivedAdvertisement(trace, pPayloadRx, &dataLengthRx); |
andrewboyson | 43:bc028d5a6424 | 115 | break; |
andrewboyson | 43:bc028d5a6424 | 116 | case 135: //Neighbour solicit |
andrewboyson | 59:e0e556c8bd46 | 117 | action = NsHandleReceivedSolicitation(trace, &type, &code, pPayloadRx, dataLengthRx, pPayloadTx, &dataLengthTx); |
andrewboyson | 43:bc028d5a6424 | 118 | break; |
andrewboyson | 43:bc028d5a6424 | 119 | case 136: //Neighbour advertisement |
andrewboyson | 59:e0e556c8bd46 | 120 | action = NsHandleReceivedAdvertisement(trace, pPayloadRx, &dataLengthRx); |
andrewboyson | 43:bc028d5a6424 | 121 | break; |
andrewboyson | 43:bc028d5a6424 | 122 | default: |
andrewboyson | 48:952dddb74b8b | 123 | LogTimeF("ICMP6 unknown packet type %d\r\n", type); |
andrewboyson | 43:bc028d5a6424 | 124 | return DO_NOTHING; |
andrewboyson | 43:bc028d5a6424 | 125 | } |
andrewboyson | 43:bc028d5a6424 | 126 | if (!action) return DO_NOTHING; |
andrewboyson | 43:bc028d5a6424 | 127 | |
andrewboyson | 49:1a6336f2b3f9 | 128 | Ip6AddressCopy(pDstIp, pSrcIp); |
andrewboyson | 49:1a6336f2b3f9 | 129 | SlaacAddressFromScope(scope, pSrcIp); |
andrewboyson | 49:1a6336f2b3f9 | 130 | Ip6AddressFromDest (ActionGetDestPart(action), pDstIp); |
andrewboyson | 43:bc028d5a6424 | 131 | |
andrewboyson | 138:5ff0c7069300 | 132 | *pSizeTx = HEADER_LENGTH + dataLengthTx; |
andrewboyson | 43:bc028d5a6424 | 133 | |
andrewboyson | 59:e0e556c8bd46 | 134 | writeHeader(pPacketTx, *pSizeTx, pSrcIp, pDstIp); |
andrewboyson | 43:bc028d5a6424 | 135 | |
andrewboyson | 43:bc028d5a6424 | 136 | if (ActionGetTracePart(action)) logHeader(); |
andrewboyson | 43:bc028d5a6424 | 137 | |
andrewboyson | 43:bc028d5a6424 | 138 | return action; |
andrewboyson | 43:bc028d5a6424 | 139 | } |
andrewboyson | 138:5ff0c7069300 | 140 | int Icmp6PollForPacketToSend(char* pPacket, int* pSize, char* pSrcIp, char* pDstIp) |
andrewboyson | 43:bc028d5a6424 | 141 | { |
andrewboyson | 138:5ff0c7069300 | 142 | char* pData = pPacket + HEADER_LENGTH; |
andrewboyson | 138:5ff0c7069300 | 143 | int dataLength = *pSize - HEADER_LENGTH; |
andrewboyson | 43:bc028d5a6424 | 144 | int action = DO_NOTHING; |
andrewboyson | 46:40d33e9037e4 | 145 | if (!action) action = RsGetWaitingSolicitation(pData, &dataLength, &type, &code); |
andrewboyson | 43:bc028d5a6424 | 146 | if (!action) action = NsGetWaitingSolicitation(pData, &dataLength, &type, &code); |
andrewboyson | 43:bc028d5a6424 | 147 | if (!action) return DO_NOTHING; |
andrewboyson | 43:bc028d5a6424 | 148 | |
andrewboyson | 44:83ce5ace337b | 149 | int scope = SCOPE_LOCAL; |
andrewboyson | 49:1a6336f2b3f9 | 150 | SlaacAddressFromScope(scope, pSrcIp); |
andrewboyson | 49:1a6336f2b3f9 | 151 | Ip6AddressFromDest (ActionGetDestPart(action), pDstIp); |
andrewboyson | 43:bc028d5a6424 | 152 | |
andrewboyson | 138:5ff0c7069300 | 153 | *pSize = HEADER_LENGTH + dataLength; |
andrewboyson | 43:bc028d5a6424 | 154 | |
andrewboyson | 43:bc028d5a6424 | 155 | writeHeader(pPacket, *pSize, pSrcIp, pDstIp); |
andrewboyson | 43:bc028d5a6424 | 156 | |
andrewboyson | 43:bc028d5a6424 | 157 | if (ActionGetTracePart(action)) logHeader(); |
andrewboyson | 43:bc028d5a6424 | 158 | |
andrewboyson | 43:bc028d5a6424 | 159 | return action; |
andrewboyson | 43:bc028d5a6424 | 160 | |
andrewboyson | 43:bc028d5a6424 | 161 | } |