141709Ssklower /* 241709Ssklower * Copyright (c) University of British Columbia, 1984 341709Ssklower * Copyright (c) 1990 The Regents of the University of California. 441709Ssklower * All rights reserved. 541709Ssklower * 641709Ssklower * This code is derived from software contributed to Berkeley by 741709Ssklower * the Laboratory for Computation Vision and the Computer Science Department 841709Ssklower * of the University of British Columbia. 941709Ssklower * 1041709Ssklower * %sccs.include.redist.c% 1141709Ssklower * 12*42140Ssklower * @(#)pk_subr.c 7.3 (Berkeley) 05/16/90 1341709Ssklower */ 1441593Ssklower 15*42140Ssklower #include "param.h" 16*42140Ssklower #include "systm.h" 17*42140Ssklower #include "mbuf.h" 18*42140Ssklower #include "socket.h" 19*42140Ssklower #include "protosw.h" 20*42140Ssklower #include "socketvar.h" 21*42140Ssklower #include "errno.h" 22*42140Ssklower #include "time.h" 23*42140Ssklower #include "kernel.h" 2441593Ssklower 25*42140Ssklower #include "x25.h" 26*42140Ssklower #include "pk.h" 27*42140Ssklower #include "pk_var.h" 28*42140Ssklower #include "x25err.h" 2941593Ssklower 3041593Ssklower int pk_sendspace = 1024 * 2 + 8; 3141593Ssklower int pk_recvspace = 1024 * 2 + 8; 3241593Ssklower 3341593Ssklower struct x25_packet *pk_template (); 3441593Ssklower 3541593Ssklower /* 3641593Ssklower * Attach X.25 protocol to socket, allocate logical channel descripter 3741593Ssklower * and buffer space, and enter LISTEN state if we are to accept 3841593Ssklower * IN-COMMING CALL packets. 3941593Ssklower * 4041593Ssklower */ 4141593Ssklower 4241593Ssklower pk_attach (so) 4341593Ssklower struct socket *so; 4441593Ssklower { 4541593Ssklower register struct pklcd *lcp; 4641593Ssklower register struct mbuf *m; 4741593Ssklower register int error; 4841593Ssklower 4941593Ssklower if (error = soreserve (so, pk_sendspace, pk_recvspace)) 5041593Ssklower return (error); 5141593Ssklower 5241593Ssklower /* Hopefully we can remove this when SEQ_PKT is available (4.3?) */ 5341593Ssklower so -> so_snd.sb_mbmax = pk_sendspace; 5441593Ssklower 5541593Ssklower if ((m = m_getclr (M_DONTWAIT, MT_PCB)) == 0) 5641593Ssklower return (ENOBUFS); 5741593Ssklower lcp = mtod (m, struct pklcd *); 5841593Ssklower so -> so_pcb = (caddr_t) lcp; 5941593Ssklower lcp -> lcd_so = so; 6041593Ssklower 6141593Ssklower if (so -> so_options & SO_ACCEPTCONN) 6241593Ssklower lcp -> lcd_state = LISTEN; 6341593Ssklower else 6441593Ssklower lcp -> lcd_state = READY; 6541593Ssklower 6641593Ssklower return (0); 6741593Ssklower } 6841593Ssklower 6941593Ssklower /* 7041593Ssklower * Disconnect X.25 protocol from socket. 7141593Ssklower */ 7241593Ssklower 7341593Ssklower pk_disconnect (lcp) 7441593Ssklower register struct pklcd *lcp; 7541593Ssklower { 7641593Ssklower register struct socket *so = lcp -> lcd_so; 7741593Ssklower register struct pklcd *l, *p; 7841593Ssklower 7941593Ssklower switch (lcp -> lcd_state) { 8041593Ssklower case LISTEN: 8141593Ssklower for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen); 8241593Ssklower if (p == 0) { 8341593Ssklower if (l != 0) 8441593Ssklower pk_listenhead = l -> lcd_listen; 8541593Ssklower } 8641593Ssklower else 8741593Ssklower if (l != 0) 8841593Ssklower p -> lcd_listen = l -> lcd_listen; 8941593Ssklower pk_close (lcp); 9041593Ssklower break; 9141593Ssklower 9241593Ssklower case READY: 9341593Ssklower pk_acct (lcp); 9441593Ssklower pk_close (lcp); 9541593Ssklower break; 9641593Ssklower 9741593Ssklower case SENT_CLEAR: 9841593Ssklower case RECEIVED_CLEAR: 9941593Ssklower break; 10041593Ssklower 10141593Ssklower default: 10241593Ssklower pk_acct (lcp); 103*42140Ssklower if (so) { 104*42140Ssklower soisdisconnecting (so); 105*42140Ssklower sbflush (&so -> so_rcv); 106*42140Ssklower } 10741593Ssklower pk_clear (lcp); 10841593Ssklower 10941593Ssklower } 11041593Ssklower } 11141593Ssklower 11241593Ssklower /* 11341593Ssklower * Close an X.25 Logical Channel. Discard all space held by the 11441593Ssklower * connection and internal descriptors. Wake up any sleepers. 11541593Ssklower */ 11641593Ssklower 11741593Ssklower pk_close (lcp) 11841593Ssklower struct pklcd *lcp; 11941593Ssklower { 12041593Ssklower register struct socket *so = lcp -> lcd_so; 12141593Ssklower 12241593Ssklower pk_freelcd (lcp); 12341593Ssklower 12441593Ssklower if (so == NULL) 12541593Ssklower return; 12641593Ssklower 12741593Ssklower so -> so_pcb = 0; 12841593Ssklower sbflush (&so -> so_snd); 12941593Ssklower sbflush (&so -> so_rcv); 13041593Ssklower soisdisconnected (so); 13141593Ssklower sofree (so); /* gak!!! you can't do that here */ 13241593Ssklower } 13341593Ssklower 13441593Ssklower /* 13541593Ssklower * Create a template to be used to send X.25 packets on a logical 13641593Ssklower * channel. It allocates an mbuf and fills in a skeletal packet 13741593Ssklower * depending on its type. This packet is passed to pk_output where 13841593Ssklower * the remainer of the packet is filled in. 13941593Ssklower */ 14041593Ssklower 14141593Ssklower struct x25_packet * 14241593Ssklower pk_template (lcn, type) 14341593Ssklower int lcn, type; 14441593Ssklower { 14541593Ssklower register struct mbuf *m; 14641593Ssklower register struct x25_packet *xp; 14741593Ssklower 14841593Ssklower MGET (m, M_DONTWAIT, MT_HEADER); 14941593Ssklower if (m == 0) 15041593Ssklower panic ("pk_template"); 15141593Ssklower m -> m_act = 0; 15241593Ssklower 15341593Ssklower /* 15441593Ssklower * Efficiency hack: leave a four byte gap at the beginning 15541593Ssklower * of the packet level header with the hope that this will 15641593Ssklower * be enough room for the link level to insert its header. 15741593Ssklower */ 158*42140Ssklower m -> m_data += 4; 15941593Ssklower m -> m_len = PKHEADERLN; 16041593Ssklower 16141593Ssklower xp = mtod (m, struct x25_packet *); 16241593Ssklower *(long *)xp = 0; /* ugly, but fast */ 16341593Ssklower /* xp -> q_bit = 0;*/ 16441593Ssklower xp -> fmt_identifier = 1; 16541593Ssklower /* xp -> lc_group_number = 0;*/ 16641593Ssklower 16741593Ssklower xp -> logical_channel_number = lcn; 16841593Ssklower xp -> packet_type = type; 16941593Ssklower 17041593Ssklower return (xp); 17141593Ssklower } 17241593Ssklower 17341593Ssklower /* 17441593Ssklower * This routine restarts all the virtual circuits. Actually, 17541593Ssklower * the virtual circuits are not "restarted" as such. Instead, 17641593Ssklower * any active switched circuit is simply returned to READY 17741593Ssklower * state. 17841593Ssklower */ 17941593Ssklower 18041593Ssklower pk_restart (pkp, restart_cause) 18141593Ssklower register struct pkcb *pkp; 18241593Ssklower int restart_cause; 18341593Ssklower { 18441593Ssklower register struct x25_packet *xp; 18541593Ssklower register struct pklcd *lcp; 18641593Ssklower register int i; 18741593Ssklower 18841593Ssklower /* Restart all logical channels. */ 189*42140Ssklower if (pkp->pk_chan == 0) 190*42140Ssklower return; 19141593Ssklower for (i = 1; i <= pkp->pk_maxlcn; ++i) 19241593Ssklower if ((lcp = pkp->pk_chan[i]) != NULL) { 19341593Ssklower if (lcp -> lcd_so) 19441593Ssklower lcp->lcd_so -> so_error = ENETRESET; 19541593Ssklower pk_close (lcp); 19641593Ssklower } 19741593Ssklower 19841593Ssklower if (restart_cause < 0) 19941593Ssklower return; 20041593Ssklower 20141593Ssklower pkp->pk_state = DTE_SENT_RESTART; 20241593Ssklower lcp = pkp->pk_chan[0]; 20341593Ssklower xp = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART); 20441593Ssklower (dtom (xp)) -> m_len++; 20541593Ssklower xp -> packet_data = 0; /* DTE only */ 20641593Ssklower pk_output (lcp); 20741593Ssklower } 20841593Ssklower 20941593Ssklower 21041593Ssklower /* 21141593Ssklower * This procedure frees up the Logical Channel Descripter. 21241593Ssklower */ 21341593Ssklower 21441593Ssklower static 21541593Ssklower pk_freelcd (lcp) 21641593Ssklower register struct pklcd *lcp; 21741593Ssklower { 21841593Ssklower if (lcp == NULL) 21941593Ssklower return; 22041593Ssklower 22141593Ssklower if (lcp -> lcd_template) 22241593Ssklower m_freem (dtom (lcp -> lcd_template)); 22341593Ssklower 22441593Ssklower if (lcp -> lcd_craddr) 22541593Ssklower m_freem (dtom (lcp -> lcd_craddr)); 22641593Ssklower 22741593Ssklower if (lcp -> lcd_ceaddr) 22841593Ssklower m_freem (dtom (lcp -> lcd_ceaddr)); 22941593Ssklower 23041593Ssklower if (lcp -> lcd_lcn > 0) 23141593Ssklower lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL; 23241593Ssklower 23341593Ssklower m_freem (dtom (lcp)); 23441593Ssklower } 23541593Ssklower 23641593Ssklower 23741593Ssklower /* 23841593Ssklower * Bind a address and protocol value to a socket. The important 23941593Ssklower * part is the protocol value - the first four characters of the 24041593Ssklower * Call User Data field. 24141593Ssklower */ 24241593Ssklower 24341593Ssklower pk_bind (lcp, nam) 24441593Ssklower struct pklcd *lcp; 24541593Ssklower struct mbuf *nam; 24641593Ssklower { 24741593Ssklower register struct sockaddr_x25 *sa; 24841593Ssklower register struct pkcb *pkp; 24941593Ssklower register struct mbuf *m; 25041593Ssklower register struct pklcd *pp; 25141593Ssklower 25241593Ssklower if (nam == NULL) 25341593Ssklower return (EADDRNOTAVAIL); 25441593Ssklower if (lcp -> lcd_ceaddr) /* XXX */ 25541593Ssklower return (EADDRINUSE); 25641593Ssklower if (checksockaddr (nam)) 25741593Ssklower return (EINVAL); 25841593Ssklower sa = mtod (nam, struct sockaddr_x25 *); 25941593Ssklower 26041593Ssklower /* 26141593Ssklower * If the user wishes to accept calls only from a particular 26241593Ssklower * net (net != 0), make sure the net is known 26341593Ssklower */ 26441593Ssklower 26541593Ssklower if (sa -> x25_net) 26641593Ssklower for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 26741593Ssklower if (pkp == 0) 26841593Ssklower return (ENETUNREACH); 26941593Ssklower if (pkp -> pk_xcp -> xc_net == sa -> x25_net) 27041593Ssklower break; 27141593Ssklower } 27241593Ssklower 27341593Ssklower for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) 27441593Ssklower if (bcmp (pp -> lcd_ceaddr -> x25_udata, sa -> x25_udata, 27541593Ssklower min (pp->lcd_ceaddr->x25_udlen, sa->x25_udlen)) == 0) 27641593Ssklower return (EADDRINUSE); 27741593Ssklower 27841593Ssklower if ((m = m_copy (nam, 0, (int)M_COPYALL)) == 0) 27941593Ssklower return (ENOBUFS); 28041593Ssklower lcp -> lcd_ceaddr = mtod (m, struct sockaddr_x25 *); 28141593Ssklower return (0); 28241593Ssklower } 28341593Ssklower 28441593Ssklower /* 28541593Ssklower * Associate a logical channel descriptor with a network. 28641593Ssklower * Fill in the default network specific parameters and then 28741593Ssklower * set any parameters explicitly specified by the user or 28841593Ssklower * by the remote DTE. 28941593Ssklower */ 29041593Ssklower 29141593Ssklower pk_assoc (pkp, lcp, sa) 29241593Ssklower register struct pkcb *pkp; 29341593Ssklower register struct pklcd *lcp; 29441593Ssklower register struct sockaddr_x25 *sa; 29541593Ssklower { 29641593Ssklower 29741593Ssklower lcp -> lcd_pkp = pkp; 29841593Ssklower lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize; 29941593Ssklower lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize; 30041593Ssklower lcp -> lcd_rsn = MODULUS - 1; 30141593Ssklower pkp -> pk_chan[lcp -> lcd_lcn] = lcp; 30241593Ssklower 30341593Ssklower if (sa -> x25_opts.op_psize) 30441593Ssklower lcp -> lcd_packetsize = sa -> x25_opts.op_psize; 30541593Ssklower else 30641593Ssklower sa -> x25_opts.op_psize = lcp -> lcd_packetsize; 30741593Ssklower if (sa -> x25_opts.op_wsize) 30841593Ssklower lcp -> lcd_windowsize = sa -> x25_opts.op_wsize; 30941593Ssklower else 31041593Ssklower sa -> x25_opts.op_wsize = lcp -> lcd_windowsize; 31141593Ssklower sa -> x25_net = pkp -> pk_xcp -> xc_net; 31241593Ssklower lcp -> lcd_flags = sa -> x25_opts.op_flags; 31341593Ssklower lcp -> lcd_stime = time.tv_sec; 31441593Ssklower } 31541593Ssklower 31641593Ssklower pk_connect (lcp, nam) 31741593Ssklower register struct pklcd *lcp; 31841593Ssklower struct mbuf *nam; 31941593Ssklower { 32041593Ssklower register struct pkcb *pkp; 32141593Ssklower register struct sockaddr_x25 *sa; 32241593Ssklower register struct mbuf *m; 32341593Ssklower 32441593Ssklower if (checksockaddr (nam)) 32541593Ssklower return (EINVAL); 32641593Ssklower sa = mtod (nam, struct sockaddr_x25 *); 32741593Ssklower if (sa -> x25_addr[0] == '\0') 32841593Ssklower return (EDESTADDRREQ); 32941593Ssklower for (pkp = pkcbhead; ; pkp = pkp->pk_next) { 33041593Ssklower if (pkp == 0) 33141593Ssklower return (ENETUNREACH); 33241593Ssklower /* 33341593Ssklower * use first net configured (last in list 33441593Ssklower * headed by pkcbhead) if net is zero 33541593Ssklower */ 33641593Ssklower if (sa -> x25_net == 0 && pkp -> pk_next == 0) 33741593Ssklower break; 33841593Ssklower if (sa -> x25_net == pkp -> pk_xcp -> xc_net) 33941593Ssklower break; 34041593Ssklower } 34141593Ssklower 34241593Ssklower if (pkp -> pk_state != DTE_READY) 34341593Ssklower return (ENETDOWN); 34441593Ssklower if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0) 34541593Ssklower return (EMFILE); 34641593Ssklower if ((m = m_copy (nam, 0, (int)M_COPYALL)) == 0) 34741593Ssklower return (ENOBUFS); 34841593Ssklower lcp -> lcd_ceaddr = mtod (m, struct sockaddr_x25 *); 34941593Ssklower pk_assoc (pkp, lcp, lcp -> lcd_ceaddr); 350*42140Ssklower if (lcp -> so) 351*42140Ssklower soisconnecting (lcp -> lcd_so); 35241593Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL); 35341593Ssklower pk_callrequest (lcp, m, pkp -> pk_xcp); 35441593Ssklower pk_output (lcp); 35541593Ssklower return (0); 35641593Ssklower } 35741593Ssklower 35841593Ssklower /* 35941593Ssklower * Build the rest of the CALL REQUEST packet. Fill in calling 36041593Ssklower * address, facilities fields and the user data field. 36141593Ssklower */ 36241593Ssklower 36341593Ssklower pk_callrequest (lcp, nam, xcp) 36441593Ssklower struct pklcd *lcp; 36541593Ssklower struct mbuf *nam; 36641593Ssklower register struct x25config *xcp; 36741593Ssklower { 36841593Ssklower register struct x25_calladdr *a; 36941593Ssklower register struct sockaddr_x25 *sa = mtod (nam, struct sockaddr_x25 *); 37041593Ssklower register struct mbuf *m = dtom (lcp -> lcd_template); 37141593Ssklower unsigned posn = 0; 37241593Ssklower octet *cp; 37341593Ssklower char addr[sizeof (xcp -> xc_ntn) * 2]; 37441593Ssklower 37541593Ssklower a = (struct x25_calladdr *) &lcp -> lcd_template -> packet_data; 37641593Ssklower a -> calling_addrlen = xcp -> xc_ntnlen; 37741593Ssklower cp = (octet *) xcp -> xc_ntn; 37841593Ssklower from_bcd (addr, &cp, xcp -> xc_ntnlen); 37941593Ssklower a -> called_addrlen = strlen (sa -> x25_addr); 38041593Ssklower cp = (octet *) a -> address_field; 38141593Ssklower to_bcd (&cp, (int)a -> called_addrlen, sa -> x25_addr, &posn); 38241593Ssklower to_bcd (&cp, (int)a -> calling_addrlen, addr, &posn); 38341593Ssklower if (posn & 0x01) 38441593Ssklower *cp++ &= 0xf0; 38541593Ssklower 38641593Ssklower build_facilities (&cp, sa, (int)xcp -> xc_type); 38741593Ssklower 38841593Ssklower bcopy (sa -> x25_udata, (caddr_t)cp, (unsigned)sa -> x25_udlen); 38941593Ssklower cp += sa -> x25_udlen; 39041593Ssklower 39141593Ssklower m -> m_len += cp - (octet *) a; 39241593Ssklower 39341593Ssklower #ifdef ANDREW 39441593Ssklower printf ("call: "); 39541593Ssklower for (cp = mtod (m, octet *), posn = 0; posn < m->m_len; ++posn) 39641593Ssklower printf ("%x ", *cp++); 39741593Ssklower printf ("\n"); 39841593Ssklower #endif 39941593Ssklower } 40041593Ssklower 40141593Ssklower build_facilities (cp, sa, type) 40241593Ssklower register octet **cp; 40341593Ssklower struct sockaddr_x25 *sa; 40441593Ssklower { 40541593Ssklower register octet *fcp; 40641593Ssklower register int revcharge; 40741593Ssklower 40841593Ssklower fcp = *cp + 1; 40941593Ssklower revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0; 41041593Ssklower /* 41141593Ssklower * This is specific to Datapac X.25(1976) DTEs. International 41241593Ssklower * calls must have the "hi priority" bit on. 41341593Ssklower */ 41441593Ssklower if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128) 41541593Ssklower revcharge |= 02; 41641593Ssklower if (revcharge) { 41741593Ssklower *fcp++ = FACILITIES_REVERSE_CHARGE; 41841593Ssklower *fcp++ = revcharge; 41941593Ssklower } 42041593Ssklower switch (type) { 42141593Ssklower case X25_1980: 42241593Ssklower case X25_1984: 42341593Ssklower *fcp++ = FACILITIES_PACKETSIZE; 42441593Ssklower *fcp++ = sa -> x25_opts.op_psize; 42541593Ssklower *fcp++ = sa -> x25_opts.op_psize; 42641593Ssklower 42741593Ssklower *fcp++ = FACILITIES_WINDOWSIZE; 42841593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 42941593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 43041593Ssklower } 43141593Ssklower **cp = fcp - *cp - 1; 43241593Ssklower *cp = fcp; 43341593Ssklower } 43441593Ssklower 43541593Ssklower to_bcd (a, len, x, posn) 43641593Ssklower register octet **a; 43741593Ssklower register char *x; 43841593Ssklower register int len; 43941593Ssklower register unsigned *posn; 44041593Ssklower { 44141593Ssklower while (--len >= 0) 44241593Ssklower if ((*posn)++ & 0x01) 44341593Ssklower *(*a)++ |= *x++ & 0x0F; 44441593Ssklower else 44541593Ssklower **a = *x++ << 4; 44641593Ssklower } 44741593Ssklower 44841593Ssklower /* 44941593Ssklower * This routine gets the first available logical channel number. The 45041593Ssklower * search is from the highest number to lowest number (DTE). 45141593Ssklower */ 45241593Ssklower 45341593Ssklower pk_getlcn (pkp) 45441593Ssklower register struct pkcb *pkp; 45541593Ssklower { 45641593Ssklower register int i; 45741593Ssklower 458*42140Ssklower if (pkp->pk_chan == 0) 459*42140Ssklower return (0); 46041593Ssklower for (i = pkp -> pk_maxlcn; i > 0; --i) 46141593Ssklower if (pkp -> pk_chan[i] == NULL) 46241593Ssklower break; 46341593Ssklower return (i); 46441593Ssklower 46541593Ssklower } 46641593Ssklower 46741593Ssklower static 46841593Ssklower checksockaddr (m) 46941593Ssklower struct mbuf *m; 47041593Ssklower { 47141593Ssklower register struct sockaddr_x25 *sa = mtod (m, struct sockaddr_x25 *); 47241593Ssklower register char *cp; 47341593Ssklower 47441593Ssklower if (m -> m_len != sizeof (struct sockaddr_x25)) 47541593Ssklower return (1); 47641593Ssklower if (sa -> x25_family != AF_CCITT || sa -> x25_udlen == 0 || 47741593Ssklower sa -> x25_udlen > sizeof (sa -> x25_udata)) 47841593Ssklower return (1); 47941593Ssklower for (cp = sa -> x25_addr; *cp; cp++) { 48041593Ssklower if (*cp < '0' || *cp > '9' || 48141593Ssklower cp >= &sa -> x25_addr[sizeof (sa -> x25_addr) - 1]) 48241593Ssklower return (1); 48341593Ssklower } 48441593Ssklower return (0); 48541593Ssklower } 48641593Ssklower 48741593Ssklower /* 48841593Ssklower * This procedure sends a CLEAR request packet. The lc state is 48941593Ssklower * set to "SENT_CLEAR". 49041593Ssklower */ 49141593Ssklower 49241593Ssklower pk_clear (lcp) 49341593Ssklower struct pklcd *lcp; 49441593Ssklower { 49541593Ssklower register struct x25_packet *xp; 49641593Ssklower 49741593Ssklower xp = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CLEAR); 49841593Ssklower (dtom (xp)) -> m_len++; 49941593Ssklower xp -> packet_data = 0; 50041593Ssklower 50141593Ssklower pk_output (lcp); 50241593Ssklower 50341593Ssklower } 50441593Ssklower 50541593Ssklower /* 50641593Ssklower * This procedure sends a RESET request packet. It re-intializes 50741593Ssklower * virtual circuit. 50841593Ssklower */ 50941593Ssklower 51041593Ssklower static 51141593Ssklower pk_reset (lcp) 51241593Ssklower register struct pklcd *lcp; 51341593Ssklower { 51441593Ssklower register struct x25_packet *xp; 51541593Ssklower register struct socket *so; 51641593Ssklower 51741593Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 51841593Ssklower return; 51941593Ssklower 52041593Ssklower lcp -> lcd_reset_condition = TRUE; 52141593Ssklower 52241593Ssklower /* Reset all the control variables for the channel. */ 52341593Ssklower lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 52441593Ssklower lcp -> lcd_intrconf_pending = FALSE; 52541593Ssklower lcp -> lcd_rsn = MODULUS - 1; 52641593Ssklower lcp -> lcd_ssn = 0; 52741593Ssklower lcp -> lcd_output_window = lcp -> lcd_input_window = 52841593Ssklower lcp -> lcd_last_transmitted_pr = 0; 529*42140Ssklower if (so = lcp -> lcd_so) { 530*42140Ssklower so -> so_error = ECONNRESET; 531*42140Ssklower sbflush (&so -> so_rcv); 532*42140Ssklower sbflush (&so -> so_snd); 533*42140Ssklower } 53441593Ssklower xp = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET); 53541593Ssklower (dtom (xp)) -> m_len += 2; 53641593Ssklower xp -> packet_data = 0; 53741593Ssklower pk_output (lcp); 53841593Ssklower 53941593Ssklower } 54041593Ssklower 54141593Ssklower 54241593Ssklower /* 54341593Ssklower * This procedure handles all local protocol procedure errors. 54441593Ssklower */ 54541593Ssklower 54641593Ssklower pk_procerror (error, lcp, errstr) 54741593Ssklower register struct pklcd *lcp; 54841593Ssklower char *errstr; 54941593Ssklower { 55041593Ssklower 55141593Ssklower pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr); 55241593Ssklower 55341593Ssklower switch (error) { 55441593Ssklower case CLEAR: 55541593Ssklower if (lcp->lcd_so) { 55641593Ssklower lcp->lcd_so -> so_error = ECONNABORTED; 55741593Ssklower soisdisconnecting (lcp->lcd_so); 55841593Ssklower } 55941593Ssklower pk_clear (lcp); 56041593Ssklower break; 56141593Ssklower 56241593Ssklower case RESET: 56341593Ssklower pk_reset (lcp); 56441593Ssklower } 56541593Ssklower } 56641593Ssklower 56741593Ssklower /* 56841593Ssklower * This procedure is called during the DATA TRANSFER state to check 56941593Ssklower * and process the P(R) values received in the DATA, RR OR RNR 57041593Ssklower * packets. 57141593Ssklower */ 57241593Ssklower 57341593Ssklower pk_ack (lcp, pr) 57441593Ssklower struct pklcd *lcp; 57541593Ssklower unsigned pr; 57641593Ssklower { 57741593Ssklower register struct socket *so = lcp -> lcd_so; 57841593Ssklower 57941593Ssklower if (lcp -> lcd_output_window == pr) 58041593Ssklower return (PACKET_OK); 58141593Ssklower if (lcp -> lcd_output_window < lcp -> lcd_ssn) { 58241593Ssklower if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) { 58341593Ssklower pk_procerror (RESET, lcp, "p(r) flow control error"); 58441593Ssklower return (ERROR_PACKET); 58541593Ssklower } 58641593Ssklower } 58741593Ssklower else { 58841593Ssklower if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) { 58941593Ssklower pk_procerror (RESET, lcp, "p(r) flow control error"); 59041593Ssklower return (ERROR_PACKET); 59141593Ssklower } 59241593Ssklower } 59341593Ssklower 59441593Ssklower lcp -> lcd_output_window = pr; /* Rotate window. */ 59541593Ssklower if (lcp -> lcd_window_condition == TRUE) 59641593Ssklower lcp -> lcd_window_condition = FALSE; 59741593Ssklower 598*42140Ssklower if (so && ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel)) 59941593Ssklower sowwakeup (so); 600*42140Ssklower if (lcp -> lcd_downq.pq_unblock) 601*42140Ssklower (*lcp -> lcd_downq.pq_unblock)(lcp); 60241593Ssklower 60341593Ssklower return (PACKET_OK); 60441593Ssklower } 60541593Ssklower 60641593Ssklower /* 60741593Ssklower * This procedure decodes the X.25 level 3 packet returning a 60841593Ssklower * code to be used in switchs or arrays. 60941593Ssklower */ 61041593Ssklower 61141593Ssklower pk_decode (xp) 61241593Ssklower register struct x25_packet *xp; 61341593Ssklower { 61441593Ssklower register int type; 61541593Ssklower 61641593Ssklower if (xp -> fmt_identifier != 1) 61741593Ssklower return (INVALID_PACKET); 61841593Ssklower 61941593Ssklower /* 62041593Ssklower * Make sure that the logical channel group number is 0. 62141593Ssklower * This restriction may be removed at some later date. 62241593Ssklower */ 62341593Ssklower if (xp -> lc_group_number != 0) 62441593Ssklower return (INVALID_PACKET); 62541593Ssklower 62641593Ssklower /* 62741593Ssklower * Test for data packet first. 62841593Ssklower */ 62941593Ssklower if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR)) 63041593Ssklower return (DATA); 63141593Ssklower 63241593Ssklower /* 63341593Ssklower * Test if flow control packet (RR or RNR). 63441593Ssklower */ 63541593Ssklower if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR)) 63641593Ssklower if (!(xp -> packet_type & RR_PACKET_DESIGNATOR)) 63741593Ssklower return (RR); 63841593Ssklower else 63941593Ssklower return (RNR); 64041593Ssklower 64141593Ssklower /* 64241593Ssklower * Determine the rest of the packet types. 64341593Ssklower */ 64441593Ssklower switch (xp -> packet_type) { 64541593Ssklower case X25_CALL: 64641593Ssklower type = CALL; 64741593Ssklower break; 64841593Ssklower 64941593Ssklower case X25_CALL_ACCEPTED: 65041593Ssklower type = CALL_ACCEPTED; 65141593Ssklower break; 65241593Ssklower 65341593Ssklower case X25_CLEAR: 65441593Ssklower type = CLEAR; 65541593Ssklower break; 65641593Ssklower 65741593Ssklower case X25_CLEAR_CONFIRM: 65841593Ssklower type = CLEAR_CONF; 65941593Ssklower break; 66041593Ssklower 66141593Ssklower case X25_INTERRUPT: 66241593Ssklower type = INTERRUPT; 66341593Ssklower break; 66441593Ssklower 66541593Ssklower case X25_INTERRUPT_CONFIRM: 66641593Ssklower type = INTERRUPT_CONF; 66741593Ssklower break; 66841593Ssklower 66941593Ssklower case X25_RESET: 67041593Ssklower type = RESET; 67141593Ssklower break; 67241593Ssklower 67341593Ssklower case X25_RESET_CONFIRM: 67441593Ssklower type = RESET_CONF; 67541593Ssklower break; 67641593Ssklower 67741593Ssklower case X25_RESTART: 67841593Ssklower type = RESTART; 67941593Ssklower break; 68041593Ssklower 68141593Ssklower case X25_RESTART_CONFIRM: 68241593Ssklower type = RESTART_CONF; 68341593Ssklower break; 68441593Ssklower 68541593Ssklower default: 68641593Ssklower type = INVALID_PACKET; 68741593Ssklower } 68841593Ssklower return (type); 68941593Ssklower } 69041593Ssklower 69141593Ssklower /* 69241593Ssklower * A restart packet has been received. Print out the reason 69341593Ssklower * for the restart. 69441593Ssklower */ 69541593Ssklower 69641593Ssklower pk_restartcause (pkp, xp) 69741593Ssklower struct pkcb *pkp; 69841593Ssklower register struct x25_packet *xp; 69941593Ssklower { 70041593Ssklower register struct x25config *xcp = pkp -> pk_xcp; 70141593Ssklower register int lcn = xp -> logical_channel_number; 70241593Ssklower 70341593Ssklower switch (xp -> packet_data) { 70441593Ssklower case X25_RESTART_LOCAL_PROCEDURE_ERROR: 70541593Ssklower pk_message (lcn, xcp, "restart: local procedure error"); 70641593Ssklower break; 70741593Ssklower 70841593Ssklower case X25_RESTART_NETWORK_CONGESTION: 70941593Ssklower pk_message (lcn, xcp, "restart: network congestion"); 71041593Ssklower break; 71141593Ssklower 71241593Ssklower case X25_RESTART_NETWORK_OPERATIONAL: 71341593Ssklower pk_message (lcn, xcp, "restart: network operational"); 71441593Ssklower break; 71541593Ssklower 71641593Ssklower default: 71741593Ssklower pk_message (lcn, xcp, "restart: unknown cause"); 71841593Ssklower } 71941593Ssklower } 72041593Ssklower 72141593Ssklower #define MAXRESETCAUSE 7 72241593Ssklower 72341593Ssklower int Reset_cause[] = { 72441593Ssklower EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG 72541593Ssklower }; 72641593Ssklower 72741593Ssklower /* 72841593Ssklower * A reset packet has arrived. Return the cause to the user. 72941593Ssklower */ 73041593Ssklower 73141593Ssklower pk_resetcause (pkp, xp) 73241593Ssklower struct pkcb *pkp; 73341593Ssklower register struct x25_packet *xp; 73441593Ssklower { 73541593Ssklower register struct pklcd *lcp = pkp->pk_chan[xp -> logical_channel_number]; 73641593Ssklower register int code = xp -> packet_data; 73741593Ssklower 73841593Ssklower if (code > MAXRESETCAUSE) 73941593Ssklower code = 7; /* EXRNCG */ 74041593Ssklower 74141593Ssklower lcp->lcd_so -> so_error = Reset_cause[code]; 74241593Ssklower } 74341593Ssklower 74441593Ssklower #define MAXCLEARCAUSE 25 74541593Ssklower 74641593Ssklower int Clear_cause[] = { 74741593Ssklower EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0, 74841593Ssklower 0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE, 74941593Ssklower 0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC 75041593Ssklower }; 75141593Ssklower 75241593Ssklower /* 75341593Ssklower * A clear packet has arrived. Return the cause to the user. 75441593Ssklower */ 75541593Ssklower 75641593Ssklower pk_clearcause (pkp, xp) 75741593Ssklower struct pkcb *pkp; 75841593Ssklower register struct x25_packet *xp; 75941593Ssklower { 76041593Ssklower register struct pklcd *lcp = pkp->pk_chan[xp -> logical_channel_number]; 76141593Ssklower register int code = xp -> packet_data; 76241593Ssklower 76341593Ssklower if (code > MAXCLEARCAUSE) 76441593Ssklower code = 5; /* EXRNCG */ 76541593Ssklower lcp->lcd_so -> so_error = Clear_cause[code]; 76641593Ssklower } 76741593Ssklower 76841593Ssklower char * 76941593Ssklower format_ntn (xcp) 77041593Ssklower register struct x25config *xcp; 77141593Ssklower { 77241593Ssklower register int i; 77341593Ssklower register char *src, *dest; 77441593Ssklower static char ntn[12]; 77541593Ssklower 77641593Ssklower src = xcp->xc_ntn; 77741593Ssklower dest = ntn; 77841593Ssklower for (i = 0; i < xcp->xc_ntnlen / 2; i++) { 77941593Ssklower *dest++ = ((*src & 0xf0) >> 4) + '0'; 78041593Ssklower *dest++ = (*src++ & 0xf) + '0'; 78141593Ssklower } 78241593Ssklower if (xcp->xc_ntnlen & 01) 78341593Ssklower dest[-1] = 0; 78441593Ssklower else 78541593Ssklower *dest = 0; 78641593Ssklower return (ntn); 78741593Ssklower } 78841593Ssklower 78941593Ssklower /* VARARGS1 */ 79041593Ssklower pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6) 79141593Ssklower struct x25config *xcp; 79241593Ssklower char *fmt; 79341593Ssklower { 79441593Ssklower 79541593Ssklower if (lcn) 79641593Ssklower if (pkcbhead -> pk_next) 79741593Ssklower printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn); 79841593Ssklower else 79941593Ssklower printf ("X.25: lcn %d: ", lcn); 80041593Ssklower else 80141593Ssklower if (pkcbhead -> pk_next) 80241593Ssklower printf ("X.25(%s): ", format_ntn (xcp)); 80341593Ssklower else 80441593Ssklower printf ("X.25: "); 80541593Ssklower 80641593Ssklower printf (fmt, a1, a2, a3, a4, a5, a6); 80741593Ssklower printf ("\n"); 80841593Ssklower } 809