sockopt.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:5k
- /* 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 */
- }