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/ip6.c
- Committer:
- andrewboyson
- Date:
- 2020-04-02
- Revision:
- 167:3ba4e3c49631
- Parent:
- 136:8a65abb0dc63
- Child:
- 172:9bc3c7b2cca1
File content as of revision 167:3ba4e3c49631:
#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 "ip6hdr.h" #include "ndp.h" #include "ntp.h" #include "mac.h" #include "http.h" bool Ip6Trace = true; static void logHeader(char* pPacket) { if (NetTraceVerbose) { Log("IP6 header\r\n"); LogF(" Version %d\r\n", Ip6HdrGetVersion (pPacket)); LogF(" Payload length %d\r\n", Ip6HdrGetPayloadLen(pPacket)); LogF(" Hop limit %d\r\n", Ip6HdrGetHopLimit (pPacket)); LogF(" Protocol "); IpProtocolLog(Ip6HdrGetProtocol (pPacket)); Log("\r\n"); Log (" Source IP "); Ip6AddressLog(Ip6HdrPtrSrc (pPacket)); Log("\r\n"); Log (" Destination IP "); Ip6AddressLog(Ip6HdrPtrDst (pPacket)); Log("\r\n"); } else { Log("IP6 header "); IpProtocolLog(Ip6HdrGetProtocol(pPacket)); Log(" "); Ip6AddressLog(Ip6HdrPtrSrc (pPacket)); Log(" >>> "); Ip6AddressLog(Ip6HdrPtrDst (pPacket)); Log("\r\n"); } } static char* pTracePacket; static void (*pTraceBack)(void); static void trace() { pTraceBack(); logHeader(pTracePacket); } int Ip6HandleReceivedPacket(void (*traceback)(void), char* pPacketRx, int sizeRx, char* pPacketTx, int* pSizeTx, char* macRemote) { pTracePacket = pPacketRx; pTraceBack = traceback; char* pDataRx = pPacketRx + IP6_HEADER_LENGTH; char* pDataTx = pPacketTx + IP6_HEADER_LENGTH; int protocol = Ip6HdrGetProtocol (pPacketRx); int payloadLengthRx = Ip6HdrGetPayloadLen(pPacketRx); static char srcIp[16]; static char dstIp[16]; Ip6AddressCopy(srcIp, Ip6HdrPtrSrc (pPacketRx)); Ip6AddressCopy(dstIp, Ip6HdrPtrDst (pPacketRx)); int dataLengthRx = sizeRx - IP6_HEADER_LENGTH; if (dataLengthRx > payloadLengthRx) dataLengthRx = payloadLengthRx; //Choose the lesser of the data length and the payload length int dataLengthTx = *pSizeTx - IP6_HEADER_LENGTH; int scope = SlaacScope(dstIp); bool isMe = scope != SCOPE_NONE; bool isMulticast = Ip6AddrIsMulticast(dstIp); bool isSolicited = Ip6AddrIsSolicited(dstIp); bool isGroup = Ip6AddrIsSameGroup(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); int remArIndex = 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, remArIndex); break; default: LogTimeF("IP6 protocol %d unhandled\r\n", protocol); return DO_NOTHING; } if (!action) return DO_NOTHING; int hoplimit; if (NdpIpNeedsToBeRouted(dstIp)) { MacCopy(macRemote, NdpRouterMac); //Send to the router MAC hoplimit = NdpHopLimit; } else { hoplimit = 255; } Ip6HdrSetVersion (pPacketTx, 6 ); Ip6HdrSetPayloadLen(pPacketTx, dataLengthTx); Ip6HdrSetProtocol (pPacketTx, protocol ); Ip6HdrSetHopLimit (pPacketTx, hoplimit ); Ip6AddressCopy(Ip6HdrPtrSrc(pPacketTx), srcIp); Ip6AddressCopy(Ip6HdrPtrDst(pPacketTx), dstIp); *pSizeTx = IP6_HEADER_LENGTH + dataLengthTx; if (ActionGetTracePart(action)) logHeader(pPacketTx); return action; } int Ip6PollForPacketToSend(char* pPacket, int* pSize, char* pDstMac) { static char srcIp[16]; static char dstIp[16]; char* pData = pPacket + IP6_HEADER_LENGTH; int dataLength = *pSize - IP6_HEADER_LENGTH; int protocol = 0; 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) { action = Tcp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp); protocol = TCP; } if (!action) return DO_NOTHING; int hoplimit = 0; 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 MULTICAST_NTP: case SOLICITED_NODE: hoplimit = 255; break; default: LogTimeF("Ip6PollForPacketToSend - undefined destination %d\r\n", dest); return DO_NOTHING; } Ip6HdrSetVersion (pPacket, 6 ); Ip6HdrSetPayloadLen(pPacket, dataLength); Ip6HdrSetProtocol (pPacket, protocol ); Ip6HdrSetHopLimit (pPacket, hoplimit ); Ip6AddressCopy(Ip6HdrPtrSrc(pPacket), srcIp); Ip6AddressCopy(Ip6HdrPtrDst(pPacket), dstIp); *pSize = IP6_HEADER_LENGTH + dataLength; if (ActionGetTracePart(action)) logHeader(pPacket); return action; }