+ /* This is required by RFC 4861 */
+ val = 255;
+ if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &val, sizeof(val)) < 0) {
+ syslog(LOG_ERR, "setsockopt(IPV6_MULTICAST_HOPS): %m");
+ ret = -1;
+ goto out;
+ }
+
+ if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ &val, sizeof(val)) < 0) {
+ syslog(LOG_ERR, "setsockopt(IPV6_UNICAST_HOPS): %m");
+ ret = -1;
+ goto out;
+ }
+
+ /* We need to know the source interface */
+ val = 1;
+ if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ &val, sizeof(val)) < 0) {
+ syslog(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO): %m");
+ ret = -1;
+ goto out;
+ }
+
+ if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
+ &val, sizeof(val)) < 0) {
+ syslog(LOG_ERR, "setsockopt(IPV6_RECVHOPLIMIT): %m");
+ ret = -1;
+ goto out;
+ }
+
+ /* Don't loop back */
+ val = 0;
+ if (setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+ &val, sizeof(val)) < 0) {
+ syslog(LOG_ERR, "setsockopt(IPV6_MULTICAST_LOOP): %m");
+ ret = -1;
+ goto out;
+ }
+
+ /* Filter ICMPv6 package types */
+ ICMP6_FILTER_SETBLOCKALL(&filt);
+ ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
+ ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
+ if (setsockopt(iface->router_event.uloop.fd, IPPROTO_ICMPV6, ICMP6_FILTER,
+ &filt, sizeof(filt)) < 0) {
+ syslog(LOG_ERR, "setsockopt(ICMP6_FILTER): %m");
+ ret = -1;
+ goto out;
+ }
+
+ iface->router_event.handle_dgram = handle_icmpv6;
+ odhcpd_register(&iface->router_event);
+ } else {
+ uloop_timeout_cancel(&iface->timer_rs);
+ iface->timer_rs.cb = NULL;
+
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.ipv6mr_interface = iface->ifindex;
+ inet_pton(AF_INET6, ALL_IPV6_NODES, &mreq.ipv6mr_multiaddr);
+ setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
+ &mreq, sizeof(mreq));
+
+ inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &mreq.ipv6mr_multiaddr);
+ setsockopt(iface->router_event.uloop.fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
+ &mreq, sizeof(mreq));
+ }
+
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.ipv6mr_interface = iface->ifindex;
+ inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &mreq.ipv6mr_multiaddr);
+
+ if (iface->ra == MODE_RELAY && iface->master) {
+ inet_pton(AF_INET6, ALL_IPV6_NODES, &mreq.ipv6mr_multiaddr);