BlinkenArea - GitList
Repositories
Blog
Wiki
mips_sys
Code
Commits
Branches
Tags
Search
Tree:
902aa40
Branches
Tags
master
mips_sys
fw
udp.c
replace email address in headers with blinkenarea address
Stefan Schuermans
commited
902aa40
at 2012-05-21 17:42:50
udp.c
Blame
History
Raw
/* MIPS I system * Copyright 2011-2012 Stefan Schuermans <stefan@blinkenarea.org> * Copyleft GNU public license V2 or later * http://www.gnu.org/copyleft/gpl.html */ #include "config.h" #include "checksum.h" #include "ethernet.h" #include "dhcp.h" #include "ip.h" #include "macros.h" #include "nethelp.h" #include "udp.h" // some kind of "token bucket" for UDP echo #define UDP_ECHO_TICKS 10 ///< allowed rate of UDP echo replies (in 200ms) static unsigned int udp_echo_tick_cnt = 0; ///< tick counter #define UDP_ECHO_REPLIES_MAX 3 ///< maximum value for udp_echo_replies static unsigned int udp_echo_replies = 0; // # of allowed UDP echo replies /// tick procedure - call every 200ms void udp_tick200(void) { // count ticks udp_echo_tick_cnt++; // time to allow one reply more if (udp_echo_tick_cnt >= UDP_ECHO_TICKS) { udp_echo_tick_cnt = 0; // increase reply count if not at maximum if (udp_echo_replies < UDP_ECHO_REPLIES_MAX) udp_echo_replies++; } } /** * @brief process a received UDP echo packet * @param[in] ptr pointer to data of packet * @param[in] sz size of packet */ static void udp_echo_recv(void *ptr, unsigned int sz) { struct udp_packet *udp_pack; udp_pack = ptr; // source port is UDP echo port if (udp_pack->udp_hdr.src_port == 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 (udp_echo_replies <= 0) return; udp_echo_replies--; // 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 udp_pack->udp_hdr.dest_port = udp_pack->udp_hdr.src_port; // to source port udp_pack->udp_hdr.src_port = htons(7); // UDP echo port ip_cpy( udp_pack->ip_hdr.dest, udp_pack->ip_hdr.src); // to source IP udp_send(udp_pack, sz); } /** * @brief process a received UDP packet * @param[in] ptr pointer to data of packet * @param[in] sz size of packet */ void udp_recv(void *ptr, unsigned int sz) { struct udp_packet *udp_pack; unsigned int len; // packet too short if (sz < sizeof(struct udp_packet)) return; udp_pack = ptr; // ignore packets sent from or to port 0 (not allowed by RFC) if (udp_pack->udp_hdr.src_port == htons(0) || udp_pack->udp_hdr.dest_port == htons(0)) return; // check total length len = sizeof(struct ethernet_header) + sizeof(struct ip_header) + ntohs(udp_pack->udp_hdr.length); // length according to UDP header if (sz < len) // packet is truncated return; sz = len; // remove IP padding from packet (maybe sz > len) // test checksum if (checksum(&udp_pack->ip_hdr.src, sz - sizeof(struct ethernet_header) - sizeof(struct ip_header ) + 8, 0x0011, ntohs(udp_pack->udp_hdr.length))) return; // branch according to destination port switch (ntohs(udp_pack->udp_hdr.dest_port)) { // UDP echo case 7: udp_echo_recv(ptr, sz); break; // DHCP case 68: dhcp_recv(ptr, sz); break; } } /** * @brief send a UDP packet * @param[in] ptr pointer to data of packet * @param[in] sz size of packet * * ptr must point to a udp_packet * with ip_hdr.proto ip_hdr.dest, udp_hdr.src_port and udp_hdr.dest_port * already initialized */ void udp_send(void *ptr, unsigned int sz) { struct udp_packet *udp_pack; unsigned int chk; // packet too short if (sz < sizeof(struct udp_packet)) return; udp_pack = ptr; // fill in header values udp_pack->udp_hdr.length = htons(sz - sizeof(struct ethernet_header) - sizeof(struct ip_header)); udp_pack->udp_hdr.chk = 0x0000; /* put IP already here into IP header because it is needed for calculation of UDP checksum */ ip_cpy(udp_pack->ip_hdr.src, config_ip.ip); // generate checksum chk = checksum(&udp_pack->ip_hdr.src, sz - sizeof(struct ethernet_header ) - sizeof(struct ip_header ) + 8, 0x0011, ntohs(udp_pack->udp_hdr.length)); udp_pack->udp_hdr.chk = htons(chk); // send UDP packet udp_pack->ip_hdr.proto = 0x11; // UDP ip_send(udp_pack, sz); }