home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netns / ns_pcb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-27  |  9.5 KB  |  364 lines

  1. /*
  2.  * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)ns_pcb.c    7.11 (Berkeley) 6/27/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "mbuf.h"
  39. #include "errno.h"
  40. #include "socket.h"
  41. #include "socketvar.h"
  42. #include "protosw.h"
  43.  
  44. #include "../net/if.h"
  45. #include "../net/route.h"
  46.  
  47. #include "ns.h"
  48. #include "ns_if.h"
  49. #include "ns_pcb.h"
  50.  
  51. struct    ns_addr zerons_addr;
  52.  
  53. ns_pcballoc(so, head)
  54.     struct socket *so;
  55.     struct nspcb *head;
  56. {
  57.     struct mbuf *m;
  58.     register struct nspcb *nsp;
  59.  
  60.     m = m_getclr(M_DONTWAIT, MT_PCB);
  61.     if (m == NULL)
  62.         return (ENOBUFS);
  63.     nsp = mtod(m, struct nspcb *);
  64.     nsp->nsp_socket = so;
  65.     insque(nsp, head);
  66.     so->so_pcb = (caddr_t)nsp;
  67.     return (0);
  68. }
  69.     
  70. ns_pcbbind(nsp, nam)
  71.     register struct nspcb *nsp;
  72.     struct mbuf *nam;
  73. {
  74.     register struct sockaddr_ns *sns;
  75.     u_short lport = 0;
  76.  
  77.     if (nsp->nsp_lport || !ns_nullhost(nsp->nsp_laddr))
  78.         return (EINVAL);
  79.     if (nam == 0)
  80.         goto noname;
  81.     sns = mtod(nam, struct sockaddr_ns *);
  82.     if (nam->m_len != sizeof (*sns))
  83.         return (EINVAL);
  84.     if (!ns_nullhost(sns->sns_addr)) {
  85.         int tport = sns->sns_port;
  86.  
  87.         sns->sns_port = 0;        /* yech... */
  88.         if (ifa_ifwithaddr((struct sockaddr *)sns) == 0)
  89.             return (EADDRNOTAVAIL);
  90.         sns->sns_port = tport;
  91.     }
  92.     lport = sns->sns_port;
  93.     if (lport) {
  94.         u_short aport = ntohs(lport);
  95.  
  96.         if (aport < NSPORT_RESERVED &&
  97.             (nsp->nsp_socket->so_state & SS_PRIV) == 0)
  98.             return (EACCES);
  99.         if (ns_pcblookup(&zerons_addr, lport, 0))
  100.             return (EADDRINUSE);
  101.     }
  102.     nsp->nsp_laddr = sns->sns_addr;
  103. noname:
  104.     if (lport == 0)
  105.         do {
  106.             if (nspcb.nsp_lport++ < NSPORT_RESERVED)
  107.                 nspcb.nsp_lport = NSPORT_RESERVED;
  108.             lport = htons(nspcb.nsp_lport);
  109.         } while (ns_pcblookup(&zerons_addr, lport, 0));
  110.     nsp->nsp_lport = lport;
  111.     return (0);
  112. }
  113.  
  114. /*
  115.  * Connect from a socket to a specified address.
  116.  * Both address and port must be specified in argument sns.
  117.  * If don't have a local address for this socket yet,
  118.  * then pick one.
  119.  */
  120. ns_pcbconnect(nsp, nam)
  121.     struct nspcb *nsp;
  122.     struct mbuf *nam;
  123. {
  124.     struct ns_ifaddr *ia;
  125.     register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
  126.     register struct ns_addr *dst;
  127.     register struct route *ro;
  128.     struct ifnet *ifp;
  129.  
  130.     if (nam->m_len != sizeof (*sns))
  131.         return (EINVAL);
  132.     if (sns->sns_family != AF_NS)
  133.         return (EAFNOSUPPORT);
  134.     if (sns->sns_port==0 || ns_nullhost(sns->sns_addr))
  135.         return (EADDRNOTAVAIL);
  136.     /*
  137.      * If we haven't bound which network number to use as ours,
  138.      * we will use the number of the outgoing interface.
  139.      * This depends on having done a routing lookup, which
  140.      * we will probably have to do anyway, so we might
  141.      * as well do it now.  On the other hand if we are
  142.      * sending to multiple destinations we may have already
  143.      * done the lookup, so see if we can use the route
  144.      * from before.  In any case, we only
  145.      * chose a port number once, even if sending to multiple
  146.      * destinations.
  147.      */
  148.     ro = &nsp->nsp_route;
  149.     dst = &satons_addr(ro->ro_dst);
  150.     if (nsp->nsp_socket->so_options & SO_DONTROUTE)
  151.         goto flush;
  152.     if (!ns_neteq(nsp->nsp_lastdst, sns->sns_addr))
  153.         goto flush;
  154.     if (!ns_hosteq(nsp->nsp_lastdst, sns->sns_addr)) {
  155.         if (ro->ro_rt && ! (ro->ro_rt->rt_flags & RTF_HOST)) {
  156.             /* can patch route to avoid rtalloc */
  157.             *dst = sns->sns_addr;
  158.         } else {
  159.     flush:
  160.             if (ro->ro_rt)
  161.                 RTFREE(ro->ro_rt);
  162.             ro->ro_rt = (struct rtentry *)0;
  163.             nsp->nsp_laddr.x_net = ns_zeronet;
  164.         }
  165.     }/* else cached route is ok; do nothing */
  166.     nsp->nsp_lastdst = sns->sns_addr;
  167.     if ((nsp->nsp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
  168.         (ro->ro_rt == (struct rtentry *)0 ||
  169.          ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
  170.             /* No route yet, so try to acquire one */
  171.             ro->ro_dst.sa_family = AF_NS;
  172.             ro->ro_dst.sa_len = sizeof(ro->ro_dst);
  173.             *dst = sns->sns_addr;
  174.             dst->x_port = 0;
  175.             rtalloc(ro);
  176.     }
  177.     if (ns_neteqnn(nsp->nsp_laddr.x_net, ns_zeronet)) {
  178.         /* 
  179.          * If route is known or can be allocated now,
  180.          * our src addr is taken from the i/f, else punt.
  181.          */
  182.  
  183.         ia = (struct ns_ifaddr *)0;
  184.         /*
  185.          * If we found a route, use the address
  186.          * corresponding to the outgoing interface
  187.          */
  188.         if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp))
  189.             for (ia = ns_ifaddr; ia; ia = ia->ia_next)
  190.                 if (ia->ia_ifp == ifp)
  191.                     break;
  192.         if (ia == 0) {
  193.             u_short fport = sns->sns_addr.x_port;
  194.             sns->sns_addr.x_port = 0;
  195.             ia = (struct ns_ifaddr *)
  196.                 ifa_ifwithdstaddr((struct sockaddr *)sns);
  197.             sns->sns_addr.x_port = fport;
  198.             if (ia == 0)
  199.                 ia = ns_iaonnetof(&sns->sns_addr);
  200.             if (ia == 0)
  201.                 ia = ns_ifaddr;
  202.             if (ia == 0)
  203.                 return (EADDRNOTAVAIL);
  204.         }
  205.         nsp->nsp_laddr.x_net = satons_addr(ia->ia_addr).x_net;
  206.     }
  207.     if (ns_pcblookup(&sns->sns_addr, nsp->nsp_lport, 0))
  208.         return (EADDRINUSE);
  209.     if (ns_nullhost(nsp->nsp_laddr)) {
  210.         if (nsp->nsp_lport == 0)
  211.             (void) ns_pcbbind(nsp, (struct mbuf *)0);
  212.         nsp->nsp_laddr.x_host = ns_thishost;
  213.     }
  214.     nsp->nsp_faddr = sns->sns_addr;
  215.     /* Includes nsp->nsp_fport = sns->sns_port; */
  216.     return (0);
  217. }
  218.  
  219. ns_pcbdisconnect(nsp)
  220.     struct nspcb *nsp;
  221. {
  222.  
  223.     nsp->nsp_faddr = zerons_addr;
  224.     if (nsp->nsp_socket->so_state & SS_NOFDREF)
  225.         ns_pcbdetach(nsp);
  226. }
  227.  
  228. ns_pcbdetach(nsp)
  229.     struct nspcb *nsp;
  230. {
  231.     struct socket *so = nsp->nsp_socket;
  232.  
  233.     so->so_pcb = 0;
  234.     sofree(so);
  235.     if (nsp->nsp_route.ro_rt)
  236.         rtfree(nsp->nsp_route.ro_rt);
  237.     remque(nsp);
  238.     (void) m_free(dtom(nsp));
  239. }
  240.  
  241. ns_setsockaddr(nsp, nam)
  242.     register struct nspcb *nsp;
  243.     struct mbuf *nam;
  244. {
  245.     register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
  246.     
  247.     nam->m_len = sizeof (*sns);
  248.     sns = mtod(nam, struct sockaddr_ns *);
  249.     bzero((caddr_t)sns, sizeof (*sns));
  250.     sns->sns_len = sizeof(*sns);
  251.     sns->sns_family = AF_NS;
  252.     sns->sns_addr = nsp->nsp_laddr;
  253. }
  254.  
  255. ns_setpeeraddr(nsp, nam)
  256.     register struct nspcb *nsp;
  257.     struct mbuf *nam;
  258. {
  259.     register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
  260.     
  261.     nam->m_len = sizeof (*sns);
  262.     sns = mtod(nam, struct sockaddr_ns *);
  263.     bzero((caddr_t)sns, sizeof (*sns));
  264.     sns->sns_len = sizeof(*sns);
  265.     sns->sns_family = AF_NS;
  266.     sns->sns_addr  = nsp->nsp_faddr;
  267. }
  268.  
  269. /*
  270.  * Pass some notification to all connections of a protocol
  271.  * associated with address dst.  Call the
  272.  * protocol specific routine to handle each connection.
  273.  * Also pass an extra paramter via the nspcb. (which may in fact
  274.  * be a parameter list!)
  275.  */
  276. ns_pcbnotify(dst, errno, notify, param)
  277.     register struct ns_addr *dst;
  278.     long param;
  279.     int errno, (*notify)();
  280. {
  281.     register struct nspcb *nsp, *oinp;
  282.     int s = splimp();
  283.  
  284.     for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb);) {
  285.         if (!ns_hosteq(*dst,nsp->nsp_faddr)) {
  286.     next:
  287.             nsp = nsp->nsp_next;
  288.             continue;
  289.         }
  290.         if (nsp->nsp_socket == 0)
  291.             goto next;
  292.         if (errno) 
  293.             nsp->nsp_socket->so_error = errno;
  294.         oinp = nsp;
  295.         nsp = nsp->nsp_next;
  296.         oinp->nsp_notify_param = param;
  297.         (*notify)(oinp);
  298.     }
  299.     splx(s);
  300. }
  301.  
  302. #ifdef notdef
  303. /*
  304.  * After a routing change, flush old routing
  305.  * and allocate a (hopefully) better one.
  306.  */
  307. ns_rtchange(nsp)
  308.     struct nspcb *nsp;
  309. {
  310.     if (nsp->nsp_route.ro_rt) {
  311.         rtfree(nsp->nsp_route.ro_rt);
  312.         nsp->nsp_route.ro_rt = 0;
  313.         /*
  314.          * A new route can be allocated the next time
  315.          * output is attempted.
  316.          */
  317.     }
  318.     /* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */
  319. }
  320. #endif
  321.  
  322. struct nspcb *
  323. ns_pcblookup(faddr, lport, wildp)
  324.     struct ns_addr *faddr;
  325.     u_short lport;
  326. {
  327.     register struct nspcb *nsp, *match = 0;
  328.     int matchwild = 3, wildcard;
  329.     u_short fport;
  330.  
  331.     fport = faddr->x_port;
  332.     for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb); nsp = nsp->nsp_next) {
  333.         if (nsp->nsp_lport != lport)
  334.             continue;
  335.         wildcard = 0;
  336.         if (ns_nullhost(nsp->nsp_faddr)) {
  337.             if (!ns_nullhost(*faddr))
  338.                 wildcard++;
  339.         } else {
  340.             if (ns_nullhost(*faddr))
  341.                 wildcard++;
  342.             else {
  343.                 if (!ns_hosteq(nsp->nsp_faddr, *faddr))
  344.                     continue;
  345.                 if (nsp->nsp_fport != fport) {
  346.                     if (nsp->nsp_fport != 0)
  347.                         continue;
  348.                     else
  349.                         wildcard++;
  350.                 }
  351.             }
  352.         }
  353.         if (wildcard && wildp==0)
  354.             continue;
  355.         if (wildcard < matchwild) {
  356.             match = nsp;
  357.             matchwild = wildcard;
  358.             if (wildcard == 0)
  359.                 break;
  360.         }
  361.     }
  362.     return (match);
  363. }
  364.