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

Revision:
61:aad055f1b0d1
Parent:
59:e0e556c8bd46
Child:
83:08c983006a6e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/udp/udp.c	Thu Jan 11 17:38:21 2018 +0000
@@ -0,0 +1,199 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+#include    "log.h"
+#include    "net.h"
+#include "action.h"
+#include    "udp.h"
+#include    "ntp.h"
+#include   "tftp.h"
+#include   "dhcp.h"
+#include    "dns.h"
+#include    "eth.h"
+#include    "ip4.h"
+#include    "ip6.h"
+#include  "slaac.h"
+#include     "ns.h"
+
+bool UdpTrace = true;
+
+__packed struct header
+{
+    uint16_t srcPort;
+    uint16_t dstPort;
+    uint16_t totalLength;
+    uint16_t checksum;
+};
+static uint16_t     srcPort;
+static uint16_t     dstPort;
+static uint16_t    checksum;
+static uint16_t totalLength;
+
+static void readHeader(void* pPacket, uint16_t size)
+{
+    struct header* pHeader = (struct header*)pPacket;
+    
+    srcPort     = NetToHost16(pHeader->srcPort);
+    dstPort     = NetToHost16(pHeader->dstPort);
+    totalLength = NetToHost16(pHeader->totalLength);
+    checksum    = NetToHost16(pHeader->checksum);
+}
+static int handlePort(void (*traceback)(void), int dataLengthRx, void* pDataRx, int* pPataLengthTx, void* pDataTx)
+{
+    switch (dstPort)
+    {
+        //Handle these
+        case DHCP_CLIENT_PORT:          return DhcpHandleResponse      (traceback,                     dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //   68
+        case NTP_PORT:                  return  NtpHandlePacketReceived(traceback,                     dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //  123
+        case DNS_UNICAST_CLIENT_PORT:   return  DnsHandlePacketReceived(traceback, DNS_PROTOCOL_UDNS,  dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //53053
+        case DNS_MDNS_PORT:             return  DnsHandlePacketReceived(traceback, DNS_PROTOCOL_MDNS,  dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  // 5353
+        case DNS_LLMNR_CLIENT_PORT:     return  DnsHandlePacketReceived(traceback, DNS_PROTOCOL_LLMNR, dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //53055
+        case DNS_LLMNR_SERVER_PORT:     return  DnsHandlePacketReceived(traceback, DNS_PROTOCOL_LLMNR, dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  // 5355
+        case TFTP_CLIENT_PORT:          return TftpHandlePacketReceived(traceback,                     dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //60690
+        
+        //Quietly drop these
+        case DHCP_SERVER_PORT:  //67
+        case TFTP_SERVER_PORT:  //69
+        case   137:             //NETBIOS name service
+        case   138:             //NETBIOS datagram service
+        case   139:             //NETBIOS session service
+        case   500:             //Key exchange - Xbox live                  
+        case  1900:             //SSDP Simple Service Discovery Protocol (uPnP)
+        case  3074:             //Xbox live
+        case  3076:             //Call of Duty - Xbox
+        case  5050:             //Don't know but have been sent by Kate and my android phones.
+        case  5224:             //Don't know but a burst was broadcast by Kate's phone containing '_logitech-reverse-bonjour._tcp.local.5446 192.168.1.36 string'
+        case  9956:             //Alljoyn part of Allseen IoT services
+        case  9997:             //VLC
+        case  9998:             //VLC
+        case  9999:             //VLC
+        case 17500:             //Dropbox LAN sync
+            return DO_NOTHING;
+            
+        //Report anything else
+        default:
+            if (UdpTrace)
+            {
+                LogTimeF("UDP unknown port %d\r\n", dstPort);
+                traceback(); //This will already include the UDP header
+            }
+            return DO_NOTHING;
+    }
+}
+int UdpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx)
+{    
+    readHeader(pPacketRx, sizeRx);
+
+    void* pDataRx    = (char*)pPacketRx + sizeof(struct header);
+    void* pDataTx    = (char*)pPacketTx + sizeof(struct header);
+    int dataLengthRx =           sizeRx - sizeof(struct header);
+    int dataLengthTx =         *pSizeTx - sizeof(struct header);
+    
+    int action = handlePort(traceback, dataLengthRx, pDataRx, &dataLengthTx, pDataTx);
+    
+    *pSizeTx = dataLengthTx + sizeof(struct header);
+    
+    uint16_t tmpPort = dstPort;
+    dstPort = srcPort;
+    srcPort = tmpPort;
+    
+    return action;
+}
+static int pollForPacketToSend(int type, int* pDataLength, void* pData)
+{
+    int action = DO_NOTHING;
+    uint16_t preferredPolledIpType = NetPreferIp4Polled ? IPV4 : IPV6;
+    
+    if (!action && type == IPV4) //DHCP only works under IPv4
+    {
+        action = DhcpPollForRequestToSend(pData, pDataLength);
+        if (action)
+        {
+            srcPort = DHCP_CLIENT_PORT;
+            dstPort = DHCP_SERVER_PORT;
+        }
+    }
+    
+    if (!action && type == preferredPolledIpType) //DNS is agnostic
+    {
+        action = DnsPollForPacketToSend(pData, pDataLength);
+        int dest = ActionGetDestPart(action);
+        if (dest)
+        {
+            switch (dest)
+            {
+                case   UNICAST_DNS:    srcPort = DNS_UNICAST_CLIENT_PORT;   dstPort = DNS_UNICAST_SERVER_PORT;   break; //53053,   53
+                case MULTICAST_MDNS:   srcPort = DNS_MDNS_PORT;             dstPort = DNS_MDNS_PORT;             break; // 5353, 5353
+                case MULTICAST_LLMNR:  srcPort = DNS_LLMNR_CLIENT_PORT;     dstPort = DNS_LLMNR_SERVER_PORT;     break; //53055, 5355
+                
+                //Report anything else
+                default:
+                    LogTimeF("DNS unknown dest %d\r\n", dest);
+                    return DO_NOTHING;
+            }
+        }
+    }
+    if (!action && type == preferredPolledIpType) //NTP is agnostic
+    {
+        action = NtpPollForPacketToSend(type, pData, pDataLength);
+        if (action)
+        {
+            srcPort = NTP_PORT;
+            dstPort = NTP_PORT;
+        }
+    }
+    if (!action && type == preferredPolledIpType) //TFTP is agnostic
+    {
+        action = TftpPollForPacketToSend(type, pData, pDataLength);
+        if (action)
+        {
+            srcPort = TFTP_CLIENT_PORT;
+            dstPort = TFTP_SERVER_PORT;
+        }
+    }
+    
+    return action;
+}
+int UdpPollForPacketToSend(int type, int* pSize, void* pPacket)
+{
+    void* pData    = (char*)pPacket + sizeof(struct header);
+    int dataLength =         *pSize - sizeof(struct header);
+    
+    int action = pollForPacketToSend(type, &dataLength, pData);
+    
+    *pSize = dataLength + sizeof(struct header);
+    return action;
+}
+
+void UdpLogHeader(uint16_t calculatedChecksum)
+{
+    if (NetTraceVerbose)
+    {
+        Log ("UDP header\r\n");
+        LogF("  Source port      %hu\r\n", srcPort);
+        LogF("  Destination port %hu\r\n", dstPort);
+        LogF("  Total length     %hu\r\n", totalLength);
+        LogF("  Checksum (hex)   %04hX\r\n", checksum);
+        LogF("  Calculated       %04hX\r\n", calculatedChecksum);
+    }
+    else
+    {
+        LogF("UDP   header %hu >>> %hu\r\n", srcPort, dstPort);
+    }
+}
+
+void UdpMakeHeader(int size, void* pPacket)
+{        
+    struct header* pHeader = (struct header*)pPacket;
+    
+    pHeader->dstPort     = NetToHost16(dstPort);
+    pHeader->srcPort     = NetToHost16(srcPort);
+    pHeader->totalLength = NetToHost16(size);
+    pHeader->checksum    = 0;
+
+}
+void UdpAddChecksum(void* pPacket, uint16_t checksum)
+{
+    struct header* pHeader = (struct header*)pPacket;
+    pHeader->checksum    = checksum;
+}