#include "logger.h"
#include "net.h"
+#define ARP_LEN \
+ (sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
+
+static uint8_t arp_buffer[ARP_LEN];
+
+static int
+send_arp(const struct interface *iface, int op, in_addr_t sip, in_addr_t tip)
+{
+ struct arphdr ar;
+ size_t len;
+ uint8_t *p;
+ int retval;
+
+ ar.ar_hrd = htons(iface->family);
+ ar.ar_pro = htons(ETHERTYPE_IP);
+ ar.ar_hln = iface->hwlen;
+ ar.ar_pln = sizeof(sip);
+ ar.ar_op = htons(op);
+ p = arp_buffer;
+ p += sizeof(ar);
+ memcpy(p, iface->hwaddr, iface->hwlen);
+ p += iface->hwlen;
+ memcpy(p, &sip, sizeof(sip));
+ p += sizeof(sip);
+ /* ARP requests should ignore this */
+ retval = iface->hwlen;
+ while (retval--)
+ *p++ = '\0';
+ memcpy(p, &tip, sizeof(tip));
+ p += sizeof(tip);
+ len = sizeof(ar) + 2 * iface->hwlen + 2 * sizeof(sip);
+ retval = send_raw_packet(iface, ETHERTYPE_ARP, arp_buffer, len);
+ return retval;
+}
+
static void
handle_arp_failure(struct interface *iface)
{
handle_arp_packet(void *arg)
{
struct interface *iface = arg;
- struct arphdr reply;
+ struct arphdr ar;
uint32_t reply_s;
uint32_t reply_t;
- uint8_t arp_reply[sizeof(reply) + 2 * sizeof(reply_s) + 2 * HWADDR_LEN];
uint8_t *hw_s, *hw_t;
ssize_t bytes;
struct if_state *state = iface->state;
state->fail.s_addr = 0;
for(;;) {
bytes = get_raw_packet(iface, ETHERTYPE_ARP,
- arp_reply, sizeof(arp_reply));
+ arp_buffer, sizeof(arp_buffer));
if (bytes == 0 || bytes == -1)
return;
/* We must have a full ARP header */
- if ((size_t)bytes < sizeof(reply))
+ if ((size_t)bytes < sizeof(ar))
continue;
- memcpy(&reply, arp_reply, sizeof(reply));
+ memcpy(&ar, arp_buffer, sizeof(ar));
/* Protocol must be IP. */
- if (reply.ar_pro != htons(ETHERTYPE_IP))
+ if (ar.ar_pro != htons(ETHERTYPE_IP))
continue;
- if (reply.ar_pln != sizeof(reply_s))
+ if (ar.ar_pln != sizeof(reply_s))
continue;
/* Only these types are recognised */
- if (reply.ar_op != htons(ARPOP_REPLY) &&
- reply.ar_op != htons(ARPOP_REQUEST))
+ if (ar.ar_op != htons(ARPOP_REPLY) &&
+ ar.ar_op != htons(ARPOP_REQUEST))
continue;
/* Get pointers to the hardware addreses */
- hw_s = arp_reply + sizeof(reply);
- hw_t = hw_s + reply.ar_hln + reply.ar_pln;
+ hw_s = arp_buffer + sizeof(ar);
+ hw_t = hw_s + ar.ar_hln + ar.ar_pln;
/* Ensure we got all the data */
- if ((hw_t + reply.ar_hln + reply.ar_pln) - arp_reply > bytes)
+ if ((hw_t + ar.ar_hln + ar.ar_pln) - arp_buffer > bytes)
continue;
/* Ignore messages from ourself */
- if (reply.ar_hln == iface->hwlen &&
+ if (ar.ar_hln == iface->hwlen &&
memcmp(hw_s, iface->hwaddr, iface->hwlen) == 0)
continue;
/* Copy out the IP addresses */
- memcpy(&reply_s, hw_s + reply.ar_hln, reply.ar_pln);
- memcpy(&reply_t, hw_t + reply.ar_hln, reply.ar_pln);
+ memcpy(&reply_s, hw_s + ar.ar_hln, ar.ar_pln);
+ memcpy(&reply_t, hw_t + ar.ar_hln, ar.ar_pln);
/* Check for conflict */
if (state->offer &&
logger(LOG_ERR, "%s: hardware address %s claims %s",
iface->name,
hwaddr_ntoa((unsigned char *)hw_s,
- (size_t)reply.ar_hln),
+ (size_t)ar.ar_hln),
inet_ntoa(state->fail));
errno = EEXIST;
handle_arp_failure(iface);
if (send_arp(iface, ARPOP_REQUEST, 0, state->offer->yiaddr) == -1)
logger(LOG_ERR, "send_arp: %s", strerror(errno));
}
+
#include "net.h"
#include "signals.h"
+static char hwaddr_buffer[(HWADDR_LEN * 3) + 1];
+
int
inet_ntocidr(struct in_addr address)
{
char *
hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen)
{
- static char buffer[(HWADDR_LEN * 3) + 1];
- char *p = buffer;
+ char *p = hwaddr_buffer;
size_t i;
for (i = 0; i < hwlen && i < HWADDR_LEN; i++) {
*p ++= '\0';
- return buffer;
+ return hwaddr_buffer;
}
size_t
open_udp_socket(struct interface *iface)
{
int s;
- union sockunion {
- struct sockaddr sa;
- struct sockaddr_in sin;
- } su;
+ struct sockaddr_in sin;
int n;
#ifdef SO_BINDTODEVICE
struct ifreq ifr;
n = 1;
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
goto eexit;
- memset(&su, 0, sizeof(su));
- su.sin.sin_family = AF_INET;
- su.sin.sin_port = htons(DHCP_CLIENT_PORT);
- su.sin.sin_addr.s_addr = iface->addr.s_addr;
- if (bind(s, &su.sa, sizeof(su)) == -1)
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(DHCP_CLIENT_PORT);
+ sin.sin_addr.s_addr = iface->addr.s_addr;
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
goto eexit;
iface->udp_fd = s;
send_packet(const struct interface *iface, struct in_addr to,
const uint8_t *data, ssize_t len)
{
- union sockunion {
- struct sockaddr sa;
- struct sockaddr_in sin;
- } su;
-
- memset(&su, 0, sizeof(su));
- su.sin.sin_family = AF_INET;
- su.sin.sin_addr.s_addr = to.s_addr;
- su.sin.sin_port = htons(DHCP_SERVER_PORT);
-
- return sendto(iface->udp_fd, data, len, 0, &su.sa, sizeof(su));
+ struct sockaddr_in sin;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = to.s_addr;
+ sin.sin_port = htons(DHCP_SERVER_PORT);
+ return sendto(iface->udp_fd, data, len, 0,
+ (struct sockaddr *)&sin, sizeof(sin));
}
struct udp_dhcp_packet
return retval;
}
-int
-send_arp(const struct interface *iface, int op, in_addr_t sip, in_addr_t tip)
-{
- struct arphdr *arp;
- size_t arpsize;
- uint8_t *p;
- int retval;
-
- arpsize = sizeof(*arp) + 2 * iface->hwlen + 2 * sizeof(sip);
- arp = xmalloc(arpsize);
- arp->ar_hrd = htons(iface->family);
- arp->ar_pro = htons(ETHERTYPE_IP);
- arp->ar_hln = iface->hwlen;
- arp->ar_pln = sizeof(sip);
- arp->ar_op = htons(op);
- p = (uint8_t *)arp;
- p += sizeof(*arp);
- memcpy(p, iface->hwaddr, iface->hwlen);
- p += iface->hwlen;
- memcpy(p, &sip, sizeof(sip));
- p += sizeof(sip);
- /* ARP requests should ignore this */
- retval = iface->hwlen;
- while (retval--)
- *p++ = '\0';
- memcpy(p, &tip, sizeof(tip));
- p += sizeof(tip);
- retval = send_raw_packet(iface, ETHERTYPE_ARP, arp, arpsize);
- free(arp);
- return retval;
-}