1*41593Ssklower /* Copyright (c) University of British Columbia, 1984 */ 2*41593Ssklower 3*41593Ssklower #include "../h/param.h" 4*41593Ssklower #include "../h/systm.h" 5*41593Ssklower #include "../h/mbuf.h" 6*41593Ssklower #include "../h/socket.h" 7*41593Ssklower #include "../h/protosw.h" 8*41593Ssklower #include "../h/socketvar.h" 9*41593Ssklower #include "../h/errno.h" 10*41593Ssklower #include "../h/time.h" 11*41593Ssklower #include "../h/kernel.h" 12*41593Ssklower 13*41593Ssklower #include "../netccitt/x25.h" 14*41593Ssklower #include "../netccitt/pk.h" 15*41593Ssklower #include "../netccitt/pk_var.h" 16*41593Ssklower #include "../netccitt/x25err.h" 17*41593Ssklower 18*41593Ssklower int pk_sendspace = 1024 * 2 + 8; 19*41593Ssklower int pk_recvspace = 1024 * 2 + 8; 20*41593Ssklower 21*41593Ssklower struct x25_packet *pk_template (); 22*41593Ssklower 23*41593Ssklower /* 24*41593Ssklower * Attach X.25 protocol to socket, allocate logical channel descripter 25*41593Ssklower * and buffer space, and enter LISTEN state if we are to accept 26*41593Ssklower * IN-COMMING CALL packets. 27*41593Ssklower * 28*41593Ssklower */ 29*41593Ssklower 30*41593Ssklower pk_attach (so) 31*41593Ssklower struct socket *so; 32*41593Ssklower { 33*41593Ssklower register struct pklcd *lcp; 34*41593Ssklower register struct mbuf *m; 35*41593Ssklower register int error; 36*41593Ssklower 37*41593Ssklower if (error = soreserve (so, pk_sendspace, pk_recvspace)) 38*41593Ssklower return (error); 39*41593Ssklower 40*41593Ssklower /* Hopefully we can remove this when SEQ_PKT is available (4.3?) */ 41*41593Ssklower so -> so_snd.sb_mbmax = pk_sendspace; 42*41593Ssklower 43*41593Ssklower if ((m = m_getclr (M_DONTWAIT, MT_PCB)) == 0) 44*41593Ssklower return (ENOBUFS); 45*41593Ssklower lcp = mtod (m, struct pklcd *); 46*41593Ssklower so -> so_pcb = (caddr_t) lcp; 47*41593Ssklower lcp -> lcd_so = so; 48*41593Ssklower 49*41593Ssklower if (so -> so_options & SO_ACCEPTCONN) 50*41593Ssklower lcp -> lcd_state = LISTEN; 51*41593Ssklower else 52*41593Ssklower lcp -> lcd_state = READY; 53*41593Ssklower 54*41593Ssklower return (0); 55*41593Ssklower } 56*41593Ssklower 57*41593Ssklower /* 58*41593Ssklower * Disconnect X.25 protocol from socket. 59*41593Ssklower */ 60*41593Ssklower 61*41593Ssklower pk_disconnect (lcp) 62*41593Ssklower register struct pklcd *lcp; 63*41593Ssklower { 64*41593Ssklower register struct socket *so = lcp -> lcd_so; 65*41593Ssklower register struct pklcd *l, *p; 66*41593Ssklower 67*41593Ssklower switch (lcp -> lcd_state) { 68*41593Ssklower case LISTEN: 69*41593Ssklower for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen); 70*41593Ssklower if (p == 0) { 71*41593Ssklower if (l != 0) 72*41593Ssklower pk_listenhead = l -> lcd_listen; 73*41593Ssklower } 74*41593Ssklower else 75*41593Ssklower if (l != 0) 76*41593Ssklower p -> lcd_listen = l -> lcd_listen; 77*41593Ssklower pk_close (lcp); 78*41593Ssklower break; 79*41593Ssklower 80*41593Ssklower case READY: 81*41593Ssklower pk_acct (lcp); 82*41593Ssklower pk_close (lcp); 83*41593Ssklower break; 84*41593Ssklower 85*41593Ssklower case SENT_CLEAR: 86*41593Ssklower case RECEIVED_CLEAR: 87*41593Ssklower break; 88*41593Ssklower 89*41593Ssklower default: 90*41593Ssklower pk_acct (lcp); 91*41593Ssklower soisdisconnecting (so); 92*41593Ssklower sbflush (&so -> so_rcv); 93*41593Ssklower pk_clear (lcp); 94*41593Ssklower 95*41593Ssklower } 96*41593Ssklower } 97*41593Ssklower 98*41593Ssklower /* 99*41593Ssklower * Close an X.25 Logical Channel. Discard all space held by the 100*41593Ssklower * connection and internal descriptors. Wake up any sleepers. 101*41593Ssklower */ 102*41593Ssklower 103*41593Ssklower pk_close (lcp) 104*41593Ssklower struct pklcd *lcp; 105*41593Ssklower { 106*41593Ssklower register struct socket *so = lcp -> lcd_so; 107*41593Ssklower 108*41593Ssklower pk_freelcd (lcp); 109*41593Ssklower 110*41593Ssklower if (so == NULL) 111*41593Ssklower return; 112*41593Ssklower 113*41593Ssklower so -> so_pcb = 0; 114*41593Ssklower sbflush (&so -> so_snd); 115*41593Ssklower sbflush (&so -> so_rcv); 116*41593Ssklower soisdisconnected (so); 117*41593Ssklower sofree (so); /* gak!!! you can't do that here */ 118*41593Ssklower } 119*41593Ssklower 120*41593Ssklower /* 121*41593Ssklower * Create a template to be used to send X.25 packets on a logical 122*41593Ssklower * channel. It allocates an mbuf and fills in a skeletal packet 123*41593Ssklower * depending on its type. This packet is passed to pk_output where 124*41593Ssklower * the remainer of the packet is filled in. 125*41593Ssklower */ 126*41593Ssklower 127*41593Ssklower struct x25_packet * 128*41593Ssklower pk_template (lcn, type) 129*41593Ssklower int lcn, type; 130*41593Ssklower { 131*41593Ssklower register struct mbuf *m; 132*41593Ssklower register struct x25_packet *xp; 133*41593Ssklower 134*41593Ssklower MGET (m, M_DONTWAIT, MT_HEADER); 135*41593Ssklower if (m == 0) 136*41593Ssklower panic ("pk_template"); 137*41593Ssklower m -> m_act = 0; 138*41593Ssklower 139*41593Ssklower /* 140*41593Ssklower * Efficiency hack: leave a four byte gap at the beginning 141*41593Ssklower * of the packet level header with the hope that this will 142*41593Ssklower * be enough room for the link level to insert its header. 143*41593Ssklower */ 144*41593Ssklower /* XXX does the above still apply? */ 145*41593Ssklower m -> m_off = MMINOFF + 4; 146*41593Ssklower m -> m_len = PKHEADERLN; 147*41593Ssklower 148*41593Ssklower xp = mtod (m, struct x25_packet *); 149*41593Ssklower *(long *)xp = 0; /* ugly, but fast */ 150*41593Ssklower /* xp -> q_bit = 0;*/ 151*41593Ssklower xp -> fmt_identifier = 1; 152*41593Ssklower /* xp -> lc_group_number = 0;*/ 153*41593Ssklower 154*41593Ssklower xp -> logical_channel_number = lcn; 155*41593Ssklower xp -> packet_type = type; 156*41593Ssklower 157*41593Ssklower return (xp); 158*41593Ssklower } 159*41593Ssklower 160*41593Ssklower /* 161*41593Ssklower * This routine restarts all the virtual circuits. Actually, 162*41593Ssklower * the virtual circuits are not "restarted" as such. Instead, 163*41593Ssklower * any active switched circuit is simply returned to READY 164*41593Ssklower * state. 165*41593Ssklower */ 166*41593Ssklower 167*41593Ssklower pk_restart (pkp, restart_cause) 168*41593Ssklower register struct pkcb *pkp; 169*41593Ssklower int restart_cause; 170*41593Ssklower { 171*41593Ssklower register struct x25_packet *xp; 172*41593Ssklower register struct pklcd *lcp; 173*41593Ssklower register int i; 174*41593Ssklower 175*41593Ssklower /* Restart all logical channels. */ 176*41593Ssklower for (i = 1; i <= pkp->pk_maxlcn; ++i) 177*41593Ssklower if ((lcp = pkp->pk_chan[i]) != NULL) { 178*41593Ssklower if (lcp -> lcd_so) 179*41593Ssklower lcp->lcd_so -> so_error = ENETRESET; 180*41593Ssklower pk_close (lcp); 181*41593Ssklower } 182*41593Ssklower 183*41593Ssklower if (restart_cause < 0) 184*41593Ssklower return; 185*41593Ssklower 186*41593Ssklower pkp->pk_state = DTE_SENT_RESTART; 187*41593Ssklower lcp = pkp->pk_chan[0]; 188*41593Ssklower xp = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART); 189*41593Ssklower (dtom (xp)) -> m_len++; 190*41593Ssklower xp -> packet_data = 0; /* DTE only */ 191*41593Ssklower pk_output (lcp); 192*41593Ssklower } 193*41593Ssklower 194*41593Ssklower 195*41593Ssklower /* 196*41593Ssklower * This procedure frees up the Logical Channel Descripter. 197*41593Ssklower */ 198*41593Ssklower 199*41593Ssklower static 200*41593Ssklower pk_freelcd (lcp) 201*41593Ssklower register struct pklcd *lcp; 202*41593Ssklower { 203*41593Ssklower if (lcp == NULL) 204*41593Ssklower return; 205*41593Ssklower 206*41593Ssklower if (lcp -> lcd_template) 207*41593Ssklower m_freem (dtom (lcp -> lcd_template)); 208*41593Ssklower 209*41593Ssklower if (lcp -> lcd_craddr) 210*41593Ssklower m_freem (dtom (lcp -> lcd_craddr)); 211*41593Ssklower 212*41593Ssklower if (lcp -> lcd_ceaddr) 213*41593Ssklower m_freem (dtom (lcp -> lcd_ceaddr)); 214*41593Ssklower 215*41593Ssklower if (lcp -> lcd_lcn > 0) 216*41593Ssklower lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL; 217*41593Ssklower 218*41593Ssklower m_freem (dtom (lcp)); 219*41593Ssklower } 220*41593Ssklower 221*41593Ssklower 222*41593Ssklower /* 223*41593Ssklower * Bind a address and protocol value to a socket. The important 224*41593Ssklower * part is the protocol value - the first four characters of the 225*41593Ssklower * Call User Data field. 226*41593Ssklower */ 227*41593Ssklower 228*41593Ssklower pk_bind (lcp, nam) 229*41593Ssklower struct pklcd *lcp; 230*41593Ssklower struct mbuf *nam; 231*41593Ssklower { 232*41593Ssklower register struct sockaddr_x25 *sa; 233*41593Ssklower register struct pkcb *pkp; 234*41593Ssklower register struct mbuf *m; 235*41593Ssklower register struct pklcd *pp; 236*41593Ssklower 237*41593Ssklower if (nam == NULL) 238*41593Ssklower return (EADDRNOTAVAIL); 239*41593Ssklower if (lcp -> lcd_ceaddr) /* XXX */ 240*41593Ssklower return (EADDRINUSE); 241*41593Ssklower if (checksockaddr (nam)) 242*41593Ssklower return (EINVAL); 243*41593Ssklower sa = mtod (nam, struct sockaddr_x25 *); 244*41593Ssklower 245*41593Ssklower /* 246*41593Ssklower * If the user wishes to accept calls only from a particular 247*41593Ssklower * net (net != 0), make sure the net is known 248*41593Ssklower */ 249*41593Ssklower 250*41593Ssklower if (sa -> x25_net) 251*41593Ssklower for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 252*41593Ssklower if (pkp == 0) 253*41593Ssklower return (ENETUNREACH); 254*41593Ssklower if (pkp -> pk_xcp -> xc_net == sa -> x25_net) 255*41593Ssklower break; 256*41593Ssklower } 257*41593Ssklower 258*41593Ssklower for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) 259*41593Ssklower if (bcmp (pp -> lcd_ceaddr -> x25_udata, sa -> x25_udata, 260*41593Ssklower min (pp->lcd_ceaddr->x25_udlen, sa->x25_udlen)) == 0) 261*41593Ssklower return (EADDRINUSE); 262*41593Ssklower 263*41593Ssklower if ((m = m_copy (nam, 0, (int)M_COPYALL)) == 0) 264*41593Ssklower return (ENOBUFS); 265*41593Ssklower lcp -> lcd_ceaddr = mtod (m, struct sockaddr_x25 *); 266*41593Ssklower return (0); 267*41593Ssklower } 268*41593Ssklower 269*41593Ssklower /* 270*41593Ssklower * Associate a logical channel descriptor with a network. 271*41593Ssklower * Fill in the default network specific parameters and then 272*41593Ssklower * set any parameters explicitly specified by the user or 273*41593Ssklower * by the remote DTE. 274*41593Ssklower */ 275*41593Ssklower 276*41593Ssklower pk_assoc (pkp, lcp, sa) 277*41593Ssklower register struct pkcb *pkp; 278*41593Ssklower register struct pklcd *lcp; 279*41593Ssklower register struct sockaddr_x25 *sa; 280*41593Ssklower { 281*41593Ssklower 282*41593Ssklower lcp -> lcd_pkp = pkp; 283*41593Ssklower lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize; 284*41593Ssklower lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize; 285*41593Ssklower lcp -> lcd_rsn = MODULUS - 1; 286*41593Ssklower pkp -> pk_chan[lcp -> lcd_lcn] = lcp; 287*41593Ssklower 288*41593Ssklower if (sa -> x25_opts.op_psize) 289*41593Ssklower lcp -> lcd_packetsize = sa -> x25_opts.op_psize; 290*41593Ssklower else 291*41593Ssklower sa -> x25_opts.op_psize = lcp -> lcd_packetsize; 292*41593Ssklower if (sa -> x25_opts.op_wsize) 293*41593Ssklower lcp -> lcd_windowsize = sa -> x25_opts.op_wsize; 294*41593Ssklower else 295*41593Ssklower sa -> x25_opts.op_wsize = lcp -> lcd_windowsize; 296*41593Ssklower sa -> x25_net = pkp -> pk_xcp -> xc_net; 297*41593Ssklower lcp -> lcd_flags = sa -> x25_opts.op_flags; 298*41593Ssklower lcp -> lcd_stime = time.tv_sec; 299*41593Ssklower } 300*41593Ssklower 301*41593Ssklower pk_connect (lcp, nam) 302*41593Ssklower register struct pklcd *lcp; 303*41593Ssklower struct mbuf *nam; 304*41593Ssklower { 305*41593Ssklower register struct pkcb *pkp; 306*41593Ssklower register struct sockaddr_x25 *sa; 307*41593Ssklower register struct mbuf *m; 308*41593Ssklower 309*41593Ssklower if (checksockaddr (nam)) 310*41593Ssklower return (EINVAL); 311*41593Ssklower sa = mtod (nam, struct sockaddr_x25 *); 312*41593Ssklower if (sa -> x25_addr[0] == '\0') 313*41593Ssklower return (EDESTADDRREQ); 314*41593Ssklower for (pkp = pkcbhead; ; pkp = pkp->pk_next) { 315*41593Ssklower if (pkp == 0) 316*41593Ssklower return (ENETUNREACH); 317*41593Ssklower /* 318*41593Ssklower * use first net configured (last in list 319*41593Ssklower * headed by pkcbhead) if net is zero 320*41593Ssklower */ 321*41593Ssklower if (sa -> x25_net == 0 && pkp -> pk_next == 0) 322*41593Ssklower break; 323*41593Ssklower if (sa -> x25_net == pkp -> pk_xcp -> xc_net) 324*41593Ssklower break; 325*41593Ssklower } 326*41593Ssklower 327*41593Ssklower if (pkp -> pk_state != DTE_READY) 328*41593Ssklower return (ENETDOWN); 329*41593Ssklower if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0) 330*41593Ssklower return (EMFILE); 331*41593Ssklower if ((m = m_copy (nam, 0, (int)M_COPYALL)) == 0) 332*41593Ssklower return (ENOBUFS); 333*41593Ssklower lcp -> lcd_ceaddr = mtod (m, struct sockaddr_x25 *); 334*41593Ssklower pk_assoc (pkp, lcp, lcp -> lcd_ceaddr); 335*41593Ssklower soisconnecting (lcp -> lcd_so); 336*41593Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL); 337*41593Ssklower pk_callrequest (lcp, m, pkp -> pk_xcp); 338*41593Ssklower pk_output (lcp); 339*41593Ssklower return (0); 340*41593Ssklower } 341*41593Ssklower 342*41593Ssklower /* 343*41593Ssklower * Build the rest of the CALL REQUEST packet. Fill in calling 344*41593Ssklower * address, facilities fields and the user data field. 345*41593Ssklower */ 346*41593Ssklower 347*41593Ssklower pk_callrequest (lcp, nam, xcp) 348*41593Ssklower struct pklcd *lcp; 349*41593Ssklower struct mbuf *nam; 350*41593Ssklower register struct x25config *xcp; 351*41593Ssklower { 352*41593Ssklower register struct x25_calladdr *a; 353*41593Ssklower register struct sockaddr_x25 *sa = mtod (nam, struct sockaddr_x25 *); 354*41593Ssklower register struct mbuf *m = dtom (lcp -> lcd_template); 355*41593Ssklower unsigned posn = 0; 356*41593Ssklower octet *cp; 357*41593Ssklower char addr[sizeof (xcp -> xc_ntn) * 2]; 358*41593Ssklower 359*41593Ssklower a = (struct x25_calladdr *) &lcp -> lcd_template -> packet_data; 360*41593Ssklower a -> calling_addrlen = xcp -> xc_ntnlen; 361*41593Ssklower cp = (octet *) xcp -> xc_ntn; 362*41593Ssklower from_bcd (addr, &cp, xcp -> xc_ntnlen); 363*41593Ssklower a -> called_addrlen = strlen (sa -> x25_addr); 364*41593Ssklower cp = (octet *) a -> address_field; 365*41593Ssklower to_bcd (&cp, (int)a -> called_addrlen, sa -> x25_addr, &posn); 366*41593Ssklower to_bcd (&cp, (int)a -> calling_addrlen, addr, &posn); 367*41593Ssklower if (posn & 0x01) 368*41593Ssklower *cp++ &= 0xf0; 369*41593Ssklower 370*41593Ssklower build_facilities (&cp, sa, (int)xcp -> xc_type); 371*41593Ssklower 372*41593Ssklower bcopy (sa -> x25_udata, (caddr_t)cp, (unsigned)sa -> x25_udlen); 373*41593Ssklower cp += sa -> x25_udlen; 374*41593Ssklower 375*41593Ssklower m -> m_len += cp - (octet *) a; 376*41593Ssklower 377*41593Ssklower #ifdef ANDREW 378*41593Ssklower printf ("call: "); 379*41593Ssklower for (cp = mtod (m, octet *), posn = 0; posn < m->m_len; ++posn) 380*41593Ssklower printf ("%x ", *cp++); 381*41593Ssklower printf ("\n"); 382*41593Ssklower #endif 383*41593Ssklower } 384*41593Ssklower 385*41593Ssklower build_facilities (cp, sa, type) 386*41593Ssklower register octet **cp; 387*41593Ssklower struct sockaddr_x25 *sa; 388*41593Ssklower { 389*41593Ssklower register octet *fcp; 390*41593Ssklower register int revcharge; 391*41593Ssklower 392*41593Ssklower fcp = *cp + 1; 393*41593Ssklower revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0; 394*41593Ssklower /* 395*41593Ssklower * This is specific to Datapac X.25(1976) DTEs. International 396*41593Ssklower * calls must have the "hi priority" bit on. 397*41593Ssklower */ 398*41593Ssklower if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128) 399*41593Ssklower revcharge |= 02; 400*41593Ssklower if (revcharge) { 401*41593Ssklower *fcp++ = FACILITIES_REVERSE_CHARGE; 402*41593Ssklower *fcp++ = revcharge; 403*41593Ssklower } 404*41593Ssklower switch (type) { 405*41593Ssklower case X25_1980: 406*41593Ssklower case X25_1984: 407*41593Ssklower *fcp++ = FACILITIES_PACKETSIZE; 408*41593Ssklower *fcp++ = sa -> x25_opts.op_psize; 409*41593Ssklower *fcp++ = sa -> x25_opts.op_psize; 410*41593Ssklower 411*41593Ssklower *fcp++ = FACILITIES_WINDOWSIZE; 412*41593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 413*41593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 414*41593Ssklower } 415*41593Ssklower **cp = fcp - *cp - 1; 416*41593Ssklower *cp = fcp; 417*41593Ssklower } 418*41593Ssklower 419*41593Ssklower to_bcd (a, len, x, posn) 420*41593Ssklower register octet **a; 421*41593Ssklower register char *x; 422*41593Ssklower register int len; 423*41593Ssklower register unsigned *posn; 424*41593Ssklower { 425*41593Ssklower while (--len >= 0) 426*41593Ssklower if ((*posn)++ & 0x01) 427*41593Ssklower *(*a)++ |= *x++ & 0x0F; 428*41593Ssklower else 429*41593Ssklower **a = *x++ << 4; 430*41593Ssklower } 431*41593Ssklower 432*41593Ssklower /* 433*41593Ssklower * This routine gets the first available logical channel number. The 434*41593Ssklower * search is from the highest number to lowest number (DTE). 435*41593Ssklower */ 436*41593Ssklower 437*41593Ssklower pk_getlcn (pkp) 438*41593Ssklower register struct pkcb *pkp; 439*41593Ssklower { 440*41593Ssklower register int i; 441*41593Ssklower 442*41593Ssklower for (i = pkp -> pk_maxlcn; i > 0; --i) 443*41593Ssklower if (pkp -> pk_chan[i] == NULL) 444*41593Ssklower break; 445*41593Ssklower return (i); 446*41593Ssklower 447*41593Ssklower } 448*41593Ssklower 449*41593Ssklower static 450*41593Ssklower checksockaddr (m) 451*41593Ssklower struct mbuf *m; 452*41593Ssklower { 453*41593Ssklower register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *); 454*41593Ssklower register char *cp; 455*41593Ssklower 456*41593Ssklower if (m -> m_len != sizeof (struct sockaddr_x25)) 457*41593Ssklower return (1); 458*41593Ssklower if (sa -> x25_family != AF_CCITT || sa -> x25_udlen == 0 || 459*41593Ssklower sa -> x25_udlen > sizeof (sa -> x25_udata)) 460*41593Ssklower return (1); 461*41593Ssklower for (cp = sa -> x25_addr; *cp; cp++) { 462*41593Ssklower if (*cp < '0' || *cp > '9' || 463*41593Ssklower cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1]) 464*41593Ssklower return (1); 465*41593Ssklower } 466*41593Ssklower return (0); 467*41593Ssklower } 468*41593Ssklower 469*41593Ssklower /* 470*41593Ssklower * This procedure sends a CLEAR request packet. The lc state is 471*41593Ssklower * set to "SENT_CLEAR". 472*41593Ssklower */ 473*41593Ssklower 474*41593Ssklower pk_clear (lcp) 475*41593Ssklower struct pklcd *lcp; 476*41593Ssklower { 477*41593Ssklower register struct x25_packet *xp; 478*41593Ssklower 479*41593Ssklower xp = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CLEAR); 480*41593Ssklower (dtom (xp)) -> m_len++; 481*41593Ssklower xp -> packet_data = 0; 482*41593Ssklower 483*41593Ssklower pk_output (lcp); 484*41593Ssklower 485*41593Ssklower } 486*41593Ssklower 487*41593Ssklower /* 488*41593Ssklower * This procedure sends a RESET request packet. It re-intializes 489*41593Ssklower * virtual circuit. 490*41593Ssklower */ 491*41593Ssklower 492*41593Ssklower static 493*41593Ssklower pk_reset (lcp) 494*41593Ssklower register struct pklcd *lcp; 495*41593Ssklower { 496*41593Ssklower register struct x25_packet *xp; 497*41593Ssklower register struct socket *so; 498*41593Ssklower 499*41593Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 500*41593Ssklower return; 501*41593Ssklower 502*41593Ssklower lcp -> lcd_reset_condition = TRUE; 503*41593Ssklower 504*41593Ssklower /* Reset all the control variables for the channel. */ 505*41593Ssklower lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 506*41593Ssklower lcp -> lcd_intrconf_pending = FALSE; 507*41593Ssklower lcp -> lcd_rsn = MODULUS - 1; 508*41593Ssklower lcp -> lcd_ssn = 0; 509*41593Ssklower lcp -> lcd_output_window = lcp -> lcd_input_window = 510*41593Ssklower lcp -> lcd_last_transmitted_pr = 0; 511*41593Ssklower so = lcp -> lcd_so; 512*41593Ssklower so -> so_error = ECONNRESET; 513*41593Ssklower sbflush (&so -> so_rcv); 514*41593Ssklower sbflush (&so -> so_snd); 515*41593Ssklower 516*41593Ssklower xp = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET); 517*41593Ssklower (dtom (xp)) -> m_len += 2; 518*41593Ssklower xp -> packet_data = 0; 519*41593Ssklower pk_output (lcp); 520*41593Ssklower 521*41593Ssklower } 522*41593Ssklower 523*41593Ssklower 524*41593Ssklower /* 525*41593Ssklower * This procedure handles all local protocol procedure errors. 526*41593Ssklower */ 527*41593Ssklower 528*41593Ssklower pk_procerror (error, lcp, errstr) 529*41593Ssklower register struct pklcd *lcp; 530*41593Ssklower char *errstr; 531*41593Ssklower { 532*41593Ssklower 533*41593Ssklower pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr); 534*41593Ssklower 535*41593Ssklower switch (error) { 536*41593Ssklower case CLEAR: 537*41593Ssklower if (lcp->lcd_so) { 538*41593Ssklower lcp->lcd_so -> so_error = ECONNABORTED; 539*41593Ssklower soisdisconnecting (lcp->lcd_so); 540*41593Ssklower } 541*41593Ssklower pk_clear (lcp); 542*41593Ssklower break; 543*41593Ssklower 544*41593Ssklower case RESET: 545*41593Ssklower pk_reset (lcp); 546*41593Ssklower } 547*41593Ssklower } 548*41593Ssklower 549*41593Ssklower /* 550*41593Ssklower * This procedure is called during the DATA TRANSFER state to check 551*41593Ssklower * and process the P(R) values received in the DATA, RR OR RNR 552*41593Ssklower * packets. 553*41593Ssklower */ 554*41593Ssklower 555*41593Ssklower pk_ack (lcp, pr) 556*41593Ssklower struct pklcd *lcp; 557*41593Ssklower unsigned pr; 558*41593Ssklower { 559*41593Ssklower register struct socket *so = lcp -> lcd_so; 560*41593Ssklower 561*41593Ssklower if (lcp -> lcd_output_window == pr) 562*41593Ssklower return (PACKET_OK); 563*41593Ssklower if (lcp -> lcd_output_window < lcp -> lcd_ssn) { 564*41593Ssklower if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) { 565*41593Ssklower pk_procerror (RESET, lcp, "p(r) flow control error"); 566*41593Ssklower return (ERROR_PACKET); 567*41593Ssklower } 568*41593Ssklower } 569*41593Ssklower else { 570*41593Ssklower if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) { 571*41593Ssklower pk_procerror (RESET, lcp, "p(r) flow control error"); 572*41593Ssklower return (ERROR_PACKET); 573*41593Ssklower } 574*41593Ssklower } 575*41593Ssklower 576*41593Ssklower lcp -> lcd_output_window = pr; /* Rotate window. */ 577*41593Ssklower if (lcp -> lcd_window_condition == TRUE) 578*41593Ssklower lcp -> lcd_window_condition = FALSE; 579*41593Ssklower 580*41593Ssklower if ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel) 581*41593Ssklower sowwakeup (so); 582*41593Ssklower 583*41593Ssklower return (PACKET_OK); 584*41593Ssklower } 585*41593Ssklower 586*41593Ssklower /* 587*41593Ssklower * This procedure decodes the X.25 level 3 packet returning a 588*41593Ssklower * code to be used in switchs or arrays. 589*41593Ssklower */ 590*41593Ssklower 591*41593Ssklower pk_decode (xp) 592*41593Ssklower register struct x25_packet *xp; 593*41593Ssklower { 594*41593Ssklower register int type; 595*41593Ssklower 596*41593Ssklower if (xp -> fmt_identifier != 1) 597*41593Ssklower return (INVALID_PACKET); 598*41593Ssklower 599*41593Ssklower /* 600*41593Ssklower * Make sure that the logical channel group number is 0. 601*41593Ssklower * This restriction may be removed at some later date. 602*41593Ssklower */ 603*41593Ssklower if (xp -> lc_group_number != 0) 604*41593Ssklower return (INVALID_PACKET); 605*41593Ssklower 606*41593Ssklower /* 607*41593Ssklower * Test for data packet first. 608*41593Ssklower */ 609*41593Ssklower if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR)) 610*41593Ssklower return (DATA); 611*41593Ssklower 612*41593Ssklower /* 613*41593Ssklower * Test if flow control packet (RR or RNR). 614*41593Ssklower */ 615*41593Ssklower if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR)) 616*41593Ssklower if (!(xp -> packet_type & RR_PACKET_DESIGNATOR)) 617*41593Ssklower return (RR); 618*41593Ssklower else 619*41593Ssklower return (RNR); 620*41593Ssklower 621*41593Ssklower /* 622*41593Ssklower * Determine the rest of the packet types. 623*41593Ssklower */ 624*41593Ssklower switch (xp -> packet_type) { 625*41593Ssklower case X25_CALL: 626*41593Ssklower type = CALL; 627*41593Ssklower break; 628*41593Ssklower 629*41593Ssklower case X25_CALL_ACCEPTED: 630*41593Ssklower type = CALL_ACCEPTED; 631*41593Ssklower break; 632*41593Ssklower 633*41593Ssklower case X25_CLEAR: 634*41593Ssklower type = CLEAR; 635*41593Ssklower break; 636*41593Ssklower 637*41593Ssklower case X25_CLEAR_CONFIRM: 638*41593Ssklower type = CLEAR_CONF; 639*41593Ssklower break; 640*41593Ssklower 641*41593Ssklower case X25_INTERRUPT: 642*41593Ssklower type = INTERRUPT; 643*41593Ssklower break; 644*41593Ssklower 645*41593Ssklower case X25_INTERRUPT_CONFIRM: 646*41593Ssklower type = INTERRUPT_CONF; 647*41593Ssklower break; 648*41593Ssklower 649*41593Ssklower case X25_RESET: 650*41593Ssklower type = RESET; 651*41593Ssklower break; 652*41593Ssklower 653*41593Ssklower case X25_RESET_CONFIRM: 654*41593Ssklower type = RESET_CONF; 655*41593Ssklower break; 656*41593Ssklower 657*41593Ssklower case X25_RESTART: 658*41593Ssklower type = RESTART; 659*41593Ssklower break; 660*41593Ssklower 661*41593Ssklower case X25_RESTART_CONFIRM: 662*41593Ssklower type = RESTART_CONF; 663*41593Ssklower break; 664*41593Ssklower 665*41593Ssklower default: 666*41593Ssklower type = INVALID_PACKET; 667*41593Ssklower } 668*41593Ssklower return (type); 669*41593Ssklower } 670*41593Ssklower 671*41593Ssklower /* 672*41593Ssklower * A restart packet has been received. Print out the reason 673*41593Ssklower * for the restart. 674*41593Ssklower */ 675*41593Ssklower 676*41593Ssklower pk_restartcause (pkp, xp) 677*41593Ssklower struct pkcb *pkp; 678*41593Ssklower register struct x25_packet *xp; 679*41593Ssklower { 680*41593Ssklower register struct x25config *xcp = pkp -> pk_xcp; 681*41593Ssklower register int lcn = xp -> logical_channel_number; 682*41593Ssklower 683*41593Ssklower switch (xp -> packet_data) { 684*41593Ssklower case X25_RESTART_LOCAL_PROCEDURE_ERROR: 685*41593Ssklower pk_message (lcn, xcp, "restart: local procedure error"); 686*41593Ssklower break; 687*41593Ssklower 688*41593Ssklower case X25_RESTART_NETWORK_CONGESTION: 689*41593Ssklower pk_message (lcn, xcp, "restart: network congestion"); 690*41593Ssklower break; 691*41593Ssklower 692*41593Ssklower case X25_RESTART_NETWORK_OPERATIONAL: 693*41593Ssklower pk_message (lcn, xcp, "restart: network operational"); 694*41593Ssklower break; 695*41593Ssklower 696*41593Ssklower default: 697*41593Ssklower pk_message (lcn, xcp, "restart: unknown cause"); 698*41593Ssklower } 699*41593Ssklower } 700*41593Ssklower 701*41593Ssklower #define MAXRESETCAUSE 7 702*41593Ssklower 703*41593Ssklower int Reset_cause[] = { 704*41593Ssklower EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG 705*41593Ssklower }; 706*41593Ssklower 707*41593Ssklower /* 708*41593Ssklower * A reset packet has arrived. Return the cause to the user. 709*41593Ssklower */ 710*41593Ssklower 711*41593Ssklower pk_resetcause (pkp, xp) 712*41593Ssklower struct pkcb *pkp; 713*41593Ssklower register struct x25_packet *xp; 714*41593Ssklower { 715*41593Ssklower register struct pklcd *lcp = pkp->pk_chan[xp -> logical_channel_number]; 716*41593Ssklower register int code = xp -> packet_data; 717*41593Ssklower 718*41593Ssklower if (code > MAXRESETCAUSE) 719*41593Ssklower code = 7; /* EXRNCG */ 720*41593Ssklower 721*41593Ssklower lcp->lcd_so -> so_error = Reset_cause[code]; 722*41593Ssklower } 723*41593Ssklower 724*41593Ssklower #define MAXCLEARCAUSE 25 725*41593Ssklower 726*41593Ssklower int Clear_cause[] = { 727*41593Ssklower EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0, 728*41593Ssklower 0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE, 729*41593Ssklower 0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC 730*41593Ssklower }; 731*41593Ssklower 732*41593Ssklower /* 733*41593Ssklower * A clear packet has arrived. Return the cause to the user. 734*41593Ssklower */ 735*41593Ssklower 736*41593Ssklower pk_clearcause (pkp, xp) 737*41593Ssklower struct pkcb *pkp; 738*41593Ssklower register struct x25_packet *xp; 739*41593Ssklower { 740*41593Ssklower register struct pklcd *lcp = pkp->pk_chan[xp -> logical_channel_number]; 741*41593Ssklower register int code = xp -> packet_data; 742*41593Ssklower 743*41593Ssklower if (code > MAXCLEARCAUSE) 744*41593Ssklower code = 5; /* EXRNCG */ 745*41593Ssklower lcp->lcd_so -> so_error = Clear_cause[code]; 746*41593Ssklower } 747*41593Ssklower 748*41593Ssklower char * 749*41593Ssklower format_ntn (xcp) 750*41593Ssklower register struct x25config *xcp; 751*41593Ssklower { 752*41593Ssklower register int i; 753*41593Ssklower register char *src, *dest; 754*41593Ssklower static char ntn[12]; 755*41593Ssklower 756*41593Ssklower src = xcp->xc_ntn; 757*41593Ssklower dest = ntn; 758*41593Ssklower for (i = 0; i < xcp->xc_ntnlen / 2; i++) { 759*41593Ssklower *dest++ = ((*src & 0xf0) >> 4) + '0'; 760*41593Ssklower *dest++ = (*src++ & 0xf) + '0'; 761*41593Ssklower } 762*41593Ssklower if (xcp->xc_ntnlen & 01) 763*41593Ssklower dest[-1] = 0; 764*41593Ssklower else 765*41593Ssklower *dest = 0; 766*41593Ssklower return (ntn); 767*41593Ssklower } 768*41593Ssklower 769*41593Ssklower /* VARARGS1 */ 770*41593Ssklower pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6) 771*41593Ssklower struct x25config *xcp; 772*41593Ssklower char *fmt; 773*41593Ssklower { 774*41593Ssklower 775*41593Ssklower if (lcn) 776*41593Ssklower if (pkcbhead -> pk_next) 777*41593Ssklower printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn); 778*41593Ssklower else 779*41593Ssklower printf ("X.25: lcn %d: ", lcn); 780*41593Ssklower else 781*41593Ssklower if (pkcbhead -> pk_next) 782*41593Ssklower printf ("X.25(%s): ", format_ntn (xcp)); 783*41593Ssklower else 784*41593Ssklower printf ("X.25: "); 785*41593Ssklower 786*41593Ssklower printf (fmt, a1, a2, a3, a4, a5, a6); 787*41593Ssklower printf ("\n"); 788*41593Ssklower } 789