/*
- * Copyright (c) 1982 Regents of the University of California.
+ * Copyright (c) 1982, 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
- * @(#)in.c 6.12 (Berkeley) %G%
+ * @(#)in.c 7.2 (Berkeley) %G%
*/
#include "param.h"
/*
* Return the host portion of an internet address.
*/
+u_long
in_lnaof(in)
struct in_addr in;
{
return (host);
}
+#ifndef SUBNETSARELOCAL
+#define SUBNETSARELOCAL 1
+#endif
+int subnetsarelocal = SUBNETSARELOCAL;
/*
* Return 1 if an internet address is for a ``local'' host
- * (one to which we have a connection through a local logical net).
+ * (one to which we have a connection). If subnetsarelocal
+ * is true, this includes other subnets of the local net.
+ * Otherwise, it includes only the directly-connected (sub)nets.
*/
in_localaddr(in)
struct in_addr in;
net = i & IN_CLASSC_NET;
for (ia = in_ifaddr; ia; ia = ia->ia_next)
- if (net == ia->ia_net)
+ if (net == (subnetsarelocal ? ia->ia_net : ia->ia_subnet))
return (1);
return (0);
}
case SIOCSIFADDR:
case SIOCSIFNETMASK:
+ case SIOCSIFDSTADDR:
if (!suser())
return (u.u_error);
break;
case SIOCSIFBRDADDR:
- case SIOCSIFDSTADDR:
if (!suser())
return (u.u_error);
/* FALLTHROUGH */
break;
case SIOCSIFDSTADDR:
+ {
+ struct sockaddr oldaddr;
+
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
return (EINVAL);
+ oldaddr = ia->ia_dstaddr;
+ ia->ia_dstaddr = ifr->ifr_dstaddr;
if (ifp->if_ioctl &&
- (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia)))
+ (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
+ ia->ia_dstaddr = oldaddr;
return (error);
- ia->ia_dstaddr = ifr->ifr_dstaddr;
+ }
+ if (ia->ia_flags & IFA_ROUTE) {
+ rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT,
+ RTF_HOST);
+ rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
+ RTF_HOST|RTF_UP);
+ }
+ }
break;
case SIOCSIFBRDADDR:
struct sockaddr_in *sin;
{
register u_long i = ntohl(sin->sin_addr.s_addr);
- struct sockaddr_in tmpaddr;
+ struct sockaddr oldaddr;
+ struct sockaddr_in netaddr;
int s = splimp(), error;
- tmpaddr = *(struct sockaddr_in *)&ia->ia_addr;
+ oldaddr = ia->ia_addr;
ia->ia_addr = *(struct sockaddr *)sin;
/*
*/
if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
splx(s);
- ia->ia_addr = *(struct sockaddr *)&tmpaddr;
+ ia->ia_addr = oldaddr;
return (error);
}
- bzero((caddr_t)&tmpaddr, sizeof (tmpaddr));
- tmpaddr.sin_family = AF_INET;
/*
* Delete any previous route for an old address.
*/
+ bzero((caddr_t)&netaddr, sizeof (netaddr));
+ netaddr.sin_family = AF_INET;
if (ia->ia_flags & IFA_ROUTE) {
- if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
- tmpaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
- rtinit((struct sockaddr *)&tmpaddr, &ia->ia_addr,
+ if (ifp->if_flags & IFF_LOOPBACK)
+ rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST);
+ else if (ifp->if_flags & IFF_POINTOPOINT)
+ rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT,
+ RTF_HOST);
+ else {
+ netaddr.sin_addr = in_makeaddr(ia->ia_subnet,
+ INADDR_ANY);
+ rtinit((struct sockaddr *)&netaddr, &oldaddr,
(int)SIOCDELRT, 0);
- } else
- rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
- (int)SIOCDELRT, RTF_HOST);
+ }
ia->ia_flags &= ~IFA_ROUTE;
}
if (IN_CLASSA(i))
/*
* Add route for the network.
*/
- if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
- tmpaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
- rtinit((struct sockaddr *)&tmpaddr, &ia->ia_addr,
- (int)SIOCADDRT, RTF_UP);
- } else
- rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr,
- (int)SIOCADDRT, RTF_HOST|RTF_UP);
+ if (ifp->if_flags & IFF_LOOPBACK)
+ rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT,
+ RTF_HOST|RTF_UP);
+ else if (ifp->if_flags & IFF_POINTOPOINT)
+ rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
+ RTF_HOST|RTF_UP);
+ else {
+ netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
+ rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
+ (int)SIOCADDRT, RTF_UP);
+ }
ia->ia_flags |= IFA_ROUTE;
return (0);
}