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:
Tue Oct 24 07:01:35 2017 +0000
Revision:
46:40d33e9037e4
Parent:
44:83ce5ace337b
Child:
47:73af5c0b0dc2
Tidied up the RA module

Who changed what in which revision?

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