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 Apr 18 19:07:05 2017 +0000
Revision:
11:c051adb70c5a
Parent:
10:f0854784e960
Child:
13:9cd54f7db57a
Tidied IPv6 code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 11:c051adb70c5a 1 #include "mbed.h"
andrewboyson 11:c051adb70c5a 2 #include "log.h"
andrewboyson 11:c051adb70c5a 3 #include "net.h"
andrewboyson 11:c051adb70c5a 4 #include "icmp6.h"
andrewboyson 11:c051adb70c5a 5 #include "udptcp6.h"
andrewboyson 11:c051adb70c5a 6 #include "ar.h"
andrewboyson 11:c051adb70c5a 7 #include "slaac.h"
andrewboyson 11:c051adb70c5a 8 #include "eth.h"
andrewboyson 11:c051adb70c5a 9 #include "ip6.h"
andrewboyson 11:c051adb70c5a 10 #include "ndp.h"
andrewboyson 11:c051adb70c5a 11
andrewboyson 11:c051adb70c5a 12 #define DEBUG false
andrewboyson 11:c051adb70c5a 13
andrewboyson 11:c051adb70c5a 14 char Ip6AllNodes [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
andrewboyson 11:c051adb70c5a 15 char Ip6AllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
andrewboyson 11:c051adb70c5a 16 char Ip6Mdns [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb};
andrewboyson 11:c051adb70c5a 17 char Ip6Llmnr [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03};
andrewboyson 11:c051adb70c5a 18
andrewboyson 11:c051adb70c5a 19 void Ip6DestIpFromAction(int action, char* pDstIp)
andrewboyson 11:c051adb70c5a 20 {
andrewboyson 11:c051adb70c5a 21 switch (action)
andrewboyson 11:c051adb70c5a 22 {
andrewboyson 11:c051adb70c5a 23 case UNICAST: break;
andrewboyson 11:c051adb70c5a 24 case UNICAST_DNS: memcpy(pDstIp, NdpDnsServer, 16); break;
andrewboyson 11:c051adb70c5a 25 case MULTICAST_NODE: memcpy(pDstIp, Ip6AllNodes, 16); break;
andrewboyson 11:c051adb70c5a 26 case MULTICAST_ROUTER: memcpy(pDstIp, Ip6AllRouters, 16); break;
andrewboyson 11:c051adb70c5a 27 case MULTICAST_MDNS: memcpy(pDstIp, Ip6Mdns, 16); break;
andrewboyson 11:c051adb70c5a 28 case MULTICAST_LLMNR: memcpy(pDstIp, Ip6Llmnr, 16); break;
andrewboyson 11:c051adb70c5a 29 default:
andrewboyson 11:c051adb70c5a 30 LogTimeF("Ip6 DestIpFromAction unknown action %d\r\n", action);
andrewboyson 11:c051adb70c5a 31 break;
andrewboyson 11:c051adb70c5a 32 }
andrewboyson 11:c051adb70c5a 33 }
andrewboyson 10:f0854784e960 34
andrewboyson 10:f0854784e960 35 #define HEADER_LENGTH 40
andrewboyson 10:f0854784e960 36 __packed struct header
andrewboyson 10:f0854784e960 37 {
andrewboyson 10:f0854784e960 38 uint32_t versionTrafficFlow;
andrewboyson 10:f0854784e960 39 uint16_t dataLength;
andrewboyson 10:f0854784e960 40 uint8_t protocol;
andrewboyson 10:f0854784e960 41 uint8_t hoplimit;
andrewboyson 10:f0854784e960 42 char src[16];
andrewboyson 10:f0854784e960 43 char dst[16];
andrewboyson 10:f0854784e960 44 };
andrewboyson 11:c051adb70c5a 45
andrewboyson 11:c051adb70c5a 46 static uint8_t version;
andrewboyson 11:c051adb70c5a 47 static int dataLength;
andrewboyson 11:c051adb70c5a 48 static uint8_t protocol;
andrewboyson 11:c051adb70c5a 49 static uint8_t hoplimit;
andrewboyson 11:c051adb70c5a 50 static char pSrcIp[16];
andrewboyson 11:c051adb70c5a 51 static char pDstIp[16];
andrewboyson 11:c051adb70c5a 52 static void* pData;
andrewboyson 11:c051adb70c5a 53
andrewboyson 11:c051adb70c5a 54 static void readHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 55 {
andrewboyson 11:c051adb70c5a 56 version = (pHeader->versionTrafficFlow >> 4) & 0xF;
andrewboyson 11:c051adb70c5a 57 dataLength = NetToHost16(pHeader->dataLength);
andrewboyson 11:c051adb70c5a 58 protocol = pHeader->protocol;
andrewboyson 11:c051adb70c5a 59 hoplimit = pHeader->hoplimit;
andrewboyson 11:c051adb70c5a 60 memcpy(pSrcIp, pHeader->src, 16);
andrewboyson 11:c051adb70c5a 61 memcpy(pDstIp, pHeader->dst, 16);
andrewboyson 11:c051adb70c5a 62 pData = (char*)pHeader + HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 63 }
andrewboyson 11:c051adb70c5a 64 static void writeHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 65 {
andrewboyson 11:c051adb70c5a 66 pHeader->versionTrafficFlow = version << 4;
andrewboyson 11:c051adb70c5a 67 pHeader->protocol = protocol;
andrewboyson 11:c051adb70c5a 68 pHeader->hoplimit = 255;
andrewboyson 11:c051adb70c5a 69 memcpy(pHeader->dst, pDstIp, 16);
andrewboyson 11:c051adb70c5a 70 memcpy(pHeader->src, pSrcIp, 16);
andrewboyson 11:c051adb70c5a 71 pHeader->dataLength = NetToHost16(dataLength);
andrewboyson 11:c051adb70c5a 72 }
andrewboyson 11:c051adb70c5a 73
andrewboyson 11:c051adb70c5a 74 static void logHeader(char* title)
andrewboyson 11:c051adb70c5a 75 {
andrewboyson 11:c051adb70c5a 76 char text[100];
andrewboyson 11:c051adb70c5a 77 LogTimeF("%s\r\n", title);
andrewboyson 11:c051adb70c5a 78 LogF(" Version %d\r\n", version);
andrewboyson 11:c051adb70c5a 79 LogF(" Payload length %d\r\n", dataLength);
andrewboyson 11:c051adb70c5a 80 LogF(" Hop limit %d\r\n", hoplimit);
andrewboyson 11:c051adb70c5a 81 NetProtocolToString(protocol, sizeof(text), text);
andrewboyson 11:c051adb70c5a 82 LogF(" Protocol %s\r\n", text);
andrewboyson 11:c051adb70c5a 83 NetIp6AddressToString(pSrcIp, sizeof(text), text);
andrewboyson 11:c051adb70c5a 84 LogF(" Source IP %s\r\n", text);
andrewboyson 11:c051adb70c5a 85 NetIp6AddressToString(pDstIp, sizeof(text), text);
andrewboyson 11:c051adb70c5a 86 LogF(" Destination IP %s\r\n", text);
andrewboyson 11:c051adb70c5a 87 }
andrewboyson 11:c051adb70c5a 88
andrewboyson 10:f0854784e960 89 static bool getIsSolicited(char* p)
andrewboyson 10:f0854784e960 90 {
andrewboyson 10:f0854784e960 91 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 92 if (*p++ != 0x02) return false;
andrewboyson 10:f0854784e960 93
andrewboyson 10:f0854784e960 94 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 95 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 96
andrewboyson 10:f0854784e960 97 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 98 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 99
andrewboyson 10:f0854784e960 100 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 101 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 102
andrewboyson 10:f0854784e960 103 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 104 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 105
andrewboyson 10:f0854784e960 106 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 107 if (*p++ != 0x01) return false;
andrewboyson 10:f0854784e960 108
andrewboyson 10:f0854784e960 109 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 110
andrewboyson 10:f0854784e960 111 return true;
andrewboyson 10:f0854784e960 112 }
andrewboyson 10:f0854784e960 113 static bool getIsSame(char* pA, char* pB)
andrewboyson 10:f0854784e960 114 {
andrewboyson 10:f0854784e960 115 return memcmp(pA, pB, 16) == 0;
andrewboyson 10:f0854784e960 116 }
andrewboyson 10:f0854784e960 117 static bool getIsSameGroup(char* pA, char* pB)
andrewboyson 10:f0854784e960 118 {
andrewboyson 10:f0854784e960 119 pA += 13;
andrewboyson 10:f0854784e960 120 pB += 13;
andrewboyson 10:f0854784e960 121 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 122 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 123 return *pA == *pB;
andrewboyson 10:f0854784e960 124 }
andrewboyson 10:f0854784e960 125 int Ip6HandleReceivedPacket(char* pSrcMac, void* pPacket, int* pSize, char* pDstMac)
andrewboyson 10:f0854784e960 126 {
andrewboyson 10:f0854784e960 127 struct header * pHeader = (header*)pPacket;
andrewboyson 11:c051adb70c5a 128 readHeader(pHeader);
andrewboyson 10:f0854784e960 129
andrewboyson 11:c051adb70c5a 130 bool isMe = getIsSame(pDstIp, SlaacLinkLocalIp);
andrewboyson 11:c051adb70c5a 131 bool isMulticast = pDstIp[0] == 0xFF;
andrewboyson 11:c051adb70c5a 132 bool isSolicited = getIsSolicited(pDstIp);
andrewboyson 11:c051adb70c5a 133 bool isGroup = isSolicited && getIsSameGroup(pDstIp, SlaacLinkLocalIp);
andrewboyson 10:f0854784e960 134
andrewboyson 10:f0854784e960 135 bool doIt = isMe || (isMulticast && !isSolicited) || isGroup;
andrewboyson 10:f0854784e960 136
andrewboyson 10:f0854784e960 137 if (!doIt) return DO_NOTHING;
andrewboyson 10:f0854784e960 138
andrewboyson 11:c051adb70c5a 139 ArAdd6(pSrcMac, pSrcIp);
andrewboyson 11:c051adb70c5a 140
andrewboyson 11:c051adb70c5a 141 if (DEBUG) logHeader("IP6 packet received");
andrewboyson 11:c051adb70c5a 142
andrewboyson 10:f0854784e960 143 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 144 switch (protocol)
andrewboyson 10:f0854784e960 145 {
andrewboyson 11:c051adb70c5a 146 case ICMP6: action = Icmp6HandleReceivedPacket(pSrcIp, pDstIp, &dataLength, pData); break;
andrewboyson 11:c051adb70c5a 147 case UDP: action = Udp6HandleReceivedPacket(pSrcIp, pDstIp, &dataLength, pData); break;
andrewboyson 11:c051adb70c5a 148 case TCP: action = Tcp6HandleReceivedPacket(pSrcIp, pDstIp, &dataLength, pData); break;
andrewboyson 10:f0854784e960 149 default:
andrewboyson 11:c051adb70c5a 150 logHeader("IP6 packet unhandled");
andrewboyson 10:f0854784e960 151 return DO_NOTHING;
andrewboyson 10:f0854784e960 152 }
andrewboyson 11:c051adb70c5a 153 if (!action) return DO_NOTHING;
andrewboyson 11:c051adb70c5a 154
andrewboyson 11:c051adb70c5a 155 memcpy(pDstMac, pSrcMac, 6);
andrewboyson 11:c051adb70c5a 156
andrewboyson 11:c051adb70c5a 157 if (DEBUG) logHeader("IP6 packet replied to");
andrewboyson 10:f0854784e960 158
andrewboyson 11:c051adb70c5a 159 writeHeader(pHeader);
andrewboyson 11:c051adb70c5a 160
andrewboyson 10:f0854784e960 161 *pSize = HEADER_LENGTH + dataLength;
andrewboyson 10:f0854784e960 162
andrewboyson 10:f0854784e960 163 return action;
andrewboyson 10:f0854784e960 164 }
andrewboyson 10:f0854784e960 165 int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
andrewboyson 10:f0854784e960 166 {
andrewboyson 11:c051adb70c5a 167 pData = (char*)pPacket + HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 168 dataLength = 0;
andrewboyson 11:c051adb70c5a 169 version = 6;
andrewboyson 11:c051adb70c5a 170 hoplimit = 255;
andrewboyson 10:f0854784e960 171
andrewboyson 10:f0854784e960 172 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 173 if (action == DO_NOTHING)
andrewboyson 10:f0854784e960 174 {
andrewboyson 10:f0854784e960 175 action = Icmp6PollForPacketToSend(pData, &dataLength, pSrcIp, pDstIp);
andrewboyson 10:f0854784e960 176 protocol = ICMP6;
andrewboyson 10:f0854784e960 177 }
andrewboyson 10:f0854784e960 178
andrewboyson 10:f0854784e960 179 if (action == DO_NOTHING)
andrewboyson 10:f0854784e960 180 {
andrewboyson 10:f0854784e960 181 action = Udp6PollForPacketToSend(pData, &dataLength, pSrcIp, pDstIp);
andrewboyson 10:f0854784e960 182 protocol = UDP;
andrewboyson 10:f0854784e960 183 }
andrewboyson 11:c051adb70c5a 184 if (!action) return DO_NOTHING;
andrewboyson 11:c051adb70c5a 185 switch (action)
andrewboyson 11:c051adb70c5a 186 {
andrewboyson 11:c051adb70c5a 187 case UNICAST:
andrewboyson 11:c051adb70c5a 188 case UNICAST_DNS:
andrewboyson 11:c051adb70c5a 189 case UNICAST_DHCP:
andrewboyson 11:c051adb70c5a 190 ArRev6(pDstIp, pDstMac); //Make the remote MAC from NP
andrewboyson 11:c051adb70c5a 191 break;
andrewboyson 11:c051adb70c5a 192 }
andrewboyson 11:c051adb70c5a 193
andrewboyson 11:c051adb70c5a 194 if (DEBUG) logHeader("IP6 polled packet sent");
andrewboyson 10:f0854784e960 195
andrewboyson 11:c051adb70c5a 196 writeHeader((header*)pPacket);
andrewboyson 11:c051adb70c5a 197
andrewboyson 10:f0854784e960 198 *pSize = HEADER_LENGTH + dataLength;
andrewboyson 10:f0854784e960 199
andrewboyson 10:f0854784e960 200 return action;
andrewboyson 10:f0854784e960 201 }