# 2.11BSD#431 - /usr/src/sys/netinet/in_pcb.c

##### Functions

    in_losing         X
    in_pcballoc       X
    in_pcbbind        X
    in_pcbconnect     X
    in_pcbdetach      X
    in_pcbdisconnect  X
    in_pcblookup      X
    in_pcbnotify      X
    in_rtchange       X
    in_setpeeraddr    X
    in_setsockaddr    X

##### Variables

    zeroin_addr       X

##### Macros

    satosin           X

       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_pcb.c	7.6.1 (2.11BSD GTE) 2/20/94
      13:  */
      14:
      15: #include "param.h"
      16: #include "systm.h"
      17: #include "user.h"
      18: #include "mbuf.h"
      19: #include "socket.h"
      20: #include "socketvar.h"
      21: #include "ioctl.h"
      22: #include "domain.h"
      23: #include "protosw.h"
      24: #include "in.h"
      25: #include "in_systm.h"
      26: #include "../net/if.h"
      27: #include "../net/route.h"
      28: #include "in_pcb.h"
      29: #include "in_var.h"
      30: #include "kernel.h"
      31:
      32: struct  in_addr zeroin_addr;
      33:
      34: in_pcballoc(so, head)
      35:     struct socket *so;
      36:     struct inpcb *head;
      37: {
      38:     struct mbuf *m;
      39:     register struct inpcb *inp;
      40:
      41:     m = m_getclr(M_DONTWAIT, MT_PCB);
      42:     if (m == NULL)
      43:         return (ENOBUFS);
      44:     inp = mtod(m, struct inpcb *);
      45:     inp->inp_head = head;
      46:     inp->inp_socket = so;
      47:     insque(inp, head);
      48:     so->so_pcb = (caddr_t)inp;
      49:     return (0);
      50: }
      51:
      52: in_pcbbind(inp, nam)
      53:     register struct inpcb *inp;
      54:     struct mbuf *nam;
      55: {
      56:     register struct socket *so = inp->inp_socket;
      57:     register struct inpcb *head = inp->inp_head;
      58:     register struct sockaddr_in *sin;
      59:     u_short lport = 0;
      60:     int wild = 0;
      61:
      62:     if (in_ifaddr == 0)
      63:         return (EADDRNOTAVAIL);
      64:     if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
      65:         return (EINVAL);
      66:     if ((so->so_options & SO_REUSEADDR) == 0 &&
      67:         ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
      68:          (so->so_options & SO_ACCEPTCONN) == 0))
      69:         wild = INPLOOKUP_WILDCARD;
      70:
      71:     if (nam == 0)
      72:         goto noname;
      73:     sin = mtod(nam, struct sockaddr_in *);
      74:     if (nam->m_len != sizeof (*sin))
      75:         return (EINVAL);
      76:     if (sin->sin_addr.s_addr != INADDR_ANY) {
      77:         int tport = sin->sin_port;
      78:
      79:         sin->sin_port = 0;      /* yech... */
      80:         if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
      81:             return (EADDRNOTAVAIL);
      82:         sin->sin_port = tport;
      83:     }
      84:     lport = sin->sin_port;
      85:     if (lport) {
      86:         u_short aport = ntohs(lport);
      87:
      88:         /* GROSS */
      89:         if (aport < IPPORT_RESERVED && u.u_uid != 0)
      90:             return (EACCES);
      91:         if (in_pcblookup(head,
      92:             zeroin_addr, 0, sin->sin_addr, lport, wild))
      93:             return (EADDRINUSE);
      94:     }
      95:     inp->inp_laddr = sin->sin_addr;
      96: noname:
      97:     if (lport == 0)
      98:         do {
      99:             if (head->inp_lport++ < IPPORT_RESERVED ||
     100:                 head->inp_lport > IPPORT_USERRESERVED)
     101:                 head->inp_lport = IPPORT_RESERVED;
     102:             lport = htons(head->inp_lport);
     103:         } while (in_pcblookup(head,
     104:                 zeroin_addr, 0, inp->inp_laddr, lport, 0));
     105:     inp->inp_lport = lport;
     106:     return (0);
     107: }
     108:
     109: /*
     110:  * Connect from a socket to a specified address.
     111:  * Both address and port must be specified in argument sin.
     112:  * If don't have a local address for this socket yet,
     113:  * then pick one.
     114:  */
     115: in_pcbconnect(inp, nam)
     116:     register struct inpcb *inp;
     117:     struct mbuf *nam;
     118: {
     119:     struct in_ifaddr *ia;
     120:     struct sockaddr_in *ifaddr;
     121:     register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
     122:
     123:     if (nam->m_len != sizeof (*sin))
     124:         return (EINVAL);
     125:     if (sin->sin_family != AF_INET)
     126:         return (EAFNOSUPPORT);
     127:     if (sin->sin_port == 0)
     128:         return (EADDRNOTAVAIL);
     129:     if (in_ifaddr) {
     130:         /*
     131: 		 * If the destination address is INADDR_ANY,
     132: 		 * use the primary local address.
     133: 		 * If the supplied address is INADDR_BROADCAST,
     134: 		 * and the primary interface supports broadcast,
     135: 		 * choose the broadcast address for that interface.
     136: 		 */
     137: #define satosin(sa) ((struct sockaddr_in *)(sa))
     138:         if (sin->sin_addr.s_addr == INADDR_ANY)
     139:             sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
     140:         else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
     141:           (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
     142:             sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
     143:     }
     144:     if (inp->inp_laddr.s_addr == INADDR_ANY) {
     145:         register struct route *ro;
     146:         struct ifnet *ifp;
     147:
     148:         ia = (struct in_ifaddr *)0;
     149:         /*
     150: 		 * If route is known or can be allocated now,
     151: 		 * our src addr is taken from the i/f, else punt.
     152: 		 */
     153:         ro = &inp->inp_route;
     154:         if (ro->ro_rt &&
     155:             (satosin(&ro->ro_dst)->sin_addr.s_addr !=
     156:             sin->sin_addr.s_addr ||
     157:             inp->inp_socket->so_options & SO_DONTROUTE)) {
     158:             RTFREE(ro->ro_rt);
     159:             ro->ro_rt = (struct rtentry *)0;
     160:         }
     161:         if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
     162:             (ro->ro_rt == (struct rtentry *)0 ||
     163:             ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
     164:             /* No route yet, so try to acquire one */
     165:             ro->ro_dst.sa_family = AF_INET;
     166:             ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
     167:                 sin->sin_addr;
     168:             rtalloc(ro);
     169:         }
     170:         /*
     171: 		 * If we found a route, use the address
     172: 		 * corresponding to the outgoing interface
     173: 		 * unless it is the loopback (in case a route
     174: 		 * to our address on another net goes to loopback).
     175: 		 */
     176:         if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp) &&
     177:             (ifp->if_flags & IFF_LOOPBACK) == 0)
     178:             for (ia = in_ifaddr; ia; ia = ia->ia_next)
     179:                 if (ia->ia_ifp == ifp)
     180:                     break;
     181:         if (ia == 0) {
     182:             int fport = sin->sin_port;
     183:
     184:             sin->sin_port = 0;
     185:             ia = (struct in_ifaddr *)
     186:                 ifa_ifwithdstaddr((struct sockaddr *)sin);
     187:             sin->sin_port = fport;
     188:             if (ia == 0)
     189:                 ia = in_iaonnetof(in_netof(sin->sin_addr));
     190:             if (ia == 0)
     191:                 ia = in_ifaddr;
     192:             if (ia == 0)
     193:                 return (EADDRNOTAVAIL);
     194:         }
     195:         ifaddr = (struct sockaddr_in *)&ia->ia_addr;
     196:     }
     197:     if (in_pcblookup(inp->inp_head,
     198:         sin->sin_addr,
     199:         sin->sin_port,
     200:         inp->inp_laddr.s_addr ? inp->inp_laddr.s_addr : ifaddr->sin_addr.s_addr,
     201:         inp->inp_lport,
     202:         0))
     203:         return (EADDRINUSE);
     204:     if (inp->inp_laddr.s_addr == INADDR_ANY) {
     205:         if (inp->inp_lport == 0)
     206:             (void)in_pcbbind(inp, (struct mbuf *)0);
     207:         inp->inp_laddr = ifaddr->sin_addr;
     208:     }
     209:     inp->inp_faddr = sin->sin_addr;
     210:     inp->inp_fport = sin->sin_port;
     211:     return (0);
     212: }
     213:
     214: in_pcbdisconnect(inp)
     215:     struct inpcb *inp;
     216: {
     217:
     218:     inp->inp_faddr.s_addr = INADDR_ANY;
     219:     inp->inp_fport = 0;
     220:     if (inp->inp_socket->so_state & SS_NOFDREF)
     221:         in_pcbdetach(inp);
     222: }
     223:
     224: in_pcbdetach(inp)
     225:     struct inpcb *inp;
     226: {
     227:     struct socket *so = inp->inp_socket;
     228:
     229:     so->so_pcb = 0;
     230:     sofree(so);
     231:     if (inp->inp_options)
     232:         (void)m_free(inp->inp_options);
     233:     if (inp->inp_route.ro_rt)
     234:         rtfree(inp->inp_route.ro_rt);
     235:     remque(inp);
     236:     (void) m_free(dtom(inp));
     237: }
     238:
     239: in_setsockaddr(inp, nam)
     240:     register struct inpcb *inp;
     241:     struct mbuf *nam;
     242: {
     243:     register struct sockaddr_in *sin;
     244:
     245:     nam->m_len = sizeof (*sin);
     246:     sin = mtod(nam, struct sockaddr_in *);
     247:     bzero((caddr_t)sin, sizeof (*sin));
     248:     sin->sin_family = AF_INET;
     249:     sin->sin_port = inp->inp_lport;
     250:     sin->sin_addr = inp->inp_laddr;
     251: }
     252:
     253: in_setpeeraddr(inp, nam)
     254:     struct inpcb *inp;
     255:     struct mbuf *nam;
     256: {
     257:     register struct sockaddr_in *sin;
     258:
     259:     nam->m_len = sizeof (*sin);
     260:     sin = mtod(nam, struct sockaddr_in *);
     261:     bzero((caddr_t)sin, sizeof (*sin));
     262:     sin->sin_family = AF_INET;
     263:     sin->sin_port = inp->inp_fport;
     264:     sin->sin_addr = inp->inp_faddr;
     265: }
     266:
     267: /*
     268:  * Pass some notification to all connections of a protocol
     269:  * associated with address dst.  The local address and/or port numbers
     270:  * may be specified to limit the search.  The "usual action" will be
     271:  * taken, depending on the ctlinput cmd.  The caller must filter any
     272:  * cmds that are uninteresting (e.g., no error in the map).
     273:  * Call the protocol specific routine (if any) to report
     274:  * any errors for each matching socket.
     275:  *
     276:  * Must be called at splnet.
     277:  */
     278: in_pcbnotify(head, dst, fport, laddr, lport, cmd, notify)
     279:     struct inpcb *head;
     280:     struct sockaddr *dst;
     281:     u_short fport, lport;
     282:     struct in_addr laddr;
     283:     int cmd, (*notify)();
     284: {
     285:     register struct inpcb *inp, *oinp;
     286:     struct in_addr faddr;
     287:     int errno;
     288:     int in_rtchange();
     289:     extern u_char inetctlerrmap[];
     290:
     291:     if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
     292:         return;
     293:     faddr = ((struct sockaddr_in *)dst)->sin_addr;
     294:     if (faddr.s_addr == INADDR_ANY)
     295:         return;
     296:
     297:     /*
     298: 	 * Redirects go to all references to the destination,
     299: 	 * and use in_rtchange to invalidate the route cache.
     300: 	 * Dead host indications: notify all references to the destination.
     301: 	 * Otherwise, if we have knowledge of the local port and address,
     302: 	 * deliver only to that socket.
     303: 	 */
     304:     if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
     305:         fport = 0;
     306:         lport = 0;
     307:         laddr.s_addr = 0;
     308:         if (cmd != PRC_HOSTDEAD)
     309:             notify = in_rtchange;
     310:     }
     311:     errno = inetctlerrmap[cmd];
     312:     for (inp = head->inp_next; inp != head;) {
     313:         if (inp->inp_faddr.s_addr != faddr.s_addr ||
     314:             inp->inp_socket == 0 ||
     315:             (lport && inp->inp_lport != lport) ||
     316:             (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||
     317:             (fport && inp->inp_fport != fport)) {
     318:             inp = inp->inp_next;
     319:             continue;
     320:         }
     321:         oinp = inp;
     322:         inp = inp->inp_next;
     323:         if (notify)
     324:             (*notify)(oinp, errno);
     325:     }
     326: }
     327:
     328: /*
     329:  * Check for alternatives when higher level complains
     330:  * about service problems.  For now, invalidate cached
     331:  * routing information.  If the route was created dynamically
     332:  * (by a redirect), time to try a default gateway again.
     333:  */
     334: in_losing(inp)
     335:     struct inpcb *inp;
     336: {
     337:     register struct rtentry *rt;
     338:
     339:     if ((rt = inp->inp_route.ro_rt)) {
     340:         if (rt->rt_flags & RTF_DYNAMIC)
     341:             (void) rtrequest((int)SIOCDELRT, rt);
     342:         rtfree(rt);
     343:         inp->inp_route.ro_rt = 0;
     344:         /*
     345: 		 * A new route can be allocated
     346: 		 * the next time output is attempted.
     347: 		 */
     348:     }
     349: }
     350:
     351: /*
     352:  * After a routing change, flush old routing
     353:  * and allocate a (hopefully) better one.
     354:  */
     355: in_rtchange(inp)
     356:     register struct inpcb *inp;
     357: {
     358:     if (inp->inp_route.ro_rt) {
     359:         rtfree(inp->inp_route.ro_rt);
     360:         inp->inp_route.ro_rt = 0;
     361:         /*
     362: 		 * A new route can be allocated the next time
     363: 		 * output is attempted.
     364: 		 */
     365:     }
     366: }
     367:
     368: struct inpcb *
     369: in_pcblookup(head, faddr, fport, laddr, lport, flags)
     370:     struct inpcb *head;
     371:     struct in_addr faddr, laddr;
     372:     u_short fport, lport;
     373:     int flags;
     374: {
     375:     register struct inpcb *inp, *match = 0;
     376:     int matchwild = 3, wildcard;
     377:
     378:     for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
     379:         if (inp->inp_lport != lport)
     380:             continue;
     381:         wildcard = 0;
     382:         if (inp->inp_laddr.s_addr != INADDR_ANY) {
     383:             if (laddr.s_addr == INADDR_ANY)
     384:                 wildcard++;
     385:             else if (inp->inp_laddr.s_addr != laddr.s_addr)
     386:                 continue;
     387:         } else {
     388:             if (laddr.s_addr != INADDR_ANY)
     389:                 wildcard++;
     390:         }
     391:         if (inp->inp_faddr.s_addr != INADDR_ANY) {
     392:             if (faddr.s_addr == INADDR_ANY)
     393:                 wildcard++;
     394:             else if (inp->inp_faddr.s_addr != faddr.s_addr ||
     395:                 inp->inp_fport != fport)
     396:                 continue;
     397:         } else {
     398:             if (faddr.s_addr != INADDR_ANY)
     399:                 wildcard++;
     400:         }
     401:         if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
     402:             continue;
     403:         if (wildcard < matchwild) {
     404:             match = inp;
     405:             matchwild = wildcard;
     406:             if (matchwild == 0)
     407:                 break;
     408:         }
     409:     }
     410:     return (match);
     411: }

#### Defined functions

in_losing defined in line 334; never used
in_pcballoc defined in line 34; never used
in_pcbbind defined in line 52; used 1 times

- in line 206

in_pcbconnect defined in line 115; never used
in_pcbdetach defined in line 224; used 1 times

- in line 221

in_pcbdisconnect defined in line 214; never used
in_pcblookup defined in line 368; used 3 times

- in line 91, 103, 197

in_pcbnotify defined in line 278; never used
in_rtchange defined in line 355; used 2 times

- in line 288, 309

in_setpeeraddr defined in line 253; never used
in_setsockaddr defined in line 239; never used

#### Defined variables

zeroin_addr defined in line 32; used 2 times

- in line 92, 104

#### Defined macros

satosin defined in line 137; used 2 times

- in line 142, 155

Last modified: 1994-02-20 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1788 |