int arp_check (interface_t *iface, struct in_addr address)
{
- unsigned char buf[256];
- struct arphdr *ah = (struct arphdr *) buf;
- unsigned char reply[4096];
+ union
+ {
+ unsigned char buffer[iface->buffer_length];
+ struct arphdr ah;
+ } arp;
+
int bytes;
- unsigned char buffer[iface->buffer_length];
struct timeval tv;
long timeout = 0;
fd_set rset;
return 0;
}
- memset (buf, 0, sizeof (buf));
+ memset (arp.buffer, 0, sizeof (arp.buffer));
- ah->ar_hrd = htons (ARPHRD_ETHER);
- ah->ar_pro = htons (ETHERTYPE_IP);
- ah->ar_hln = ETHER_ADDR_LEN;
- ah->ar_pln = sizeof (struct in_addr);
- ah->ar_op = htons (ARPOP_REQUEST);
- memcpy (ar_sha (ah), &iface->ethernet_address, ah->ar_hln);
- memcpy (ar_tpa (ah), &address, ah->ar_pln);
+ arp.ah.ar_hrd = htons (ARPHRD_ETHER);
+ arp.ah.ar_pro = htons (ETHERTYPE_IP);
+ arp.ah.ar_hln = ETHER_ADDR_LEN;
+ arp.ah.ar_pln = sizeof (struct in_addr);
+ arp.ah.ar_op = htons (ARPOP_REQUEST);
+ memcpy (ar_sha (&arp.ah), &iface->ethernet_address, arp.ah.ar_hln);
+ memcpy (ar_tpa (&arp.ah), &address, arp.ah.ar_pln);
logger (LOG_INFO, "checking %s is available on attached networks", inet_ntoa
(address));
open_socket (iface, true);
- send_packet (iface, ETHERTYPE_ARP, (unsigned char *) &buf, arphdr_len(ah));
+ send_packet (iface, ETHERTYPE_ARP, (unsigned char *) &arp.buffer,
+ arphdr_len (&arp.ah));
timeout = uptime() + TIMEOUT;
while (1)
{
- int buflen = sizeof (buffer);
+ int buflen = sizeof (arp.buffer);
int bufpos = -1;
tv.tv_sec = timeout - uptime ();
if (! FD_ISSET (iface->fd, &rset))
continue;
- memset (buffer, 0, sizeof (buffer));
+ memset (arp.buffer, 0, sizeof (arp.buffer));
while (bufpos != 0)
{
- memset (reply, 0, sizeof (reply));
- if ((bytes = get_packet (iface, (unsigned char *) &reply, buffer,
+ union
+ {
+ unsigned char buffer[sizeof (struct arphdr)];
+ struct arphdr hdr;
+ } reply;
+ union
+ {
+ unsigned char *c;
+ struct in_addr a;
+ } ra;
+
+ memset (reply.buffer, 0, sizeof (struct arphdr));
+ if ((bytes = get_packet (iface, reply.buffer, arp.buffer,
&buflen, &bufpos)) < 0)
break;
- ah = (struct arphdr *) reply;
-
/* Only these types are recognised */
- if (ah->ar_op != htons(ARPOP_REPLY)
- || ah->ar_hrd != htons (ARPHRD_ETHER))
+ if (reply.hdr.ar_op != htons(ARPOP_REPLY)
+ || reply.hdr.ar_hrd != htons (ARPHRD_ETHER))
continue;
/* Protocol must be IP. */
- if (ah->ar_pro != htons (ETHERTYPE_IP))
+ if (reply.hdr.ar_pro != htons (ETHERTYPE_IP))
continue;
- if (ah->ar_pln != sizeof (struct in_addr))
+ if (reply.hdr.ar_pln != sizeof (struct in_addr))
continue;
- if (ah->ar_hln != ETHER_ADDR_LEN)
+ if (reply.hdr.ar_hln != ETHER_ADDR_LEN)
continue;
- if ((unsigned) bytes < sizeof (*ah) + 2 * (4 + ah->ar_hln))
+ if ((unsigned) bytes < sizeof (reply.hdr) + 2 * (4 + reply.hdr.ar_hln))
continue;
+ ra.c = ar_spa (&reply.hdr);
logger (LOG_ERR, "ARPOP_REPLY received from %s (%s)",
- inet_ntoa (* (struct in_addr *) ar_spa (ah)),
- ether_ntoa ((struct ether_addr *) ar_sha (ah)));
+ inet_ntoa (ra.a),
+ ether_ntoa ((struct ether_addr *) ar_sha (&reply.hdr)));
close (iface->fd);
iface->fd = -1;
return 1;
for (p = ifap; p; p = p->ifa_next)
{
- struct sockaddr_dl *sdl = (struct sockaddr_dl *) p->ifa_addr;
+ union
+ {
+ struct sockaddr *sa;
+ struct sockaddr_dl *sdl;
+ } us;
if (strcmp (p->ifa_name, ifname) != 0)
continue;
-
- if (p->ifa_addr->sa_family != AF_LINK || sdl->sdl_type != IFT_ETHER)
+
+ us.sa = p->ifa_addr;
+
+ if (p->ifa_addr->sa_family != AF_LINK || us.sdl->sdl_type != IFT_ETHER)
{
logger (LOG_ERR, "not Ethernet");
freeifaddrs (ifap);
return NULL;
}
- memcpy (hwaddr, sdl->sdl_data + sdl->sdl_nlen, ETHER_ADDR_LEN);
+ memcpy (hwaddr, us.sdl->sdl_data + us.sdl->sdl_nlen, ETHER_ADDR_LEN);
break;
}
freeifaddrs (ifap);
#define ADDADDR(_var, _addr) \
{ \
- struct sockaddr_in *_sin = (struct sockaddr_in *) &_var; \
- _sin->sin_family = AF_INET; \
- _sin->sin_len = sizeof (struct sockaddr_in); \
- memcpy (&_sin->sin_addr, &_addr, sizeof (struct in_addr)); \
+ union { struct sockaddr *sa; struct sockaddr_in *sin; } _s; \
+ _s.sa = &_var; \
+ _s.sin->sin_family = AF_INET; \
+ _s.sin->sin_len = sizeof (struct sockaddr_in); \
+ memcpy (&_s.sin->sin_addr, &_addr, sizeof (struct in_addr)); \
}
ADDADDR (ifa.ifra_addr, address);
for (p = ifap; p; p = p->ifa_next)
{
- struct sockaddr_in *sin = (struct sockaddr_in*) p->ifa_addr;
+ union
+ {
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
+ } us;
+
if (strcmp (p->ifa_name, ifname) != 0)
continue;
- if (sin->sin_family == AF_INET)
- if (del_address (ifname, sin->sin_addr) < 0)
+ us.sa = p->ifa_addr;
+
+ if (us.sin->sin_family == AF_INET)
+ if (del_address (ifname, us.sin->sin_addr) < 0)
retval = -1;
}
freeifaddrs (ifap);
static uint16_t checksum (unsigned char *addr, uint16_t len)
{
uint32_t sum = 0;
- uint16_t *w = (uint16_t *) addr;
+ union
+ {
+ unsigned char *addr;
+ uint16_t *i;
+ } p;
uint16_t nleft = len;
+ p.addr = addr;
while (nleft > 1)
{
- sum += *w++;
+ sum += *p.i++;
nleft -= 2;
}
+
if (nleft == 1)
{
uint8_t a = 0;
- memcpy (&a, w, 1);
+ memcpy (&a, p.i, 1);
sum += ntohs (a) << 8;
}
ip->ip_len = udp->uh_ulen;
udp->uh_sum = checksum ((unsigned char *) packet,
sizeof (struct udp_dhcp_packet));
-
+
ip->ip_v = IPVERSION;
ip->ip_hl = 5;
ip->ip_id = 0;
static int valid_dhcp_packet (unsigned char *data)
{
- struct udp_dhcp_packet *packet = (struct udp_dhcp_packet *) data;
- uint16_t bytes = ntohs (packet->ip.ip_len);
- uint16_t ipsum = packet->ip.ip_sum;
- uint16_t iplen = packet->ip.ip_len;
- uint16_t udpsum = packet->udp.uh_sum;
+ union
+ {
+ unsigned char *data;
+ struct udp_dhcp_packet *packet;
+ } d;
+ uint16_t bytes;
+ uint16_t ipsum;
+ uint16_t iplen;
+ uint16_t udpsum;
struct in_addr source;
struct in_addr dest;
int retval = 0;
- packet->ip.ip_sum = 0;
- if (ipsum != checksum ((unsigned char *) &packet->ip, sizeof (struct ip)))
+ d.data = data;
+ bytes = ntohs (d.packet->ip.ip_len);
+ ipsum = d.packet->ip.ip_sum;
+ iplen = d.packet->ip.ip_len;
+ udpsum = d.packet->udp.uh_sum;
+
+ d.data = data;
+ d.packet->ip.ip_sum = 0;
+ if (ipsum != checksum ((unsigned char *) &d.packet->ip, sizeof (struct ip)))
{
logger (LOG_DEBUG, "bad IP header checksum, ignoring");
retval = -1;
goto eexit;
}
- memcpy (&source, &packet->ip.ip_src, sizeof (struct in_addr));
- memcpy (&dest, &packet->ip.ip_dst, sizeof (struct in_addr));
- memset (&packet->ip, 0, sizeof (struct ip));
- packet->udp.uh_sum = 0;
+ memcpy (&source, &d.packet->ip.ip_src, sizeof (struct in_addr));
+ memcpy (&dest, &d.packet->ip.ip_dst, sizeof (struct in_addr));
+ memset (&d.packet->ip, 0, sizeof (struct ip));
+ d.packet->udp.uh_sum = 0;
- packet->ip.ip_p = IPPROTO_UDP;
- memcpy (&packet->ip.ip_src, &source, sizeof (struct in_addr));
- memcpy (&packet->ip.ip_dst, &dest, sizeof (struct in_addr));
- packet->ip.ip_len = packet->udp.uh_ulen;
- if (udpsum && udpsum != checksum ((unsigned char *) packet, bytes))
+ d.packet->ip.ip_p = IPPROTO_UDP;
+ memcpy (&d.packet->ip.ip_src, &source, sizeof (struct in_addr));
+ memcpy (&d.packet->ip.ip_dst, &dest, sizeof (struct in_addr));
+ d.packet->ip.ip_len = d.packet->udp.uh_ulen;
+ if (udpsum && udpsum != checksum (d.data, bytes))
{
logger (LOG_ERR, "bad UDP checksum, ignoring");
retval = -1;
}
eexit:
- packet->ip.ip_sum = ipsum;
- packet->ip.ip_len = iplen;
- packet->udp.uh_sum = udpsum;
+ d.packet->ip.ip_sum = ipsum;
+ d.packet->ip.ip_len = iplen;
+ d.packet->udp.uh_sum = udpsum;
return retval;
}
/* Install the DHCP filter */
if (arp)
{
- printf ("arp!");
p.bf_insns = arp_bpf_filter;
p.bf_len = sizeof (arp_bpf_filter) / sizeof (struct bpf_insn);
}
int get_packet (const interface_t *iface, unsigned char *data,
unsigned char *buffer, int *buffer_len, int *buffer_pos)
{
- unsigned char *buf = buffer;
- struct bpf_hdr *packet;
- struct ether_header *hw;
- unsigned char *hdr;
+ union
+ {
+ unsigned char *buffer;
+ struct bpf_hdr *packet;
+ } bpf;
+
+ bpf.buffer = buffer;
if (*buffer_pos < 1)
{
- memset (buf, 0, iface->buffer_length);
- *buffer_len = read (iface->fd, buf, iface->buffer_length);
+ memset (bpf.buffer, 0, iface->buffer_length);
+ *buffer_len = read (iface->fd, bpf.buffer, iface->buffer_length);
*buffer_pos = 0;
if (*buffer_len < 1)
{
}
}
else
- buf += *buffer_pos;
+ bpf.buffer += *buffer_pos;
- packet = (struct bpf_hdr *) buf;
- while (packet)
+ while (bpf.packet)
{
int len = -1;
+ union
+ {
+ unsigned char *buffer;
+ struct ether_header *hw;
+ } hdr;
+ unsigned char *payload;
/* Ensure that the entire packet is in our buffer */
- if (*buffer_pos + packet->bh_hdrlen + packet->bh_caplen
+ if (*buffer_pos + bpf.packet->bh_hdrlen + bpf.packet->bh_caplen
> (unsigned) *buffer_len)
break;
- hw = (struct ether_header *) ((char *) packet + packet->bh_hdrlen);
- hdr = (unsigned char *) ((char *) hw + sizeof (struct ether_header));
+ hdr.buffer = bpf.buffer + bpf.packet->bh_hdrlen;
+ payload = hdr.buffer + sizeof (struct ether_header);
/* If it's an ARP reply, then just send it back */
- if (hw->ether_type == htons (ETHERTYPE_ARP))
+ if (hdr.hw->ether_type == htons (ETHERTYPE_ARP))
{
- len = packet->bh_caplen - sizeof (struct ether_header);
- memcpy (data, hdr, len);
+ len = bpf.packet->bh_caplen - sizeof (struct ether_header);
+ memcpy (data, payload, len);
}
else
{
- if (valid_dhcp_packet (hdr) >= 0)
+ if (valid_dhcp_packet (payload) >= 0)
{
- struct udp_dhcp_packet *dhcp = (struct udp_dhcp_packet *) hdr;
- len = ntohs (dhcp->ip.ip_len) - sizeof (struct ip) -
+ union
+ {
+ unsigned char *buffer;
+ struct udp_dhcp_packet *packet;
+ } pay;
+ pay.buffer = payload;
+ len = ntohs (pay.packet->ip.ip_len) - sizeof (struct ip) -
sizeof (struct udphdr);
- memcpy (data, &dhcp->dhcp, len);
+ memcpy (data, &pay.packet->dhcp, len);
}
}
/* Update the buffer_pos pointer */
- packet += BPF_WORDALIGN (packet->bh_hdrlen + packet->bh_caplen);
- if (packet - (struct bpf_hdr *) buffer < *buffer_len)
- *buffer_pos = (packet - (struct bpf_hdr *) buffer);
+ bpf.buffer +=
+ BPF_WORDALIGN (bpf.packet->bh_hdrlen + bpf.packet->bh_caplen);
+ if (bpf.buffer - buffer < *buffer_len)
+ *buffer_pos = bpf.buffer - buffer;
else
*buffer_pos = 0;