blob: e2beca9f9ca019a69ed1acbaaf8a263562d09c8f [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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}