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