/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "defs.h"
static int setup_listen_sock(int ifindex);
static void resetup_listen_sock(struct interface *, int);
/*
* This is called at startup and after that, every CHECK_INTERVAL seconds or
* when a SIGHUP is received.
*/
void
initifs(void)
{
int bufsize;
int numifs;
int n;
int netmaskchange = 0;
lifn.lifn_flags = 0;
return;
}
return;
}
}
lifc.lifc_flags = 0;
"initifs: ioctl (get interface configuration): %m");
return;
}
/*
* Mark all of the currently known interfaces in order to determine
* which of the these interfaces no longer exist.
*/
"initifs: ioctl (get interface flags): %m");
continue;
}
continue;
} else {
/*
* If there is an transition from up to
* down for an exisiting interface,
* increment the counter.
*/
ifp->int_transitions++;
}
}
continue;
}
/*
* For point-to-point interfaces, retrieve both the
* local and the remote addresses.
*/
"initifs: ioctl (get interface address): "
"%m");
continue;
}
"initifs: ioctl (get destination address): "
"%m");
continue;
}
} else {
/*
* For other interfaces, retreieve the prefix (including
* the prefix length.
*/
"initifs: ioctl (get subnet prefix): %m");
continue;
}
/*
* This should never happen but check for it in any case
* since the kernel stores it as an signed integer.
*/
if (lifr.lifr_addrlen < 0 ||
"initifs: ioctl (get subnet prefix) "
"returned invalid prefix length of %d",
continue;
}
}
lifr.lifr_metric < 0)
else
continue;
}
continue;
}
/*
* If the interface's recorded MTU doesn't make sense, use
* IPV6_MIN_MTU instead.
*/
else
/*
* RIP6_IFF_NORTEXCH flag change by itself shouldn't
* cause an if_purge() call, which also purges all the
* routes heard off this interface. So, let's suppress
* changes of RIP6_IFF_NORTEXCH in the following
* comparisons.
*/
/*
* Now let's make sure we capture the latest
* value of RIP6_IFF_NORTEXCH flag.
*/
else
continue;
&ifs.int_dstaddr))
continue;
}
netmaskchange = 1;
/*
* If there is an transition from down to up for an
* exisiting interface, increment the counter.
*/
ifp->int_transitions++;
/*
* If the interface index has changed, we may need to
* set up the listen socket again.
*/
}
}
} else {
char *cp;
int log_num;
return;
}
return;
}
ifp->int_ifbase =
return;
}
/*
* Verify that the value following the separator
* is an integer greater than zero (the only
* possible value for a logical interface).
*/
if (log_num <= 0) {
"initifs: interface name %s could "
return;
}
*cp = '\0';
} else {
log_num = 0;
}
if (log_num == 0) {
} else {
}
}
}
/*
* Any remaining interfaces that are still marked and which were in an
* up state (RIP6_IFF_UP) need to removed from the routing table.
*/
(RIP6_IFF_MARKED | RIP6_IFF_UP)) {
}
}
if (netmaskchange)
rtchangeall();
}
static void
{
else
return;
}
}
static int
{
int sock;
int off = 0;
int recvsize;
if (sock == -1)
goto sock_fail;
sizeof (ifindex)) < 0) {
"setup_listen_sock: setsockopt: IPV6_BOUND_IF: %m");
goto sock_fail;
}
sizeof (hops)) < 0) {
"setup_listen_sock: setsockopt: IPV6_UNICAST_HOPS: %m");
goto sock_fail;
}
sizeof (hops)) < 0) {
"setup_listen_sock: setsockopt: IPV6_MULTICAST_HOPS: %m");
goto sock_fail;
}
sizeof (off)) < 0) {
"setup_listen_sock: setsockopt: IPV6_MULTICAST_LOOP: %m");
goto sock_fail;
}
(char *)&allrouters_mreq, sizeof (allrouters_mreq)) < 0) {
if (errno != EADDRINUSE) {
"setup_listen_sock: setsockopt: "
"IPV6_JOIN_GROUP: %m");
goto sock_fail;
}
}
sizeof (off)) < 0) {
"setup_listen_sock: setsockopt: IPV6_RECVHOPLIMIT: %m");
goto sock_fail;
}
sizeof (on)) < 0) {
"setup_listen_sock: setsockopt: SO_REUSEADDR: %m");
goto sock_fail;
}
sizeof (int)) < 0) {
goto sock_fail;
}
goto sock_fail;
}
poll_ifs_num++;
} else if (poll_ifs_num > max_poll_ifs) {
max_poll_ifs *= 2;
max_poll_ifs * sizeof (struct pollfd));
}
goto sock_fail;
}
return (sock);
if (sock > 0)
return (-1);
}
/*
* resetup_listen_sock is primarily used in the case where a tunnel was
* plumbed, unplumbed, then plumbed again. This would cause the binding set by
* IPV6_BOUND_IF to be useless, and sends to the associated socket will be
* transmitted on the wrong interface. resetup_listen_sock
* closes the socket,
* removes the socket from poll_ifs[]
* plugs the hole in poll_ifs[]
* calls setup_listen_sock to set up the socket again
*/
void
{
int i;
/* Remove socket from poll_ifs[]. */
for (i = poll_ifs_num - 1; i >= 0; i--) {
/*
* Remove hole in poll_ifs. Possibly exchange
* poll_ifs[i] with poll_ifs[poll_ifs_num-1].
*/
if (i != poll_ifs_num - 1) {
}
poll_ifs_num--;
/* Now set everything up again. */
break;
}
}
}