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

udp/udp.cpp

Committer:
andrewboyson
Date:
2017-05-09
Revision:
15:6ca6778168b1
Parent:
14:e75a59c1123d
Child:
22:914b970356f0

File content as of revision 15:6ca6778168b1:

#include  "mbed.h"
#include   "log.h"
#include   "net.h"
#include   "udp.h"
#include   "ntp.h"
#include  "dhcp.h"
#include   "dns.h"
#include   "eth.h"
#include   "ip4.h"
#include   "ip6.h"
#include "slaac.h"
#include   "ndp.h"
#include    "io.h"

#define UNKNOWN true

#define HEADER_SIZE 8
__packed struct header
{
    uint16_t srcPort;
    uint16_t dstPort;
    uint16_t totalLength;
    uint16_t checksum;
};
uint16_t     UdpSrcPort;
uint16_t     UdpDstPort;
static uint16_t    checksum;
static uint16_t totalLength;

static int handlePort(int* pDataLength, void* pData)
{
    switch (UdpDstPort)
    {
        //Handle these
        case DHCP_CLIENT_PORT:          return DhcpHandleResponse      (                    pDataLength, pData);  //   68
        case NTP_PORT:                  return  NtpHandleRequest       (                    pDataLength, pData);  //  123
        case DNS_UNICAST_CLIENT_PORT:   return  DnsHandlePacketReceived(DNS_PROTOCOL_UDNS,  pDataLength, pData);  //53053
        case DNS_MDNS_PORT:             return  DnsHandlePacketReceived(DNS_PROTOCOL_MDNS,  pDataLength, pData);  // 5353
        case DNS_LLMNR_CLIENT_PORT:     return  DnsHandlePacketReceived(DNS_PROTOCOL_LLMNR, pDataLength, pData);  //53055
        case DNS_LLMNR_SERVER_PORT:     return  DnsHandlePacketReceived(DNS_PROTOCOL_LLMNR, pDataLength, pData);  // 5355
        
        //Quietly drop these
        case DHCP_SERVER_PORT:                                                          //67
        case   137:                                                                     //NETBIOS name service
        case   138:                                                                     //NETBIOS datagram service
        case   139:                                                                     //NETBIOS session service
        case  1900:                                                                     //SSDP Simple Service Discovery Protocol (uPnP)
        case  3076:                                                                     //Call of Duty - Xbox
        case  9956:                                                                     //Alljoyn part af 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 (UNKNOWN) LogTimeF("UDP unknown port %d\r\n", UdpDstPort);
            return DO_NOTHING;
    }
}
int UdpHandleReceivedPacket(int* pSize, void* pPacket)
{    
    void* pData    = (char*)pPacket + HEADER_SIZE;
    int dataLength =         *pSize - HEADER_SIZE;
    
    int action = handlePort(&dataLength, pData);
    
    *pSize = dataLength + HEADER_SIZE;
    
    uint16_t tmpPort = UdpDstPort;
    UdpDstPort = UdpSrcPort;
    UdpSrcPort = tmpPort;
    
    return action;
}
static int pollForPacketToSend(int type, int* pDataLength, void* pData)
{
    int action = 0;
    
    if (!action && type == IPV4) //DHCP only works under IPv4
    {
        action = DhcpPollForRequestToSend(pData, pDataLength);
        if (action)
        {
            UdpSrcPort = DHCP_CLIENT_PORT;
            UdpDstPort = DHCP_SERVER_PORT;
        }
    }
    
    if (!action) //DNS is agnostic
    {
        action = DnsPollForPacketToSend(pData, pDataLength);
        if (action)
        {
            switch (action)
            {
                case   UNICAST_DNS:    UdpSrcPort = DNS_UNICAST_CLIENT_PORT;   UdpDstPort = DNS_UNICAST_SERVER_PORT;   break; //53053,   53
                case MULTICAST_MDNS:   UdpSrcPort = DNS_MDNS_PORT;             UdpDstPort = DNS_MDNS_PORT;             break; // 5353, 5353
                case MULTICAST_LLMNR:  UdpSrcPort = DNS_LLMNR_CLIENT_PORT;     UdpDstPort = DNS_LLMNR_SERVER_PORT;     break; //53055, 5355
                
                //Report anything else
                default:
                    LogTimeF("DNS unknown action %d\r\n", action);
                    return DO_NOTHING;
            }
        }
    }
    return action;
}
int UdpPollForPacketToSend(int type, int* pSize, void* pPacket)
{
    void* pData    = (char*)pPacket + HEADER_SIZE;
    int dataLength =         *pSize - HEADER_SIZE;
    
    int action = pollForPacketToSend(type, &dataLength, pData);
    
    *pSize = dataLength + HEADER_SIZE;
    return action;
}

void UdpLogHeader(char* title, void* pPacket, uint16_t calculatedChecksum)
{    
    LogTimeF("UDP %s\r\n", title);
    LogF("  Source port      %hu\r\n", UdpSrcPort);
    LogF("  Destination port %hu\r\n", UdpDstPort);
    LogF("  Total length     %hu\r\n", totalLength);
    LogF("  Checksum (hex)   %04hX\r\n", checksum);
    LogF("  Calculated       %04hX\r\n", calculatedChecksum);
}

void UdpMakeHeader(int size, void* pPacket)
{        
    struct header* pHeader = (header*)pPacket;
    
    pHeader->dstPort     = NetToHost16(UdpDstPort);
    pHeader->srcPort     = NetToHost16(UdpSrcPort);
    pHeader->totalLength = NetToHost16(size);
    pHeader->checksum    = 0;

}
void UdpAddChecksum(void* pPacket, uint16_t checksum)
{
    struct header* pHeader = (header*)pPacket;
    pHeader->checksum    = checksum;
}
void UdpReadHeader(void* pPacket, uint16_t size)
{
    struct header* pHeader = (header*)pPacket;
    
    UdpSrcPort  = NetToHost16(pHeader->srcPort);
    UdpDstPort  = NetToHost16(pHeader->dstPort);
    totalLength = NetToHost16(pHeader->totalLength);
    checksum    = NetToHost16(pHeader->checksum);
}