diff options
| author | Roy Marples <roy@marples.name> | 2008-06-08 20:07:54 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2008-06-08 20:07:54 +0000 |
| commit | 5fb580a7713ca5bca9b7238a57977f1d739cdd46 (patch) | |
| tree | 1f10e990c22847a6f203107b2b90365ad9a91122 /lpf.c | |
| parent | 27e5226dc33c91862912b03c1f3d9162579dbcac (diff) | |
| download | dhcpcd-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 'lpf.c')
| -rw-r--r-- | lpf.c | 65 |
1 files changed, 34 insertions, 31 deletions
@@ -57,9 +57,6 @@ #include "net.h" #include "bpf-filter.h" -/* A suitably large buffer for all transactions. */ -#define BUFFER_LENGTH 4096 - /* Broadcast address for IPoIB */ static const uint8_t ipv4_bcast_addr[] = { 0x00, 0xff, 0xff, 0xff, @@ -79,6 +76,7 @@ open_socket(struct interface *iface, int protocol) } su; struct sock_fprog pf; int flags; + int *fd; if ((s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol))) == -1) return -1; @@ -92,10 +90,13 @@ open_socket(struct interface *iface, int protocol) } /* Install the DHCP filter */ memset(&pf, 0, sizeof(pf)); +#ifdef ENABLE_ARP if (protocol == ETHERTYPE_ARP) { pf.filter = UNCONST(arp_bpf_filter); pf.len = arp_bpf_filter_len; - } else { + } else +#endif + { pf.filter = UNCONST(dhcp_bpf_filter); pf.len = dhcp_bpf_filter_len; } @@ -108,15 +109,15 @@ open_socket(struct interface *iface, int protocol) goto eexit; if (close_on_exec(s) == -1) goto eexit; - if (iface->fd > -1) - close(iface->fd); - iface->fd = s; - iface->socket_protocol = protocol; - if (iface->buffer == NULL) { - iface->buffer_size = BUFFER_LENGTH; - iface->buffer = xmalloc(iface->buffer_size); - iface->buffer_len = iface->buffer_pos = 0; - } +#ifdef ENABLE_ARP + if (protocol == ETHERTYPE_ARP) + fd = &iface->arp_fd; + else +#endif + fd = &iface->fd; + if (*fd != -1) + close(*fd); + *fd = s; return s; eexit: @@ -125,7 +126,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) { union sockunion { @@ -133,10 +134,11 @@ send_raw_packet(const struct interface *iface, int type, struct sockaddr_ll sll; struct sockaddr_storage ss; } su; + int fd; memset(&su, 0, sizeof(su)); su.sll.sll_family = AF_PACKET; - su.sll.sll_protocol = htons(type); + su.sll.sll_protocol = htons(protocol); if (!(su.sll.sll_ifindex = if_nametoindex(iface->name))) { errno = ENOENT; return -1; @@ -148,30 +150,31 @@ send_raw_packet(const struct interface *iface, int type, &ipv4_bcast_addr, sizeof(ipv4_bcast_addr)); else memset(&su.sll.sll_addr, 0xff, iface->hwlen); +#ifdef ENABLE_ARP + if (protocol == ETHERTYPE_ARP) + fd = iface->arp_fd; + else +#endif + fd = iface->fd; - return sendto(iface->fd, data, len, 0, &su.sa, sizeof(su)); + return sendto(fd, data, len, 0, &su.sa, sizeof(su)); } 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) { ssize_t bytes; - const uint8_t *p; + int fd; - bytes = read(iface->fd, iface->buffer, iface->buffer_size); +#ifdef ENABLE_ARP + if (protocol == ETHERTYPE_ARP) + fd = iface->arp_fd; + else +#endif + fd = iface->fd; + bytes = read(fd, data, len); if (bytes == -1) return errno == EAGAIN ? 0 : -1; - - /* If it's an ARP reply, then just send it back */ - if (iface->socket_protocol == ETHERTYPE_ARP) { - p = iface->buffer; - } else { - if (valid_udp_packet(iface->buffer) != 0) - return -1; - bytes = get_udp_data(&p, iface->buffer); - } - if (bytes > len) - bytes = len; - memcpy(data, p, bytes); return bytes; } |
