]>
git.proxmox.com Git - mirror_frr.git/blob - lib/sockopt.c
1 /* setsockopt functions
2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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
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.
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
27 setsockopt_so_recvbuf (int sock
, int size
)
31 if ( (ret
= setsockopt (sock
, SOL_SOCKET
, SO_RCVBUF
, (char *)
32 &size
, sizeof (int))) < 0)
33 zlog_err ("fd %d: can't setsockopt SO_RCVBUF to %d: %s",
34 sock
,size
,safe_strerror(errno
));
40 getsockopt_cmsg_data (struct msghdr
*msgh
, int level
, int type
)
45 for (cmsg
= CMSG_FIRSTHDR(msgh
);
47 cmsg
= CMSG_NXTHDR(msgh
, cmsg
))
48 if (cmsg
->cmsg_level
== level
&& cmsg
->cmsg_type
)
49 return (ptr
= CMSG_DATA(cmsg
));
55 /* Set IPv6 packet info to the socket. */
57 setsockopt_ipv6_pktinfo (int sock
, int val
)
61 #ifdef IPV6_RECVPKTINFO /*2292bis-01*/
62 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
, &val
, sizeof(val
));
64 zlog_warn ("can't setsockopt IPV6_RECVPKTINFO : %s", safe_strerror (errno
));
66 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_PKTINFO
, &val
, sizeof(val
));
68 zlog_warn ("can't setsockopt IPV6_PKTINFO : %s", safe_strerror (errno
));
69 #endif /* INIA_IPV6 */
73 /* Set multicast hops val to the socket. */
75 setsockopt_ipv6_checksum (int sock
, int val
)
80 ret
= setsockopt(sock
, IPPROTO_RAW
, IPV6_CHECKSUM
, &val
, sizeof(val
));
82 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_CHECKSUM
, &val
, sizeof(val
));
83 #endif /* GNU_LINUX */
85 zlog_warn ("can't setsockopt IPV6_CHECKSUM");
89 /* Set multicast hops val to the socket. */
91 setsockopt_ipv6_multicast_hops (int sock
, int val
)
95 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_MULTICAST_HOPS
, &val
, sizeof(val
));
97 zlog_warn ("can't setsockopt IPV6_MULTICAST_HOPS");
101 /* Set multicast hops val to the socket. */
103 setsockopt_ipv6_unicast_hops (int sock
, int val
)
107 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_UNICAST_HOPS
, &val
, sizeof(val
));
109 zlog_warn ("can't setsockopt IPV6_UNICAST_HOPS");
114 setsockopt_ipv6_hoplimit (int sock
, int val
)
118 #ifdef IPV6_RECVHOPLIMIT /*2292bis-01*/
119 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_RECVHOPLIMIT
, &val
, sizeof(val
));
121 zlog_warn ("can't setsockopt IPV6_RECVHOPLIMIT");
123 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_HOPLIMIT
, &val
, sizeof(val
));
125 zlog_warn ("can't setsockopt IPV6_HOPLIMIT");
130 /* Set multicast loop zero to the socket. */
132 setsockopt_ipv6_multicast_loop (int sock
, int val
)
136 ret
= setsockopt (sock
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
, &val
,
139 zlog_warn ("can't setsockopt IPV6_MULTICAST_LOOP");
144 getsockopt_ipv6_ifindex (struct msghdr
*msgh
)
146 struct in6_pktinfo
*pktinfo
;
148 pktinfo
= getsockopt_cmsg_data (msgh
, IPPROTO_IPV6
, IPV6_PKTINFO
);
150 return pktinfo
->ipi6_ifindex
;
152 #endif /* HAVE_IPV6 */
155 /* Set up a multicast socket options for IPv4
156 This is here so that people only have to do their OS multicast mess
157 in one place rather than all through zebra, ospfd, and ripd
158 NB: This is a hookpoint for specific OS functionality */
160 setsockopt_multicast_ipv4(int sock
,
162 struct in_addr if_addr
,
163 unsigned int mcast_addr
,
164 unsigned int ifindex
)
167 /* Linux 2.2.0 and up */
168 #if defined(GNU_LINUX) && LINUX_VERSION_CODE > 131584
169 /* This is better because it uses ifindex directly */
170 struct ip_mreqn mreqn
;
174 case IP_MULTICAST_IF
:
175 case IP_ADD_MEMBERSHIP
:
176 case IP_DROP_MEMBERSHIP
:
177 memset (&mreqn
, 0, sizeof(mreqn
));
180 mreqn
.imr_multiaddr
.s_addr
= mcast_addr
;
183 mreqn
.imr_ifindex
= ifindex
;
185 mreqn
.imr_address
= if_addr
;
187 return setsockopt(sock
, IPPROTO_IP
, optname
, (void *)&mreqn
, sizeof(mreqn
));
191 /* Can out and give an understandable error */
197 /* Example defines for another OS, boilerplate off other code in this
198 function, AND handle optname as per other sections for consistency !! */
199 /* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */
200 /* Add your favourite OS here! */
202 #else /* #if OS_TYPE */
203 /* default OS support */
210 case IP_MULTICAST_IF
:
213 return setsockopt (sock
, IPPROTO_IP
, optname
, (void *)&m
, sizeof(m
));
216 case IP_ADD_MEMBERSHIP
:
217 case IP_DROP_MEMBERSHIP
:
218 memset (&mreq
, 0, sizeof(mreq
));
219 mreq
.imr_multiaddr
.s_addr
= mcast_addr
;
220 mreq
.imr_interface
= if_addr
;
222 return setsockopt (sock
,
230 /* Can out and give an understandable error */
235 #endif /* #if OS_TYPE */
240 setsockopt_ipv4_ifindex (int sock
, int val
)
244 #if defined (IP_PKTINFO)
245 ret
= setsockopt (sock
, IPPROTO_IP
, IP_PKTINFO
, &val
, sizeof (val
));
246 #elif defined (IP_RECVIF)
247 ret
= setsockopt (sock
, IPPROTO_IP
, IP_RECVIF
, &val
, sizeof (val
));
249 #warning "Neither IP_PKTINFO nor IP_RECVIF is available."
250 #warning "Will not be able to receive link info."
251 #warning "Things might be seriously broken.."
255 zlog_warn ("Can't set IP_PKTINFO option");
260 setsockopt_ifindex (int af
, int sock
, int val
)
267 ret
= setsockopt_ipv4_ifindex (sock
, val
);
271 ret
= setsockopt_ipv6_pktinfo (sock
, val
);
275 zlog_warn ("setsockopt_ifindex: unknown address family %d", af
);
281 getsockopt_ipv4_ifindex (struct msghdr
*msgh
)
284 #if defined(IP_PKTINFO)
285 /* Linux pktinfo based ifindex retrieval */
286 struct in_pktinfo
*pktinfo
;
289 (struct in_pktinfo
*)getsockopt_cmsg_data (msgh
, IPPROTO_IP
, IP_PKTINFO
);
290 ifindex
= pktinfo
->ipi_ifindex
;
292 #elif defined(IP_RECVIF)
293 /* BSD/other IP_RECVIF based ifindex retrieval */
295 /* RECVIF, but not SUNOS, so BSD */
296 struct sockaddr_dl
*sdl
;
298 /* SUNOS_5 doesn't need a structure to extract ifindex */
302 (struct sockaddr_dl
*)getsockopt_cmsg_data (msgh
, IPPROTO_IP
, IP_RECVIF
);
303 ifindex
= sdl
->sdl_index
;
305 ifindex
= *(uint_t
*)getsockopt_cmsg_data (msgh
, IPPROTO_IP
, IP_RECVIF
);
308 #else /* neither IP_PKTINFO nor IP_RECVIF, broken */
310 #warning "getsockopt_ipv4_pktinfo_ifindex: dont have PKTINFO or RECVIF"
311 #warning "things probably will be broken on this platform!"
312 /* XXX why not -1 - this is a failure condition. */
314 #endif /* IP_PKTINFO */
318 /* return ifindex, 0 if none found */
320 getsockopt_ifindex (int af
, struct msghdr
*msgh
)
327 return (getsockopt_ipv4_ifindex (msgh
));
331 return (getsockopt_ipv6_ifindex (msgh
));
335 zlog_warn ("getsockopt_ifindex: unknown address family %d", af
);
336 return (ifindex
= 0);
340 /* swab iph between order system uses for IP_HDRINCL and host order */
342 sockopt_iphdrincl_swab_htosys (struct ip
*iph
)
344 /* BSD and derived take iph in network order, except for
347 #ifndef HAVE_IP_HDRINCL_BSD_ORDER
348 iph
->ip_len
= htons(iph
->ip_len
);
349 iph
->ip_off
= htons(iph
->ip_off
);
350 #endif /* HAVE_IP_HDRINCL_BSD_ORDER */
352 iph
->ip_id
= htons(iph
->ip_id
);
356 sockopt_iphdrincl_swab_systoh (struct ip
*iph
)
358 #ifndef HAVE_IP_HDRINCL_BSD_ORDER
359 iph
->ip_len
= ntohs(iph
->ip_len
);
360 iph
->ip_off
= ntohs(iph
->ip_off
);
361 #endif /* HAVE_IP_HDRINCL_BSD_ORDER */
363 iph
->ip_id
= ntohs(iph
->ip_id
);