summaryrefslogtreecommitdiffstats
path: root/bpf.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2008-06-08 20:07:54 +0000
committerRoy Marples <roy@marples.name>2008-06-08 20:07:54 +0000
commit5fb580a7713ca5bca9b7238a57977f1d739cdd46 (patch)
tree1f10e990c22847a6f203107b2b90365ad9a91122 /bpf.c
parent27e5226dc33c91862912b03c1f3d9162579dbcac (diff)
downloaddhcpcd-5fb580a7713ca5bca9b7238a57977f1d739cdd46.tar.xz
Re-write the client state engine around a simple timer instead of complex loops. Use the re-transmission times as per RFC 2131. Integrate the ARP handling code in the new engine so we are able to defend our IPV4LL address whilst negotiating a DHCP lease. This also means we're able to bind the address and fork BEFORE waiting to send announcements which makes us appear faster on the commandline.
Diffstat (limited to 'bpf.c')
-rw-r--r--bpf.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/bpf.c b/bpf.c
index 37a92f3d..cf7cb8f2 100644
--- a/bpf.c
+++ b/bpf.c
@@ -52,6 +52,7 @@ int
open_socket(struct interface *iface, int protocol)
{
int fd = -1;
+ int *fdp;
struct ifreq ifr;
int buf_len = 0;
struct bpf_version pv;
@@ -106,22 +107,24 @@ open_socket(struct interface *iface, int protocol)
#endif
/* Install the DHCP filter */
+#ifdef ENABLE_ARP
if (protocol == ETHERTYPE_ARP) {
pf.bf_insns = UNCONST(arp_bpf_filter);
pf.bf_len = arp_bpf_filter_len;
- } else {
+ fdp = &iface->arp_fd;
+ } else
+#endif
+ {
pf.bf_insns = UNCONST(dhcp_bpf_filter);
pf.bf_len = dhcp_bpf_filter_len;
+ fdp = &iface->fd;
}
if (ioctl(fd, BIOCSETF, &pf) == -1)
goto eexit;
-
- if (iface->fd != -1)
- close(iface->fd);
-
close_on_exec(fd);
- iface->fd = fd;
-
+ if (*fdp != -1)
+ close(*fdp);
+ *fdp = fd;
return fd;
eexit:
@@ -132,7 +135,7 @@ eexit:
}
ssize_t
-send_raw_packet(const struct interface *iface, int type,
+send_raw_packet(const struct interface *iface, int protocol,
const void *data, ssize_t len)
{
struct iovec iov[2];
@@ -140,7 +143,7 @@ send_raw_packet(const struct interface *iface, int type,
memset(&hw, 0, sizeof(hw));
memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN);
- hw.ether_type = htons(type);
+ hw.ether_type = htons(protocol);
iov[0].iov_base = &hw;
iov[0].iov_len = sizeof(hw);
iov[1].iov_base = UNCONST(data);
@@ -150,19 +153,27 @@ send_raw_packet(const struct interface *iface, int type,
}
/* BPF requires that we read the entire buffer.
- * So we pass the buffer in the API so we can loop on >1 dhcp packet. */
+ * So we pass the buffer in the API so we can loop on >1 packet. */
ssize_t
-get_packet(struct interface *iface, void *data, ssize_t len)
+get_raw_packet(struct interface *iface, _unused int protocol,
+ void *data, ssize_t len)
{
+ int fd;
struct bpf_hdr packet;
struct ether_header hw;
ssize_t bytes;
- const unsigned char *payload, *d;
+ const unsigned char *payload;
+
+#ifdef ENABLE_ARP
+ if (procotol == ETHERTYPE_ARP)
+ fd = iface->arp_fd;
+ else
+#endif
+ fd = iface->fd;
for (;;) {
if (iface->buffer_len == 0) {
- bytes = read(iface->fd, iface->buffer,
- iface->buffer_size);
+ bytes = read(fd, iface->buffer, iface->buffer_size);
if (bytes == -1)
return errno == EAGAIN ? 0 : -1;
else if ((size_t)bytes < sizeof(packet))
@@ -178,20 +189,11 @@ get_packet(struct interface *iface, void *data, ssize_t len)
if (iface->buffer_pos + packet.bh_caplen + packet.bh_hdrlen >
iface->buffer_len)
goto next; /* Packet beyond buffer, drop. */
- memcpy(&hw, iface->buffer + packet.bh_hdrlen, sizeof(hw));
payload = iface->buffer + packet.bh_hdrlen + sizeof(hw);
- if (hw.ether_type == htons(ETHERTYPE_ARP)) {
- bytes = packet.bh_caplen - sizeof(hw);
- if (bytes > len)
- bytes = len;
- memcpy(data, payload, bytes);
- } else if (valid_udp_packet(payload) >= 0) {
- bytes = get_udp_data(&d, payload);
- if (bytes > len)
- bytes = len;
- memcpy(data, d, bytes);
- } else
- bytes = -1;
+ bytes = packet.bh_caplen - sizeof(hw);
+ if (bytes > len)
+ bytes = len;
+ memcpy(data, payload, bytes);
next:
iface->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
packet.bh_caplen);