#include <fcntl.h>
#include <arpa/inet.h>
#include <inttypes.h>
+#include <linux/filter.h>
#include <linux/gen_stats.h>
#include <linux/if_ether.h>
#include <linux/if_tun.h>
/* Sockets used for ioctl operations. */
static int af_inet_sock = -1; /* AF_INET, SOCK_DGRAM. */
-/* A Netlink routing socket that is not subscribed to any multicast groups. */
-static struct nl_sock *rtnl_sock;
-
/* This is set pretty low because we probably won't learn anything from the
* additional log messages. */
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
af_inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
status = af_inet_sock >= 0 ? 0 : errno;
if (status) {
- VLOG_ERR("failed to create inet socket: %s", strerror(status));
- }
-
- /* Create rtnetlink socket. */
- if (!status) {
- status = nl_sock_create(NETLINK_ROUTE, &rtnl_sock);
- if (status) {
- VLOG_ERR_RL(&rl, "failed to create rtnetlink socket: %s",
- strerror(status));
- }
+ VLOG_ERR("failed to create inet socket: %s", ovs_strerror(status));
}
}
return status;
state->fd = open(tap_dev, O_RDWR);
if (state->fd < 0) {
error = errno;
- VLOG_WARN("opening \"%s\" failed: %s", tap_dev, strerror(error));
+ VLOG_WARN("opening \"%s\" failed: %s", tap_dev, ovs_strerror(error));
goto error_unref_notifier;
}
ovs_strzcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
if (ioctl(state->fd, TUNSETIFF, &ifr) == -1) {
VLOG_WARN("%s: creating tap device failed: %s", name,
- strerror(errno));
+ ovs_strerror(errno));
error = errno;
goto error_unref_notifier;
}
} else {
struct sockaddr_ll sll;
int ifindex;
+ /* Result of tcpdump -dd inbound */
+ static struct sock_filter filt[] = {
+ { 0x28, 0, 0, 0xfffff004 }, /* ldh [0] */
+ { 0x15, 0, 1, 0x00000004 }, /* jeq #4 jt 2 jf 3 */
+ { 0x6, 0, 0, 0x00000000 }, /* ret #0 */
+ { 0x6, 0, 0, 0x0000ffff } /* ret #65535 */
+ };
+ static struct sock_fprog fprog = { ARRAY_SIZE(filt), filt };
/* Create file descriptor. */
fd = socket(PF_PACKET, SOCK_RAW, 0);
if (fd < 0) {
error = errno;
- VLOG_ERR("failed to create raw socket (%s)", strerror(error));
+ VLOG_ERR("failed to create raw socket (%s)", ovs_strerror(error));
goto error;
}
if (bind(fd, (struct sockaddr *) &sll, sizeof sll) < 0) {
error = errno;
VLOG_ERR("%s: failed to bind raw socket (%s)",
- netdev_get_name(netdev_), strerror(error));
+ netdev_get_name(netdev_), ovs_strerror(error));
+ goto error;
+ }
+
+ /* Filter for only inbound packets. */
+ error = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog,
+ sizeof fprog);
+ if (error) {
+ error = errno;
+ VLOG_ERR("%s: failed attach filter (%s)",
+ netdev_get_name(netdev_), ovs_strerror(error));
goto error;
}
}
: recv(rx->fd, data, size, MSG_TRUNC));
} while (retval < 0 && errno == EINTR);
- if (retval > size) {
- return -EMSGSIZE;
- } else if (retval >= 0) {
- return retval;
+ if (retval >= 0) {
+ return retval > size ? -EMSGSIZE : retval;
} else {
if (errno != EAGAIN) {
VLOG_WARN_RL(&rl, "error receiving Ethernet packet on %s: %s",
- strerror(errno), netdev_rx_get_name(rx_));
+ ovs_strerror(errno), netdev_rx_get_name(rx_));
}
return -errno;
}
/* Use the tap fd to send to this device. This is essential for
* tap devices, because packets sent to a tap device with an
* AF_PACKET socket will loop back to be *received* again on the
- * tap device. */
+ * tap device. This doesn't occur on other interface types
+ * because we attach a socket filter to the rx socket. */
struct netdev_linux *netdev = netdev_linux_cast(netdev_);
retval = write(netdev->state.tap.fd, data, size);
continue;
} else if (errno != EAGAIN) {
VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: %s",
- netdev_get_name(netdev_), strerror(errno));
+ netdev_get_name(netdev_), ovs_strerror(errno));
}
return errno;
} else if (retval != size) {
} else {
VLOG_INFO("RTM_GETLINK failed (%s), obtaining netdev stats "
"via proc (you are probably running a pre-2.6.19 "
- "kernel)", strerror(error));
+ "kernel)", ovs_strerror(error));
return false;
}
}
error = get_stats_via_vport__(netdev_, stats);
if (error && error != ENOENT) {
VLOG_WARN_RL(&rl, "%s: obtaining netdev stats via vport failed "
- "(%s)", netdev_get_name(netdev_), strerror(error));
+ "(%s)",
+ netdev_get_name(netdev_), ovs_strerror(error));
}
netdev->vport_stats_error = error;
netdev->cache_valid |= VALID_VPORT_STAT_ERROR;
error = tc_add_del_ingress_qdisc(netdev_, false);
if (error) {
VLOG_WARN_RL(&rl, "%s: removing policing failed: %s",
- netdev_name, strerror(error));
+ netdev_name, ovs_strerror(error));
goto out;
}
error = tc_add_del_ingress_qdisc(netdev_, true);
if (error) {
VLOG_WARN_RL(&rl, "%s: adding policing qdisc failed: %s",
- netdev_name, strerror(error));
+ netdev_name, ovs_strerror(error));
goto out;
}
error = tc_add_policer(netdev_, kbits_rate, kbits_burst);
if (error){
VLOG_WARN_RL(&rl, "%s: adding policing action failed: %s",
- netdev_name, strerror(error));
+ netdev_name, ovs_strerror(error));
goto out;
}
}
return false;
}
tcmsg->tcm_parent = 0;
- nl_dump_start(dump, rtnl_sock, &request);
+ nl_dump_start(dump, NETLINK_ROUTE, &request);
ofpbuf_uninit(&request);
return true;
}
rt.rt_flags = RTF_UP | RTF_GATEWAY;
error = ioctl(af_inet_sock, SIOCADDRT, &rt) < 0 ? errno : 0;
if (error) {
- VLOG_WARN("ioctl(SIOCADDRT): %s", strerror(error));
+ VLOG_WARN("ioctl(SIOCADDRT): %s", ovs_strerror(error));
}
return error;
}
*netdev_name = NULL;
stream = fopen(fn, "r");
if (stream == NULL) {
- VLOG_WARN_RL(&rl, "%s: open failed: %s", fn, strerror(errno));
+ VLOG_WARN_RL(&rl, "%s: open failed: %s", fn, ovs_strerror(errno));
return errno;
}
memcpy(mac, r.arp_ha.sa_data, ETH_ADDR_LEN);
} else if (retval != ENXIO) {
VLOG_WARN_RL(&rl, "%s: could not look up ARP entry for "IP_FMT": %s",
- netdev_get_name(netdev), IP_ARGS(ip), strerror(retval));
+ netdev_get_name(netdev), IP_ARGS(ip),
+ ovs_strerror(retval));
}
return retval;
}
tc_get_major(handle), tc_get_minor(handle),
tc_get_major(parent), tc_get_minor(parent),
class->min_rate, class->max_rate,
- class->burst, class->priority, strerror(error));
+ class->burst, class->priority, ovs_strerror(error));
}
return error;
}
netdev_get_name(netdev),
tc_get_major(handle), tc_get_minor(handle),
tc_get_major(parent), tc_get_minor(parent),
- class->min_rate, class->max_rate, strerror(error));
+ class->min_rate, class->max_rate, ovs_strerror(error));
}
return error;
static int
tc_transact(struct ofpbuf *request, struct ofpbuf **replyp)
{
- int error = nl_sock_transact(rtnl_sock, request, replyp);
+ int error = nl_transact(NETLINK_ROUTE, request, replyp);
ofpbuf_uninit(request);
return error;
}
stream = fopen(fn, "r");
if (!stream) {
- VLOG_WARN("%s: open failed: %s", fn, strerror(errno));
+ VLOG_WARN("%s: open failed: %s", fn, ovs_strerror(errno));
return;
}
netdev_get_name(netdev),
tc_get_major(handle), tc_get_minor(handle),
tc_get_major(parent), tc_get_minor(parent),
- strerror(error));
+ ovs_strerror(error));
}
return error;
}
VLOG_WARN_RL(&rl, "delete %s class %u:%u failed (%s)",
netdev_get_name(netdev),
tc_get_major(handle), tc_get_minor(handle),
- strerror(error));
+ ovs_strerror(error));
}
return error;
}
} else {
/* Who knows? Maybe the device got deleted. */
VLOG_WARN_RL(&rl, "query %s qdisc failed (%s)",
- netdev_get_name(netdev_), strerror(error));
+ netdev_get_name(netdev_), ovs_strerror(error));
ops = &tc_ops_other;
}
ifi = ofpbuf_put_zeros(&request, sizeof *ifi);
ifi->ifi_family = PF_UNSPEC;
ifi->ifi_index = ifindex;
- error = nl_sock_transact(rtnl_sock, &request, &reply);
+ error = nl_transact(NETLINK_ROUTE, &request, &reply);
ofpbuf_uninit(&request);
if (error) {
return error;
stream = fopen(fn, "r");
if (!stream) {
- VLOG_WARN_RL(&rl, "%s: open failed: %s", fn, strerror(errno));
+ VLOG_WARN_RL(&rl, "%s: open failed: %s", fn, ovs_strerror(errno));
return errno;
}
COVERAGE_INC(netdev_get_ifindex);
if (ioctl(af_inet_sock, SIOCGIFINDEX, &ifr) < 0) {
VLOG_WARN_RL(&rl, "ioctl(SIOCGIFINDEX) on %s device failed: %s",
- netdev_name, strerror(errno));
+ netdev_name, ovs_strerror(errno));
return -errno;
}
return ifr.ifr_ifindex;
* to INFO for that case. */
VLOG(errno == ENODEV ? VLL_INFO : VLL_ERR,
"ioctl(SIOCGIFHWADDR) on %s device failed: %s",
- netdev_name, strerror(errno));
+ netdev_name, ovs_strerror(errno));
return errno;
}
hwaddr_family = ifr.ifr_hwaddr.sa_family;
COVERAGE_INC(netdev_set_hwaddr);
if (ioctl(af_inet_sock, SIOCSIFHWADDR, &ifr) < 0) {
VLOG_ERR("ioctl(SIOCSIFHWADDR) on %s device failed: %s",
- netdev_name, strerror(errno));
+ netdev_name, ovs_strerror(errno));
return errno;
}
return 0;
} else {
if (errno != EOPNOTSUPP) {
VLOG_WARN_RL(&rl, "ethtool command %s on network device %s "
- "failed: %s", cmd_name, name, strerror(errno));
+ "failed: %s", cmd_name, name, ovs_strerror(errno));
} else {
/* The device doesn't support this operation. That's pretty
* common, so there's no point in logging anything. */
ovs_strzcpy(ifr->ifr_name, name, sizeof ifr->ifr_name);
if (ioctl(af_inet_sock, cmd, ifr) == -1) {
VLOG_DBG_RL(&rl, "%s: ioctl(%s) failed: %s", name, cmd_name,
- strerror(errno));
+ ovs_strerror(errno));
return errno;
}
return 0;
}
} else {
sock = -errno;
- VLOG_ERR("failed to create packet socket: %s", strerror(errno));
+ VLOG_ERR("failed to create packet socket: %s",
+ ovs_strerror(errno));
}
}