200 lines
5.1 KiB
C
Executable File
200 lines
5.1 KiB
C
Executable File
/* setsockopt functions
|
|
* Copyright (C) 1999 Kunihiro Ishiguro
|
|
*
|
|
* This file is part of GNU Zebra.
|
|
*
|
|
* GNU Zebra is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
* later version.
|
|
*
|
|
* GNU Zebra is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
|
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
#include "log.h"
|
|
|
|
#ifdef HAVE_IPV6
|
|
/* Set IPv6 packet info to the socket. */
|
|
int
|
|
setsockopt_ipv6_pktinfo (int sock, int val)
|
|
{
|
|
int ret;
|
|
|
|
#ifdef IPV6_RECVPKTINFO /*2292bis-01*/
|
|
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val));
|
|
if (ret < 0)
|
|
zlog_warn ("can't setsockopt IPV6_RECVPKTINFO : %s", strerror (errno));
|
|
#else /*RFC2292*/
|
|
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &val, sizeof(val));
|
|
if (ret < 0)
|
|
zlog_warn ("can't setsockopt IPV6_PKTINFO : %s", strerror (errno));
|
|
#endif /* INIA_IPV6 */
|
|
return ret;
|
|
}
|
|
|
|
/* Set multicast hops val to the socket. */
|
|
int
|
|
setsockopt_ipv6_checksum (int sock, int val)
|
|
{
|
|
int ret;
|
|
|
|
#ifdef GNU_LINUX
|
|
ret = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));
|
|
#else
|
|
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val));
|
|
#endif /* GNU_LINUX */
|
|
if (ret < 0)
|
|
zlog_warn ("can't setsockopt IPV6_CHECKSUM");
|
|
return ret;
|
|
}
|
|
|
|
/* Set multicast hops val to the socket. */
|
|
int
|
|
setsockopt_ipv6_multicast_hops (int sock, int val)
|
|
{
|
|
int ret;
|
|
|
|
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val));
|
|
if (ret < 0)
|
|
zlog_warn ("can't setsockopt IPV6_MULTICAST_HOPS");
|
|
return ret;
|
|
}
|
|
|
|
/* Set multicast hops val to the socket. */
|
|
int
|
|
setsockopt_ipv6_unicast_hops (int sock, int val)
|
|
{
|
|
int ret;
|
|
|
|
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val));
|
|
if (ret < 0)
|
|
zlog_warn ("can't setsockopt IPV6_UNICAST_HOPS");
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
setsockopt_ipv6_hoplimit (int sock, int val)
|
|
{
|
|
int ret;
|
|
|
|
#ifdef IPV6_RECVHOPLIMIT /*2292bis-01*/
|
|
ret = setsockopt (sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val));
|
|
if (ret < 0)
|
|
zlog_warn ("can't setsockopt IPV6_RECVHOPLIMIT");
|
|
#else /*RFC2292*/
|
|
ret = setsockopt (sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &val, sizeof(val));
|
|
if (ret < 0)
|
|
zlog_warn ("can't setsockopt IPV6_HOPLIMIT");
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
/* Set multicast loop zero to the socket. */
|
|
int
|
|
setsockopt_ipv6_multicast_loop (int sock, int val)
|
|
{
|
|
int ret;
|
|
|
|
ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val,
|
|
sizeof (val));
|
|
if (ret < 0)
|
|
zlog_warn ("can't setsockopt IPV6_MULTICAST_LOOP");
|
|
return ret;
|
|
}
|
|
|
|
#endif /* HAVE_IPV6 */
|
|
|
|
|
|
/* Set up a multicast socket options for IPv4
|
|
This is here so that people only have to do their OS multicast mess
|
|
in one place rather than all through zebra, ospfd, and ripd
|
|
NB: This is a hookpoint for specific OS functionality */
|
|
int
|
|
setsockopt_multicast_ipv4(int sock,
|
|
int optname,
|
|
struct in_addr if_addr,
|
|
unsigned int mcast_addr,
|
|
unsigned int ifindex)
|
|
{
|
|
|
|
/* Linux 2.2.0 and up */
|
|
#if defined(GNU_LINUX) && LINUX_VERSION_CODE > 131584
|
|
/* This is better because it uses ifindex directly */
|
|
struct ip_mreqn mreqn;
|
|
|
|
switch (optname)
|
|
{
|
|
case IP_MULTICAST_IF:
|
|
case IP_ADD_MEMBERSHIP:
|
|
case IP_DROP_MEMBERSHIP:
|
|
memset (&mreqn, 0, sizeof(mreqn));
|
|
|
|
if (mcast_addr)
|
|
mreqn.imr_multiaddr.s_addr = mcast_addr;
|
|
|
|
if (ifindex)
|
|
mreqn.imr_ifindex = ifindex;
|
|
else
|
|
mreqn.imr_address = if_addr;
|
|
|
|
return setsockopt(sock, IPPROTO_IP, optname, (void *)&mreqn, sizeof(mreqn));
|
|
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
|
|
function, AND handle optname as per other sections for consistency !! */
|
|
/* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */
|
|
/* Add your favourite OS here! */
|
|
|
|
#else /* #if OS_TYPE */
|
|
/* default OS support */
|
|
|
|
struct in_addr m;
|
|
struct ip_mreq mreq;
|
|
|
|
switch (optname)
|
|
{
|
|
case IP_MULTICAST_IF:
|
|
m = if_addr;
|
|
|
|
return setsockopt (sock, IPPROTO_IP, optname, (void *)&m, sizeof(m));
|
|
break;
|
|
|
|
case IP_ADD_MEMBERSHIP:
|
|
case IP_DROP_MEMBERSHIP:
|
|
memset (&mreq, 0, sizeof(mreq));
|
|
mreq.imr_multiaddr.s_addr = mcast_addr;
|
|
mreq.imr_interface = if_addr;
|
|
|
|
return setsockopt (sock,
|
|
IPPROTO_IP,
|
|
optname,
|
|
(void *)&mreq,
|
|
sizeof(mreq));
|
|
break;
|
|
|
|
default:
|
|
/* Can out and give an understandable error */
|
|
errno = EINVAL;
|
|
return -1;
|
|
break;
|
|
}
|
|
#endif /* #if OS_TYPE */
|
|
|
|
}
|