BlinkenArea - GitList
Repositories
Blog
Wiki
bluebox
Code
Commits
Branches
Tags
Search
Tree:
fd252ce
Branches
Tags
master
bluebox
BlueDataDistributor
firmware
udp.c
initial commit of files from bluebox project
Stefan Schuermans
commited
fd252ce
at 2015-12-19 20:16:38
udp.c
Blame
History
Raw
/* BlueDataDistributor - data distribution module from ethernet to 32 serial ports * version 0.1.1 date 2006-10-07 * Copyright (C) 2006 Stefan Schuermans <stefan@blinkenarea.org> * a BlinkenArea project - http://www.blinkenarea.org/ */ #include "config.h" #include "checksum.h" #include "ethernet.h" #include "ip.h" #include "macros.h" #include "nethelp.h" #include "serial.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 ) return; UdpEchoReplies--; // 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 serial output packet static void UdpSerOutRecv( unsigned char * pData, unsigned short Length ) { // short packet if( Length < sizeof( struct UdpPacket ) ) return; // get pointer to data and length of data unsigned char * ptr = pData + sizeof( struct UdpPacket ); unsigned short len = Length - sizeof( struct UdpPacket ); // output serial data SerialOutput( ptr, len ); } // 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; // branch according to destination port switch( ntohs( pUdpPack->UdpHdr.DestPort ) ) { // UDP echo case 7: UdpEchoRecv( pData, Length ); break; // serial output case 2342: UdpSerOutRecv( pData, Length ); 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; // 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 ); }