BlinkenArea - GitList
Repositories
Blog
Wiki
flaneth
Code
Commits
Branches
Tags
Search
Tree:
e8658d5
Branches
Tags
master
flaneth
firmware.dartboard
udp.c
initial commit after making CF identify work
Stefan Schuermans
commited
e8658d5
at 2012-04-15 19:57:57
udp.c
Blame
History
Raw
/* flaneth - flash and ethernet - dartboard mod * version 0.1 date 2008-11-09 * Copyright (C) 2007-2008 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 "dart.h" #include "debug.h" #include "dhcp.h" #include "ethernet.h" #include "ip.h" #include "macros.h" #include "nethelp.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; // dart board case 501: DartRequest( pUdpPack->IpHdr.Src, ntohs( pUdpPack->UdpHdr.SrcPort ) ); 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 ); }