Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
ip6/icmp/icmp6.cpp
- Committer:
- andrewboyson
- Date:
- 2017-10-31
- Revision:
- 48:952dddb74b8b
- Parent:
- 47:73af5c0b0dc2
- Child:
- 49:1a6336f2b3f9
File content as of revision 48:952dddb74b8b:
#include "mbed.h"
#include "log.h"
#include "net.h"
#include "action.h"
#include "ns.h"
#include "ra.h"
#include "rs.h"
#include "ip.h"
#include "ip6.h"
#include "slaac.h"
#include "echo6.h"
#define HEADER_LENGTH 4
__packed struct header
{
uint8_t type;
uint8_t code;
uint16_t checksum;
};
static uint8_t type;
static uint8_t code;
static uint16_t checksum;
static uint16_t calculatedChecksum;
static int dataLength;
static void* pData;
static void logType(uint8_t type)
{
switch (type)
{
case 1: Log ("Destination uneaceable" ); break;
case 128: Log ("Echo Request" ); break;
case 129: Log ("Echo Reply" ); break;
case 133: Log ("Router solicit" ); break;
case 134: Log ("Router advertisement" ); break;
case 135: Log ("Neighbour solicit" ); break;
case 136: Log ("Neighbour advertisement"); break;
case 137: Log ("Redirect" ); break;
default: LogF("Unknown type %u", type ); break;
}
}
static uint16_t calculateChecksum(char* pSrcIp, char* pDstIp, int size, void* pPacket)
{
__packed struct pseudo
{
char src[16];
char dst[16];
uint32_t len;
uint8_t zer[3];
uint8_t pro;
} pseudo;
Ip6Copy(pseudo.src, pSrcIp);
Ip6Copy(pseudo.dst, pDstIp);
pseudo.len = NetToHost32(size);
pseudo.zer[0] = 0;
pseudo.zer[1] = 0;
pseudo.zer[2] = 0;
pseudo.pro = ICMP6;
return NetCheckSumTwo(sizeof(pseudo), &pseudo, size, pPacket);
}
static void logHeader()
{
if (NetTraceVerbose)
{
Log ("ICMP6 header\r\n");
Log (" Type "); logType(type); Log("\r\n");
LogF(" Code %u\r\n", code);
LogF(" Checksum (hex) %04hX\r\n", checksum);
LogF(" Calculated %04hX\r\n", calculatedChecksum);
LogF(" Data length %d\r\n", dataLength);
}
else
{
Log ("ICMP6 header ");
logType(type);
Log("\r\n");
}
}
static void readHeader(char* pSrcIp, char* pDstIp, void* pPacket, int size)
{
struct header* pHeader = (header*)pPacket;
type = pHeader->type;
code = pHeader->code;
checksum = NetToHost16(pHeader->checksum);
calculatedChecksum = calculateChecksum(pSrcIp, pDstIp, size, pPacket);
pData = (char*)pPacket + HEADER_LENGTH;
dataLength = size - HEADER_LENGTH;
}
static void writeHeader(void* pPacket, int size, char* pSrcIp, char* pDstIp)
{
struct header* pHeader = (header*)pPacket;
pHeader->type = type;
pHeader->code = code;
pHeader->checksum = 0;
checksum = calculateChecksum(pSrcIp, pDstIp, size, pPacket);
pHeader->checksum = checksum;
calculatedChecksum = 0;
}
static void (*pTraceBack)(void);
static void trace()
{
pTraceBack();
logHeader();
}
int Icmp6HandleReceivedPacket(void (*traceback)(void), int scope, char* pSrcIp, char* pDstIp, int* pSize, void* pPacket)
{
pTraceBack = traceback;
readHeader(pSrcIp, pDstIp, pPacket, *pSize);
int action = DO_NOTHING;
switch (type)
{
case 128: //Echo request - Ping
action = Echo6HandleRequest(trace, &type, &code);
break;
case 133: //Router solicit
return DO_NOTHING; //We are not a router so quietly drop this
case 134: //Router advertisement
action = RaHandleReceivedAdvertisement(trace, pData, &dataLength);
break;
case 135: //Neighbour solicit
action = NsHandleReceivedSolicitation(trace, pData, &dataLength, &type, &code);
break;
case 136: //Neighbour advertisement
action = NsHandleReceivedAdvertisement(trace, pData, &dataLength);
break;
default:
LogTimeF("ICMP6 unknown packet type %d\r\n", type);
return DO_NOTHING;
}
if (!action) return DO_NOTHING;
Ip6Copy(pDstIp, pSrcIp);
Ip6SrcIpFromScope(scope, pSrcIp);
Ip6DstIpFromDest (ActionGetDestPart(action), pDstIp);
*pSize = HEADER_LENGTH + dataLength;
writeHeader(pPacket, *pSize, pSrcIp, pDstIp);
if (ActionGetTracePart(action)) logHeader();
return action;
}
int Icmp6PollForPacketToSend(void* pPacket, int* pSize, char* pSrcIp, char* pDstIp)
{
pData = (char*)pPacket + HEADER_LENGTH;
int action = DO_NOTHING;
if (!action) action = RsGetWaitingSolicitation(pData, &dataLength, &type, &code);
if (!action) action = NsGetWaitingSolicitation(pData, &dataLength, &type, &code);
if (!action) return DO_NOTHING;
int scope = SCOPE_LOCAL;
Ip6SrcIpFromScope(scope, pSrcIp);
Ip6DstIpFromDest (ActionGetDestPart(action), pDstIp);
*pSize = HEADER_LENGTH + dataLength;
writeHeader(pPacket, *pSize, pSrcIp, pDstIp);
if (ActionGetTracePart(action)) logHeader();
return action;
}