From: Roy Marples Date: Thu, 15 May 2008 11:12:44 +0000 (+0000) Subject: Fix some valgrind errors, and work on Linux again. X-Git-Tag: v4.0.2~402 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3581b92aa447e9a29952aafc13d74aaa38415abf;p=thirdparty%2Fdhcpcd.git Fix some valgrind errors, and work on Linux again. --- diff --git a/bpf.c b/bpf.c index 7d429533..46a08c55 100644 --- a/bpf.c +++ b/bpf.c @@ -153,22 +153,24 @@ get_packet(struct interface *iface, void *data, ssize_t len) { struct bpf_hdr packet; struct ether_header hw; - ssize_t cur_len; + ssize_t bytes; const unsigned char *payload, *d; + if ((size_t)len > iface->buffer_size) { + errno = ENOBUFS; + return -1; + } for (;;) { if (iface->buffer_len == 0) { - cur_len = read(iface->fd, iface->buffer, - iface->buffer_size); - if (cur_len == -1) + bytes = read(iface->fd, iface->buffer, + iface->buffer_size); + if (bytes == -1) return errno == EAGAIN ? 0 : -1; - else if ((size_t)cur_len < sizeof(packet)) + else if ((size_t)bytes < sizeof(packet)) return -1; - iface->buffer_len = cur_len; + iface->buffer_len = bytes; } - - cur_len = -1; - + bytes = -1; memcpy(&packet, iface->buffer + iface->buffer_pos, sizeof(packet)); if (packet.bh_caplen != packet.bh_datalen) @@ -179,19 +181,23 @@ get_packet(struct interface *iface, void *data, ssize_t len) memcpy(&hw, iface->buffer + packet.bh_hdrlen, sizeof(hw)); payload = iface->buffer + packet.bh_hdrlen + sizeof(hw); if (hw.ether_type == htons(ETHERTYPE_ARP)) { - cur_len = packet.bh_caplen - sizeof(hw); - memcpy(data, payload, len); + bytes = packet.bh_caplen - sizeof(hw); + if (bytes > len) + bytes = len; + memcpy(data, payload, bytes); } else if (valid_udp_packet(payload) >= 0) { - cur_len = get_udp_data(&d, payload); - memcpy(data, d, cur_len); + bytes = get_udp_data(&d, payload); + if (bytes > len) + bytes = len; + memcpy(data, d, bytes); } else - cur_len = -1; + bytes = -1; next: iface->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen + packet.bh_caplen); if (iface->buffer_pos >= iface->buffer_len) iface->buffer_len = iface->buffer_pos = 0; - if (cur_len != -1) - return cur_len; + if (bytes != -1) + return bytes; } } diff --git a/client.c b/client.c index 9639e85c..9d143348 100644 --- a/client.c +++ b/client.c @@ -1188,7 +1188,8 @@ handle_packet(struct if_state *state, const struct options *options) * the first one fails for any reason, we can use the next. */ dhcp = xmalloc(sizeof(*dhcp)); - do { + do { + memset(dhcp, 0, sizeof(*dhcp)); bytes = get_packet(iface, dhcp, sizeof(*dhcp)); if (bytes == -1) break; @@ -1287,6 +1288,7 @@ eexit: do_socket(state, SOCKET_CLOSED); free_routes(iface->routes); free(iface->clientid); + free(iface->buffer); free(iface); } diff --git a/net.c b/net.c index b79af243..6f7a7dec 100644 --- a/net.c +++ b/net.c @@ -285,7 +285,6 @@ read_interface(const char *ifname, _unused int metric) unsigned char *hwaddr = NULL; size_t hwlen = 0; sa_family_t family = 0; - unsigned short mtu; #ifdef __linux__ char *p; #endif @@ -340,7 +339,6 @@ read_interface(const char *ifname, _unused int metric) if (ioctl(s, SIOCSIFMTU, &ifr) == -1) goto eexit; } - mtu = ifr.ifr_mtu; strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); #ifdef __linux__ diff --git a/net.h b/net.h index 8e5d2b37..e7ed5941 100644 --- a/net.h +++ b/net.h @@ -105,7 +105,7 @@ struct interface int fd; int udp_fd; - size_t buffer_size, buffer_pos, buffer_len; + size_t buffer_size, buffer_len, buffer_pos; unsigned char *buffer; #ifdef __linux__ diff --git a/socket.c b/socket.c index 136a609b..ecf8f321 100644 --- a/socket.c +++ b/socket.c @@ -54,11 +54,8 @@ #include "net.h" #include "bpf-filter.h" -/* A suitably large buffer for all transactions. - * BPF buffer size is set by the kernel, so no define. */ -#ifdef __linux__ -# define BUFFER_LENGTH 4096 -#endif +/* A suitably large buffer for all transactions. */ +#define BUFFER_LENGTH 4096 /* Broadcast address for IPoIB */ static const uint8_t ipv4_bcast_addr[] = { @@ -91,7 +88,7 @@ setup_packet_filters(void) int open_socket(struct interface *iface, int protocol) { - int flags, s; + int s; union sockunion { struct sockaddr sa; struct sockaddr_in sin; @@ -132,7 +129,9 @@ open_socket(struct interface *iface, int protocol) close(iface->fd); iface->fd = s; iface->socket_protocol = protocol; - iface->buffer_length = 0; + iface->buffer_size = BUFFER_LENGTH; + iface->buffer = xmalloc(iface->buffer_size); + iface->buffer_len = iface->buffer_pos = 0; return s; eexit: @@ -168,29 +167,27 @@ send_raw_packet(const struct interface *iface, int type, return sendto(iface->fd, data, len, 0, &su.sa, sizeof(su)); } -/* Linux has no need for the buffer as we can read as much as we want. - * We only have the buffer listed to keep the same API. */ ssize_t get_packet(struct interface *iface, void *data, ssize_t len) { ssize_t bytes; - struct timespec ts; const uint8_t *p; - memset(data, 0, len); - bytes = read(iface->fd, data, len); + bytes = read(iface->fd, iface->buffer, iface->buffer_size); if (bytes == -1) - return errno == EGAIN ? 0 : -1; + return errno == EAGAIN ? 0 : -1; /* If it's an ARP reply, then just send it back */ if (iface->socket_protocol == ETHERTYPE_ARP) return bytes; - if (valid_udp_packet(data) != 0) + if (valid_udp_packet(iface->buffer) != 0) return -1; - bytes = get_udp_data(&p, buffer); - memmove(data, p, bytes); + bytes = get_udp_data(&p, iface->buffer); + if (bytes > len) + bytes = len; + memcpy(data, p, bytes); return bytes; }