1*41595Ssklower /* Copyright (c) University of British Columbia, 1984 */ 2*41595Ssklower 3*41595Ssklower #include "../h/param.h" 4*41595Ssklower #include "../h/systm.h" 5*41595Ssklower #include "../h/mbuf.h" 6*41595Ssklower #include "../h/socket.h" 7*41595Ssklower #include "../h/protosw.h" 8*41595Ssklower #include "../h/socketvar.h" 9*41595Ssklower #include "../h/errno.h" 10*41595Ssklower #ifdef BSD4_3 11*41595Ssklower #include "../net/if.h" 12*41595Ssklower #include "ioctl.h" 13*41595Ssklower #include "dir.h" 14*41595Ssklower #include "user.h" 15*41595Ssklower #include "stat.h" 16*41595Ssklower #endif 17*41595Ssklower 18*41595Ssklower #include "../netccitt/x25.h" 19*41595Ssklower #include "../netccitt/pk.h" 20*41595Ssklower #include "../netccitt/pk_var.h" 21*41595Ssklower 22*41595Ssklower struct x25_packet *pk_template (); 23*41595Ssklower 24*41595Ssklower /* 25*41595Ssklower * 26*41595Ssklower * X.25 Packet level protocol interface to socket abstraction. 27*41595Ssklower * 28*41595Ssklower * Process an X.25 user request on a logical channel. If this is a send 29*41595Ssklower * request then m is the mbuf chain of the send data. If this is a timer 30*41595Ssklower * expiration (called from the software clock routine) them timertype is 31*41595Ssklower * the particular timer. 32*41595Ssklower * 33*41595Ssklower */ 34*41595Ssklower 35*41595Ssklower pk_usrreq (so, req, m, nam, rights) 36*41595Ssklower struct socket *so; 37*41595Ssklower int req; 38*41595Ssklower register struct mbuf *m, *nam; 39*41595Ssklower struct mbuf *rights; 40*41595Ssklower { 41*41595Ssklower register struct pklcd *lcp = (struct pklcd *) so -> so_pcb; 42*41595Ssklower register struct x25_packet *xp; 43*41595Ssklower register int s = splnet (), error = 0; 44*41595Ssklower 45*41595Ssklower #ifdef BSD4_3 46*41595Ssklower if (req == PRU_CONTROL) { 47*41595Ssklower error = pk_control(so, (int)m, (caddr_t)nam, 48*41595Ssklower (struct ifnet *)rights); 49*41595Ssklower splx (s); 50*41595Ssklower return (error); 51*41595Ssklower } 52*41595Ssklower #endif 53*41595Ssklower if (rights && rights -> m_len) { 54*41595Ssklower splx (s); 55*41595Ssklower return (EINVAL); 56*41595Ssklower } 57*41595Ssklower 58*41595Ssklower /* 59*41595Ssklower pk_trace (pkcbhead, TR_USER, (struct pklcd *)0, 60*41595Ssklower req, (struct x25_packet *)0); 61*41595Ssklower */ 62*41595Ssklower 63*41595Ssklower if (lcp == NULL && req != PRU_ATTACH) { 64*41595Ssklower splx (s); 65*41595Ssklower return (EINVAL); 66*41595Ssklower } 67*41595Ssklower 68*41595Ssklower switch (req) { 69*41595Ssklower /* 70*41595Ssklower * X.25 attaches to socket via PRU_ATTACH and allocates a logical 71*41595Ssklower * channel descriptor. If the socket is to receive connections, 72*41595Ssklower * then the LISTEN state is entered. 73*41595Ssklower */ 74*41595Ssklower case PRU_ATTACH: 75*41595Ssklower if (lcp) { 76*41595Ssklower error = EISCONN; 77*41595Ssklower /* Socket already connected. */ 78*41595Ssklower break; 79*41595Ssklower } 80*41595Ssklower error = pk_attach (so); 81*41595Ssklower break; 82*41595Ssklower 83*41595Ssklower /* 84*41595Ssklower * Detach a logical channel from the socket. If the state of the 85*41595Ssklower * channel is embryonic, simply discard it. Otherwise we have to 86*41595Ssklower * initiate a PRU_DISCONNECT which will finish later. 87*41595Ssklower */ 88*41595Ssklower case PRU_DETACH: 89*41595Ssklower pk_disconnect (lcp); 90*41595Ssklower break; 91*41595Ssklower 92*41595Ssklower /* 93*41595Ssklower * Give the socket an address. 94*41595Ssklower */ 95*41595Ssklower case PRU_BIND: 96*41595Ssklower if (nam -> m_len == sizeof (struct x25_sockaddr)) 97*41595Ssklower old_to_new (nam); 98*41595Ssklower error = pk_bind (lcp, nam); 99*41595Ssklower break; 100*41595Ssklower 101*41595Ssklower /* 102*41595Ssklower * Prepare to accept connections. 103*41595Ssklower */ 104*41595Ssklower case PRU_LISTEN: 105*41595Ssklower if (lcp -> lcd_ceaddr == 0) { 106*41595Ssklower error = EDESTADDRREQ; 107*41595Ssklower break; 108*41595Ssklower } 109*41595Ssklower lcp -> lcd_state = LISTEN; 110*41595Ssklower lcp -> lcd_listen = pk_listenhead; 111*41595Ssklower pk_listenhead = lcp; 112*41595Ssklower break; 113*41595Ssklower 114*41595Ssklower /* 115*41595Ssklower * Initiate a CALL REQUEST to peer entity. Enter state SENT_CALL 116*41595Ssklower * and mark the socket as connecting. Set timer waiting for 117*41595Ssklower * CALL ACCEPT or CLEAR. 118*41595Ssklower */ 119*41595Ssklower case PRU_CONNECT: 120*41595Ssklower if (nam -> m_len == sizeof (struct x25_sockaddr)) 121*41595Ssklower old_to_new (nam); 122*41595Ssklower error = pk_connect (lcp, nam); 123*41595Ssklower break; 124*41595Ssklower 125*41595Ssklower /* 126*41595Ssklower * Initiate a disconnect to peer entity via a CLEAR REQUEST packet. 127*41595Ssklower * The socket will be disconnected when we receive a confirmation 128*41595Ssklower * or a clear collision. 129*41595Ssklower */ 130*41595Ssklower case PRU_DISCONNECT: 131*41595Ssklower pk_disconnect (lcp); 132*41595Ssklower break; 133*41595Ssklower 134*41595Ssklower /* 135*41595Ssklower * Accept an INCOMING CALL. Most of the work has already been done 136*41595Ssklower * by pk_input. Just return the callers address to the user. 137*41595Ssklower */ 138*41595Ssklower case PRU_ACCEPT: 139*41595Ssklower if (lcp -> lcd_craddr == NULL) 140*41595Ssklower break; 141*41595Ssklower bcopy ((caddr_t)lcp -> lcd_craddr, mtod (nam, caddr_t), 142*41595Ssklower sizeof (struct sockaddr_x25)); 143*41595Ssklower nam -> m_len = sizeof (struct sockaddr_x25); 144*41595Ssklower if (lcp -> lcd_flags & X25_OLDSOCKADDR) 145*41595Ssklower new_to_old (nam); 146*41595Ssklower break; 147*41595Ssklower 148*41595Ssklower /* 149*41595Ssklower * After a receive, we should send a RR. 150*41595Ssklower */ 151*41595Ssklower case PRU_RCVD: 152*41595Ssklower lcp -> lcd_rxcnt++; 153*41595Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RR); 154*41595Ssklower pk_output (lcp); 155*41595Ssklower break; 156*41595Ssklower 157*41595Ssklower /* 158*41595Ssklower * Do send by placing data on the socket output queue. 159*41595Ssklower * SHOULD WE USE m_cat HERE. 160*41595Ssklower */ 161*41595Ssklower case PRU_SEND: 162*41595Ssklower error = pk_send (lcp, m); 163*41595Ssklower break; 164*41595Ssklower 165*41595Ssklower /* 166*41595Ssklower * Abort a virtual circuit. For example all completed calls 167*41595Ssklower * waiting acceptance. 168*41595Ssklower */ 169*41595Ssklower case PRU_ABORT: 170*41595Ssklower pk_disconnect (lcp); 171*41595Ssklower break; 172*41595Ssklower 173*41595Ssklower /* Begin unimplemented hooks. */ 174*41595Ssklower 175*41595Ssklower case PRU_SHUTDOWN: 176*41595Ssklower error = EOPNOTSUPP; 177*41595Ssklower break; 178*41595Ssklower 179*41595Ssklower case PRU_CONTROL: 180*41595Ssklower error = EOPNOTSUPP; 181*41595Ssklower break; 182*41595Ssklower 183*41595Ssklower case PRU_SENSE: 184*41595Ssklower #ifdef BSD4_3 185*41595Ssklower ((struct stat *)m) -> st_blksize = so -> so_snd.sb_hiwat; 186*41595Ssklower #else 187*41595Ssklower error = EOPNOTSUPP; 188*41595Ssklower #endif 189*41595Ssklower break; 190*41595Ssklower 191*41595Ssklower /* End unimplemented hooks. */ 192*41595Ssklower 193*41595Ssklower case PRU_SOCKADDR: 194*41595Ssklower if (lcp -> lcd_ceaddr == 0) 195*41595Ssklower return (EADDRNOTAVAIL); 196*41595Ssklower nam -> m_len = sizeof (struct sockaddr_x25); 197*41595Ssklower bcopy ((caddr_t)lcp -> lcd_ceaddr, mtod (nam, caddr_t), 198*41595Ssklower sizeof (struct sockaddr_x25)); 199*41595Ssklower if (lcp -> lcd_flags & X25_OLDSOCKADDR) 200*41595Ssklower new_to_old (nam); 201*41595Ssklower break; 202*41595Ssklower 203*41595Ssklower case PRU_PEERADDR: 204*41595Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 205*41595Ssklower return (ENOTCONN); 206*41595Ssklower nam -> m_len = sizeof (struct sockaddr_x25); 207*41595Ssklower bcopy (lcp -> lcd_craddr ? (caddr_t)lcp -> lcd_craddr : 208*41595Ssklower (caddr_t)lcp -> lcd_ceaddr, 209*41595Ssklower mtod (nam, caddr_t), sizeof (struct sockaddr_x25)); 210*41595Ssklower if (lcp -> lcd_flags & X25_OLDSOCKADDR) 211*41595Ssklower new_to_old (nam); 212*41595Ssklower break; 213*41595Ssklower 214*41595Ssklower /* 215*41595Ssklower * Receive INTERRUPT packet. 216*41595Ssklower */ 217*41595Ssklower case PRU_RCVOOB: 218*41595Ssklower m -> m_len = 1; 219*41595Ssklower *mtod (m, char *) = lcp -> lcd_intrdata; 220*41595Ssklower break; 221*41595Ssklower 222*41595Ssklower /* 223*41595Ssklower * Send INTERRUPT packet. 224*41595Ssklower */ 225*41595Ssklower case PRU_SENDOOB: 226*41595Ssklower m_freem (m); 227*41595Ssklower if (lcp -> lcd_intrconf_pending) { 228*41595Ssklower error = ETOOMANYREFS; 229*41595Ssklower break; 230*41595Ssklower } 231*41595Ssklower lcp -> lcd_intrcnt++; 232*41595Ssklower xp = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_INTERRUPT); 233*41595Ssklower xp -> packet_data = 0; 234*41595Ssklower (dtom (xp)) -> m_len++; 235*41595Ssklower pk_output (lcp); 236*41595Ssklower break; 237*41595Ssklower 238*41595Ssklower default: 239*41595Ssklower panic ("pk_usrreq"); 240*41595Ssklower } 241*41595Ssklower 242*41595Ssklower splx (s); 243*41595Ssklower return (error); 244*41595Ssklower } 245*41595Ssklower 246*41595Ssklower #ifdef BSD4_3 247*41595Ssklower /*ARGSUSED*/ 248*41595Ssklower pk_control (so, cmd, data, ifp) 249*41595Ssklower struct socket *so; 250*41595Ssklower int cmd; 251*41595Ssklower caddr_t data; 252*41595Ssklower register struct ifnet *ifp; 253*41595Ssklower { 254*41595Ssklower register struct ifreq *ifr = (struct ifreq *)data; 255*41595Ssklower register struct ifaddr *ifa = 0; 256*41595Ssklower register int error, s; 257*41595Ssklower struct sockaddr oldaddr; 258*41595Ssklower 259*41595Ssklower /* 260*41595Ssklower * Find address for this interface, if it exists. 261*41595Ssklower */ 262*41595Ssklower if (ifp) 263*41595Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 264*41595Ssklower if (ifa->ifa_addr.sa_family == AF_CCITT) 265*41595Ssklower break; 266*41595Ssklower 267*41595Ssklower switch (cmd) { 268*41595Ssklower case SIOCGIFADDR: 269*41595Ssklower if (ifa == 0) 270*41595Ssklower return (EADDRNOTAVAIL); 271*41595Ssklower ifr -> ifr_addr = ifa->ifa_addr; 272*41595Ssklower return (0); 273*41595Ssklower 274*41595Ssklower case SIOCSIFADDR: 275*41595Ssklower if (!suser()) 276*41595Ssklower return (u.u_error); 277*41595Ssklower 278*41595Ssklower if (ifp == 0) 279*41595Ssklower panic("pk_control"); 280*41595Ssklower if (ifa == (struct ifaddr *)0) { 281*41595Ssklower register struct ifaddr *ia; 282*41595Ssklower register struct mbuf *m; 283*41595Ssklower 284*41595Ssklower m = m_getclr(M_WAIT, MT_IFADDR); 285*41595Ssklower if (m == (struct mbuf *)NULL) 286*41595Ssklower return (ENOBUFS); 287*41595Ssklower ia = mtod(m, struct ifaddr *); 288*41595Ssklower if (ifa = ifp->if_addrlist) { 289*41595Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 290*41595Ssklower ; 291*41595Ssklower ifa->ifa_next = ia; 292*41595Ssklower } else 293*41595Ssklower ifp->if_addrlist = ia; 294*41595Ssklower ifa = ia; 295*41595Ssklower ifa->ifa_ifp = ifp; 296*41595Ssklower } 297*41595Ssklower oldaddr = ifa->ifa_addr; 298*41595Ssklower s = splimp(); 299*41595Ssklower ifa->ifa_addr = ifr->ifr_addr; 300*41595Ssklower /* 301*41595Ssklower * Give the interface a chance to initialize if this 302*41595Ssklower * is its first address, and to validate the address. 303*41595Ssklower */ 304*41595Ssklower if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ifa))) { 305*41595Ssklower splx(s); 306*41595Ssklower ifa->ifa_addr = oldaddr; 307*41595Ssklower return (error); 308*41595Ssklower } 309*41595Ssklower splx(s); 310*41595Ssklower #ifndef WATERLOO 311*41595Ssklower (void) pk_accton (); 312*41595Ssklower #endif 313*41595Ssklower return (0); 314*41595Ssklower 315*41595Ssklower default: 316*41595Ssklower if (ifp == 0 || ifp->if_ioctl == 0) 317*41595Ssklower return (EOPNOTSUPP); 318*41595Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 319*41595Ssklower } 320*41595Ssklower } 321*41595Ssklower #endif 322*41595Ssklower 323*41595Ssklower /* 324*41595Ssklower * Do an in-place conversion of an "old style" 325*41595Ssklower * socket address to the new style 326*41595Ssklower */ 327*41595Ssklower 328*41595Ssklower static 329*41595Ssklower old_to_new (m) 330*41595Ssklower register struct mbuf *m; 331*41595Ssklower { 332*41595Ssklower register struct x25_sockaddr *oldp; 333*41595Ssklower register struct sockaddr_x25 *newp; 334*41595Ssklower register char *ocp, *ncp; 335*41595Ssklower struct sockaddr_x25 new; 336*41595Ssklower 337*41595Ssklower oldp = mtod (m, struct x25_sockaddr *); 338*41595Ssklower newp = &new; 339*41595Ssklower bzero ((caddr_t)newp, sizeof (*newp)); 340*41595Ssklower 341*41595Ssklower newp -> x25_family = AF_CCITT; 342*41595Ssklower newp->x25_opts.op_flags = (oldp->xaddr_facilities & X25_REVERSE_CHARGE) 343*41595Ssklower | X25_MQBIT | X25_OLDSOCKADDR; 344*41595Ssklower if (oldp -> xaddr_facilities & XS_HIPRIO) /* Datapac specific */ 345*41595Ssklower newp -> x25_opts.op_psize = X25_PS128; 346*41595Ssklower bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr, 347*41595Ssklower (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1)); 348*41595Ssklower bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4); 349*41595Ssklower newp -> x25_udlen = 4; 350*41595Ssklower 351*41595Ssklower ocp = (caddr_t)oldp -> xaddr_userdata; 352*41595Ssklower ncp = newp -> x25_udata + 4; 353*41595Ssklower while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) { 354*41595Ssklower *ncp++ = *ocp++; 355*41595Ssklower newp -> x25_udlen++; 356*41595Ssklower } 357*41595Ssklower 358*41595Ssklower bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp)); 359*41595Ssklower m->m_len = sizeof (*newp); 360*41595Ssklower } 361*41595Ssklower 362*41595Ssklower /* 363*41595Ssklower * Do an in-place conversion of a new style 364*41595Ssklower * socket address to the old style 365*41595Ssklower */ 366*41595Ssklower 367*41595Ssklower static 368*41595Ssklower new_to_old (m) 369*41595Ssklower register struct mbuf *m; 370*41595Ssklower { 371*41595Ssklower register struct x25_sockaddr *oldp; 372*41595Ssklower register struct sockaddr_x25 *newp; 373*41595Ssklower register char *ocp, *ncp; 374*41595Ssklower struct x25_sockaddr old; 375*41595Ssklower 376*41595Ssklower oldp = &old; 377*41595Ssklower newp = mtod (m, struct sockaddr_x25 *); 378*41595Ssklower bzero ((caddr_t)oldp, sizeof (*oldp)); 379*41595Ssklower 380*41595Ssklower oldp -> xaddr_facilities = newp -> x25_opts.op_flags & X25_REVERSE_CHARGE; 381*41595Ssklower if (newp -> x25_opts.op_psize == X25_PS128) 382*41595Ssklower oldp -> xaddr_facilities |= XS_HIPRIO; /* Datapac specific */ 383*41595Ssklower ocp = (char *)oldp -> xaddr_addr; 384*41595Ssklower ncp = newp -> x25_addr; 385*41595Ssklower while (*ncp) { 386*41595Ssklower *ocp++ = *ncp++; 387*41595Ssklower oldp -> xaddr_len++; 388*41595Ssklower } 389*41595Ssklower 390*41595Ssklower bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4); 391*41595Ssklower bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata, 392*41595Ssklower (unsigned)(newp -> x25_udlen - 4)); 393*41595Ssklower 394*41595Ssklower bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp)); 395*41595Ssklower m -> m_len = sizeof (*oldp); 396*41595Ssklower } 397*41595Ssklower 398*41595Ssklower pk_send (lcp, m) 399*41595Ssklower register struct pklcd *lcp; 400*41595Ssklower register struct mbuf *m; 401*41595Ssklower { 402*41595Ssklower register struct x25_packet *xp; 403*41595Ssklower register struct mbuf *m0; 404*41595Ssklower register int len; 405*41595Ssklower 406*41595Ssklower m0 = dtom ((xp = pk_template (lcp -> lcd_lcn, X25_DATA))); 407*41595Ssklower m0 -> m_next = m; 408*41595Ssklower /* 409*41595Ssklower * Application has elected (at call setup time) to prepend 410*41595Ssklower * a control byte to each packet written indicating m-bit 411*41595Ssklower * and q-bit status. Examine and then discard this byte. 412*41595Ssklower */ 413*41595Ssklower if (lcp -> lcd_flags & X25_MQBIT) { 414*41595Ssklower register octet *cp; 415*41595Ssklower 416*41595Ssklower if (m -> m_len < 1) { 417*41595Ssklower m_freem (m0); 418*41595Ssklower return (EMSGSIZE); 419*41595Ssklower } 420*41595Ssklower cp = mtod (m, octet *); 421*41595Ssklower if (*cp & 0x80) /* XXX */ 422*41595Ssklower xp -> q_bit = 1; 423*41595Ssklower xp -> packet_type |= (*cp & 0x40) >> 2; /* XXX */ 424*41595Ssklower m -> m_len--; 425*41595Ssklower m -> m_off++; 426*41595Ssklower } 427*41595Ssklower len = m -> m_len; 428*41595Ssklower while (m -> m_next) { 429*41595Ssklower m = m -> m_next; 430*41595Ssklower len += m -> m_len; 431*41595Ssklower } 432*41595Ssklower if (len > (1 << lcp -> lcd_packetsize)) { 433*41595Ssklower m_freem (m0); 434*41595Ssklower return (EMSGSIZE); 435*41595Ssklower } 436*41595Ssklower 437*41595Ssklower #ifdef BSD4_3 438*41595Ssklower sbappendrecord (&lcp -> lcd_so -> so_snd, m0); 439*41595Ssklower #else 440*41595Ssklower m -> m_act = (struct mbuf *) 1; 441*41595Ssklower sbappend (&lcp -> lcd_so -> so_snd, m0); 442*41595Ssklower #endif 443*41595Ssklower lcp -> lcd_template = 0; 444*41595Ssklower lcp -> lcd_txcnt++; 445*41595Ssklower pk_output (lcp); 446*41595Ssklower return (0); 447*41595Ssklower } 448