/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <config.h>
#include "netlink-socket.h"
-#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
rcvbuf = 1024 * 1024;
if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUFFORCE,
&rcvbuf, sizeof rcvbuf)) {
- VLOG_WARN_RL(&rl, "setting %d-byte socket receive buffer failed (%s)",
- rcvbuf, strerror(errno));
+ /* Only root can use SO_RCVBUFFORCE. Everyone else gets EPERM.
+ * Warn only if the failure is therefore unexpected. */
+ if (errno != EPERM || !getuid()) {
+ VLOG_WARN_RL(&rl, "setting %d-byte socket receive buffer failed "
+ "(%s)", rcvbuf, strerror(errno));
+ }
}
retval = get_socket_rcvbuf(sock->fd);
int
nl_sock_leave_mcgroup(struct nl_sock *sock, unsigned int multicast_group)
{
- assert(!sock->dump);
+ ovs_assert(!sock->dump);
if (setsockopt(sock->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
&multicast_group, sizeof multicast_group) < 0) {
VLOG_WARN("could not leave multicast group %u (%s)",
}
static int
-nl_sock_send__(struct nl_sock *sock, const struct ofpbuf *msg, bool wait)
+nl_sock_send__(struct nl_sock *sock, const struct ofpbuf *msg,
+ uint32_t nlmsg_seq, bool wait)
{
struct nlmsghdr *nlmsg = nl_msg_nlmsghdr(msg);
int error;
nlmsg->nlmsg_len = msg->size;
- nlmsg->nlmsg_seq = nl_sock_allocate_seq(sock, 1);
+ nlmsg->nlmsg_seq = nlmsg_seq;
nlmsg->nlmsg_pid = sock->pid;
do {
int retval;
}
/* Tries to send 'msg', which must contain a Netlink message, to the kernel on
- * 'sock'. nlmsg_len in 'msg' will be finalized to match msg->size, and
- * nlmsg_pid will be set to 'sock''s pid, before the message is sent.
+ * 'sock'. nlmsg_len in 'msg' will be finalized to match msg->size, nlmsg_pid
+ * will be set to 'sock''s pid, and nlmsg_seq will be initialized to a fresh
+ * sequence number, before the message is sent.
*
* Returns 0 if successful, otherwise a positive errno value. If
* 'wait' is true, then the send will wait until buffer space is ready;
* otherwise, returns EAGAIN if the 'sock' send buffer is full. */
int
nl_sock_send(struct nl_sock *sock, const struct ofpbuf *msg, bool wait)
+{
+ return nl_sock_send_seq(sock, msg, nl_sock_allocate_seq(sock, 1), wait);
+}
+
+/* Tries to send 'msg', which must contain a Netlink message, to the kernel on
+ * 'sock'. nlmsg_len in 'msg' will be finalized to match msg->size, nlmsg_pid
+ * will be set to 'sock''s pid, and nlmsg_seq will be initialized to
+ * 'nlmsg_seq', before the message is sent.
+ *
+ * Returns 0 if successful, otherwise a positive errno value. If
+ * 'wait' is true, then the send will wait until buffer space is ready;
+ * otherwise, returns EAGAIN if the 'sock' send buffer is full.
+ *
+ * This function is suitable for sending a reply to a request that was received
+ * with sequence number 'nlmsg_seq'. Otherwise, use nl_sock_send() instead. */
+int
+nl_sock_send_seq(struct nl_sock *sock, const struct ofpbuf *msg,
+ uint32_t nlmsg_seq, bool wait)
{
int error = nl_sock_cow__(sock);
if (error) {
return error;
}
- return nl_sock_send__(sock, msg, wait);
+ return nl_sock_send__(sock, msg, nlmsg_seq, wait);
}
/* This stress option is useful for testing that OVS properly tolerates
struct msghdr msg;
ssize_t retval;
- assert(buf->allocated >= sizeof *nlmsghdr);
+ ovs_assert(buf->allocated >= sizeof *nlmsghdr);
ofpbuf_clear(buf);
iov[0].iov_base = buf->base;
struct nl_transaction *transactionp;
struct nl_transaction transaction;
- transaction.request = (struct ofpbuf *) request;
+ transaction.request = CONST_CAST(struct ofpbuf *, request);
transaction.reply = replyp ? ofpbuf_new(1024) : NULL;
transactionp = &transaction;
}
nl_msg_nlmsghdr(request)->nlmsg_flags |= NLM_F_DUMP | NLM_F_ACK;
- dump->status = nl_sock_send__(sock, request, true);
+ dump->status = nl_sock_send__(sock, request, nl_sock_allocate_seq(sock, 1),
+ true);
dump->seq = nl_msg_nlmsghdr(request)->nlmsg_seq;
}
while (!dump->status) {
struct ofpbuf reply;
if (!nl_dump_next(dump, &reply)) {
- assert(dump->status);
+ ovs_assert(dump->status);
}
}
}
ofpbuf_delete(reply);
- assert(*number != 0);
+ ovs_assert(*number != 0);
}
return *number > 0 ? 0 : -*number;
}