summaryrefslogtreecommitdiffstats
path: root/arp.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2008-09-04 08:31:00 +0000
committerRoy Marples <roy@marples.name>2008-09-04 08:31:00 +0000
commitf0f4b8b6df73aaa57672c47a7f339b52db23e68f (patch)
treeec6ce5531dbe3863b5206f1930b237fb4793fbcd /arp.c
parent25312cdd58c66ead7c218ce88e5994f47e7c9266 (diff)
downloaddhcpcd-f0f4b8b6df73aaa57672c47a7f339b52db23e68f.tar.xz
Use static buffers for ARP and move the send code to arp.c. Also, move the hwaddr buffer to the top of the file for clarity.
Diffstat (limited to 'arp.c')
-rw-r--r--arp.c67
1 files changed, 51 insertions, 16 deletions
diff --git a/arp.c b/arp.c
index 8935ea65..9cf6b899 100644
--- a/arp.c
+++ b/arp.c
@@ -40,6 +40,41 @@
#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)
{
@@ -56,10 +91,9 @@ static void
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;
@@ -67,36 +101,36 @@ handle_arp_packet(void *arg)
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 &&
@@ -114,7 +148,7 @@ handle_arp_packet(void *arg)
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);
@@ -205,3 +239,4 @@ send_arp_probe(void *arg)
if (send_arp(iface, ARPOP_REQUEST, 0, state->offer->yiaddr) == -1)
logger(LOG_ERR, "send_arp: %s", strerror(errno));
}
+