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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers udp.c Source File

udp.c

00001 #include <stdint.h>
00002 #include <stdbool.h>
00003 
00004 #include "log.h"
00005 #include "net.h"
00006 #include "action.h"
00007 #include "udp.h"
00008 #include "ntp.h"
00009 #include "tftp.h"
00010 #include "dhcp.h"
00011 #include "dns.h"
00012 #include "eth.h"
00013 #include "ip4.h"
00014 #include "ip6.h"
00015 #include "slaac.h"
00016 #include "ns.h"
00017 #include "ntpclient.h"
00018 #include "restart.h"
00019 #include "user.h"
00020 
00021 bool UdpTrace = true;
00022 
00023 static char* hdrPtrSrcPort    (char* pPacket) { return pPacket + 0; } //2
00024 static char* hdrPtrDstPort    (char* pPacket) { return pPacket + 2; } //2
00025 static char* hdrPtrTotalLength(char* pPacket) { return pPacket + 4; } //2
00026 static char* hdrPtrChecksum   (char* pPacket) { return pPacket + 6; } //2
00027 static const int HEADER_LENGTH = 8;
00028 
00029 void UdpHdrSetChecksum(void* pPacket, uint16_t checksum)
00030 {
00031     NetDirect16(hdrPtrChecksum(pPacket), &checksum);
00032 }
00033 static uint16_t     srcPort;
00034 static uint16_t     dstPort;
00035 static uint16_t    checksum;
00036 static uint16_t totalLength;
00037 
00038 static void readHeader(char* pPacket)
00039 {
00040     NetInvert16(&srcPort,     hdrPtrSrcPort    (pPacket));
00041     NetInvert16(&dstPort,     hdrPtrDstPort    (pPacket));
00042     NetDirect16(&checksum,    hdrPtrChecksum   (pPacket));
00043     NetInvert16(&totalLength, hdrPtrTotalLength(pPacket));
00044 }
00045 void UdpMakeHeader(int size, char* pPacket)
00046 {
00047     checksum = 0;
00048     NetInvert16(hdrPtrSrcPort    (pPacket), &srcPort    );
00049     NetInvert16(hdrPtrDstPort    (pPacket), &dstPort    );
00050     NetDirect16(hdrPtrChecksum   (pPacket), &checksum   );
00051     NetInvert16(hdrPtrTotalLength(pPacket), &size       );
00052 
00053 }
00054 
00055 void UdpLogHeader(uint16_t calculatedChecksum)
00056 {
00057     if (NetTraceVerbose)
00058     {
00059         Log ("UDP header\r\n");
00060         LogF("  Source port      %hu\r\n", srcPort);
00061         LogF("  Destination port %hu\r\n", dstPort);
00062         LogF("  Total length     %hu\r\n", totalLength);
00063         LogF("  Checksum (hex)   %04hX\r\n", checksum);
00064         LogF("  Calculated       %04hX\r\n", calculatedChecksum);
00065     }
00066     else
00067     {
00068         LogF("UDP   header %hu >>> %hu\r\n", srcPort, dstPort);
00069     }
00070 }
00071 
00072 static int handlePort(void (*traceback)(void), int dataLengthRx, char* pDataRx, int* pPataLengthTx, char* pDataTx)
00073 {
00074     if (UserHandleReceivedUdpPacket && (dstPort == UserUdpPort1 || dstPort == UserUdpPort2)) return UserHandleReceivedUdpPacket(dstPort, traceback, dataLengthRx, pDataRx, pPataLengthTx, pDataTx);
00075     
00076     switch (dstPort)
00077     {
00078         //Handle these
00079         case DHCP_CLIENT_PORT:          return DhcpHandleResponse      (traceback,                     dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //   68
00080         case NTP_PORT:                  return  NtpHandlePacketReceived(traceback,                     dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //  123
00081         case DNS_UNICAST_CLIENT_PORT:   return  DnsHandlePacketReceived(traceback, DNS_PROTOCOL_UDNS,  dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //53053
00082         case DNS_MDNS_PORT:             return  DnsHandlePacketReceived(traceback, DNS_PROTOCOL_MDNS,  dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  // 5353
00083         case DNS_LLMNR_CLIENT_PORT:     return  DnsHandlePacketReceived(traceback, DNS_PROTOCOL_LLMNR, dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //53055
00084         case DNS_LLMNR_SERVER_PORT:     return  DnsHandlePacketReceived(traceback, DNS_PROTOCOL_LLMNR, dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  // 5355
00085         case TFTP_CLIENT_PORT:          return TftpHandlePacketReceived(traceback,                     dataLengthRx, pDataRx, pPataLengthTx, pDataTx);  //60690
00086         
00087         //Quietly drop these
00088         case     0:             //Unused but can be generated accidentally. For example the WIZ lights send it when powered up.
00089         case DHCP_SERVER_PORT:  //67
00090         case TFTP_SERVER_PORT:  //69
00091         case   137:             //NETBIOS name service
00092         case   138:             //NETBIOS datagram service
00093         case   139:             //NETBIOS session service
00094         case   500:             //Key exchange - Xbox live                  
00095         case  1900:             //SSDP Simple Service Discovery Protocol (uPnP)
00096         case  3074:             //Xbox live
00097         case  3076:             //Call of Duty - Xbox
00098         case  5050:             //Don't know but have been sent by Kate and my android phones.
00099         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'
00100         case  5684:             //CoAps
00101         case  9956:             //Alljoyn part of Allseen IoT services
00102         case  9997:             //VLC
00103         case  9998:             //VLC
00104         case  9999:             //VLC
00105         case 17500:             //Dropbox LAN sync
00106         case 38899:             //WIZ
00107         case 38900:             //WIZ
00108         case 57621:             //Spotify P2P
00109             return DO_NOTHING;
00110             
00111         //Report anything else
00112         default:
00113             if (UdpTrace)
00114             {
00115                 LogTimeF("UDP unknown port %d\r\n", dstPort);
00116                 traceback(); //This will already include the UDP header
00117             }
00118             return DO_NOTHING;
00119     }
00120 }
00121 int UdpHandleReceivedPacket(void (*traceback)(void), int sizeRx, char* pPacketRx, int* pSizeTx, char* pPacketTx)
00122 {    
00123     int lastRestartPoint = RestartPoint;
00124     RestartPoint = FAULT_POINT_UdpHandleReceivedPacket;
00125     
00126     readHeader(pPacketRx);
00127 
00128     void* pDataRx    = pPacketRx + HEADER_LENGTH;
00129     void* pDataTx    = pPacketTx + HEADER_LENGTH;
00130     int dataLengthRx =    sizeRx - HEADER_LENGTH;
00131     int dataLengthTx =  *pSizeTx - HEADER_LENGTH;
00132     
00133     int action = handlePort(traceback, dataLengthRx, pDataRx, &dataLengthTx, pDataTx);
00134     
00135     *pSizeTx = dataLengthTx + HEADER_LENGTH;
00136     
00137     uint16_t tmpPort = dstPort;
00138     dstPort = srcPort;
00139     srcPort = tmpPort;
00140     
00141     RestartPoint = lastRestartPoint;
00142     return action;
00143 }
00144 static int pollForPacketToSend(int type, int* pDataLength, char* pData)
00145 {
00146     int action = DO_NOTHING;
00147     
00148     if (!action && type == ETH_IPV4) //DHCP only works under IPv4
00149     {
00150         action = DhcpPollForRequestToSend(pData, pDataLength);
00151         if (action)
00152         {
00153             srcPort = DHCP_CLIENT_PORT;
00154             dstPort = DHCP_SERVER_PORT;
00155         }
00156     }
00157     
00158     //if (!action && type == (DnsSendRequestsViaIp4 ? ETH_IPV4 : ETH_IPV6)) //DNS is agnostic
00159     if (!action) //DNS is agnostic
00160     {
00161         action = DnsPollForPacketToSend(type, pData, pDataLength);
00162         int dest = ActionGetDestPart(action);
00163         if (dest)
00164         {
00165             switch (dest)
00166             {
00167                 case   UNICAST_DNS:    srcPort = DNS_UNICAST_CLIENT_PORT;   dstPort = DNS_UNICAST_SERVER_PORT;   break; //53053,   53
00168                 case MULTICAST_MDNS:   srcPort = DNS_MDNS_PORT;             dstPort = DNS_MDNS_PORT;             break; // 5353, 5353
00169                 case MULTICAST_LLMNR:  srcPort = DNS_LLMNR_CLIENT_PORT;     dstPort = DNS_LLMNR_SERVER_PORT;     break; //53055, 5355
00170                 
00171                 //Report anything else
00172                 default:
00173                     LogTimeF("DNS unknown dest %d\r\n", dest);
00174                     return DO_NOTHING;
00175             }
00176         }
00177     }
00178     if (!action && type == (NtpClientQuerySendRequestsViaIp4 ? ETH_IPV4 : ETH_IPV6)) //NTP is agnostic
00179     {
00180         action = NtpPollForPacketToSend(type, pData, pDataLength);
00181         if (action)
00182         {
00183             srcPort = NTP_PORT;
00184             dstPort = NTP_PORT;
00185         }
00186     }
00187     if (!action && type == (TftpSendRequestsViaIp4 ? ETH_IPV4 : ETH_IPV6)) //TFTP is agnostic
00188     {
00189         action = TftpPollForPacketToSend(type, pData, pDataLength);
00190         if (action)
00191         {
00192             srcPort = TFTP_CLIENT_PORT;
00193             dstPort = TFTP_SERVER_PORT;
00194         }
00195     }
00196     if (UserPollForUdpPacketToSend)
00197     {
00198         if (!action)
00199         {
00200             action = UserPollForUdpPacketToSend(type, pDataLength, pData);
00201             if (action)
00202             {
00203                 srcPort = UserUdpDstPort;
00204                 dstPort = UserUdpSrcPort;
00205             }
00206         }
00207     }
00208     
00209     return action;
00210 }
00211 int UdpPollForPacketToSend(int type, int* pSize, char* pPacket)
00212 {
00213     void* pData    = pPacket + HEADER_LENGTH;
00214     int dataLength =  *pSize - HEADER_LENGTH;
00215     
00216     int action = pollForPacketToSend(type, &dataLength, pData);
00217     
00218     *pSize = dataLength + HEADER_LENGTH;
00219     return action;
00220 }