Commit 77a288d2 authored by Alessandro Rubini's avatar Alessandro Rubini

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's avatarAlessandro Rubini <rubini@gnudd.com>
parent 9515bdd8
......@@ -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);
......
......@@ -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
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
/*
* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment