1/* setsockopt functions 2 * Copyright (C) 1999 Kunihiro Ishiguro 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#include <zebra.h> 23#include "log.h" 24 25#ifdef HAVE_IPV6 26/* Set IPv6 packet info to the socket. */ 27int 28setsockopt_ipv6_pktinfo (int sock, int val) 29{ 30 int ret; 31 32#ifdef IPV6_RECVPKTINFO /*2292bis-01*/ 33 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)); 34 if (ret < 0) 35 zlog_warn ("can't setsockopt IPV6_RECVPKTINFO : %s", strerror (errno)); 36#else /*RFC2292*/ 37 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &val, sizeof(val)); 38 if (ret < 0) 39 zlog_warn ("can't setsockopt IPV6_PKTINFO : %s", strerror (errno)); 40#endif /* INIA_IPV6 */ 41 return ret; 42} 43 44/* Set multicast hops val to the socket. */ 45int 46setsockopt_ipv6_checksum (int sock, int val) 47{ 48 int ret; 49 50#ifdef GNU_LINUX 51 ret = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val)); 52#else 53 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val)); 54#endif /* GNU_LINUX */ 55 if (ret < 0) 56 zlog_warn ("can't setsockopt IPV6_CHECKSUM"); 57 return ret; 58} 59 60/* Set multicast hops val to the socket. */ 61int 62setsockopt_ipv6_multicast_hops (int sock, int val) 63{ 64 int ret; 65 66 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val)); 67 if (ret < 0) 68 zlog_warn ("can't setsockopt IPV6_MULTICAST_HOPS"); 69 return ret; 70} 71 72/* Set multicast hops val to the socket. */ 73int 74setsockopt_ipv6_unicast_hops (int sock, int val) 75{ 76 int ret; 77 78 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val)); 79 if (ret < 0) 80 zlog_warn ("can't setsockopt IPV6_UNICAST_HOPS"); 81 return ret; 82} 83 84int 85setsockopt_ipv6_hoplimit (int sock, int val) 86{ 87 int ret; 88 89#ifdef IPV6_RECVHOPLIMIT /*2292bis-01*/ 90 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val)); 91 if (ret < 0) 92 zlog_warn ("can't setsockopt IPV6_RECVHOPLIMIT"); 93#else /*RFC2292*/ 94 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &val, sizeof(val)); 95 if (ret < 0) 96 zlog_warn ("can't setsockopt IPV6_HOPLIMIT"); 97#endif 98 return ret; 99} 100 101/* Set multicast loop zero to the socket. */ 102int 103setsockopt_ipv6_multicast_loop (int sock, int val) 104{ 105 int ret; 106 107 ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, 108 sizeof (val)); 109 if (ret < 0) 110 zlog_warn ("can't setsockopt IPV6_MULTICAST_LOOP"); 111 return ret; 112} 113 114#endif /* HAVE_IPV6 */ 115 116 117/* Set up a multicast socket options for IPv4 118 This is here so that people only have to do their OS multicast mess 119 in one place rather than all through zebra, ospfd, and ripd 120 NB: This is a hookpoint for specific OS functionality */ 121int 122setsockopt_multicast_ipv4(int sock, 123 int optname, 124 struct in_addr if_addr, 125 unsigned int mcast_addr, 126 unsigned int ifindex) 127{ 128 129 /* Linux 2.2.0 and up */ 130#if defined(GNU_LINUX) && LINUX_VERSION_CODE > 131584 131 /* This is better because it uses ifindex directly */ 132 struct ip_mreqn mreqn; 133 134 switch (optname) 135 { 136 case IP_MULTICAST_IF: 137 case IP_ADD_MEMBERSHIP: 138 case IP_DROP_MEMBERSHIP: 139 memset (&mreqn, 0, sizeof(mreqn)); 140 141 if (mcast_addr) 142 mreqn.imr_multiaddr.s_addr = mcast_addr; 143 144 if (ifindex) 145 mreqn.imr_ifindex = ifindex; 146 else 147 mreqn.imr_address = if_addr; 148 149 return setsockopt(sock, IPPROTO_IP, optname, (void *)&mreqn, sizeof(mreqn)); 150 break; 151 152 default: 153 /* Can out and give an understandable error */ 154 errno = EINVAL; 155 return -1; 156 break; 157 } 158 159 /* Example defines for another OS, boilerplate off other code in this 160 function, AND handle optname as per other sections for consistency !! */ 161 /* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */ 162 /* Add your favourite OS here! */ 163 164#else /* #if OS_TYPE */ 165 /* default OS support */ 166 167 struct in_addr m; 168 struct ip_mreq mreq; 169 170 switch (optname) 171 { 172 case IP_MULTICAST_IF: 173 m = if_addr; 174 175 return setsockopt (sock, IPPROTO_IP, optname, (void *)&m, sizeof(m)); 176 break; 177 178 case IP_ADD_MEMBERSHIP: 179 case IP_DROP_MEMBERSHIP: 180 memset (&mreq, 0, sizeof(mreq)); 181 mreq.imr_multiaddr.s_addr = mcast_addr; 182 mreq.imr_interface = if_addr; 183 184 return setsockopt (sock, 185 IPPROTO_IP, 186 optname, 187 (void *)&mreq, 188 sizeof(mreq)); 189 break; 190 191 default: 192 /* Can out and give an understandable error */ 193 errno = EINVAL; 194 return -1; 195 break; 196 } 197#endif /* #if OS_TYPE */ 198 199} 200