1*21479Ssklower /* idp_usrreq.c 6.1 85/05/30 */ 2*21479Ssklower 3*21479Ssklower #include "param.h" 4*21479Ssklower #include "dir.h" 5*21479Ssklower #include "user.h" 6*21479Ssklower #include "mbuf.h" 7*21479Ssklower #include "protosw.h" 8*21479Ssklower #include "socket.h" 9*21479Ssklower #include "socketvar.h" 10*21479Ssklower #include "errno.h" 11*21479Ssklower #include "stat.h" 12*21479Ssklower 13*21479Ssklower #include "../net/if.h" 14*21479Ssklower #include "../net/route.h" 15*21479Ssklower 16*21479Ssklower #include "ns.h" 17*21479Ssklower #include "ns_pcb.h" 18*21479Ssklower #include "idp.h" 19*21479Ssklower #include "idp_var.h" 20*21479Ssklower #include "ns_error.h" 21*21479Ssklower 22*21479Ssklower /* 23*21479Ssklower * IDP protocol implementation. 24*21479Ssklower */ 25*21479Ssklower 26*21479Ssklower struct sockaddr_ns idp_ns = { AF_NS }; 27*21479Ssklower 28*21479Ssklower int 29*21479Ssklower idp_input_panic = 1; 30*21479Ssklower idp_input(m, nsp) 31*21479Ssklower struct mbuf *m; 32*21479Ssklower register struct nspcb *nsp; 33*21479Ssklower { 34*21479Ssklower register struct idp *idp = mtod(m, struct idp *); 35*21479Ssklower if (idp_input_panic) { 36*21479Ssklower if ((nsp==0) || ((idp->idp_pt==5) && (!(nsp->nsp_flags&NSP_RAWIN)))) 37*21479Ssklower panic("Impossible idp_input"); 38*21479Ssklower } 39*21479Ssklower 40*21479Ssklower /* 41*21479Ssklower * Construct sockaddr format source address. 42*21479Ssklower * Stuff source address and datagram in user buffer. 43*21479Ssklower */ 44*21479Ssklower idp_ns.sns_addr = idp->idp_sna; 45*21479Ssklower nsp->nsp_rpt = idp->idp_pt; 46*21479Ssklower if ( ! (nsp->nsp_flags & NSP_RAWIN) ) { 47*21479Ssklower m->m_len -= sizeof (struct idp); 48*21479Ssklower m->m_off += sizeof (struct idp); 49*21479Ssklower } 50*21479Ssklower if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns, 51*21479Ssklower m, (struct mbuf *)0) == 0) 52*21479Ssklower goto bad; 53*21479Ssklower sorwakeup(nsp->nsp_socket); 54*21479Ssklower return; 55*21479Ssklower bad: 56*21479Ssklower m_freem(m); 57*21479Ssklower } 58*21479Ssklower 59*21479Ssklower idp_abort(nsp) 60*21479Ssklower struct nspcb *nsp; 61*21479Ssklower { 62*21479Ssklower struct socket *so = nsp->nsp_socket; 63*21479Ssklower 64*21479Ssklower ns_pcbdisconnect(nsp); 65*21479Ssklower soisdisconnected(so); 66*21479Ssklower } 67*21479Ssklower 68*21479Ssklower idp_output(nsp, m0) 69*21479Ssklower struct nspcb *nsp; 70*21479Ssklower struct mbuf *m0; 71*21479Ssklower { 72*21479Ssklower register struct mbuf *m; 73*21479Ssklower register struct idp *idp; 74*21479Ssklower register struct socket *so; 75*21479Ssklower register int len = 0; 76*21479Ssklower register struct route *ro; 77*21479Ssklower struct mbuf *mprev; 78*21479Ssklower extern int idpcksum; 79*21479Ssklower 80*21479Ssklower /* 81*21479Ssklower * Calculate data length. 82*21479Ssklower */ 83*21479Ssklower for (m = m0; m; m = m->m_next) { 84*21479Ssklower mprev = m; 85*21479Ssklower len += m->m_len; 86*21479Ssklower } 87*21479Ssklower /* 88*21479Ssklower * Make sure packet is actually of even length. 89*21479Ssklower */ 90*21479Ssklower 91*21479Ssklower if (len & 1) { 92*21479Ssklower m = mprev; 93*21479Ssklower if (m->m_len + m->m_off < MMAXOFF) { 94*21479Ssklower m->m_len++; 95*21479Ssklower } else { 96*21479Ssklower struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); 97*21479Ssklower 98*21479Ssklower if (m1 == 0) return (ENOBUFS); 99*21479Ssklower m1->m_len = 1; 100*21479Ssklower m1->m_off = MMAXOFF - 1; 101*21479Ssklower * mtod(m1, char *) = 0; 102*21479Ssklower m->m_next = m1; 103*21479Ssklower } 104*21479Ssklower } 105*21479Ssklower 106*21479Ssklower /* 107*21479Ssklower * Fill in mbuf with extended IDP header 108*21479Ssklower * and addresses and length put into network format. 109*21479Ssklower */ 110*21479Ssklower if (nsp->nsp_flags & NSP_RAWOUT) { 111*21479Ssklower m = m0; 112*21479Ssklower idp = mtod(m, struct idp *); 113*21479Ssklower } else { 114*21479Ssklower m = m_get(M_DONTWAIT, MT_HEADER); 115*21479Ssklower if (m == 0) { 116*21479Ssklower m_freem(m0); 117*21479Ssklower return (ENOBUFS); 118*21479Ssklower } 119*21479Ssklower m->m_off = MMAXOFF - sizeof (struct idp); 120*21479Ssklower m->m_len = sizeof (struct idp); 121*21479Ssklower m->m_next = m0; 122*21479Ssklower idp = mtod(m, struct idp *); 123*21479Ssklower idp->idp_tc = 0; 124*21479Ssklower idp->idp_pt = nsp->nsp_dpt; 125*21479Ssklower idp->idp_sna = nsp->nsp_laddr; 126*21479Ssklower idp->idp_dna = nsp->nsp_faddr; 127*21479Ssklower len += sizeof (struct idp); 128*21479Ssklower } 129*21479Ssklower 130*21479Ssklower idp->idp_len = htons((u_short)len); 131*21479Ssklower 132*21479Ssklower if (idpcksum) { 133*21479Ssklower idp->idp_sum = 0; 134*21479Ssklower len = ((len - 1) | 1) + 1; 135*21479Ssklower idp->idp_sum = ns_cksum(m, len); 136*21479Ssklower } else 137*21479Ssklower idp->idp_sum = 0xffff; 138*21479Ssklower 139*21479Ssklower /* 140*21479Ssklower * Output datagram. 141*21479Ssklower */ 142*21479Ssklower so = nsp->nsp_socket; 143*21479Ssklower if (so->so_options & SO_DONTROUTE) 144*21479Ssklower return (ns_output(m, (struct route *)0, 145*21479Ssklower (so->so_options & SO_BROADCAST) | NS_ROUTETOIF)); 146*21479Ssklower /* 147*21479Ssklower * Use cached route for previous datagram if 148*21479Ssklower * this is also to the same destination. 149*21479Ssklower * 150*21479Ssklower * NB: We don't handle broadcasts because that 151*21479Ssklower * would require 3 subroutine calls. 152*21479Ssklower */ 153*21479Ssklower ro = &nsp->nsp_route; 154*21479Ssklower if (ro->ro_rt && 155*21479Ssklower ((*(long *)&nsp->nsp_lastnet)!=ns_netof(idp->idp_dna)) && 156*21479Ssklower !(ns_hosteq(satons_addr(ro->ro_dst), idp->idp_dna))) { 157*21479Ssklower RTFREE(ro->ro_rt); 158*21479Ssklower ro->ro_rt = (struct rtentry *)0; 159*21479Ssklower nsp->nsp_lastnet = idp->idp_dna.x_net; 160*21479Ssklower } 161*21479Ssklower return (ns_output(m, ro, so->so_options & SO_BROADCAST)); 162*21479Ssklower } 163*21479Ssklower /*ARGSUSED*/ 164*21479Ssklower idp_ctloutput(req, so, level, name, value) 165*21479Ssklower int req, level; 166*21479Ssklower struct socket *so; 167*21479Ssklower int name; 168*21479Ssklower struct mbuf **value; 169*21479Ssklower { 170*21479Ssklower register struct mbuf *m; 171*21479Ssklower struct nspcb *nsp = sotonspcb(so); 172*21479Ssklower int mask, error = 0; 173*21479Ssklower 174*21479Ssklower if (nsp == NULL) { 175*21479Ssklower error = EINVAL; 176*21479Ssklower goto release; 177*21479Ssklower } 178*21479Ssklower 179*21479Ssklower switch (req) { 180*21479Ssklower case PRCO_GETOPT: 181*21479Ssklower if (value==NULL) { 182*21479Ssklower error = EINVAL; 183*21479Ssklower goto release; 184*21479Ssklower } 185*21479Ssklower m = m_get(M_DONTWAIT, MT_DATA); 186*21479Ssklower switch (name) { 187*21479Ssklower case SO_HEADERS_ON_INPUT: 188*21479Ssklower mask = NSP_RAWIN; 189*21479Ssklower goto get_flags; 190*21479Ssklower case SO_HEADERS_ON_OUTPUT: 191*21479Ssklower mask = NSP_RAWOUT; 192*21479Ssklower get_flags: 193*21479Ssklower m->m_len = sizeof(short); 194*21479Ssklower m->m_off = MMAXOFF - sizeof(short); 195*21479Ssklower *mtod(m, short *) = nsp->nsp_flags & mask; 196*21479Ssklower break; 197*21479Ssklower case SO_DEFAULT_HEADERS: 198*21479Ssklower m->m_len = sizeof(struct idp); 199*21479Ssklower m->m_off = MMAXOFF - sizeof(struct idp); 200*21479Ssklower { 201*21479Ssklower register struct idp *idp = mtod(m, struct idp *); 202*21479Ssklower idp->idp_len = 0; 203*21479Ssklower idp->idp_sum = 0; 204*21479Ssklower idp->idp_tc = 0; 205*21479Ssklower idp->idp_pt = nsp->nsp_dpt; 206*21479Ssklower idp->idp_dna = nsp->nsp_faddr; 207*21479Ssklower idp->idp_sna = nsp->nsp_laddr; 208*21479Ssklower } 209*21479Ssklower } 210*21479Ssklower *value = m; 211*21479Ssklower break; 212*21479Ssklower case PRCO_SETOPT: 213*21479Ssklower switch (name) { 214*21479Ssklower int mask, *ok; 215*21479Ssklower 216*21479Ssklower case SO_HEADERS_ON_INPUT: 217*21479Ssklower mask = NSP_RAWIN; 218*21479Ssklower goto set_head; 219*21479Ssklower case SO_HEADERS_ON_OUTPUT: 220*21479Ssklower mask = NSP_RAWOUT; 221*21479Ssklower set_head: 222*21479Ssklower if (value && *value) { 223*21479Ssklower ok = mtod(*value, int *); 224*21479Ssklower if (*ok) 225*21479Ssklower nsp->nsp_flags |= mask; 226*21479Ssklower else 227*21479Ssklower nsp->nsp_flags &= ~mask; 228*21479Ssklower } else error = EINVAL; 229*21479Ssklower break; 230*21479Ssklower case SO_DEFAULT_HEADERS: 231*21479Ssklower { 232*21479Ssklower register struct idp *idp 233*21479Ssklower = mtod(*value, struct idp *); 234*21479Ssklower nsp->nsp_dpt = idp->idp_pt; 235*21479Ssklower } 236*21479Ssklower #ifdef NSIP 237*21479Ssklower break; 238*21479Ssklower case SO_NSIP_ROUTE: 239*21479Ssklower error = nsip_route(*value); 240*21479Ssklower break; 241*21479Ssklower #endif NSIP 242*21479Ssklower } 243*21479Ssklower if (value && *value) 244*21479Ssklower m_freem(*value); 245*21479Ssklower break; 246*21479Ssklower } 247*21479Ssklower release: 248*21479Ssklower return(error); 249*21479Ssklower } 250*21479Ssklower 251*21479Ssklower /*ARGSUSED*/ 252*21479Ssklower idp_usrreq(so, req, m, nam, rights) 253*21479Ssklower struct socket *so; 254*21479Ssklower int req; 255*21479Ssklower struct mbuf *m, *nam, *rights; 256*21479Ssklower { 257*21479Ssklower struct nspcb *nsp = sotonspcb(so); 258*21479Ssklower int error = 0; 259*21479Ssklower 260*21479Ssklower if (req == PRU_CONTROL) 261*21479Ssklower return (ns_control(so, (int)m, (caddr_t)nam, 262*21479Ssklower (struct ifnet *)rights)); 263*21479Ssklower if (rights && rights->m_len) { 264*21479Ssklower error = EINVAL; 265*21479Ssklower goto release; 266*21479Ssklower } 267*21479Ssklower if (nsp == NULL && req != PRU_ATTACH) { 268*21479Ssklower error = EINVAL; 269*21479Ssklower goto release; 270*21479Ssklower } 271*21479Ssklower switch (req) { 272*21479Ssklower 273*21479Ssklower case PRU_ATTACH: 274*21479Ssklower if (nsp != NULL) { 275*21479Ssklower error = EINVAL; 276*21479Ssklower break; 277*21479Ssklower } 278*21479Ssklower error = ns_pcballoc(so, &nspcb); 279*21479Ssklower if (error) 280*21479Ssklower break; 281*21479Ssklower error = soreserve(so, 2048, 2048); 282*21479Ssklower if (error) 283*21479Ssklower break; 284*21479Ssklower break; 285*21479Ssklower 286*21479Ssklower case PRU_DETACH: 287*21479Ssklower if (nsp == NULL) { 288*21479Ssklower error = ENOTCONN; 289*21479Ssklower break; 290*21479Ssklower } 291*21479Ssklower ns_pcbdetach(nsp); 292*21479Ssklower break; 293*21479Ssklower 294*21479Ssklower case PRU_BIND: 295*21479Ssklower error = ns_pcbbind(nsp, nam); 296*21479Ssklower break; 297*21479Ssklower 298*21479Ssklower case PRU_LISTEN: 299*21479Ssklower error = EOPNOTSUPP; 300*21479Ssklower break; 301*21479Ssklower 302*21479Ssklower case PRU_CONNECT: 303*21479Ssklower if (!ns_nullhost(nsp->nsp_faddr)) { 304*21479Ssklower error = EISCONN; 305*21479Ssklower break; 306*21479Ssklower } 307*21479Ssklower error = ns_pcbconnect(nsp, nam); 308*21479Ssklower if (error == 0) 309*21479Ssklower soisconnected(so); 310*21479Ssklower break; 311*21479Ssklower 312*21479Ssklower case PRU_CONNECT2: 313*21479Ssklower error = EOPNOTSUPP; 314*21479Ssklower break; 315*21479Ssklower 316*21479Ssklower case PRU_ACCEPT: 317*21479Ssklower error = EOPNOTSUPP; 318*21479Ssklower break; 319*21479Ssklower 320*21479Ssklower case PRU_DISCONNECT: 321*21479Ssklower if (ns_nullhost(nsp->nsp_faddr)) { 322*21479Ssklower error = ENOTCONN; 323*21479Ssklower break; 324*21479Ssklower } 325*21479Ssklower ns_pcbdisconnect(nsp); 326*21479Ssklower soisdisconnected(so); 327*21479Ssklower break; 328*21479Ssklower 329*21479Ssklower case PRU_SHUTDOWN: 330*21479Ssklower socantsendmore(so); 331*21479Ssklower break; 332*21479Ssklower 333*21479Ssklower case PRU_SEND: 334*21479Ssklower { 335*21479Ssklower struct ns_addr laddr; 336*21479Ssklower int s; 337*21479Ssklower 338*21479Ssklower if (nam) { 339*21479Ssklower laddr = nsp->nsp_laddr; 340*21479Ssklower if (!ns_nullhost(nsp->nsp_faddr)) { 341*21479Ssklower error = EISCONN; 342*21479Ssklower break; 343*21479Ssklower } 344*21479Ssklower /* 345*21479Ssklower * Must block input while temporarily connected. 346*21479Ssklower */ 347*21479Ssklower s = splnet(); 348*21479Ssklower error = ns_pcbconnect(nsp, nam); 349*21479Ssklower if (error) { 350*21479Ssklower splx(s); 351*21479Ssklower break; 352*21479Ssklower } 353*21479Ssklower } else { 354*21479Ssklower if (ns_nullhost(nsp->nsp_faddr)) { 355*21479Ssklower error = ENOTCONN; 356*21479Ssklower break; 357*21479Ssklower } 358*21479Ssklower } 359*21479Ssklower error = idp_output(nsp, m); 360*21479Ssklower m = NULL; 361*21479Ssklower if (nam) { 362*21479Ssklower ns_pcbdisconnect(nsp); 363*21479Ssklower splx(s); 364*21479Ssklower nsp->nsp_laddr.x_host = laddr.x_host; 365*21479Ssklower nsp->nsp_laddr.x_port = laddr.x_port; 366*21479Ssklower } 367*21479Ssklower } 368*21479Ssklower break; 369*21479Ssklower 370*21479Ssklower case PRU_ABORT: 371*21479Ssklower ns_pcbdetach(nsp); 372*21479Ssklower sofree(so); 373*21479Ssklower soisdisconnected(so); 374*21479Ssklower break; 375*21479Ssklower 376*21479Ssklower case PRU_SOCKADDR: 377*21479Ssklower ns_setsockaddr(nsp, nam); 378*21479Ssklower break; 379*21479Ssklower 380*21479Ssklower case PRU_PEERADDR: 381*21479Ssklower ns_setpeeraddr(nsp, nam); 382*21479Ssklower break; 383*21479Ssklower 384*21479Ssklower case PRU_SENSE: 385*21479Ssklower /* 386*21479Ssklower * stat: don't bother with a blocksize. 387*21479Ssklower */ 388*21479Ssklower return (0); 389*21479Ssklower 390*21479Ssklower case PRU_SENDOOB: 391*21479Ssklower case PRU_FASTTIMO: 392*21479Ssklower case PRU_SLOWTIMO: 393*21479Ssklower case PRU_PROTORCV: 394*21479Ssklower case PRU_PROTOSEND: 395*21479Ssklower error = EOPNOTSUPP; 396*21479Ssklower break; 397*21479Ssklower 398*21479Ssklower case PRU_CONTROL: 399*21479Ssklower case PRU_RCVD: 400*21479Ssklower case PRU_RCVOOB: 401*21479Ssklower return (EOPNOTSUPP); /* do not free mbuf's */ 402*21479Ssklower 403*21479Ssklower default: 404*21479Ssklower panic("idp_usrreq"); 405*21479Ssklower } 406*21479Ssklower release: 407*21479Ssklower if (m != NULL) 408*21479Ssklower m_freem(m); 409*21479Ssklower return (error); 410*21479Ssklower } 411*21479Ssklower /*ARGSUSED*/ 412*21479Ssklower idp_raw_usrreq(so, req, m, nam, rights) 413*21479Ssklower struct socket *so; 414*21479Ssklower int req; 415*21479Ssklower struct mbuf *m, *nam, *rights; 416*21479Ssklower { 417*21479Ssklower int error = 0; 418*21479Ssklower struct nspcb *nsp = sotonspcb(so); 419*21479Ssklower extern struct nspcb nsrawpcb; 420*21479Ssklower 421*21479Ssklower switch (req) { 422*21479Ssklower 423*21479Ssklower case PRU_ATTACH: 424*21479Ssklower 425*21479Ssklower if (nsp != NULL) { 426*21479Ssklower error = EINVAL; 427*21479Ssklower break; 428*21479Ssklower } 429*21479Ssklower error = ns_pcballoc(so, &nsrawpcb); 430*21479Ssklower if (error) 431*21479Ssklower break; 432*21479Ssklower error = soreserve(so, 2048, 2048); 433*21479Ssklower if (error) 434*21479Ssklower break; 435*21479Ssklower nsp = sotonspcb(so); 436*21479Ssklower nsp->nsp_faddr.x_host = ns_broadhost; 437*21479Ssklower nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT; 438*21479Ssklower break; 439*21479Ssklower default: 440*21479Ssklower error = idp_usrreq(so, req, m, nam, rights); 441*21479Ssklower } 442*21479Ssklower return(error); 443*21479Ssklower } 444*21479Ssklower 445