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:
Mon May 01 18:20:55 2017 +0000
Revision:
13:9cd54f7db57a
Parent:
11:c051adb70c5a
Child:
14:e75a59c1123d
Added ability to read DNS queries with encoded IP addresses

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