1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)in.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "param.h"
  10: #include "ioctl.h"
  11: #include "mbuf.h"
  12: #include "protosw.h"
  13: #include "socket.h"
  14: #include "socketvar.h"
  15: #include "uio.h"
  16: #include "dir.h"
  17: #include "user.h"
  18: #include "in_systm.h"
  19: #include "../net/if.h"
  20: #include "../net/route.h"
  21: #include "../net/af.h"
  22: #include "in.h"
  23: #include "in_var.h"
  24: 
  25: #ifdef INET
  26: inet_hash(sin, hp)
  27:     register struct sockaddr_in *sin;
  28:     struct afhash *hp;
  29: {
  30:     register u_long n;
  31: 
  32:     n = in_netof(sin->sin_addr);
  33:     if (n)
  34:         while ((n & 0xff) == 0)
  35:         n >>= 8;
  36:     hp->afh_nethash = n;
  37:     hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
  38: }
  39: 
  40: inet_netmatch(sin1, sin2)
  41:     struct sockaddr_in *sin1, *sin2;
  42: {
  43: 
  44:     return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
  45: }
  46: 
  47: /*
  48:  * Formulate an Internet address from network + host.
  49:  */
  50: struct in_addr
  51: in_makeaddr(net, host)
  52:     u_long net, host;
  53: {
  54:     register struct in_ifaddr *ia;
  55:     register u_long mask;
  56:     u_long addr;
  57: 
  58:     if (IN_CLASSA(net))
  59:         mask = IN_CLASSA_HOST;
  60:     else if (IN_CLASSB(net))
  61:         mask = IN_CLASSB_HOST;
  62:     else
  63:         mask = IN_CLASSC_HOST;
  64:     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  65:         if ((ia->ia_netmask & net) == ia->ia_net) {
  66:             mask = ~ia->ia_subnetmask;
  67:             break;
  68:         }
  69:     addr = htonl(net | (host & mask));
  70:     return (*(struct in_addr *)&addr);
  71: }
  72: 
  73: /*
  74:  * Return the network number from an internet address.
  75:  */
  76: u_long
  77: in_netof(in)
  78:     struct in_addr in;
  79: {
  80:     register u_long i = ntohl(in.s_addr);
  81:     register u_long net;
  82:     register struct in_ifaddr *ia;
  83: 
  84:     if (IN_CLASSA(i))
  85:         net = i & IN_CLASSA_NET;
  86:     else if (IN_CLASSB(i))
  87:         net = i & IN_CLASSB_NET;
  88:     else
  89:         net = i & IN_CLASSC_NET;
  90: 
  91:     /*
  92: 	 * Check whether network is a subnet;
  93: 	 * if so, return subnet number.
  94: 	 */
  95:     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  96:         if (net == ia->ia_net)
  97:             return (i & ia->ia_subnetmask);
  98:     return (net);
  99: }
 100: 
 101: /*
 102:  * Return the host portion of an internet address.
 103:  */
 104: u_long
 105: in_lnaof(in)
 106:     struct in_addr in;
 107: {
 108:     register u_long i = ntohl(in.s_addr);
 109:     register u_long net, host;
 110:     register struct in_ifaddr *ia;
 111: 
 112:     if (IN_CLASSA(i)) {
 113:         net = i & IN_CLASSA_NET;
 114:         host = i & IN_CLASSA_HOST;
 115:     } else if (IN_CLASSB(i)) {
 116:         net = i & IN_CLASSB_NET;
 117:         host = i & IN_CLASSB_HOST;
 118:     } else {
 119:         net = i & IN_CLASSC_NET;
 120:         host = i & IN_CLASSC_HOST;
 121:     }
 122: 
 123:     /*
 124: 	 * Check whether network is a subnet;
 125: 	 * if so, use the modified interpretation of `host'.
 126: 	 */
 127:     for (ia = in_ifaddr; ia; ia = ia->ia_next)
 128:         if (net == ia->ia_net)
 129:             return (host &~ ia->ia_subnetmask);
 130:     return (host);
 131: }
 132: 
 133: #ifndef SUBNETSARELOCAL
 134: #define SUBNETSARELOCAL 1
 135: #endif
 136: int subnetsarelocal = SUBNETSARELOCAL;
 137: /*
 138:  * Return 1 if an internet address is for a ``local'' host
 139:  * (one to which we have a connection).  If subnetsarelocal
 140:  * is true, this includes other subnets of the local net.
 141:  * Otherwise, it includes only the directly-connected (sub)nets.
 142:  */
 143: in_localaddr(in)
 144:     struct in_addr in;
 145: {
 146:     register u_long i = ntohl(in.s_addr);
 147:     register u_long net;
 148:     register struct in_ifaddr *ia;
 149: 
 150:     if (IN_CLASSA(i))
 151:         net = i & IN_CLASSA_NET;
 152:     else if (IN_CLASSB(i))
 153:         net = i & IN_CLASSB_NET;
 154:     else
 155:         net = i & IN_CLASSC_NET;
 156: 
 157:     for (ia = in_ifaddr; ia; ia = ia->ia_next)
 158:         if (net == subnetsarelocal ? ia->ia_net : ia->ia_subnet)
 159:             return (1);
 160:     return (0);
 161: }
 162: 
 163: int in_interfaces;      /* number of external internet interfaces */
 164: extern  struct ifnet loif;
 165: 
 166: /*
 167:  * Generic internet control operations (ioctl's).
 168:  * Ifp is 0 if not an interface-specific ioctl.
 169:  */
 170: /* ARGSUSED */
 171: in_control(so, cmd, data, ifp)
 172:     struct socket *so;
 173:     int cmd;
 174:     caddr_t data;
 175:     register struct ifnet *ifp;
 176: {
 177:     register struct ifreq *ifr = (struct ifreq *)data;
 178:     register struct in_ifaddr *ia = 0;
 179:     u_long tmp;
 180:     struct ifaddr *ifa;
 181:     struct mbuf *m;
 182:     int error;
 183: 
 184:     /*
 185: 	 * Find address for this interface, if it exists.
 186: 	 */
 187:     if (ifp)
 188:         for (ia = in_ifaddr; ia; ia = ia->ia_next)
 189:             if (ia->ia_ifp == ifp)
 190:                 break;
 191: 
 192:     switch (cmd) {
 193: 
 194:     case SIOCSIFADDR:
 195:     case SIOCSIFNETMASK:
 196:     case SIOCSIFDSTADDR:
 197:         if (!suser())
 198:             return (u.u_error);
 199: 
 200:         if (ifp == 0)
 201:             panic("in_control");
 202:         if (ia == (struct in_ifaddr *)0) {
 203:             m = m_getclr(M_WAIT, MT_IFADDR);
 204:             if (m == (struct mbuf *)NULL)
 205:                 return (ENOBUFS);
 206:             if (ia = in_ifaddr) {
 207:                 for ( ; ia->ia_next; ia = ia->ia_next)
 208:                     ;
 209:                 ia->ia_next = mtod(m, struct in_ifaddr *);
 210:             } else
 211:                 in_ifaddr = mtod(m, struct in_ifaddr *);
 212:             ia = mtod(m, struct in_ifaddr *);
 213:             if (ifa = ifp->if_addrlist) {
 214:                 for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
 215:                     ;
 216:                 ifa->ifa_next = (struct ifaddr *) ia;
 217:             } else
 218:                 ifp->if_addrlist = (struct ifaddr *) ia;
 219:             ia->ia_ifp = ifp;
 220:             IA_SIN(ia)->sin_family = AF_INET;
 221:             if (ifp != &loif)
 222:                 in_interfaces++;
 223:         }
 224:         break;
 225: 
 226:     case SIOCSIFBRDADDR:
 227:         if (!suser())
 228:             return (u.u_error);
 229:         /* FALLTHROUGH */
 230: 
 231:     default:
 232:         if (ia == (struct in_ifaddr *)0)
 233:             return (EADDRNOTAVAIL);
 234:         break;
 235:     }
 236: 
 237:     switch (cmd) {
 238: 
 239:     case SIOCGIFADDR:
 240:         ifr->ifr_addr = ia->ia_addr;
 241:         break;
 242: 
 243:     case SIOCGIFBRDADDR:
 244:         if ((ifp->if_flags & IFF_BROADCAST) == 0)
 245:             return (EINVAL);
 246:         ifr->ifr_dstaddr = ia->ia_broadaddr;
 247:         break;
 248: 
 249:     case SIOCGIFDSTADDR:
 250:         if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
 251:             return (EINVAL);
 252:         ifr->ifr_dstaddr = ia->ia_dstaddr;
 253:         break;
 254: 
 255:     case SIOCGIFNETMASK:
 256: #define satosin(sa) ((struct sockaddr_in *)(sa))
 257:         satosin(&ifr->ifr_addr)->sin_family = AF_INET;
 258:         satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask);
 259:         break;
 260: 
 261:     case SIOCSIFDSTADDR:
 262:         {
 263:         struct sockaddr oldaddr;
 264: 
 265:         if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
 266:             return (EINVAL);
 267:         oldaddr = ia->ia_dstaddr;
 268:         ia->ia_dstaddr = ifr->ifr_dstaddr;
 269:         if (ifp->if_ioctl &&
 270:             (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
 271:             ia->ia_dstaddr = oldaddr;
 272:             return (error);
 273:         }
 274:         if (ia->ia_flags & IFA_ROUTE) {
 275:             rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT,
 276:                 RTF_HOST);
 277:             rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
 278:                 RTF_HOST|RTF_UP);
 279:         }
 280:         }
 281:         break;
 282: 
 283:     case SIOCSIFBRDADDR:
 284:         if ((ifp->if_flags & IFF_BROADCAST) == 0)
 285:             return (EINVAL);
 286:         ia->ia_broadaddr = ifr->ifr_broadaddr;
 287:         tmp = ntohl(satosin(&ia->ia_broadaddr)->sin_addr.s_addr);
 288:         if ((tmp &~ ia->ia_subnetmask) == ~ia->ia_subnetmask)
 289:             tmp |= ~ia->ia_netmask;
 290:         else if ((tmp &~ ia->ia_subnetmask) == 0)
 291:             tmp &= ia->ia_netmask;
 292:         ia->ia_netbroadcast.s_addr = htonl(tmp);
 293:         break;
 294: 
 295:     case SIOCSIFADDR:
 296:         return (in_ifinit(ifp, ia, &ifr->ifr_addr));
 297: 
 298:     case SIOCSIFNETMASK:
 299:         ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr);
 300:         break;
 301: 
 302:     default:
 303:         if (ifp == 0 || ifp->if_ioctl == 0)
 304:             return (EOPNOTSUPP);
 305:         return ((*ifp->if_ioctl)(ifp, cmd, data));
 306:     }
 307:     return (0);
 308: }
 309: 
 310: /*
 311:  * Initialize an interface's internet address
 312:  * and routing table entry.
 313:  */
 314: in_ifinit(ifp, ia, sin)
 315:     register struct ifnet *ifp;
 316:     register struct in_ifaddr *ia;
 317:     struct sockaddr_in *sin;
 318: {
 319:     register u_long i = ntohl(sin->sin_addr.s_addr);
 320:     struct sockaddr oldaddr;
 321:     struct sockaddr_in netaddr;
 322:     int s = splimp(), error;
 323: 
 324:     oldaddr = ia->ia_addr;
 325:     ia->ia_addr = *(struct sockaddr *)sin;
 326: 
 327:     /*
 328: 	 * Give the interface a chance to initialize
 329: 	 * if this is its first address,
 330: 	 * and to validate the address if necessary.
 331: 	 */
 332:     if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
 333:         splx(s);
 334:         ia->ia_addr = oldaddr;
 335:         return (error);
 336:     }
 337: 
 338:     /*
 339: 	 * Delete any previous route for an old address.
 340: 	 */
 341:     bzero((caddr_t)&netaddr, sizeof (netaddr));
 342:     netaddr.sin_family = AF_INET;
 343:     if (ia->ia_flags & IFA_ROUTE) {
 344:         if (ifp->if_flags & IFF_LOOPBACK)
 345:             rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST);
 346:         else if (ifp->if_flags & IFF_POINTOPOINT)
 347:             rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT,
 348:                 RTF_HOST);
 349:         else {
 350:             netaddr.sin_addr = in_makeaddr(ia->ia_subnet,
 351:                 INADDR_ANY);
 352:             rtinit((struct sockaddr *)&netaddr, &oldaddr,
 353:                 (int)SIOCDELRT, 0);
 354:         }
 355:         ia->ia_flags &= ~IFA_ROUTE;
 356:     }
 357:     if (IN_CLASSA(i))
 358:         ia->ia_netmask = IN_CLASSA_NET;
 359:     else if (IN_CLASSB(i))
 360:         ia->ia_netmask = IN_CLASSB_NET;
 361:     else
 362:         ia->ia_netmask = IN_CLASSC_NET;
 363:     ia->ia_net = i & ia->ia_netmask;
 364:     /*
 365: 	 * The subnet mask includes at least the standard network part,
 366: 	 * but may already have been set to a larger value.
 367: 	 */
 368:     ia->ia_subnetmask |= ia->ia_netmask;
 369:     ia->ia_subnet = i & ia->ia_subnetmask;
 370:     if (ifp->if_flags & IFF_BROADCAST) {
 371:         ia->ia_broadaddr.sa_family = AF_INET;
 372:         ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr =
 373:             in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
 374:         ia->ia_netbroadcast.s_addr =
 375:             htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
 376:     }
 377:     splx(s);
 378:     /*
 379: 	 * Add route for the network.
 380: 	 */
 381:     if (ifp->if_flags & IFF_LOOPBACK)
 382:         rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT,
 383:             RTF_HOST|RTF_UP);
 384:     else if (ifp->if_flags & IFF_POINTOPOINT)
 385:         rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
 386:             RTF_HOST|RTF_UP);
 387:     else {
 388:         netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
 389:         rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
 390:             (int)SIOCADDRT, RTF_UP);
 391:     }
 392:     ia->ia_flags |= IFA_ROUTE;
 393:     return (0);
 394: }
 395: 
 396: /*
 397:  * Return address info for specified internet network.
 398:  */
 399: struct in_ifaddr *
 400: in_iaonnetof(net)
 401:     u_long net;
 402: {
 403:     register struct in_ifaddr *ia;
 404: 
 405:     for (ia = in_ifaddr; ia; ia = ia->ia_next)
 406:         if (ia->ia_subnet == net)
 407:             return (ia);
 408:     return ((struct in_ifaddr *)0);
 409: }
 410: 
 411: /*
 412:  * Return 1 if the address is a local broadcast address.
 413:  */
 414: in_broadcast(in)
 415:     struct in_addr in;
 416: {
 417:     register struct in_ifaddr *ia;
 418: 
 419:     /*
 420: 	 * Look through the list of addresses for a match
 421: 	 * with a broadcast address.
 422: 	 */
 423:     for (ia = in_ifaddr; ia; ia = ia->ia_next)
 424:         if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr ==
 425:         in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST))
 426:              return (1);
 427:     return (0);
 428: }
 429: #endif

Defined functions

in_ifinit defined in line 314; used 1 times
in_localaddr defined in line 143; used 1 times
in_makeaddr defined in line 50; used 7 times
inet_hash defined in line 26; used 2 times
inet_netmatch defined in line 40; used 2 times

Defined variables

in_interfaces defined in line 163; used 2 times
subnetsarelocal defined in line 136; used 1 times

Defined macros

SUBNETSARELOCAL defined in line 134; used 2 times
satosin defined in line 256; used 4 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1986
Valid CSS Valid XHTML 1.0 Strict