BlinkenArea - GitList
Repositories
Blog
Wiki
flaneth
Code
Commits
Branches
Tags
Search
Tree:
d48e86e
Branches
Tags
master
flaneth
firmware
udp.c
header fix
Stefan Schuermans
commited
d48e86e
at 2012-05-02 18:39:39
udp.c
Blame
History
Raw
/* flaneth - flash and ethernet Copyright (C) 2007-2012 Stefan Schuermans <stefan@schuermans.info> Copyleft: GNU public license V2 - http://www.gnu.org/copyleft/gpl.html a BlinkenArea project - http://www.blinkenarea.org/ */ #include "config.h" #include "checksum.h" #include "debug.h" #include "dhcp.h" #include "ethernet.h" #include "ip.h" #include "macros.h" #include "nethelp.h" #include "ser62500.h" #include "udp.h" // some kind of "token bucket" for UDP echo #define UdpEchoTicks 10 // allowed rate of UDP echo replies (in 200ms steps) unsigned char UdpEchoTickCnt = 0; // tick counter #define UdpEchoReliesMax 3 // maximum value for UdpEchoReplies unsigned char UdpEchoReplies = 0; // number of UDP echo replies that // may be sent at the moment // tick procedure - call every 200ms void UdpTick200(void) // (extern) { // count ticks UdpEchoTickCnt++; // time to allow one reply more if (UdpEchoTickCnt >= UdpEchoTicks) { UdpEchoTickCnt = 0; // increase reply count if not at maximum if (UdpEchoReplies < UdpEchoReliesMax) UdpEchoReplies++; } } // process a received UDP echo packet static void UdpEchoRecv(unsigned char *pData, unsigned short Length) { struct UdpPacket *pUdpPack; // convert pointer to UDP packet // (this saves us from always casting pData) pUdpPack = (struct UdpPacket *)pData; // source port is UDP echo port if (pUdpPack->UdpHdr.SrcPort == htons(7)) // ignore this packet // - UDP echo answer to another UDP echo port will result in endless // echoing return; // only reply with allowed packet rate if (UdpEchoReplies == 0) { debug_udp_printf("echo len=%u (dropped)", Length); return; } UdpEchoReplies--; debug_udp_printf("echo len=%u", Length); // send an UDP echo // - use same buffer to send reply // - this saves us from allocating a new buffer // - this saves us from copying the data pUdpPack->UdpHdr.DestPort = pUdpPack->UdpHdr.SrcPort; // back to // originationg port pUdpPack->UdpHdr.SrcPort = htons(7); // UDP echo port ip_cpy(pUdpPack->IpHdr.Dest, pUdpPack->IpHdr.Src); // back to // originating IP UdpSend(pData, Length); } // process a received UDP packet void UdpRecv(unsigned char *pData, unsigned short Length) // (extern) { struct UdpPacket *pUdpPack; unsigned int len; // packet too short if (Length < sizeof(struct UdpPacket)) return; // convert pointer to UDP packet // (this saves us from always casting pData) pUdpPack = (struct UdpPacket *)pData; // ignore packets sent from or to port 0 // - this might be some attack if (pUdpPack->UdpHdr.SrcPort == htons(0) || pUdpPack->UdpHdr.DestPort == htons(0)) return; // check total length len = sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + ntohs(pUdpPack->UdpHdr.Length); // length // according // to // UDP // header if (Length < len) // packet is truncated return; Length = len; // remove IP padding from packet (maybe Length > len) // test checksum if (Checksum((unsigned char *)&pUdpPack->IpHdr.Src, Length - sizeof(struct EthernetHeader) - sizeof(struct IpHeader) + 8, 0x0011, ntohs(pUdpPack->UdpHdr.Length)) != 0) return; debug_udp_printf("recv src=%u dest=%u len=%u", ntohs(pUdpPack->UdpHdr.SrcPort), ntohs(pUdpPack->UdpHdr.DestPort), Length); // branch according to destination port switch (ntohs(pUdpPack->UdpHdr.DestPort)) { // UDP echo case 7: UdpEchoRecv(pData, Length); break; // DHCP case 68: DhcpRecv(pData, Length); break; // serial output with 62500 baud in 9N2 protocol case 62500: Ser62500Send9N2(pData + sizeof(struct UdpPacket), Length - sizeof(struct UdpPacket)); break; } } // send an UDP packet // pData must point to a struct UdpPacket with UdpHdr.SrcPort, // UdpHdr.DestPort and IpHdr.Dest already initialized void UdpSend(unsigned char *pData, unsigned short Length) // (extern) { struct UdpPacket *pUdpPack; unsigned int chk; // packet too short if (Length < sizeof(struct UdpPacket)) return; // convert pointer to UDP packet // (this saves us from always casting pData) pUdpPack = (struct UdpPacket *)pData; debug_udp_printf("send src=%u dest=%u len=%u", ntohs(pUdpPack->UdpHdr.SrcPort), ntohs(pUdpPack->UdpHdr.DestPort), Length); // fill in header values pUdpPack->UdpHdr.Length = htons(Length - sizeof(struct EthernetHeader) - sizeof(struct IpHeader)); pUdpPack->UdpHdr.Chk = 0x0000; ip_cpy(pUdpPack->IpHdr.Src, ConfigIp); // put IP already here into // IP header // because it is needed for calculation of UDP checksum // generate checksum chk = Checksum((unsigned char *)&pUdpPack->IpHdr.Src, Length - sizeof(struct EthernetHeader) - sizeof(struct IpHeader) + 8, 0x0011, ntohs(pUdpPack->UdpHdr.Length)); pUdpPack->UdpHdr.Chk = htons(chk); // send UDP packet pUdpPack->IpHdr.Proto = 0x11; // UDP IpSend(pData, Length); }