bootp.c 2.63 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * This work is part of the White Rabbit project
 *
 * Copyright (C) 2012 GSI (www.gsi.de)
 * Author: Wesley W. Terpstra <w.terpstra@gsi.de>
 *
 * Released according to the GNU GPL, version 2 or any later version.
 */
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
9
#include <string.h>
10 11
#include <wrc.h>
#include "endpoint.h"
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

#include "ipv4.h"

#define BOOTP_OP	(UDP_END)
#define BOOTP_HTYPE	(BOOTP_OP+1)
#define BOOTP_HLEN	(BOOTP_HTYPE+1)
#define BOOTP_HOPS	(BOOTP_HLEN+1)
#define BOOTP_XID	(BOOTP_HOPS+1)
#define BOOTP_SECS	(BOOTP_XID+4)
#define BOOTP_UNUSED	(BOOTP_SECS+2)
#define BOOTP_CIADDR	(BOOTP_UNUSED+2)
#define BOOTP_YIADDR	(BOOTP_CIADDR+4)
#define BOOTP_SIADDR	(BOOTP_YIADDR+4)
#define BOOTP_GIADDR	(BOOTP_SIADDR+4)
#define BOOTP_CHADDR	(BOOTP_GIADDR+4)
#define BOOTP_SNAME	(BOOTP_CHADDR+16)
#define BOOTP_FILE	(BOOTP_SNAME+64)
#define BOOTP_VEND	(BOOTP_FILE+128)
#define BOOTP_END	(BOOTP_VEND+64)

32
int prepare_bootp(struct wr_sockaddr *addr, uint8_t * buf, int retry)
33
{
34
	struct wr_udp_addr uaddr;
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

	// ----------- BOOTP ------------
	buf[BOOTP_OP] = 1;	/* bootrequest */
	buf[BOOTP_HTYPE] = 1;	/* ethernet */
	buf[BOOTP_HLEN] = 6;	/* MAC length */
	buf[BOOTP_HOPS] = 0;

	/* A unique identifier for the request !!! FIXME */
	get_mac_addr(buf + BOOTP_XID);
	buf[BOOTP_XID + 0] ^= buf[BOOTP_XID + 4];
	buf[BOOTP_XID + 1] ^= buf[BOOTP_XID + 5];
	buf[BOOTP_XID + 2] ^= (retry >> 8) & 0xFF;
	buf[BOOTP_XID + 3] ^= retry & 0xFF;

	buf[BOOTP_SECS] = (retry >> 8) & 0xFF;
	buf[BOOTP_SECS + 1] = retry & 0xFF;
	memset(buf + BOOTP_UNUSED, 0, 2);

	memset(buf + BOOTP_CIADDR, 0, 4);	/* own IP if known */
	memset(buf + BOOTP_YIADDR, 0, 4);
	memset(buf + BOOTP_SIADDR, 0, 4);
	memset(buf + BOOTP_GIADDR, 0, 4);

	memset(buf + BOOTP_CHADDR, 0, 16);
	get_mac_addr(buf + BOOTP_CHADDR);	/* own MAC address */

	memset(buf + BOOTP_SNAME, 0, 64);	/* desired BOOTP server */
	memset(buf + BOOTP_FILE, 0, 128);	/* desired BOOTP file */
	memset(buf + BOOTP_VEND, 0, 64);	/* vendor extensions */

65 66 67 68 69 70 71
	/* 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);
72

73 74
	/* and fix destination before sending it */
	memset(addr->mac, 0xFF, 6);
75
	// pp_printf("Sending BOOTP request...\n");
76
	return BOOTP_END;
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
77 78
}

79
int process_bootp(uint8_t * buf, int len)
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
80
{
81
	uint8_t mac[6];
82
	uint8_t ip[4];
83

84
	get_mac_addr(mac);
85

86 87
	if (len != BOOTP_END)
		return 0;
88

89
	if (buf[UDP_SPORT] != 0 || buf[UDP_SPORT + 1] != 67)
90
		return 0;
91

92 93
	if (memcmp(buf + BOOTP_CHADDR, mac, 6))
		return 0;
94

95
	ip_status = IP_OK_BOOTP;
96
	setIP(buf + BOOTP_YIADDR);
97

98
	getIP(ip);
99
	pp_printf("Discovered IP address (%d.%d.%d.%d)!\n",
100
	        ip[0], ip[1], ip[2], ip[3]);
101

102
	return 1;
Wesley W. Terpstra's avatar
Wesley W. Terpstra committed
103
}