summaryrefslogtreecommitdiffstats
path: root/socket.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2008-03-29 08:40:55 +0000
committerRoy Marples <roy@marples.name>2008-03-29 08:40:55 +0000
commit453072ef8fa4589a255f797c7fdc64fccb775e5f (patch)
treeac97ea86af5eea0b05e1d043be9fce764b05a0cd /socket.c
parentf57164233dfc48c62679106c8c870bc88119885b (diff)
downloaddhcpcd-453072ef8fa4589a255f797c7fdc64fccb775e5f.tar.xz
Rework our error handling code a little to save ~5k on x86_64
Diffstat (limited to 'socket.c')
-rw-r--r--socket.c116
1 files changed, 54 insertions, 62 deletions
diff --git a/socket.c b/socket.c
index 4d345fbe..3bd765ac 100644
--- a/socket.c
+++ b/socket.c
@@ -53,7 +53,6 @@
#include "config.h"
#include "dhcp.h"
#include "if.h"
-#include "logger.h"
#include "socket.h"
#include "bpf-filter.h"
@@ -85,6 +84,42 @@ setup_packet_filters(void)
arp_bpf_filter[2].k -= ETH_HLEN;
}
+static int open_listen_socket(struct interface *iface)
+{
+ int fd;
+ union sockunion {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ } su;
+ struct ifreq ifr;
+ int n = 1;
+
+ if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+ return -1;
+
+ memset(&su, 0, sizeof(su));
+ su.sin.sin_family = AF_INET;
+ su.sin.sin_port = htons(DHCP_CLIENT_PORT);
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
+ goto eexit;
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
+ goto eexit;
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
+ goto eexit;
+ if (bind(fd, &su.sa, sizeof(su)) == -1)
+ goto eexit;
+
+ iface->listen_fd = fd;
+ close_on_exec(fd);
+ return 0;
+
+eexit:
+ close(fd);
+ return -1;
+}
+
int
open_socket(struct interface *iface, int protocol)
{
@@ -96,60 +131,25 @@ open_socket(struct interface *iface, int protocol)
struct sockaddr_storage ss;
} su;
struct sock_fprog pf;
- struct ifreq ifr;
- int n = 1;
/* We need to bind to a port, otherwise Linux generate ICMP messages
* that cannot contect the port when we have an address.
* We don't actually use this fd at all, instead using our packet
* filter socket. */
- if (iface->listen_fd == -1 && protocol == ETHERTYPE_IP) {
- if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
- logger(LOG_ERR, "socket: %s", strerror(errno));
- } else {
- memset(&su, 0, sizeof(su));
- su.sin.sin_family = AF_INET;
- su.sin.sin_port = htons(DHCP_CLIENT_PORT);
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- &n, sizeof(n)) == -1)
- logger(LOG_ERR, "SO_REUSEADDR: %s",
- strerror(errno));
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
- &n, sizeof(n)) == -1)
- logger(LOG_ERR, "SO_RCVBUF: %s",
- strerror(errno));
- memset (&ifr, 0, sizeof(ifr));
- strncpy (ifr.ifr_name, iface->name,
- sizeof(ifr.ifr_name));
- if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
- &ifr, sizeof(ifr)) == -1)
- logger(LOG_ERR, "SO_SOBINDTODEVICE: %s",
- strerror(errno));
- if (bind(fd, &su.sa, sizeof(su)) == -1) {
- logger(LOG_ERR, "bind: %s", strerror(errno));
- close(fd);
- } else {
- iface->listen_fd = fd;
- close_on_exec(fd);
- }
- }
- }
+ if (iface->listen_fd == -1 && protocol == ETHERTYPE_IP)
+ if (open_listen_socket(iface) == -1)
+ return -1;
- if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(protocol))) == -1) {
- logger(LOG_ERR, "socket: %s", strerror(errno));
+ if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(protocol))) == -1)
return -1;
- }
+
close_on_exec(fd);
-
memset(&su, 0, sizeof(su));
su.sll.sll_family = PF_PACKET;
su.sll.sll_protocol = htons(protocol);
if (!(su.sll.sll_ifindex = if_nametoindex(iface->name))) {
- logger(LOG_ERR,
- "if_nametoindex: no index for interface `%s'",
- iface->name);
- close(fd);
- return -1;
+ errno = ENOENT;
+ goto eexit;
}
/* Install the DHCP filter */
@@ -162,17 +162,10 @@ open_socket(struct interface *iface, int protocol)
pf.len = sizeof(dhcp_bpf_filter) / sizeof(dhcp_bpf_filter[0]);
}
if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) != 0)
- {
- logger(LOG_ERR, "SO_ATTACH_FILTER: %s", strerror(errno));
- close(fd);
- return -1;
- }
+ goto eexit;
- if (bind(fd, &su.sa, sizeof(su)) == -1) {
- logger(LOG_ERR, "bind: %s", strerror(errno));
- close(fd);
- return -1;
- }
+ if (bind(fd, &su.sa, sizeof(su)) == -1)
+ goto eexit;
if (iface->fd > -1)
close(iface->fd);
@@ -181,6 +174,10 @@ open_socket(struct interface *iface, int protocol)
iface->buffer_length = BUFFER_LENGTH;
return fd;
+
+eexit:
+ close(fd);
+ return -1;
}
ssize_t
@@ -192,15 +189,13 @@ send_packet(const struct interface *iface, int type,
struct sockaddr_ll sll;
struct sockaddr_storage ss;
} su;
- ssize_t retval;
memset(&su, 0, sizeof(su));
su.sll.sll_family = AF_PACKET;
su.sll.sll_protocol = htons(type);
if (!(su.sll.sll_ifindex = if_nametoindex(iface->name))) {
- logger(LOG_ERR, "if_nametoindex: no index for interface `%s'",
- iface->name);
+ errno = ENOENT;
return -1;
}
@@ -212,9 +207,7 @@ send_packet(const struct interface *iface, int type,
else
memset(&su.sll.sll_addr, 0xff, iface->hwlen);
- if ((retval = sendto(iface->fd, data, len,0,&su.sa,sizeof(su))) == -1)
- logger(LOG_ERR, "sendto: %s", strerror(errno));
- return retval;
+ 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.
@@ -238,7 +231,6 @@ get_packet(const struct interface *iface, unsigned char *data,
bytes = read(iface->fd, buffer, iface->buffer_length);
if (bytes == -1) {
- logger(LOG_ERR, "read: %s", strerror(errno));
ts.tv_sec = 3;
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
@@ -254,13 +246,13 @@ get_packet(const struct interface *iface, unsigned char *data,
if ((unsigned)bytes < (sizeof(pay.packet->ip) +sizeof(pay.packet->udp)))
{
- logger(LOG_DEBUG, "message too short, ignoring");
+ errno = EBADMSG;
return -1;
}
pay.buffer = buffer;
if (bytes < ntohs(pay.packet->ip.ip_len)) {
- logger(LOG_DEBUG, "truncated packet, ignoring");
+ errno = EBADMSG;
return -1;
}