From 77a288d2672905d4a2164cdca961725328019823 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini <rubini@gnudd.com> Date: Thu, 14 Jan 2016 00:39:18 +0100 Subject: [PATCH] net: added UDP helper; use it in bootp This pair of commits costs around 300 bytes overall, in network-using configurations. Signed-off-by: Alessandro Rubini <rubini@gnudd.com> --- lib/bootp.c | 56 ++++++--------------------------------- lib/ipv4.h | 11 ++++++++ lib/lib.mk | 2 +- lib/udp.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 49 deletions(-) create mode 100644 lib/udp.c diff --git a/lib/bootp.c b/lib/bootp.c index 197c13d57..7e4338d3a 100644 --- a/lib/bootp.c +++ b/lib/bootp.c @@ -31,7 +31,7 @@ int prepare_bootp(struct wr_sockaddr *addr, uint8_t * buf, int retry) { - unsigned short sum; + struct wr_udp_addr uaddr; // ----------- BOOTP ------------ buf[BOOTP_OP] = 1; /* bootrequest */ @@ -62,53 +62,13 @@ int prepare_bootp(struct wr_sockaddr *addr, uint8_t * buf, int retry) memset(buf + BOOTP_FILE, 0, 128); /* desired BOOTP file */ memset(buf + BOOTP_VEND, 0, 64); /* vendor extensions */ - // ------------ UDP ------------- - memset(buf + UDP_VIRT_SADDR, 0, 4); - memset(buf + UDP_VIRT_DADDR, 0xFF, 4); - buf[UDP_VIRT_ZEROS] = 0; - buf[UDP_VIRT_PROTO] = 0x11; /* UDP */ - buf[UDP_VIRT_LENGTH] = (BOOTP_END - IP_END) >> 8; - buf[UDP_VIRT_LENGTH + 1] = (BOOTP_END - IP_END) & 0xff; - - buf[UDP_SPORT] = 0; - buf[UDP_SPORT + 1] = 68; /* BOOTP client */ - buf[UDP_DPORT] = 0; - buf[UDP_DPORT + 1] = 67; /* BOOTP server */ - buf[UDP_LENGTH] = (BOOTP_END - IP_END) >> 8; - buf[UDP_LENGTH + 1] = (BOOTP_END - IP_END) & 0xff; - buf[UDP_CHECKSUM] = 0; - buf[UDP_CHECKSUM + 1] = 0; - - sum = - ipv4_checksum((unsigned short *)(buf + UDP_VIRT_SADDR), - (BOOTP_END - UDP_VIRT_SADDR) / 2); - if (sum == 0) - sum = 0xFFFF; - - buf[UDP_CHECKSUM + 0] = (sum >> 8); - buf[UDP_CHECKSUM + 1] = sum & 0xff; - - // ------------ IP -------------- - buf[IP_VERSION] = 0x45; - buf[IP_TOS] = 0; - buf[IP_LEN + 0] = (BOOTP_END) >> 8; - buf[IP_LEN + 1] = (BOOTP_END) & 0xff; - buf[IP_ID + 0] = 0; - buf[IP_ID + 1] = 0; - buf[IP_FLAGS + 0] = 0; - buf[IP_FLAGS + 1] = 0; - buf[IP_TTL] = 63; - buf[IP_PROTOCOL] = 17; /* UDP */ - buf[IP_CHECKSUM + 0] = 0; - buf[IP_CHECKSUM + 1] = 0; - memset(buf + IP_SOURCE, 0, 4); - memset(buf + IP_DEST, 0xFF, 4); - - sum = - ipv4_checksum((unsigned short *)(buf + IP_VERSION), - (IP_END - IP_VERSION) / 2); - buf[IP_CHECKSUM + 0] = sum >> 8; - buf[IP_CHECKSUM + 1] = sum & 0xff; + /* complete with udp helper */ + memset(&uaddr.saddr, 0, 4); + memset(&uaddr.daddr, 0xff, 4); + uaddr.sport = ntohs(68); + uaddr.dport = ntohs(67); + + fill_udp(buf, BOOTP_END, &uaddr); /* and fix destination before sending it */ memset(addr->mac, 0xFF, 6); diff --git a/lib/ipv4.h b/lib/ipv4.h index 34b839598..2c5a3dbe8 100644 --- a/lib/ipv4.h +++ b/lib/ipv4.h @@ -50,4 +50,15 @@ int process_icmp(uint8_t * buf, int len); int process_bootp(uint8_t * buf, int len); /* non-zero if IP was set */ int prepare_bootp(struct wr_sockaddr *addr, uint8_t * buf, int retry); +/* The UDP helper needs some information, if not replying to a frame */ +struct wr_udp_addr { + uint32_t saddr; /* all fields in network order, for memcpy */ + uint32_t daddr; + uint16_t sport; + uint16_t dport; +}; + +void fill_udp(uint8_t * buf, int len, struct wr_udp_addr *uaddr); + + #endif diff --git a/lib/lib.mk b/lib/lib.mk index b477d4e43..b68a722a6 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -1,5 +1,5 @@ obj-y += lib/util.o lib/atoi.o obj-y += lib/usleep.o -obj-$(CONFIG_WR_NODE) += lib/net.o +obj-$(CONFIG_WR_NODE) += lib/net.o lib/udp.o obj-$(CONFIG_WR_NODE) += lib/arp.o lib/icmp.o lib/ipv4.o lib/bootp.o diff --git a/lib/udp.c b/lib/udp.c new file mode 100644 index 000000000..99262aa17 --- /dev/null +++ b/lib/udp.c @@ -0,0 +1,75 @@ +/* + * This work is part of the White Rabbit project + * + * Copyright (C) 2016 GSI (www.gsi.de) + * Author: Alessandro Rubini <a.rubini@gsi.de> + * + * Released according to the GNU GPL, version 2 or any later version. + */ + +#include <string.h> +#include "ipv4.h" +#include "ptpd_netif.h" + +void fill_udp(uint8_t * buf, int len, struct wr_udp_addr *uaddr) +{ + unsigned short sum; + struct wr_udp_addr addr; + + /* if there is no user-provided uaddr, we are replying */ + if (!uaddr) { + memcpy(&addr.daddr, buf + IP_SOURCE, 4); + memcpy(&addr.saddr, buf + IP_DEST, 4); + memcpy(&addr.dport, buf + UDP_SPORT, 2); + memcpy(&addr.sport, buf + UDP_DPORT, 2); + uaddr = &addr; + } + + // ------------ UDP ------------- + memcpy(buf + UDP_VIRT_SADDR, &uaddr->saddr, 4); + memcpy(buf + UDP_VIRT_DADDR, &uaddr->daddr, 4); + buf[UDP_VIRT_ZEROS] = 0; + buf[UDP_VIRT_PROTO] = 0x11; /* UDP */ + buf[UDP_VIRT_LENGTH] = (len - IP_END) >> 8; + buf[UDP_VIRT_LENGTH + 1] = (len - IP_END) & 0xff; + + memcpy(buf + UDP_SPORT, &uaddr->sport, 2); + memcpy(buf + UDP_DPORT, &uaddr->dport, 2); + buf[UDP_LENGTH] = (len - IP_END) >> 8; + buf[UDP_LENGTH + 1] = (len - IP_END) & 0xff; + buf[UDP_CHECKSUM] = 0; + buf[UDP_CHECKSUM + 1] = 0; + + sum = + ipv4_checksum((unsigned short *)(buf + UDP_VIRT_SADDR), + (len - UDP_VIRT_SADDR) / 2); + if (sum == 0) + sum = 0xFFFF; + + buf[UDP_CHECKSUM + 0] = (sum >> 8); + buf[UDP_CHECKSUM + 1] = sum & 0xff; + + // ------------ IP -------------- + buf[IP_VERSION] = 0x45; + buf[IP_TOS] = 0; + buf[IP_LEN + 0] = len >> 8; + buf[IP_LEN + 1] = len & 0xff; + buf[IP_ID + 0] = 0; + buf[IP_ID + 1] = 0; + buf[IP_FLAGS + 0] = 0; + buf[IP_FLAGS + 1] = 0; + buf[IP_TTL] = 63; + buf[IP_PROTOCOL] = 17; /* UDP */ + buf[IP_CHECKSUM + 0] = 0; + buf[IP_CHECKSUM + 1] = 0; + memcpy(buf + IP_SOURCE, &uaddr->saddr, 4); + memcpy(buf + IP_DEST, &uaddr->daddr, 4); + + sum = + ipv4_checksum((unsigned short *)(buf + IP_VERSION), + (IP_END - IP_VERSION) / 2); + buf[IP_CHECKSUM + 0] = sum >> 8; + buf[IP_CHECKSUM + 1] = sum & 0xff; + + return; +} -- GitLab