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