1*21489Ssklower /* ns_pcb.c 6.1 85/05/30 */ 2*21489Ssklower 3*21489Ssklower #include "param.h" 4*21489Ssklower #include "systm.h" 5*21489Ssklower #include "dir.h" 6*21489Ssklower #include "user.h" 7*21489Ssklower #include "mbuf.h" 8*21489Ssklower #include "socket.h" 9*21489Ssklower #include "socketvar.h" 10*21489Ssklower #include "../net/if.h" 11*21489Ssklower #include "../net/route.h" 12*21489Ssklower #include "protosw.h" 13*21489Ssklower 14*21489Ssklower #include "ns.h" 15*21489Ssklower #include "ns_if.h" 16*21489Ssklower #include "ns_pcb.h" 17*21489Ssklower 18*21489Ssklower struct ns_addr zerons_addr; 19*21489Ssklower 20*21489Ssklower ns_pcballoc(so, head) 21*21489Ssklower struct socket *so; 22*21489Ssklower struct nsp *head; 23*21489Ssklower { 24*21489Ssklower struct mbuf *m; 25*21489Ssklower register struct nspcb *nsp; 26*21489Ssklower 27*21489Ssklower m = m_getclr(M_DONTWAIT, MT_PCB); 28*21489Ssklower if (m == NULL) 29*21489Ssklower return (ENOBUFS); 30*21489Ssklower nsp = mtod(m, struct nspcb *); 31*21489Ssklower nsp->nsp_socket = so; 32*21489Ssklower insque(nsp, head); 33*21489Ssklower so->so_pcb = (caddr_t)nsp; 34*21489Ssklower return (0); 35*21489Ssklower } 36*21489Ssklower 37*21489Ssklower ns_pcbbind(nsp, nam) 38*21489Ssklower register struct nspcb *nsp; 39*21489Ssklower struct mbuf *nam; 40*21489Ssklower { 41*21489Ssklower register struct sockaddr_ns *sns; 42*21489Ssklower u_short lport = 0; 43*21489Ssklower 44*21489Ssklower if(nsp->nsp_lport || !ns_nullhost(nsp->nsp_laddr)) 45*21489Ssklower return (EINVAL); 46*21489Ssklower if (nam == 0) 47*21489Ssklower goto noname; 48*21489Ssklower sns = mtod(nam, struct sockaddr_ns *); 49*21489Ssklower if (nam->m_len != sizeof (*sns)) 50*21489Ssklower return (EINVAL); 51*21489Ssklower if (!ns_nullhost(sns->sns_addr)) { 52*21489Ssklower int tport = sns->sns_port; 53*21489Ssklower 54*21489Ssklower sns->sns_port = 0; /* yech... */ 55*21489Ssklower if (ifa_ifwithaddr((struct sockaddr *)sns) == 0) 56*21489Ssklower return (EADDRNOTAVAIL); 57*21489Ssklower sns->sns_port = tport; 58*21489Ssklower } 59*21489Ssklower lport = sns->sns_port; 60*21489Ssklower if (lport) { 61*21489Ssklower u_short aport = ntohs(lport); 62*21489Ssklower 63*21489Ssklower if (aport < NSPORT_RESERVED && u.u_uid != 0) 64*21489Ssklower return (EACCES); 65*21489Ssklower if (ns_pcblookup(&zerons_addr, lport, 0)) 66*21489Ssklower return (EADDRINUSE); 67*21489Ssklower } 68*21489Ssklower nsp->nsp_laddr = sns->sns_addr; 69*21489Ssklower noname: 70*21489Ssklower if (lport == 0) 71*21489Ssklower do { 72*21489Ssklower if (nspcb.nsp_lport++ < NSPORT_RESERVED) 73*21489Ssklower nspcb.nsp_lport = NSPORT_RESERVED; 74*21489Ssklower lport = htons(nspcb.nsp_lport); 75*21489Ssklower } while (ns_pcblookup(&zerons_addr, lport, 0)); 76*21489Ssklower nsp->nsp_lport = lport; 77*21489Ssklower return (0); 78*21489Ssklower } 79*21489Ssklower 80*21489Ssklower /* 81*21489Ssklower * Connect from a socket to a specified address. 82*21489Ssklower * Both address and port must be specified in argument sns. 83*21489Ssklower * If don't have a local address for this socket yet, 84*21489Ssklower * then pick one. 85*21489Ssklower */ 86*21489Ssklower ns_pcbconnect(nsp, nam) 87*21489Ssklower struct nspcb *nsp; 88*21489Ssklower struct mbuf *nam; 89*21489Ssklower { 90*21489Ssklower struct ns_ifaddr *ia; 91*21489Ssklower struct sockaddr_ns *ifaddr; 92*21489Ssklower register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); 93*21489Ssklower 94*21489Ssklower if (nam->m_len != sizeof (*sns)) 95*21489Ssklower return (EINVAL); 96*21489Ssklower if (sns->sns_family != AF_NS) 97*21489Ssklower return (EAFNOSUPPORT); 98*21489Ssklower if (sns->sns_port==0 || ns_nullhost(sns->sns_addr)) 99*21489Ssklower return (EADDRNOTAVAIL); 100*21489Ssklower if (ns_nullhost(nsp->nsp_laddr) && 101*21489Ssklower ((*(long *)&nsp->nsp_lastnet)!=ns_netof(sns->sns_addr))) { 102*21489Ssklower ia = (struct ns_ifaddr *)ifa_ifwithnet((struct sockaddr *)sns); 103*21489Ssklower if (ia == 0) { 104*21489Ssklower register struct route *ro; 105*21489Ssklower struct ifnet *ifp; 106*21489Ssklower 107*21489Ssklower /* 108*21489Ssklower * If route is known or can be allocated now, 109*21489Ssklower * our src addr is taken from the i/f, else punt. 110*21489Ssklower */ 111*21489Ssklower ro = &nsp->nsp_route; 112*21489Ssklower #define satosns(sa) ((struct sockaddr_ns *)(sa)) 113*21489Ssklower if (ro->ro_rt && 114*21489Ssklower !ns_hosteq(satosns(&ro->ro_dst)->sns_addr, 115*21489Ssklower sns->sns_addr)) { 116*21489Ssklower RTFREE(ro->ro_rt); 117*21489Ssklower ro->ro_rt = (struct rtentry *)0; 118*21489Ssklower } 119*21489Ssklower if ((ro->ro_rt == (struct rtentry *)0) || 120*21489Ssklower (ifp = ro->ro_rt->rt_ifp) == (struct ifnet *)0) { 121*21489Ssklower /* No route yet, so try to acquire one */ 122*21489Ssklower ro->ro_dst.sa_family = AF_NS; 123*21489Ssklower ((struct sockaddr_ns *) &ro->ro_dst)->sns_addr = 124*21489Ssklower sns->sns_addr; 125*21489Ssklower rtalloc(ro); 126*21489Ssklower if (ro->ro_rt == 0) 127*21489Ssklower ia = (struct ns_ifaddr *) 0; 128*21489Ssklower else 129*21489Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 130*21489Ssklower if (ia->ia_ifp == ifp) 131*21489Ssklower break; 132*21489Ssklower } 133*21489Ssklower if (ia == 0) 134*21489Ssklower ia = ns_ifaddr; 135*21489Ssklower if (ia == 0) 136*21489Ssklower return (EADDRNOTAVAIL); 137*21489Ssklower } 138*21489Ssklower ifaddr = (struct sockaddr_ns *)&ia->ia_addr; 139*21489Ssklower nsp->nsp_laddr.x_net = ifaddr->sns_addr.x_net; 140*21489Ssklower nsp->nsp_lastnet = sns->sns_addr.x_net; 141*21489Ssklower } 142*21489Ssklower if (ns_pcblookup(&sns->sns_addr, nsp->nsp_lport, 0)) 143*21489Ssklower return (EADDRINUSE); 144*21489Ssklower if (ns_nullhost(nsp->nsp_laddr)) { 145*21489Ssklower if (nsp->nsp_lport == 0) 146*21489Ssklower ns_pcbbind(nsp, (struct mbuf *)0); 147*21489Ssklower nsp->nsp_laddr.x_host = ns_thishost; 148*21489Ssklower } 149*21489Ssklower nsp->nsp_faddr = sns->sns_addr; 150*21489Ssklower /* Includes nsp->nsp_fport = sns->sns_port; */ 151*21489Ssklower return (0); 152*21489Ssklower } 153*21489Ssklower 154*21489Ssklower ns_pcbdisconnect(nsp) 155*21489Ssklower struct nspcb *nsp; 156*21489Ssklower { 157*21489Ssklower 158*21489Ssklower nsp->nsp_faddr = zerons_addr; 159*21489Ssklower if (nsp->nsp_socket->so_state & SS_NOFDREF) 160*21489Ssklower ns_pcbdetach(nsp); 161*21489Ssklower } 162*21489Ssklower 163*21489Ssklower ns_pcbdetach(nsp) 164*21489Ssklower struct nspcb *nsp; 165*21489Ssklower { 166*21489Ssklower struct socket *so = nsp->nsp_socket; 167*21489Ssklower 168*21489Ssklower so->so_pcb = 0; 169*21489Ssklower sofree(so); 170*21489Ssklower if (nsp->nsp_route.ro_rt) 171*21489Ssklower rtfree(nsp->nsp_route.ro_rt); 172*21489Ssklower remque(nsp); 173*21489Ssklower (void) m_free(dtom(nsp)); 174*21489Ssklower } 175*21489Ssklower 176*21489Ssklower ns_setsockaddr(nsp, nam) 177*21489Ssklower register struct nspcb *nsp; 178*21489Ssklower struct mbuf *nam; 179*21489Ssklower { 180*21489Ssklower register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); 181*21489Ssklower 182*21489Ssklower nam->m_len = sizeof (*sns); 183*21489Ssklower sns = mtod(nam, struct sockaddr_ns *); 184*21489Ssklower bzero((caddr_t)sns, sizeof (*sns)); 185*21489Ssklower sns->sns_family = AF_NS; 186*21489Ssklower sns->sns_addr = nsp->nsp_laddr; 187*21489Ssklower } 188*21489Ssklower 189*21489Ssklower ns_setpeeraddr(nsp, nam) 190*21489Ssklower register struct nspcb *nsp; 191*21489Ssklower struct mbuf *nam; 192*21489Ssklower { 193*21489Ssklower register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *); 194*21489Ssklower 195*21489Ssklower nam->m_len = sizeof (*sns); 196*21489Ssklower sns = mtod(nam, struct sockaddr_ns *); 197*21489Ssklower bzero((caddr_t)sns, sizeof (*sns)); 198*21489Ssklower sns->sns_family = AF_NS; 199*21489Ssklower sns->sns_addr = nsp->nsp_faddr; 200*21489Ssklower } 201*21489Ssklower 202*21489Ssklower /* 203*21489Ssklower * Pass some notification to all connections of a protocol 204*21489Ssklower * associated with address dst. Call the 205*21489Ssklower * protocol specific routine to handle each connection. 206*21489Ssklower * Also pass an extra paramter via the nspcb. (which may in fact 207*21489Ssklower * be a parameter list!) 208*21489Ssklower */ 209*21489Ssklower ns_pcbnotify(dst, errno, notify, param) 210*21489Ssklower register struct ns_addr *dst; 211*21489Ssklower long param; 212*21489Ssklower int errno, (*notify)(); 213*21489Ssklower { 214*21489Ssklower register struct nspcb *nsp, *oinp; 215*21489Ssklower int s = splimp(); 216*21489Ssklower 217*21489Ssklower for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb);) { 218*21489Ssklower if (!ns_hosteq(*dst,nsp->nsp_faddr)) { 219*21489Ssklower next: 220*21489Ssklower nsp = nsp->nsp_next; 221*21489Ssklower continue; 222*21489Ssklower } 223*21489Ssklower if (nsp->nsp_socket == 0) 224*21489Ssklower goto next; 225*21489Ssklower if (errno) 226*21489Ssklower nsp->nsp_socket->so_error = errno; 227*21489Ssklower oinp = nsp; 228*21489Ssklower nsp = nsp->nsp_next; 229*21489Ssklower oinp->nsp_notify_param = param; 230*21489Ssklower (*notify)(oinp); 231*21489Ssklower } 232*21489Ssklower splx(s); 233*21489Ssklower } 234*21489Ssklower 235*21489Ssklower /* 236*21489Ssklower * After a routing change, flush old routing 237*21489Ssklower * and allocate a (hopefully) better one. 238*21489Ssklower */ 239*21489Ssklower ns_rtchange(nsp) 240*21489Ssklower struct nspcb *nsp; 241*21489Ssklower { 242*21489Ssklower if (nsp->nsp_route.ro_rt) { 243*21489Ssklower rtfree(nsp->nsp_route.ro_rt); 244*21489Ssklower nsp->nsp_route.ro_rt = 0; 245*21489Ssklower /* 246*21489Ssklower * A new route can be allocated the next time 247*21489Ssklower * output is attempted. 248*21489Ssklower */ 249*21489Ssklower } 250*21489Ssklower /* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */ 251*21489Ssklower } 252*21489Ssklower 253*21489Ssklower struct nspcb * 254*21489Ssklower ns_pcblookup(faddr, lport, wildp) 255*21489Ssklower struct ns_addr *faddr; 256*21489Ssklower u_short lport; 257*21489Ssklower { 258*21489Ssklower register struct nspcb *nsp, *match = 0; 259*21489Ssklower int matchwild = 3, wildcard; 260*21489Ssklower u_short fport; 261*21489Ssklower 262*21489Ssklower fport = faddr->x_port; 263*21489Ssklower for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb); nsp = nsp->nsp_next) { 264*21489Ssklower if (nsp->nsp_lport != lport) 265*21489Ssklower continue; 266*21489Ssklower wildcard = 0; 267*21489Ssklower if (ns_nullhost(nsp->nsp_faddr)) { 268*21489Ssklower if (!ns_nullhost(*faddr)) 269*21489Ssklower wildcard++; 270*21489Ssklower } else { 271*21489Ssklower if (ns_nullhost(*faddr)) 272*21489Ssklower wildcard++; 273*21489Ssklower else { 274*21489Ssklower if (!ns_hosteq(nsp->nsp_faddr, *faddr)) 275*21489Ssklower continue; 276*21489Ssklower if( nsp->nsp_fport != fport) { 277*21489Ssklower if(nsp->nsp_fport != 0) 278*21489Ssklower continue; 279*21489Ssklower else 280*21489Ssklower wildcard++; 281*21489Ssklower } 282*21489Ssklower } 283*21489Ssklower } 284*21489Ssklower if (wildcard && wildp==0) 285*21489Ssklower continue; 286*21489Ssklower if (wildcard < matchwild) { 287*21489Ssklower match = nsp; 288*21489Ssklower matchwild = wildcard; 289*21489Ssklower if (wildcard == 0) 290*21489Ssklower break; 291*21489Ssklower } 292*21489Ssklower } 293*21489Ssklower return (match); 294*21489Ssklower } 295