+ if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
+ rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
+ else
+ rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
+ ia->ia_flags &= ~IFA_ROUTE;
+}
+
+/*
+ * Initialize an interface's internet address
+ * and routing table entry.
+ */
+in_ifinit(ifp, ia, sin, scrub)
+ register struct ifnet *ifp;
+ register struct in_ifaddr *ia;
+ struct sockaddr_in *sin;
+{
+ register u_long i = ntohl(sin->sin_addr.s_addr);
+ struct sockaddr_in oldaddr;
+ int s = splimp(), error;
+
+ oldaddr = ia->ia_addr;
+ ia->ia_addr = *sin;
+ /*
+ * Give the interface a chance to initialize
+ * if this is its first address,
+ * and to validate the address if necessary.
+ */
+ if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
+ splx(s);
+ ia->ia_addr = oldaddr;
+ return (error);
+ }
+ if (scrub) {
+ ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
+ in_ifscrub(ifp, ia);
+ ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
+ }
+ if (IN_CLASSA(i))
+ ia->ia_netmask = IN_CLASSA_NET;
+ else if (IN_CLASSB(i))
+ ia->ia_netmask = IN_CLASSB_NET;
+ else
+ ia->ia_netmask = IN_CLASSC_NET;
+ ia->ia_net = i & ia->ia_netmask;
+ /*
+ * The subnet mask includes at least the standard network part,
+ * but may already have been set to a larger value.
+ */
+ ia->ia_subnetmask |= ia->ia_netmask;
+ ia->ia_subnet = i & ia->ia_subnetmask;
+ ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
+ {
+ register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr));
+ register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr);
+ while (--cp >= cpbase)
+ if (*cp) {
+ ia->ia_sockmask.sin_len =
+ 1 + cp - (char *) &(ia->ia_sockmask);
+ break;
+ }
+ }
+ if (ifp->if_flags & IFF_BROADCAST) {
+ ia->ia_broadaddr.sin_addr =
+ in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
+ ia->ia_netbroadcast.s_addr =
+ htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
+ }
+ /*
+ * Add route for the network.
+ */
+ if (ifp->if_flags & IFF_LOOPBACK) {
+ ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
+ rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
+ } else if (ifp->if_flags & IFF_POINTOPOINT &&
+ ia->ia_dstaddr.sin_family == AF_INET)
+ rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
+ else {
+ rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
+ }
+ ia->ia_flags |= IFA_ROUTE;
+ splx(s);
+ return (0);
+}
+
+/*
+ * Return address info for specified internet network.
+ */
+struct in_ifaddr *
+in_iaonnetof(net)
+ u_long net;
+{
+ register struct in_ifaddr *ia;
+
+ for (ia = in_ifaddr; ia; ia = ia->ia_next)
+ if (ia->ia_subnet == net)
+ return (ia);
+ return ((struct in_ifaddr *)0);
+}
+
+/*
+ * Return 1 if the address might be a local broadcast address.
+ */
+in_broadcast(in)
+ struct in_addr in;
+{
+ register struct in_ifaddr *ia;
+ u_long t;
+
+ /*
+ * Look through the list of addresses for a match
+ * with a broadcast address.
+ */
+ for (ia = in_ifaddr; ia; ia = ia->ia_next)
+ if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
+ if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
+ return (1);
+ /*
+ * Check for old-style (host 0) broadcast.
+ */
+ if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
+ return (1);
+ }
+ if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
+ return (1);
+ return (0);