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
Diff: udp/udp.c
- 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; +}