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
Diff: ip6/ip6.c
- Revision:
- 61:aad055f1b0d1
- Parent:
- 59:e0e556c8bd46
- Child:
- 71:736a5747ade1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ip6/ip6.c Thu Jan 11 17:38:21 2018 +0000 @@ -0,0 +1,254 @@ +#include <stdint.h> +#include <stdbool.h> + +#include "log.h" +#include "net.h" +#include "action.h" +#include "icmp6.h" +#include "udptcp6.h" +#include "ar6.h" +#include "nr6.h" +#include "slaac.h" +#include "eth.h" +#include "ip.h" +#include "ip6addr.h" +#include "ndp.h" +#include "ntp.h" +#include "mac.h" +#include "http.h" + +bool Ip6Trace = true; + +__packed struct header +{ + uint32_t versionTrafficFlow; + uint16_t payloadLength; + uint8_t protocol; + uint8_t hoplimit; + char src[16]; + char dst[16]; +}; + +static uint8_t version; +static int payloadLength; +static uint8_t protocol; +static uint8_t hoplimit; +static char srcIp[16]; +static char dstIp[16]; + +static void readHeader(struct header * pHeader) +{ + version = (pHeader->versionTrafficFlow >> 4) & 0x0F; + payloadLength = NetToHost16(pHeader->payloadLength); + protocol = pHeader->protocol; + hoplimit = pHeader->hoplimit; + Ip6AddressCopy(srcIp, pHeader->src); + Ip6AddressCopy(dstIp, pHeader->dst); +} +static void writeHeader(struct header * pHeader) +{ + pHeader->versionTrafficFlow = version << 4; + pHeader->payloadLength = NetToHost16(payloadLength); + pHeader->protocol = protocol; + pHeader->hoplimit = hoplimit; + Ip6AddressCopy(pHeader->dst, dstIp); + Ip6AddressCopy(pHeader->src, srcIp); +} + +static void logHeader() +{ + if (NetTraceVerbose) + { + Log("IP6 header\r\n"); + LogF(" Version %d\r\n", version); + LogF(" Payload length %d\r\n", payloadLength); + LogF(" Hop limit %d\r\n", hoplimit); + LogF(" Protocol "); IpProtocolLog(protocol); Log("\r\n"); + Log (" Source IP "); Ip6AddressLog(srcIp); Log("\r\n"); + Log (" Destination IP "); Ip6AddressLog(dstIp); Log("\r\n"); + } + else + { + Log("IP6 header "); + IpProtocolLog(protocol); + Log(" "); + Ip6AddressLog(srcIp); + Log(" >>> "); + Ip6AddressLog(dstIp); + Log("\r\n"); + } +} + +static bool getIsSolicited(char* p) +{ + if (*p++ != 0xff) return false; + if (*p++ != 0x02) return false; + + if (*p++ != 0x00) return false; + if (*p++ != 0x00) return false; + + if (*p++ != 0x00) return false; + if (*p++ != 0x00) return false; + + if (*p++ != 0x00) return false; + if (*p++ != 0x00) return false; + + if (*p++ != 0x00) return false; + if (*p++ != 0x00) return false; + + if (*p++ != 0x00) return false; + if (*p++ != 0x01) return false; + + if (*p++ != 0xff) return false; + + return true; +} +static bool getIsSameGroup(char* pA, char* pB) +{ + pA += 13; + pB += 13; + if (*pA++ != *pB++) return false; + if (*pA++ != *pB++) return false; + return *pA == *pB; +} +static void (*pTraceBack)(void); +static void trace() +{ + pTraceBack(); + logHeader(); +} +int Ip6HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* macRemote) +{ + pTraceBack = traceback; + + struct header* pHeaderRx = (struct header*)pPacketRx; + struct header* pHeaderTx = (struct header*)pPacketTx; + + char* pDataRx = (char*)pHeaderRx + sizeof(struct header); + char* pDataTx = (char*)pHeaderTx + sizeof(struct header); + + readHeader(pHeaderRx); //This also fetches the payload length out of the header + + int dataLengthRx = sizeRx - sizeof(struct header); + if (payloadLength < dataLengthRx) dataLengthRx = payloadLength; //Choose the lesser of the data length and the payload length + int dataLengthTx = *pSizeTx - sizeof(struct header); + + int scope = SlaacScope(dstIp); + bool isMe = scope != SCOPE_NONE; + bool isMulticast = dstIp[0] == 0xFF; + bool isSolicited = getIsSolicited(dstIp); + bool isGroup = getIsSameGroup(dstIp, SlaacLinkLocalIp); + + bool doIt = isMe || (isMulticast && !isSolicited) || (isGroup && isSolicited); + + if (!doIt) + { + if (Ip6Trace) + { + LogTime("IP6 filtered out ip "); + Ip6AddressLog(dstIp); + LogF(" from "); + Ip6AddressLog(srcIp); + Log("\r\n"); + } + return DO_NOTHING; + } + + NetTraceHostCheckIp6(srcIp); + + Ar6AddIpRecord(trace, macRemote, srcIp); + Nr6MakeRequestForNameFromIp(srcIp); + + int action = DO_NOTHING; + switch (protocol) + { + case HOPOPT: action = DO_NOTHING; break; + case ICMP6: action = Icmp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break; + case UDP: action = Udp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break; + case TCP: action = Tcp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break; + default: + LogTimeF("IP6 protocol %d unhandled\r\n", protocol); + return DO_NOTHING; + } + if (!action) return DO_NOTHING; + + if (NdpIpNeedsToBeRouted(dstIp)) + { + MacCopy(macRemote, NdpRouterMac); //Send to the router MAC + hoplimit = NdpHopLimit; + } + else + { + hoplimit = 255; + } + + payloadLength = dataLengthTx; + + writeHeader(pHeaderTx); + + *pSizeTx = sizeof(struct header) + payloadLength; + + if (ActionGetTracePart(action)) logHeader(); + + return action; +} +int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac) +{ + char* pData = (char*)pPacket + sizeof(struct header); + int dataLength = *pSize - sizeof(struct header); + + int action = DO_NOTHING; + if (!action) + { + action = Icmp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp); + protocol = ICMP6; + } + + if (!action) + { + action = Udp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp); + protocol = UDP; + } + if (!action) return DO_NOTHING; + + int dest = ActionGetDestPart(action); + switch (dest) + { + case UNICAST: + case UNICAST_DNS: + case UNICAST_DHCP: + case UNICAST_NTP: + case UNICAST_TFTP: + if (NdpIpNeedsToBeRouted(dstIp)) + { + MacCopy(pDstMac, NdpRouterMac); //Send to the router MAC + hoplimit = NdpHopLimit; + } + else + { + Ar6IpToMac(dstIp, pDstMac); //Make the remote MAC from NP + hoplimit = 255; + } + break; + case MULTICAST_NODE: + case MULTICAST_ROUTER: + case MULTICAST_MDNS: + case MULTICAST_LLMNR: + case SOLICITED_NODE: + hoplimit = 255; + break; + default: + LogTimeF("Ip6PollForPacketToSend - undefined destination %d\r\n", dest); + return DO_NOTHING; + } + + payloadLength = dataLength; + version = 6; + writeHeader((struct header*)pPacket); + + *pSize = sizeof(struct header) + payloadLength; + + if (ActionGetTracePart(action)) logHeader(); + + return action; +}