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

Defined functions

in_broadcast defined in line 431; never used
in_canforward defined in line 174; never used
in_control defined in line 197; never used
in_iaonnetof defined in line 416; never used
in_ifinit defined in line 331; used 1 times
in_lnaof defined in line 111; never used
in_localaddr defined in line 151; never used
in_makeaddr defined in line 55; used 3 times
in_netof defined in line 81; used 3 times
inet_hash defined in line 31; never used
inet_netmatch defined in line 45; never used

Defined variables

subnetsarelocal defined in line 144; used 1 times

Defined macros

SUBNETSARELOCAL defined in line 142; used 2 times
satosin defined in line 279; used 4 times
Last modified: 1995-10-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4815
Valid CSS Valid XHTML 1.0 Strict