1/*
2 *   $Id: socket.c 241182 2011-02-17 21:50:03Z $
3 *
4 *   Authors:
5 *    Pedro Roque		<roque@di.fc.ul.pt>
6 *    Lars Fenneberg		<lf@elemental.net>
7 *
8 *   This software is Copyright 1996,1997 by the above mentioned author(s),
9 *   All Rights Reserved.
10 *
11 *   The license which is distributed with this software in the file COPYRIGHT
12 *   applies to this software. If your distribution is missing this file, you
13 *   may request it from <pekkas@netcore.fi>.
14 *
15 */
16
17#include <config.h>
18#include <includes.h>
19#include <radvd.h>
20
21/* Note: these are applicable to receiving sockopts only */
22#if defined IPV6_HOPLIMIT && !defined IPV6_RECVHOPLIMIT
23# define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
24#endif
25
26#if defined IPV6_PKTINFO && !defined IPV6_RECVPKTINFO
27# define IPV6_RECVPKTINFO IPV6_PKTINFO
28#endif
29
30int
31open_icmpv6_socket(void)
32{
33	int sock;
34	struct icmp6_filter filter;
35	int err, val;
36
37        sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
38	if (sock < 0)
39	{
40		flog(LOG_ERR, "can't create socket(AF_INET6): %s", strerror(errno));
41		return (-1);
42	}
43
44	val = 1;
45	err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val));
46	if (err < 0)
47	{
48		flog(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO): %s", strerror(errno));
49		return (-1);
50	}
51
52	val = 2;
53#ifdef __linux__
54	err = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));
55#else
56	err = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val));
57#endif
58	if (err < 0)
59	{
60		flog(LOG_ERR, "setsockopt(IPV6_CHECKSUM): %s", strerror(errno));
61		return (-1);
62	}
63
64	val = 255;
65	err = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &val, sizeof(val));
66	if (err < 0)
67	{
68		flog(LOG_ERR, "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno));
69		return (-1);
70	}
71
72	val = 255;
73	err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val));
74	if (err < 0)
75	{
76		flog(LOG_ERR, "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno));
77		return (-1);
78	}
79
80#ifdef IPV6_RECVHOPLIMIT
81	val = 1;
82	err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val));
83	if (err < 0)
84	{
85		flog(LOG_ERR, "setsockopt(IPV6_RECVHOPLIMIT): %s", strerror(errno));
86		return (-1);
87	}
88#endif
89
90	/*
91	 * setup ICMP filter
92	 */
93
94	ICMP6_FILTER_SETBLOCKALL(&filter);
95	ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
96	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
97
98	err = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
99			 sizeof(filter));
100	if (err < 0)
101	{
102		flog(LOG_ERR, "setsockopt(ICMPV6_FILTER): %s", strerror(errno));
103		return (-1);
104	}
105
106	return sock;
107}
108