summaryrefslogtreecommitdiffstats
path: root/lib/sockopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sockopt.c')
-rw-r--r--lib/sockopt.c317
1 files changed, 200 insertions, 117 deletions
diff --git a/lib/sockopt.c b/lib/sockopt.c
index 3e4580ac..ad4af9af 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -25,44 +25,56 @@
#include "sockunion.h"
int
-setsockopt_so_recvbuf (int sock, int size)
+setsockopt_so_recvbuf (int sock_fd, int size)
{
int ret;
- if ( (ret = setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (char *)
- &size, sizeof (int))) < 0)
- zlog_err ("fd %d: can't setsockopt SO_RCVBUF to %d: %s",
- sock,size,safe_strerror(errno));
+ ret = setsockopt (sock_fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) ;
+ if (ret < 0)
+ {
+ int err = errno ;
+ zlog_err ("socket %d: cannot setsockopt SO_RCVBUF to %d: %s",
+ sock_fd, size, safe_strerror(err)) ;
+ errno = err ;
+ } ;
return ret;
}
int
-setsockopt_so_sendbuf (const int sock, int size)
+setsockopt_so_sendbuf (const int sock_fd, int size)
{
- int ret = setsockopt (sock, SOL_SOCKET, SO_SNDBUF,
- (char *)&size, sizeof (int));
+ int ret ;
+
+ ret = setsockopt (sock_fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
if (ret < 0)
- zlog_err ("fd %d: can't setsockopt SO_SNDBUF to %d: %s",
- sock, size, safe_strerror (errno));
+ {
+ int err = errno ;
+ zlog_err ("socket %d: cannot setsockopt SO_SNDBUF to %d: %s",
+ sock_fd, size, safe_strerror (err));
+ errno = err ;
+ } ;
return ret;
}
int
-getsockopt_so_sendbuf (const int sock)
+getsockopt_so_sendbuf (const int sock_fd)
{
u_int32_t optval;
socklen_t optlen = sizeof (optval);
- int ret = getsockopt (sock, SOL_SOCKET, SO_SNDBUF,
- (char *)&optval, &optlen);
+
+ int ret = getsockopt (sock_fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen);
if (ret < 0)
{
- zlog_err ("fd %d: can't getsockopt SO_SNDBUF: %d (%s)",
- sock, errno, safe_strerror (errno));
+ int err = errno ;
+ zlog_err ("socket %d: cannot getsockopt SO_SNDBUF: %s",
+ sock_fd, safe_strerror (err));
+ errno = err ;
return ret;
}
+
return optval;
}
@@ -84,89 +96,125 @@ getsockopt_cmsg_data (struct msghdr *msgh, int level, int type)
#ifdef HAVE_IPV6
/* Set IPv6 packet info to the socket. */
int
-setsockopt_ipv6_pktinfo (int sock, int val)
+setsockopt_ipv6_pktinfo (int sock_fd, int val)
{
int ret;
#ifdef IPV6_RECVPKTINFO /*2292bis-01*/
- ret = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val));
+ ret = setsockopt(sock_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val));
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_RECVPKTINFO : %s", safe_strerror (errno));
+ {
+ int err = errno ;
+ zlog_warn ("cannot setsockopt IPV6_RECVPKTINFO: %s", safe_strerror (err));
+ errno = err ;
+ } ;
#else /*RFC2292*/
- ret = setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &val, sizeof(val));
+ ret = setsockopt(sock_fd, IPPROTO_IPV6, IPV6_PKTINFO, &val, sizeof(val));
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_PKTINFO : %s", safe_strerror (errno));
+ {
+ int err = errno ;
+ zlog_warn ("cannot setsockopt IPV6_PKTINFO: %s", safe_strerror (err));
+ errno = err ;
+ } ;
#endif /* INIA_IPV6 */
return ret;
}
/* Set multicast hops val to the socket. */
int
-setsockopt_ipv6_checksum (int sock, int val)
+setsockopt_ipv6_checksum (int sock_fd, int val)
{
int ret;
#ifdef GNU_LINUX
- ret = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));
+ ret = setsockopt(sock_fd, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));
#else
- ret = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val));
+ ret = setsockopt(sock_fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val));
#endif /* GNU_LINUX */
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_CHECKSUM");
+ {
+ int err = errno ;
+ zlog_warn ("cannot setsockopt IPV6_CHECKSUM: %s", safe_strerror (err));
+ errno = err ;
+ } ;
return ret;
}
/* Set multicast hops val to the socket. */
int
-setsockopt_ipv6_multicast_hops (int sock, int val)
+setsockopt_ipv6_multicast_hops (int sock_fd, int val)
{
int ret;
- ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val));
+ ret = setsockopt(sock_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val,
+ sizeof(val));
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_MULTICAST_HOPS");
+ {
+ int err = errno ;
+ zlog_warn ("cannot setsockopt IPV6_MULTICAST_HOPS: %s",
+ safe_strerror (err));
+ errno = err ;
+ } ;
return ret;
}
/* Set multicast hops val to the socket. */
int
-setsockopt_ipv6_unicast_hops (int sock, int val)
+setsockopt_ipv6_unicast_hops (int sock_fd, int val)
{
int ret;
- ret = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val));
+ ret = setsockopt(sock_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val));
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_UNICAST_HOPS");
+ {
+ int err = errno ;
+ zlog_warn("cannot setsockopt IPV6_UNICAST_HOPS: %s", safe_strerror (err));
+ errno = err ;
+ } ;
return ret;
}
int
-setsockopt_ipv6_hoplimit (int sock, int val)
+setsockopt_ipv6_hoplimit (int sock_fd, int val)
{
int ret;
#ifdef IPV6_RECVHOPLIMIT /*2292bis-01*/
- ret = setsockopt (sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val));
+ ret = setsockopt (sock_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val,
+ sizeof(val));
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_RECVHOPLIMIT");
+ {
+ int err = errno ;
+ zlog_warn("cannot setsockopt IPV6_RECVHOPLIMIT: %s", safe_strerror (err));
+ errno = err ;
+ } ;
#else /*RFC2292*/
- ret = setsockopt (sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &val, sizeof(val));
+ ret = setsockopt (sock_fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &val, sizeof(val));
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_HOPLIMIT");
+ {
+ int err = errno ;
+ zlog_warn ("cannot setsockopt IPV6_HOPLIMIT: %s", safe_strerror (err));
+ errno = err ;
+ } ;
#endif
return ret;
}
/* Set multicast loop zero to the socket. */
int
-setsockopt_ipv6_multicast_loop (int sock, int val)
+setsockopt_ipv6_multicast_loop (int sock_fd, int val)
{
int ret;
- ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val,
- sizeof (val));
+ ret = setsockopt (sock_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val,
+ sizeof (val));
if (ret < 0)
- zlog_warn ("can't setsockopt IPV6_MULTICAST_LOOP");
+ {
+ int err = errno ;
+ zlog_warn ("cannot setsockopt IPV6_MULTICAST_LOOP: %s",
+ safe_strerror (err));
+ errno = err ;
+ } ;
return ret;
}
@@ -204,12 +252,14 @@ getsockopt_ipv6_ifindex (struct msghdr *msgh)
* allow leaves, or implicitly leave all groups joined to down interfaces.
*/
int
-setsockopt_multicast_ipv4(int sock,
- int optname,
- struct in_addr if_addr /* required */,
- unsigned int mcast_addr,
- unsigned int ifindex /* optional: if non-zero, may be
- used instead of if_addr */)
+setsockopt_multicast_ipv4(int sock_fd,
+ int optname,
+ struct in_addr if_addr /* required */,
+ unsigned int mcast_addr,
+ unsigned int ifindex /* optional: if non-zero,
+ may be used instead of
+ if_addr */
+ )
{
#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
@@ -232,31 +282,28 @@ setsockopt_multicast_ipv4(int sock,
else
mreqn.imr_address = if_addr;
- ret = setsockopt(sock, IPPROTO_IP, optname,
- (void *)&mreqn, sizeof(mreqn));
+ ret = setsockopt(sock_fd, IPPROTO_IP, optname, &mreqn, sizeof(mreqn));
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
{
/* see above: handle possible problem when interface comes back up */
char buf[2][INET_ADDRSTRLEN];
zlog_info("setsockopt_multicast_ipv4 attempting to drop and "
"re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)",
- sock,
+ sock_fd,
inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])),
inet_ntop(AF_INET, &mreqn.imr_multiaddr,
buf[1], sizeof(buf[1])), ifindex);
- setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (void *)&mreqn, sizeof(mreqn));
- ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (void *)&mreqn, sizeof(mreqn));
+ setsockopt(sock_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ &mreqn, sizeof(mreqn));
+ ret = setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ &mreqn, sizeof(mreqn));
}
return ret;
- break;
default:
/* Can out and give an understandable error */
errno = EINVAL;
return -1;
- break;
}
/* Example defines for another OS, boilerplate off other code in this
@@ -281,7 +328,7 @@ setsockopt_multicast_ipv4(int sock,
switch (optname)
{
case IP_MULTICAST_IF:
- return setsockopt (sock, IPPROTO_IP, optname, (void *)&m, sizeof(m));
+ return setsockopt (sock_fd, IPPROTO_IP, optname, (void *)&m, sizeof(m));
break;
case IP_ADD_MEMBERSHIP:
@@ -290,48 +337,56 @@ setsockopt_multicast_ipv4(int sock,
mreq.imr_multiaddr.s_addr = mcast_addr;
mreq.imr_interface = m;
- ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq));
+ ret = setsockopt (sock_fd, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq));
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
{
/* see above: handle possible problem when interface comes back up */
char buf[2][INET_ADDRSTRLEN];
zlog_info("setsockopt_multicast_ipv4 attempting to drop and "
"re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)",
- sock,
+ sock_fd,
inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])),
inet_ntop(AF_INET, &mreq.imr_multiaddr,
buf[1], sizeof(buf[1])), ifindex);
- setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (void *)&mreq, sizeof(mreq));
- ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (void *)&mreq, sizeof(mreq));
+ setsockopt (sock_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ &mreq, sizeof(mreq));
+ ret = setsockopt (sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ &mreq, sizeof(mreq));
}
return ret;
- break;
default:
/* Can out and give an understandable error */
errno = EINVAL;
return -1;
- break;
}
#endif /* #if OS_TYPE */
}
static int
-setsockopt_ipv4_ifindex (int sock, int val)
+setsockopt_ipv4_ifindex (int sock_fd, int val)
{
int ret;
#if defined (IP_PKTINFO)
- if ((ret = setsockopt (sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof (val))) < 0)
- zlog_warn ("Can't set IP_PKTINFO option for fd %d to %d: %s",
- sock,val,safe_strerror(errno));
+ ret = setsockopt (sock_fd, IPPROTO_IP, IP_PKTINFO, &val, sizeof (val)) ;
+ if (ret < 0)
+ {
+ int err = errno ;
+ zlog_warn ("Can't set IP_PKTINFO option for fd %d to %d: %s",
+ sock_fd, val, safe_strerror(err));
+ errno = err ;
+ } ;
#elif defined (IP_RECVIF)
- if ((ret = setsockopt (sock, IPPROTO_IP, IP_RECVIF, &val, sizeof (val))) < 0)
- zlog_warn ("Can't set IP_RECVIF option for fd %d to %d: %s",
- sock,val,safe_strerror(errno));
+ ret = setsockopt (sock_fd, IPPROTO_IP, IP_RECVIF, &val, sizeof (val)) ;
+ if (ret < 0)
+ {
+ int err = errno ;
+ zlog_warn ("Can't set IP_RECVIF option for fd %d to %d: %s",
+ sock_fd, val, safe_strerror(err));
+ errno = err ;
+ } ;
#else
#warning "Neither IP_PKTINFO nor IP_RECVIF is available."
#warning "Will not be able to receive link info."
@@ -343,35 +398,42 @@ setsockopt_ipv4_ifindex (int sock, int val)
}
int
-setsockopt_ipv4_tos(int sock, int tos)
+setsockopt_ipv4_tos(int sock_fd, int tos)
{
int ret;
- ret = setsockopt (sock, IPPROTO_IP, IP_TOS, &tos, sizeof (tos));
+ ret = setsockopt (sock_fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos));
if (ret < 0)
- zlog_warn ("Can't set IP_TOS option for fd %d to %#x: %s",
- sock, tos, safe_strerror(errno));
+ {
+ int err = errno ;
+ zlog_warn ("Can't set IP_TOS option for fd %d to %#x: %s",
+ sock_fd, tos, safe_strerror(err));
+ errno = err ;
+ } ;
return ret;
}
int
-setsockopt_ifindex (int af, int sock, int val)
+setsockopt_ifindex (int af, int sock_fd, int val)
{
int ret = -1;
switch (af)
{
case AF_INET:
- ret = setsockopt_ipv4_ifindex (sock, val);
+ ret = setsockopt_ipv4_ifindex (sock_fd, val);
break;
#ifdef HAVE_IPV6
case AF_INET6:
- ret = setsockopt_ipv6_pktinfo (sock, val);
+ ret = setsockopt_ipv6_pktinfo (sock_fd, val);
break;
#endif
default:
zlog_warn ("setsockopt_ifindex: unknown address family %d", af);
+ ret = -1 ;
+ errno = EINVAL;
+ break ;
}
return ret;
}
@@ -498,17 +560,17 @@ sockopt_iphdrincl_swab_systoh (struct ip *iph)
/*==============================================================================
* Set TCP MD5 signature socket option.
*
- * Returns: 0 => OK
- * errno => failed.
+ * Returns: >= 0 => OK
+ * < 0 => failed, see errno.
*
* NB: returns ENOSYS if TCP MD5 is not supported
*/
int
-sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
+sockopt_tcp_signature (int sock_fd, union sockunion *su, const char *password)
{
+#if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX)
int ret ;
-#if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX)
/* Support for the old Linux 2.4 TCP-MD5 patch, taken from Hasso Tepper's
* version of the Quagga patch (based on work by Rick Payne, and Bruce
* Simpson)
@@ -529,9 +591,9 @@ sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
cmd.keylen = (password != NULL ? strlen (password) : 0);
cmd.key = password;
- ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd) ;
+ ret = setsockopt (sock_fd, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd) ;
- return (ret >= 0) ? 0 : errno ;
+ return (ret >= 0) ? 0 : -1 ;
#elif HAVE_DECL_TCP_MD5SIG
#ifndef GNU_LINUX
@@ -545,11 +607,13 @@ sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
struct tcp_md5sig md5sig ;
union sockunion *su2 ;
union sockunion susock ;
+ int ret, err ;
/* Figure out whether the socket and the sockunion are the same family..
* adding AF_INET to AF_INET6 needs to be v4 mapped, you'd think..
*/
- if ((ret = sockunion_getsockname(sock, &susock)) != 0)
+ ret = sockunion_getsockname(sock_fd, &susock) ;
+ if (ret < 0)
return ret ;
if (susock.sa.sa_family == su->sa.sa_family)
@@ -564,7 +628,7 @@ sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
#ifdef HAVE_IPV6
/* If this does not work, then all users of this sockopt will need to
- * differentiate between IPv4 and IPv6, and keep seperate sockets for
+ * differentiate between IPv4 and IPv6, and keep separate sockets for
* each.
*
* Sadly, it doesn't seem to work at present. It's unknown whether
@@ -590,65 +654,84 @@ sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
#endif /* GNU_LINUX */
- ret = setsockopt(sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig) ;
+ err = 0 ;
+ ret = setsockopt(sock_fd, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof(md5sig)) ;
if (ret < 0)
{
- ret = errno ;
+ err = errno ;
/* ENOENT is harmless. It is returned when we clear a password for which
one was not previously set. */
- if (ret == ENOENT)
- ret = 0 ;
+ if (err == ENOENT)
+ err = 0 ;
else
- zlog_err ("sockopt_tcp_signature: setsockopt(%d): %s",
- sock, safe_strerror(ret));
+ {
+ zlog_err ("sockopt_tcp_signature: setsockopt(%d): %s",
+ sock_fd, safe_strerror(err));
+ errno = err ;
+ } ;
}
- else
- ret = 0 ; /* no error */
+
+ return (err == 0) ? 0 : -1 ;
#else /* HAVE_TCP_MD5SIG */
- ret = ENOSYS ; /* TCP MD5 is not supported */
+ errno = ENOSYS ; /* TCP MD5 is not supported */
+ return -1 ;
#endif /* !HAVE_TCP_MD5SIG */
-
- return ret;
} ;
/*==============================================================================
- * Set TTL for socket (only used in bgpd)
+ * Set TTL for socket
*
- * Returns: 0 : OK (so far so good)
- * != 0 : error number (from errno or otherwise)
+ * Returns: >= 0 => OK
+ * < 0 => failed, see errno.
*/
-
int
-sockopt_ttl (int family, int sock, int ttl)
+sockopt_ttl (int sock_fd, int ttl)
{
const char* msg ;
int ret ;
+ int family ;
ret = 0 ;
+ msg = NULL ;
+ family = sockunion_getsockfamily(sock_fd) ;
+ if (family < 0)
+ return -1 ;
+
+ switch (family)
+ {
+ case AF_INET:
#ifdef IP_TTL
- if (family == AF_INET)
- {
- ret = setsockopt (sock, IPPROTO_IP, IP_TTL,(void*)&ttl, sizeof(int));
- msg = "can't set sockopt IP_TTL %d to socket %d" ;
- }
+ ret = setsockopt (sock_fd, IPPROTO_IP, IP_TTL,(void*)&ttl, sizeof(int));
+ msg = "IP_TTL" ;
#endif /* IP_TTL */
+ break ;
+
#ifdef HAVE_IPV6
- if (family == AF_INET6)
- {
- ret = setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
- (void*)&ttl, sizeof(int));
- msg = "can't set sockopt IPV6_UNICAST_HOPS %d to socket %d" ;
- }
-#endif /* HAVE_IPV6 */
+ case AF_INET6:
+ ret = setsockopt (sock_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ (void*)&ttl, sizeof(int));
+ msg = "IPV6_UNICAST_HOPS" ;
+ break ;
+#endif
- ret = (ret < 0) ? errno : 0 ;
+ default: /* ignore unknown family */
+ ret = 0 ;
+ break ;
+ } ;
if (ret != 0)
- zlog (NULL, LOG_WARNING, msg, ttl, sock) ;
-
- return ret ;
+ {
+ int err = errno ;
+ zlog (NULL, LOG_WARNING,
+ "cannot set sockopt %s %d to socket %d: %s", msg, ttl, sock_fd,
+ safe_strerror(err)) ;
+ errno = err ;
+ return -1 ;
+ } ;
+
+ return 0 ;
} ;