141709Ssklower /* 241709Ssklower * Copyright (c) University of British Columbia, 1984 357024Ssklower * Copyright (C) Computer Science Department IV, 457024Ssklower * University of Erlangen-Nuremberg, Germany, 1992 557024Ssklower * Copyright (c) 1991, 1992 The Regents of the University of California. 641709Ssklower * All rights reserved. 741709Ssklower * 857024Ssklower * This code is derived from software contributed to Berkeley by the 957024Ssklower * Laboratory for Computation Vision and the Computer Science Department 1057024Ssklower * of the the University of British Columbia and the Computer Science 1157024Ssklower * Department (IV) of the University of Erlangen-Nuremberg, Germany. 1241709Ssklower * 1341709Ssklower * %sccs.include.redist.c% 1441709Ssklower * 15*57032Ssklower * @(#)pk_subr.c 7.24 (Berkeley) 12/08/92 1641709Ssklower */ 1741593Ssklower 1856530Sbostic #include <sys/param.h> 1956530Sbostic #include <sys/systm.h> 2056530Sbostic #include <sys/mbuf.h> 2156530Sbostic #include <sys/socket.h> 2256530Sbostic #include <sys/protosw.h> 2356530Sbostic #include <sys/socketvar.h> 2456530Sbostic #include <sys/errno.h> 2556530Sbostic #include <sys/time.h> 2656530Sbostic #include <sys/kernel.h> 2741593Ssklower 2856530Sbostic #include <net/if.h> 29*57032Ssklower #include <net/route.h> 3042277Ssklower 3157024Ssklower #include <netccitt/dll.h> 3256530Sbostic #include <netccitt/x25.h> 3357024Ssklower #include <netccitt/x25err.h> 3456530Sbostic #include <netccitt/pk.h> 3556530Sbostic #include <netccitt/pk_var.h> 3641593Ssklower 3741593Ssklower int pk_sendspace = 1024 * 2 + 8; 3841593Ssklower int pk_recvspace = 1024 * 2 + 8; 3941593Ssklower 4047271Ssklower struct pklcd_q pklcd_q = {&pklcd_q, &pklcd_q}; 4147271Ssklower 4257024Ssklower struct x25bitslice x25_bitslice[] = { 4357024Ssklower /* mask, shift value */ 4457024Ssklower { 0xf0, 0x4 }, 4557024Ssklower { 0xf, 0x0 }, 4657024Ssklower { 0x80, 0x7 }, 4757024Ssklower { 0x40, 0x6 }, 4857024Ssklower { 0x30, 0x4 }, 4957024Ssklower { 0xe0, 0x5 }, 5057024Ssklower { 0x10, 0x4 }, 5157024Ssklower { 0xe, 0x1 }, 5257024Ssklower { 0x1, 0x0 } 5357024Ssklower }; 5457024Ssklower 5557024Ssklower 5641593Ssklower /* 5741593Ssklower * Attach X.25 protocol to socket, allocate logical channel descripter 5841593Ssklower * and buffer space, and enter LISTEN state if we are to accept 5941593Ssklower * IN-COMMING CALL packets. 6041593Ssklower * 6141593Ssklower */ 6241593Ssklower 6342277Ssklower struct pklcd * 6441593Ssklower pk_attach (so) 6541593Ssklower struct socket *so; 6641593Ssklower { 6741593Ssklower register struct pklcd *lcp; 6842277Ssklower register int error = ENOBUFS; 6949018Ssklower int pk_output(); 7041593Ssklower 7147271Ssklower MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT); 7242277Ssklower if (lcp) { 7347271Ssklower bzero ((caddr_t)lcp, sizeof (*lcp)); 7447271Ssklower insque (&lcp -> lcd_q, &pklcd_q); 7549595Ssklower lcp -> lcd_state = READY; 7649595Ssklower lcp -> lcd_send = pk_output; 7742277Ssklower if (so) { 7842277Ssklower error = soreserve (so, pk_sendspace, pk_recvspace); 7942277Ssklower lcp -> lcd_so = so; 8042277Ssklower if (so -> so_options & SO_ACCEPTCONN) 8142277Ssklower lcp -> lcd_state = LISTEN; 8243361Ssklower } else 8345165Ssklower sbreserve (&lcp -> lcd_sb, pk_sendspace); 8442277Ssklower } 8542277Ssklower if (so) { 8642277Ssklower so -> so_pcb = (caddr_t) lcp; 8742277Ssklower so -> so_error = error; 8842277Ssklower } 8942277Ssklower return (lcp); 9041593Ssklower } 9141593Ssklower 9241593Ssklower /* 9341593Ssklower * Disconnect X.25 protocol from socket. 9441593Ssklower */ 9541593Ssklower 9641593Ssklower pk_disconnect (lcp) 9741593Ssklower register struct pklcd *lcp; 9841593Ssklower { 9941593Ssklower register struct socket *so = lcp -> lcd_so; 10041593Ssklower register struct pklcd *l, *p; 10141593Ssklower 10241593Ssklower switch (lcp -> lcd_state) { 10341593Ssklower case LISTEN: 10441593Ssklower for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen); 10541593Ssklower if (p == 0) { 10641593Ssklower if (l != 0) 10741593Ssklower pk_listenhead = l -> lcd_listen; 10841593Ssklower } 10941593Ssklower else 11041593Ssklower if (l != 0) 11141593Ssklower p -> lcd_listen = l -> lcd_listen; 11241593Ssklower pk_close (lcp); 11341593Ssklower break; 11441593Ssklower 11541593Ssklower case READY: 11641593Ssklower pk_acct (lcp); 11741593Ssklower pk_close (lcp); 11841593Ssklower break; 11941593Ssklower 12041593Ssklower case SENT_CLEAR: 12141593Ssklower case RECEIVED_CLEAR: 12241593Ssklower break; 12341593Ssklower 12441593Ssklower default: 12541593Ssklower pk_acct (lcp); 12642140Ssklower if (so) { 12742140Ssklower soisdisconnecting (so); 12842140Ssklower sbflush (&so -> so_rcv); 12942140Ssklower } 13045895Ssklower pk_clear (lcp, 241, 0); /* Normal Disconnect */ 13141593Ssklower 13241593Ssklower } 13341593Ssklower } 13441593Ssklower 13541593Ssklower /* 13641593Ssklower * Close an X.25 Logical Channel. Discard all space held by the 13741593Ssklower * connection and internal descriptors. Wake up any sleepers. 13841593Ssklower */ 13941593Ssklower 14041593Ssklower pk_close (lcp) 14141593Ssklower struct pklcd *lcp; 14241593Ssklower { 14341593Ssklower register struct socket *so = lcp -> lcd_so; 14441593Ssklower 14557024Ssklower /* 14657024Ssklower * If the X.25 connection is torn down due to link 14757024Ssklower * level failure (e.g. LLC2 FRMR) and at the same the user 14857024Ssklower * level is still filling up the socket send buffer that 14957024Ssklower * send buffer is locked. An attempt to sbflush() that send 15057024Ssklower * buffer will lead us into - no, not temptation but - panic! 15157024Ssklower * So - we'll just check wether the send buffer is locked 15257024Ssklower * and if that's the case we'll mark the lcp as zombie and 15357024Ssklower * have the pk_timer() do the cleaning ... 15457024Ssklower */ 15557024Ssklower 15657024Ssklower if (so && so -> so_snd.sb_flags & SB_LOCK) 15757024Ssklower lcp -> lcd_state = LCN_ZOMBIE; 15857024Ssklower else 15957024Ssklower pk_freelcd (lcp); 16041593Ssklower 16141593Ssklower if (so == NULL) 16241593Ssklower return; 16341593Ssklower 16441593Ssklower so -> so_pcb = 0; 16541593Ssklower soisdisconnected (so); 16645895Ssklower /* sofree (so); /* gak!!! you can't do that here */ 16741593Ssklower } 16841593Ssklower 16941593Ssklower /* 17041593Ssklower * Create a template to be used to send X.25 packets on a logical 17141593Ssklower * channel. It allocates an mbuf and fills in a skeletal packet 17241593Ssklower * depending on its type. This packet is passed to pk_output where 17341593Ssklower * the remainer of the packet is filled in. 17441593Ssklower */ 17541593Ssklower 17645895Ssklower struct mbuf * 17741593Ssklower pk_template (lcn, type) 17841593Ssklower int lcn, type; 17941593Ssklower { 18041593Ssklower register struct mbuf *m; 18141593Ssklower register struct x25_packet *xp; 18241593Ssklower 18345297Ssklower MGETHDR (m, M_DONTWAIT, MT_HEADER); 18441593Ssklower if (m == 0) 18541593Ssklower panic ("pk_template"); 18641593Ssklower m -> m_act = 0; 18741593Ssklower 18841593Ssklower /* 18941593Ssklower * Efficiency hack: leave a four byte gap at the beginning 19041593Ssklower * of the packet level header with the hope that this will 19141593Ssklower * be enough room for the link level to insert its header. 19241593Ssklower */ 19345297Ssklower m -> m_data += max_linkhdr; 19449595Ssklower m -> m_pkthdr.len = m -> m_len = PKHEADERLN; 19541593Ssklower 19641593Ssklower xp = mtod (m, struct x25_packet *); 19741593Ssklower *(long *)xp = 0; /* ugly, but fast */ 19841593Ssklower /* xp -> q_bit = 0;*/ 19957024Ssklower X25SBITS(xp -> bits, fmt_identifier, 1); 20041593Ssklower /* xp -> lc_group_number = 0;*/ 20141593Ssklower 20245574Ssklower SET_LCN(xp, lcn); 20341593Ssklower xp -> packet_type = type; 20441593Ssklower 20545895Ssklower return (m); 20641593Ssklower } 20741593Ssklower 20841593Ssklower /* 20941593Ssklower * This routine restarts all the virtual circuits. Actually, 21041593Ssklower * the virtual circuits are not "restarted" as such. Instead, 21141593Ssklower * any active switched circuit is simply returned to READY 21241593Ssklower * state. 21341593Ssklower */ 21441593Ssklower 21541593Ssklower pk_restart (pkp, restart_cause) 21641593Ssklower register struct pkcb *pkp; 21741593Ssklower int restart_cause; 21841593Ssklower { 21945895Ssklower register struct mbuf *m; 22041593Ssklower register struct pklcd *lcp; 22141593Ssklower register int i; 22241593Ssklower 22341593Ssklower /* Restart all logical channels. */ 22445297Ssklower if (pkp -> pk_chan == 0) 22542140Ssklower return; 22657024Ssklower 22757024Ssklower /* 22857024Ssklower * Don't do this if we're doing a restart issued from 22957024Ssklower * inside pk_connect() --- which is only done if and 23057024Ssklower * only if the X.25 link is down, i.e. a RESTART needs 23157024Ssklower * to be done to get it up. 23257024Ssklower */ 23357024Ssklower if (!(pkp -> pk_dxerole & DTE_CONNECTPENDING)) { 23457024Ssklower for (i = 1; i <= pkp -> pk_maxlcn; ++i) 23557024Ssklower if ((lcp = pkp -> pk_chan[i]) != NULL) { 23657024Ssklower if (lcp -> lcd_so) { 23757024Ssklower lcp -> lcd_so -> so_error = ENETRESET; 23857024Ssklower pk_close (lcp); 23957024Ssklower } else { 24057024Ssklower pk_flush (lcp); 24157024Ssklower lcp -> lcd_state = READY; 24257024Ssklower if (lcp -> lcd_upper) 24357024Ssklower lcp -> lcd_upper (lcp, 0); 24457024Ssklower } 24545895Ssklower } 24657024Ssklower } 24741593Ssklower 24841593Ssklower if (restart_cause < 0) 24941593Ssklower return; 25041593Ssklower 25145297Ssklower pkp -> pk_state = DTE_SENT_RESTART; 25257024Ssklower pkp -> pk_dxerole &= ~(DTE_PLAYDCE | DTE_PLAYDTE); 25345297Ssklower lcp = pkp -> pk_chan[0]; 25445895Ssklower m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART); 25549595Ssklower m -> m_pkthdr.len = m -> m_len += 2; 25647271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; /* DTE only */ 25747271Ssklower mtod (m, octet *)[4] = restart_cause; 25841593Ssklower pk_output (lcp); 25941593Ssklower } 26041593Ssklower 26141593Ssklower 26241593Ssklower /* 26341593Ssklower * This procedure frees up the Logical Channel Descripter. 26441593Ssklower */ 26541593Ssklower 26641593Ssklower pk_freelcd (lcp) 26741593Ssklower register struct pklcd *lcp; 26841593Ssklower { 26941593Ssklower if (lcp == NULL) 27041593Ssklower return; 27141593Ssklower 27241593Ssklower if (lcp -> lcd_lcn > 0) 27341593Ssklower lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL; 27441593Ssklower 27547271Ssklower pk_flush (lcp); 27647271Ssklower remque (&lcp -> lcd_q); 27747271Ssklower free ((caddr_t)lcp, M_PCB); 27841593Ssklower } 27941593Ssklower 28041593Ssklower 28141593Ssklower /* 28241593Ssklower * Bind a address and protocol value to a socket. The important 28341593Ssklower * part is the protocol value - the first four characters of the 28441593Ssklower * Call User Data field. 28541593Ssklower */ 28641593Ssklower 28757024Ssklower #define XTRACTPKP(rt) ((rt)->rt_flags & RTF_GATEWAY ? \ 28857024Ssklower ((rt)->rt_llinfo ? \ 28957024Ssklower (struct pkcb *) ((struct rtentry *)((rt)->rt_llinfo))->rt_llinfo : \ 29057024Ssklower (struct pkcb *) NULL) : \ 29157024Ssklower (struct pkcb *)((rt)->rt_llinfo)) 29257024Ssklower 29341593Ssklower pk_bind (lcp, nam) 29441593Ssklower struct pklcd *lcp; 29541593Ssklower struct mbuf *nam; 29641593Ssklower { 29741593Ssklower register struct pkcb *pkp; 29841593Ssklower register struct pklcd *pp; 29942277Ssklower register struct sockaddr_x25 *sa; 30057024Ssklower register struct rtentry *rt; 30141593Ssklower 30241593Ssklower if (nam == NULL) 30341593Ssklower return (EADDRNOTAVAIL); 30441593Ssklower if (lcp -> lcd_ceaddr) /* XXX */ 30541593Ssklower return (EADDRINUSE); 30645895Ssklower if (pk_checksockaddr (nam)) 30741593Ssklower return (EINVAL); 30841593Ssklower sa = mtod (nam, struct sockaddr_x25 *); 30941593Ssklower 31041593Ssklower /* 31141593Ssklower * If the user wishes to accept calls only from a particular 31241593Ssklower * net (net != 0), make sure the net is known 31341593Ssklower */ 31441593Ssklower 31557024Ssklower if ( !(rt = rtalloc1(sa, 1))) 31657024Ssklower return (ENETUNREACH); 31757024Ssklower pkp = XTRACTPKP(rt); 31841593Ssklower 31945895Ssklower /* 32045895Ssklower * For ISO's sake permit default listeners, but only one such . . . 32145895Ssklower */ 32245895Ssklower for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) { 32345895Ssklower register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr; 32445895Ssklower if ((sa2 -> x25_udlen == sa -> x25_udlen) && 32545895Ssklower (sa2 -> x25_udlen == 0 || 32645895Ssklower (bcmp (sa2 -> x25_udata, sa -> x25_udata, 32745895Ssklower min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0))) 32845895Ssklower return (EADDRINUSE); 32945895Ssklower } 33042277Ssklower lcp -> lcd_laddr = *sa; 33142277Ssklower lcp -> lcd_ceaddr = &lcp -> lcd_laddr; 33241593Ssklower return (0); 33341593Ssklower } 33441593Ssklower 33541593Ssklower /* 33645895Ssklower * Include a bound control block in the list of listeners. 33745895Ssklower */ 33845895Ssklower pk_listen (lcp) 33945895Ssklower register struct pklcd *lcp; 34045895Ssklower { 34145895Ssklower register struct pklcd **pp; 34245895Ssklower 34345895Ssklower if (lcp -> lcd_ceaddr == 0) 34445895Ssklower return (EDESTADDRREQ); 34545895Ssklower 34645895Ssklower lcp -> lcd_state = LISTEN; 34745895Ssklower /* 34845895Ssklower * Add default listener at end, any others at start. 34945895Ssklower */ 35045895Ssklower if (lcp -> lcd_ceaddr -> x25_udlen == 0) { 35145895Ssklower for (pp = &pk_listenhead; *pp; ) 35245895Ssklower pp = &((*pp) -> lcd_listen); 35345895Ssklower *pp = lcp; 35445895Ssklower } else { 35545895Ssklower lcp -> lcd_listen = pk_listenhead; 35645895Ssklower pk_listenhead = lcp; 35745895Ssklower } 35845895Ssklower return (0); 35945895Ssklower } 36045895Ssklower /* 36145895Ssklower * Include a listening control block for the benefit of other protocols. 36245895Ssklower */ 36345895Ssklower pk_protolisten (spi, spilen, callee) 36447271Ssklower int (*callee) (); 36545895Ssklower { 36645895Ssklower register struct pklcd *lcp = pk_attach ((struct socket *)0); 36745895Ssklower register struct mbuf *nam; 36845895Ssklower register struct sockaddr_x25 *sa; 36945895Ssklower int error = ENOBUFS; 37045895Ssklower 37145895Ssklower if (lcp) { 37247271Ssklower if (nam = m_getclr (MT_SONAME, M_DONTWAIT)) { 37347271Ssklower sa = mtod (nam, struct sockaddr_x25 *); 37445895Ssklower sa -> x25_family = AF_CCITT; 37545895Ssklower sa -> x25_len = nam -> m_len = sizeof (*sa); 37645895Ssklower sa -> x25_udlen = spilen; 37745895Ssklower sa -> x25_udata[0] = spi; 37845895Ssklower lcp -> lcd_upper = callee; 37945895Ssklower lcp -> lcd_flags = X25_MBS_HOLD; 38049929Ssklower if ((error = pk_bind (lcp, nam)) == 0) 38149929Ssklower error = pk_listen (lcp); 38245895Ssklower (void) m_free (nam); 38345895Ssklower } 38445895Ssklower if (error) 38547271Ssklower pk_freelcd (lcp); 38645895Ssklower } 38745895Ssklower return error; /* Hopefully Zero !*/ 38845895Ssklower } 38945895Ssklower 39045895Ssklower /* 39141593Ssklower * Associate a logical channel descriptor with a network. 39241593Ssklower * Fill in the default network specific parameters and then 39341593Ssklower * set any parameters explicitly specified by the user or 39441593Ssklower * by the remote DTE. 39541593Ssklower */ 39641593Ssklower 39741593Ssklower pk_assoc (pkp, lcp, sa) 39841593Ssklower register struct pkcb *pkp; 39941593Ssklower register struct pklcd *lcp; 40041593Ssklower register struct sockaddr_x25 *sa; 40141593Ssklower { 40241593Ssklower 40341593Ssklower lcp -> lcd_pkp = pkp; 40441593Ssklower lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize; 40541593Ssklower lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize; 40641593Ssklower lcp -> lcd_rsn = MODULUS - 1; 40741593Ssklower pkp -> pk_chan[lcp -> lcd_lcn] = lcp; 40841593Ssklower 40941593Ssklower if (sa -> x25_opts.op_psize) 41041593Ssklower lcp -> lcd_packetsize = sa -> x25_opts.op_psize; 41141593Ssklower else 41241593Ssklower sa -> x25_opts.op_psize = lcp -> lcd_packetsize; 41341593Ssklower if (sa -> x25_opts.op_wsize) 41441593Ssklower lcp -> lcd_windowsize = sa -> x25_opts.op_wsize; 41541593Ssklower else 41641593Ssklower sa -> x25_opts.op_wsize = lcp -> lcd_windowsize; 41745165Ssklower sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net; 41850020Ssklower lcp -> lcd_flags |= sa -> x25_opts.op_flags; 41941593Ssklower lcp -> lcd_stime = time.tv_sec; 42041593Ssklower } 42141593Ssklower 42245895Ssklower pk_connect (lcp, sa) 42341593Ssklower register struct pklcd *lcp; 42442277Ssklower register struct sockaddr_x25 *sa; 42541593Ssklower { 42641593Ssklower register struct pkcb *pkp; 42757024Ssklower register struct rtentry *rt; 42857024Ssklower register struct rtentry *nrt; 42941593Ssklower 43057024Ssklower struct rtentry *npaidb_enter(); 43157024Ssklower struct pkcb *pk_newlink(); 43257024Ssklower 43341593Ssklower if (sa -> x25_addr[0] == '\0') 43441593Ssklower return (EDESTADDRREQ); 43557024Ssklower 43657024Ssklower /* 43757024Ssklower * Is the destination address known? 43857024Ssklower */ 43957024Ssklower if (!(rt = rtalloc1 (sa, 1))) 44057024Ssklower return (ENETUNREACH); 44157024Ssklower 44257024Ssklower if (!(pkp = XTRACTPKP(rt))) 44357024Ssklower pkp = pk_newlink((struct x25_ifaddr *) (rt -> rt_ifa), 44457024Ssklower (caddr_t) 0); 44557024Ssklower 44657024Ssklower /* 44757024Ssklower * Have we entered the LLC address? 44857024Ssklower */ 44957024Ssklower if (nrt = npaidb_enter(rt -> rt_gateway, rt_key(rt), rt, 0)) 45057024Ssklower pkp -> pk_llrt = nrt; 45157024Ssklower 45257024Ssklower /* 45357024Ssklower * Have we allocated an LLC2 link yet? 45457024Ssklower */ 45557024Ssklower if (pkp->pk_llnext == (caddr_t)0 && pkp->pk_llctlinput) { 45657024Ssklower struct dll_ctlinfo ctlinfo; 45757024Ssklower 45857024Ssklower ctlinfo.dlcti_rt = rt; 45957024Ssklower ctlinfo.dlcti_pcb = (caddr_t) pkp; 46057024Ssklower ctlinfo.dlcti_conf = 46157024Ssklower (struct dllconfig *) (&((struct x25_ifaddr *)(rt->rt_ifa))->ia_xc); 46257024Ssklower pkp->pk_llnext = 46357024Ssklower (pkp->pk_llctlinput)(PRC_CONNECT_REQUEST, 0, &ctlinfo); 46441593Ssklower } 46541593Ssklower 46657024Ssklower if (pkp -> pk_state != DTE_READY && pkp -> pk_state != DTE_WAITING) 46757024Ssklower return (ENETDOWN); 46841593Ssklower if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0) 46941593Ssklower return (EMFILE); 47057024Ssklower 47142277Ssklower lcp -> lcd_faddr = *sa; 47245297Ssklower lcp -> lcd_ceaddr = & lcp -> lcd_faddr; 47341593Ssklower pk_assoc (pkp, lcp, lcp -> lcd_ceaddr); 47457024Ssklower 47557024Ssklower /* 47657024Ssklower * If the link is not up yet, initiate an X.25 RESTART 47757024Ssklower */ 47857024Ssklower if (pkp -> pk_state == DTE_WAITING) { 47957024Ssklower pkp -> pk_dxerole |= DTE_CONNECTPENDING; 48057024Ssklower pk_ctlinput(PRC_LINKUP, (struct sockaddr *)0, pkp); 48157024Ssklower if (lcp -> lcd_so) 48257024Ssklower soisconnecting (lcp -> lcd_so); 48357024Ssklower return 0; 48457024Ssklower } 48557024Ssklower 48645165Ssklower if (lcp -> lcd_so) 48742140Ssklower soisconnecting (lcp -> lcd_so); 48841593Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL); 48942277Ssklower pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp); 49049929Ssklower return (*pkp -> pk_ia -> ia_start) (lcp); 49141593Ssklower } 49241593Ssklower 49357024Ssklower /* 49457024Ssklower * Complete all pending X.25 call requests --- this gets called after 49557024Ssklower * the X.25 link has been restarted. 49657024Ssklower */ 49757024Ssklower #define RESHUFFLELCN(maxlcn, lcn) ((maxlcn) - (lcn) + 1) 49857024Ssklower 49957024Ssklower pk_callcomplete(pkp) 50057024Ssklower register struct pkcb *pkp; 50157024Ssklower { 50257024Ssklower register struct pklcd *lcp; 50357024Ssklower register int i; 50457024Ssklower register int ni; 50557024Ssklower 50657024Ssklower 50757024Ssklower if (pkp -> pk_dxerole & DTE_CONNECTPENDING) 50857024Ssklower pkp -> pk_dxerole &= ~DTE_CONNECTPENDING; 50957024Ssklower else return; 51057024Ssklower 51157024Ssklower if (pkp -> pk_chan == 0) 51257024Ssklower return; 51357024Ssklower 51457024Ssklower /* 51557024Ssklower * We pretended to be a DTE for allocating lcns, if 51657024Ssklower * it turns out that we are in reality performing as a 51757024Ssklower * DCE we need to reshuffle the lcps. 51857024Ssklower * 51957024Ssklower * /+---------------+-------- - 52057024Ssklower * / | a (maxlcn-1) | \ 52157024Ssklower * / +---------------+ \ 52257024Ssklower * +--- * | b (maxlcn-2) | \ 52357024Ssklower * | \ +---------------+ \ 52457024Ssklower * r | \ | c (maxlcn-3) | \ 52557024Ssklower * e | \+---------------+ | 52657024Ssklower * s | | . | 52757024Ssklower * h | | . | m 52857024Ssklower * u | | . | a 52957024Ssklower * f | | . | x 53057024Ssklower * f | | . | l 53157024Ssklower * l | /+---------------+ | c 53257024Ssklower * e | / | c' ( 3 ) | | n 53357024Ssklower * | / +---------------+ | 53457024Ssklower * +--> * | b' ( 2 ) | / 53557024Ssklower * \ +---------------+ / 53657024Ssklower * \ | a' ( 1 ) | / 53757024Ssklower * \+---------------+ / 53857024Ssklower * | 0 | / 53957024Ssklower * +---------------+-------- - 54057024Ssklower * 54157024Ssklower */ 54257024Ssklower if (pkp -> pk_dxerole & DTE_PLAYDCE) { 54357024Ssklower /* Sigh, reshuffle it */ 54457024Ssklower for (i = pkp -> pk_maxlcn; i > 0; --i) 54557024Ssklower if (pkp -> pk_chan[i]) { 54657024Ssklower ni = RESHUFFLELCN(pkp -> pk_maxlcn, i); 54757024Ssklower pkp -> pk_chan[ni] = pkp -> pk_chan[i]; 54857024Ssklower pkp -> pk_chan[i] = NULL; 54957024Ssklower pkp -> pk_chan[ni] -> lcd_lcn = ni; 55057024Ssklower } 55157024Ssklower } 55257024Ssklower 55357024Ssklower for (i = 1; i <= pkp -> pk_maxlcn; ++i) 55457024Ssklower if ((lcp = pkp -> pk_chan[i]) != NULL) { 55557024Ssklower /* if (lcp -> lcd_so) 55657024Ssklower soisconnecting (lcp -> lcd_so); */ 55757024Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL); 55857024Ssklower pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp); 55957024Ssklower (*pkp -> pk_ia -> ia_start)(lcp); 56057024Ssklower } 56157024Ssklower } 56257024Ssklower 56349747Ssklower struct bcdinfo { 56449747Ssklower octet *cp; 56549747Ssklower unsigned posn; 56649747Ssklower }; 56741593Ssklower /* 56841593Ssklower * Build the rest of the CALL REQUEST packet. Fill in calling 56941593Ssklower * address, facilities fields and the user data field. 57041593Ssklower */ 57141593Ssklower 57242277Ssklower pk_callrequest (lcp, sa, xcp) 57341593Ssklower struct pklcd *lcp; 57442277Ssklower register struct sockaddr_x25 *sa; 57541593Ssklower register struct x25config *xcp; 57641593Ssklower { 57741593Ssklower register struct x25_calladdr *a; 57845895Ssklower register struct mbuf *m = lcp -> lcd_template; 57947271Ssklower register struct x25_packet *xp = mtod (m, struct x25_packet *); 58049747Ssklower struct bcdinfo b; 58141593Ssklower 58245574Ssklower if (lcp -> lcd_flags & X25_DBIT) 58357024Ssklower X25SBITS(xp -> bits, d_bit, 1); 58445895Ssklower a = (struct x25_calladdr *) &xp -> packet_data; 58549747Ssklower b.cp = (octet *) a -> address_field; 58649747Ssklower b.posn = 0; 58757024Ssklower X25SBITS(a -> addrlens, called_addrlen, to_bcd (&b, sa, xcp)); 58857024Ssklower X25SBITS(a -> addrlens, calling_addrlen, to_bcd (&b, &xcp -> xc_addr, xcp)); 58949747Ssklower if (b.posn & 0x01) 59049747Ssklower *b.cp++ &= 0xf0; 59149747Ssklower m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a; 59241593Ssklower 59345895Ssklower if (lcp -> lcd_facilities) { 59447271Ssklower m -> m_pkthdr.len += 59549747Ssklower (m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len; 59645895Ssklower lcp -> lcd_facilities = 0; 59745895Ssklower } else 59849747Ssklower pk_build_facilities (m, sa, (int)xcp -> xc_type); 59941593Ssklower 60047271Ssklower m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata); 60141593Ssklower } 60241593Ssklower 60349747Ssklower pk_build_facilities (m, sa, type) 60445895Ssklower register struct mbuf *m; 60541593Ssklower struct sockaddr_x25 *sa; 60641593Ssklower { 60745895Ssklower register octet *cp; 60841593Ssklower register octet *fcp; 60941593Ssklower register int revcharge; 61041593Ssklower 61147271Ssklower cp = mtod (m, octet *) + m -> m_len; 61245895Ssklower fcp = cp + 1; 61341593Ssklower revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0; 61441593Ssklower /* 61541593Ssklower * This is specific to Datapac X.25(1976) DTEs. International 61641593Ssklower * calls must have the "hi priority" bit on. 61741593Ssklower */ 61841593Ssklower if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128) 61941593Ssklower revcharge |= 02; 62041593Ssklower if (revcharge) { 62141593Ssklower *fcp++ = FACILITIES_REVERSE_CHARGE; 62241593Ssklower *fcp++ = revcharge; 62341593Ssklower } 62441593Ssklower switch (type) { 62541593Ssklower case X25_1980: 62641593Ssklower case X25_1984: 62741593Ssklower *fcp++ = FACILITIES_PACKETSIZE; 62841593Ssklower *fcp++ = sa -> x25_opts.op_psize; 62941593Ssklower *fcp++ = sa -> x25_opts.op_psize; 63041593Ssklower 63141593Ssklower *fcp++ = FACILITIES_WINDOWSIZE; 63241593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 63341593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 63441593Ssklower } 63545895Ssklower *cp = fcp - cp - 1; 63645895Ssklower m -> m_pkthdr.len = (m -> m_len += *cp + 1); 63741593Ssklower } 63841593Ssklower 63949747Ssklower to_bcd (b, sa, xcp) 64049747Ssklower register struct bcdinfo *b; 64149747Ssklower struct sockaddr_x25 *sa; 64249747Ssklower register struct x25config *xcp; 64341593Ssklower { 64449747Ssklower register char *x = sa -> x25_addr; 64549747Ssklower unsigned start = b -> posn; 64649747Ssklower /* 64749747Ssklower * The nodnic and prepnd0 stuff looks tedious, 64849747Ssklower * but it does allow full X.121 addresses to be used, 64949747Ssklower * which is handy for routing info (& OSI type 37 addresses). 65049747Ssklower */ 65149747Ssklower if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) { 65249747Ssklower char dnicname[sizeof(long) * NBBY/3 + 2]; 65349747Ssklower register char *p = dnicname; 65449747Ssklower 65549747Ssklower sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff); 65649747Ssklower for (; *p; p++) /* *p == 0 means dnic matched */ 65749747Ssklower if ((*p ^ *x++) & 0x0f) 65849747Ssklower break; 65949747Ssklower if (*p || xcp -> xc_nodnic == 0) 66049747Ssklower x = sa -> x25_addr; 66149747Ssklower if (*p && xcp -> xc_prepnd0) { 66249747Ssklower if ((b -> posn)++ & 0x01) 66349747Ssklower *(b -> cp)++; 66449747Ssklower else 66549747Ssklower *(b -> cp) = 0; 66649747Ssklower } 66749747Ssklower } 66849747Ssklower while (*x) 66949747Ssklower if ((b -> posn)++ & 0x01) 67049747Ssklower *(b -> cp)++ |= *x++ & 0x0F; 67141593Ssklower else 67249747Ssklower *(b -> cp) = *x++ << 4; 67349747Ssklower return ((b -> posn) - start); 67441593Ssklower } 67541593Ssklower 67641593Ssklower /* 67741593Ssklower * This routine gets the first available logical channel number. The 67857024Ssklower * search is 67957024Ssklower * - from the highest number to lowest number if playing DTE, and 68057024Ssklower * - from lowest to highest number if playing DCE. 68141593Ssklower */ 68241593Ssklower 68341593Ssklower pk_getlcn (pkp) 68441593Ssklower register struct pkcb *pkp; 68541593Ssklower { 68641593Ssklower register int i; 68741593Ssklower 68845297Ssklower if (pkp -> pk_chan == 0) 68942140Ssklower return (0); 69057024Ssklower if ( pkp -> pk_dxerole & DTE_PLAYDCE ) { 69157024Ssklower for (i = 1; i <= pkp -> pk_maxlcn; ++i) 69257024Ssklower if (pkp -> pk_chan[i] == NULL) 69357024Ssklower break; 69457024Ssklower } else { 69557024Ssklower for (i = pkp -> pk_maxlcn; i > 0; --i) 69657024Ssklower if (pkp -> pk_chan[i] == NULL) 69757024Ssklower break; 69857024Ssklower } 69957024Ssklower i = ( i > pkp -> pk_maxlcn ? 0 : i ); 70041593Ssklower return (i); 70141593Ssklower } 70241593Ssklower 70341593Ssklower /* 70441593Ssklower * This procedure sends a CLEAR request packet. The lc state is 70541593Ssklower * set to "SENT_CLEAR". 70641593Ssklower */ 70741593Ssklower 70845895Ssklower pk_clear (lcp, diagnostic, abortive) 70945895Ssklower register struct pklcd *lcp; 71041593Ssklower { 71145895Ssklower register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR); 71241593Ssklower 71345895Ssklower m -> m_len += 2; 71451739Ssklower m -> m_pkthdr.len += 2; 71547271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; 71647271Ssklower mtod (m, octet *)[4] = diagnostic; 71745895Ssklower if (lcp -> lcd_facilities) { 71845895Ssklower m -> m_next = lcp -> lcd_facilities; 71945895Ssklower m -> m_pkthdr.len += m -> m_next -> m_len; 72045895Ssklower lcp -> lcd_facilities = 0; 72145895Ssklower } 72245895Ssklower if (abortive) 72345895Ssklower lcp -> lcd_template = m; 72445895Ssklower else { 72545895Ssklower struct socket *so = lcp -> lcd_so; 72645895Ssklower struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb; 72747271Ssklower sbappendrecord (sb, m); 72845895Ssklower } 72941593Ssklower pk_output (lcp); 73041593Ssklower 73141593Ssklower } 73241593Ssklower 73347271Ssklower /* 73447271Ssklower * This procedure generates RNR's or RR's to inhibit or enable 73547271Ssklower * inward data flow, if the current state changes (blocked ==> open or 73647271Ssklower * vice versa), or if forced to generate one. One forces RNR's to ack data. 73747271Ssklower */ 73847271Ssklower pk_flowcontrol (lcp, inhibit, forced) 73947271Ssklower register struct pklcd *lcp; 74047271Ssklower { 74147271Ssklower inhibit = (inhibit != 0); 74247271Ssklower if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER || 74347271Ssklower (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit)) 74447271Ssklower return; 74547271Ssklower lcp -> lcd_rxrnr_condition = inhibit; 74649929Ssklower lcp -> lcd_template = 74749929Ssklower pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR); 74847271Ssklower pk_output (lcp); 74947271Ssklower } 75047271Ssklower 75141593Ssklower /* 75247271Ssklower * This procedure sends a RESET request packet. It re-intializes 75341593Ssklower * virtual circuit. 75441593Ssklower */ 75541593Ssklower 75641593Ssklower static 75745895Ssklower pk_reset (lcp, diagnostic) 75841593Ssklower register struct pklcd *lcp; 75941593Ssklower { 76045895Ssklower register struct mbuf *m; 76145895Ssklower register struct socket *so = lcp -> lcd_so; 76241593Ssklower 76341593Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 76441593Ssklower return; 76541593Ssklower 76645895Ssklower if (so) 76745895Ssklower so -> so_error = ECONNRESET; 76841593Ssklower lcp -> lcd_reset_condition = TRUE; 76941593Ssklower 77041593Ssklower /* Reset all the control variables for the channel. */ 77145895Ssklower pk_flush (lcp); 77241593Ssklower lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 77341593Ssklower lcp -> lcd_intrconf_pending = FALSE; 77441593Ssklower lcp -> lcd_rsn = MODULUS - 1; 77541593Ssklower lcp -> lcd_ssn = 0; 77641593Ssklower lcp -> lcd_output_window = lcp -> lcd_input_window = 77741593Ssklower lcp -> lcd_last_transmitted_pr = 0; 77845895Ssklower m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET); 77949595Ssklower m -> m_pkthdr.len = m -> m_len += 2; 78047271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; 78147271Ssklower mtod (m, octet *)[4] = diagnostic; 78245895Ssklower pk_output (lcp); 78345895Ssklower 78445895Ssklower } 78545895Ssklower 78645895Ssklower /* 78745895Ssklower * This procedure frees all data queued for output or delivery on a 78845895Ssklower * virtual circuit. 78945895Ssklower */ 79045895Ssklower 79145895Ssklower pk_flush (lcp) 79245895Ssklower register struct pklcd *lcp; 79345895Ssklower { 79445895Ssklower register struct socket *so; 79545895Ssklower 79645895Ssklower if (lcp -> lcd_template) 79745895Ssklower m_freem (lcp -> lcd_template); 79845895Ssklower 79945895Ssklower if (lcp -> lcd_cps) { 80047271Ssklower m_freem (lcp -> lcd_cps); 80145895Ssklower lcp -> lcd_cps = 0; 80245895Ssklower } 80347271Ssklower if (lcp -> lcd_facilities) { 80447271Ssklower m_freem (lcp -> lcd_facilities); 80547271Ssklower lcp -> lcd_facilities = 0; 80647271Ssklower } 80757024Ssklower if (so = lcp -> lcd_so) 80842140Ssklower sbflush (&so -> so_snd); 80957024Ssklower else 81045895Ssklower sbflush (&lcp -> lcd_sb); 81141593Ssklower } 81241593Ssklower 81341593Ssklower /* 81441593Ssklower * This procedure handles all local protocol procedure errors. 81541593Ssklower */ 81641593Ssklower 81745895Ssklower pk_procerror (error, lcp, errstr, diagnostic) 81841593Ssklower register struct pklcd *lcp; 81941593Ssklower char *errstr; 82041593Ssklower { 82141593Ssklower 82241593Ssklower pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr); 82341593Ssklower 82441593Ssklower switch (error) { 82541593Ssklower case CLEAR: 82645297Ssklower if (lcp -> lcd_so) { 82745297Ssklower lcp -> lcd_so -> so_error = ECONNABORTED; 82845297Ssklower soisdisconnecting (lcp -> lcd_so); 82941593Ssklower } 83045895Ssklower pk_clear (lcp, diagnostic, 1); 83141593Ssklower break; 83241593Ssklower 83341593Ssklower case RESET: 83445895Ssklower pk_reset (lcp, diagnostic); 83541593Ssklower } 83641593Ssklower } 83741593Ssklower 83841593Ssklower /* 83941593Ssklower * This procedure is called during the DATA TRANSFER state to check 84041593Ssklower * and process the P(R) values received in the DATA, RR OR RNR 84141593Ssklower * packets. 84241593Ssklower */ 84341593Ssklower 84441593Ssklower pk_ack (lcp, pr) 84541593Ssklower struct pklcd *lcp; 84641593Ssklower unsigned pr; 84741593Ssklower { 84841593Ssklower register struct socket *so = lcp -> lcd_so; 84941593Ssklower 85041593Ssklower if (lcp -> lcd_output_window == pr) 85141593Ssklower return (PACKET_OK); 85241593Ssklower if (lcp -> lcd_output_window < lcp -> lcd_ssn) { 85341593Ssklower if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) { 85445895Ssklower pk_procerror (RESET, lcp, 85545895Ssklower "p(r) flow control error", 2); 85641593Ssklower return (ERROR_PACKET); 85741593Ssklower } 85841593Ssklower } 85941593Ssklower else { 86041593Ssklower if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) { 86145895Ssklower pk_procerror (RESET, lcp, 86247271Ssklower "p(r) flow control error #2", 2); 86341593Ssklower return (ERROR_PACKET); 86441593Ssklower } 86541593Ssklower } 86641593Ssklower 86741593Ssklower lcp -> lcd_output_window = pr; /* Rotate window. */ 86841593Ssklower if (lcp -> lcd_window_condition == TRUE) 86941593Ssklower lcp -> lcd_window_condition = FALSE; 87041593Ssklower 87157024Ssklower if (so && ((so -> so_snd.sb_flags & SB_WAIT) || 87257024Ssklower (so -> so_snd.sb_flags & SB_NOTIFY))) 87341593Ssklower sowwakeup (so); 87441593Ssklower 87541593Ssklower return (PACKET_OK); 87641593Ssklower } 87741593Ssklower 87841593Ssklower /* 87941593Ssklower * This procedure decodes the X.25 level 3 packet returning a 88041593Ssklower * code to be used in switchs or arrays. 88141593Ssklower */ 88241593Ssklower 88341593Ssklower pk_decode (xp) 88441593Ssklower register struct x25_packet *xp; 88541593Ssklower { 88641593Ssklower register int type; 88741593Ssklower 88857024Ssklower if (X25GBITS(xp -> bits, fmt_identifier) != 1) 88941593Ssklower return (INVALID_PACKET); 89045895Ssklower #ifdef ancient_history 89141593Ssklower /* 89241593Ssklower * Make sure that the logical channel group number is 0. 89341593Ssklower * This restriction may be removed at some later date. 89441593Ssklower */ 89541593Ssklower if (xp -> lc_group_number != 0) 89641593Ssklower return (INVALID_PACKET); 89745895Ssklower #endif 89841593Ssklower /* 89941593Ssklower * Test for data packet first. 90041593Ssklower */ 90141593Ssklower if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR)) 90241593Ssklower return (DATA); 90341593Ssklower 90441593Ssklower /* 90541593Ssklower * Test if flow control packet (RR or RNR). 90641593Ssklower */ 90741593Ssklower if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR)) 90847271Ssklower switch (xp -> packet_type & 0x1f) { 90947271Ssklower case X25_RR: 91041593Ssklower return (RR); 91147271Ssklower case X25_RNR: 91241593Ssklower return (RNR); 91347271Ssklower case X25_REJECT: 91447271Ssklower return (REJECT); 91547271Ssklower } 91641593Ssklower 91741593Ssklower /* 91841593Ssklower * Determine the rest of the packet types. 91941593Ssklower */ 92041593Ssklower switch (xp -> packet_type) { 92141593Ssklower case X25_CALL: 92241593Ssklower type = CALL; 92341593Ssklower break; 92441593Ssklower 92541593Ssklower case X25_CALL_ACCEPTED: 92641593Ssklower type = CALL_ACCEPTED; 92741593Ssklower break; 92841593Ssklower 92941593Ssklower case X25_CLEAR: 93041593Ssklower type = CLEAR; 93141593Ssklower break; 93241593Ssklower 93341593Ssklower case X25_CLEAR_CONFIRM: 93441593Ssklower type = CLEAR_CONF; 93541593Ssklower break; 93641593Ssklower 93741593Ssklower case X25_INTERRUPT: 93841593Ssklower type = INTERRUPT; 93941593Ssklower break; 94041593Ssklower 94141593Ssklower case X25_INTERRUPT_CONFIRM: 94241593Ssklower type = INTERRUPT_CONF; 94341593Ssklower break; 94441593Ssklower 94541593Ssklower case X25_RESET: 94641593Ssklower type = RESET; 94741593Ssklower break; 94841593Ssklower 94941593Ssklower case X25_RESET_CONFIRM: 95041593Ssklower type = RESET_CONF; 95141593Ssklower break; 95241593Ssklower 95341593Ssklower case X25_RESTART: 95441593Ssklower type = RESTART; 95541593Ssklower break; 95641593Ssklower 95741593Ssklower case X25_RESTART_CONFIRM: 95841593Ssklower type = RESTART_CONF; 95941593Ssklower break; 96041593Ssklower 96147271Ssklower case X25_DIAGNOSTIC: 96248873Ssklower type = DIAG_TYPE; 96347271Ssklower break; 96447271Ssklower 96541593Ssklower default: 96641593Ssklower type = INVALID_PACKET; 96741593Ssklower } 96841593Ssklower return (type); 96941593Ssklower } 97041593Ssklower 97141593Ssklower /* 97241593Ssklower * A restart packet has been received. Print out the reason 97341593Ssklower * for the restart. 97441593Ssklower */ 97541593Ssklower 97641593Ssklower pk_restartcause (pkp, xp) 97741593Ssklower struct pkcb *pkp; 97841593Ssklower register struct x25_packet *xp; 97941593Ssklower { 98041593Ssklower register struct x25config *xcp = pkp -> pk_xcp; 98145574Ssklower register int lcn = LCN(xp); 98241593Ssklower 98341593Ssklower switch (xp -> packet_data) { 98441593Ssklower case X25_RESTART_LOCAL_PROCEDURE_ERROR: 98541593Ssklower pk_message (lcn, xcp, "restart: local procedure error"); 98641593Ssklower break; 98741593Ssklower 98841593Ssklower case X25_RESTART_NETWORK_CONGESTION: 98941593Ssklower pk_message (lcn, xcp, "restart: network congestion"); 99041593Ssklower break; 99141593Ssklower 99241593Ssklower case X25_RESTART_NETWORK_OPERATIONAL: 99341593Ssklower pk_message (lcn, xcp, "restart: network operational"); 99441593Ssklower break; 99541593Ssklower 99641593Ssklower default: 99741593Ssklower pk_message (lcn, xcp, "restart: unknown cause"); 99841593Ssklower } 99941593Ssklower } 100041593Ssklower 100141593Ssklower #define MAXRESETCAUSE 7 100241593Ssklower 100341593Ssklower int Reset_cause[] = { 100441593Ssklower EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG 100541593Ssklower }; 100641593Ssklower 100741593Ssklower /* 100841593Ssklower * A reset packet has arrived. Return the cause to the user. 100941593Ssklower */ 101041593Ssklower 101141593Ssklower pk_resetcause (pkp, xp) 101241593Ssklower struct pkcb *pkp; 101341593Ssklower register struct x25_packet *xp; 101441593Ssklower { 101545297Ssklower register struct pklcd *lcp = 101645574Ssklower pkp -> pk_chan[LCN(xp)]; 101741593Ssklower register int code = xp -> packet_data; 101841593Ssklower 101941593Ssklower if (code > MAXRESETCAUSE) 102041593Ssklower code = 7; /* EXRNCG */ 102141593Ssklower 102247271Ssklower pk_message(LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x", 102347271Ssklower xp -> packet_data, 4[(u_char *)xp]); 102447271Ssklower 102549929Ssklower if (lcp -> lcd_so) 102649929Ssklower lcp -> lcd_so -> so_error = Reset_cause[code]; 102741593Ssklower } 102841593Ssklower 102941593Ssklower #define MAXCLEARCAUSE 25 103041593Ssklower 103141593Ssklower int Clear_cause[] = { 103241593Ssklower EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0, 103341593Ssklower 0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE, 103441593Ssklower 0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC 103541593Ssklower }; 103641593Ssklower 103741593Ssklower /* 103841593Ssklower * A clear packet has arrived. Return the cause to the user. 103941593Ssklower */ 104041593Ssklower 104141593Ssklower pk_clearcause (pkp, xp) 104241593Ssklower struct pkcb *pkp; 104341593Ssklower register struct x25_packet *xp; 104441593Ssklower { 104545297Ssklower register struct pklcd *lcp = 104645574Ssklower pkp -> pk_chan[LCN(xp)]; 104741593Ssklower register int code = xp -> packet_data; 104841593Ssklower 104941593Ssklower if (code > MAXCLEARCAUSE) 105041593Ssklower code = 5; /* EXRNCG */ 105149595Ssklower if (lcp -> lcd_so) 105249595Ssklower lcp -> lcd_so -> so_error = Clear_cause[code]; 105341593Ssklower } 105441593Ssklower 105541593Ssklower char * 105641593Ssklower format_ntn (xcp) 105741593Ssklower register struct x25config *xcp; 105841593Ssklower { 105941593Ssklower 106045165Ssklower return (xcp -> xc_addr.x25_addr); 106141593Ssklower } 106241593Ssklower 106341593Ssklower /* VARARGS1 */ 106441593Ssklower pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6) 106541593Ssklower struct x25config *xcp; 106641593Ssklower char *fmt; 106741593Ssklower { 106841593Ssklower 106941593Ssklower if (lcn) 107057024Ssklower if (!PQEMPTY) 107141593Ssklower printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn); 107241593Ssklower else 107341593Ssklower printf ("X.25: lcn %d: ", lcn); 107441593Ssklower else 107557024Ssklower if (!PQEMPTY) 107641593Ssklower printf ("X.25(%s): ", format_ntn (xcp)); 107741593Ssklower else 107841593Ssklower printf ("X.25: "); 107941593Ssklower 108041593Ssklower printf (fmt, a1, a2, a3, a4, a5, a6); 108141593Ssklower printf ("\n"); 108241593Ssklower } 108345297Ssklower 108447271Ssklower pk_fragment (lcp, m0, qbit, mbit, wait) 108545297Ssklower struct mbuf *m0; 108645297Ssklower register struct pklcd *lcp; 108745297Ssklower { 108845297Ssklower register struct mbuf *m = m0; 108945297Ssklower register struct x25_packet *xp; 109045297Ssklower register struct sockbuf *sb; 109147271Ssklower struct mbuf *head = 0, *next, **mp = &head, *m_split (); 109245297Ssklower int totlen, psize = 1 << (lcp -> lcd_packetsize); 109345297Ssklower 109445297Ssklower if (m == 0) 109549595Ssklower return 0; 109657024Ssklower if (m -> m_flags & M_PKTHDR == 0) 109747271Ssklower panic ("pk_fragment"); 109845297Ssklower totlen = m -> m_pkthdr.len; 109945574Ssklower m -> m_act = 0; 110045297Ssklower sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb; 110145297Ssklower do { 110245297Ssklower if (totlen > psize) { 110347271Ssklower if ((next = m_split (m, psize, wait)) == 0) 110445297Ssklower goto abort; 110545297Ssklower totlen -= psize; 110645574Ssklower } else 110745574Ssklower next = 0; 110845297Ssklower M_PREPEND(m, PKHEADERLN, wait); 110945297Ssklower if (m == 0) 111045297Ssklower goto abort; 111145574Ssklower *mp = m; 111245574Ssklower mp = & m -> m_act; 111345574Ssklower *mp = 0; 111447271Ssklower xp = mtod (m, struct x25_packet *); 111545297Ssklower 0[(char *)xp] = 0; 111645297Ssklower if (qbit) 111757024Ssklower X25SBITS(xp -> bits, q_bit, 1); 111845574Ssklower if (lcp -> lcd_flags & X25_DBIT) 111957024Ssklower X25SBITS(xp -> bits, d_bit, 1); 112057024Ssklower X25SBITS(xp -> bits, fmt_identifier, 1); 112145297Ssklower xp -> packet_type = X25_DATA; 112245574Ssklower SET_LCN(xp, lcp -> lcd_lcn); 112345574Ssklower if (next || (mbit && (totlen == psize || 112445574Ssklower (lcp -> lcd_flags & X25_DBIT)))) 112557024Ssklower SMBIT(xp, 1); 112645297Ssklower } while (m = next); 112745574Ssklower for (m = head; m; m = next) { 112845297Ssklower next = m -> m_act; 112945297Ssklower m -> m_act = 0; 113047271Ssklower sbappendrecord (sb, m); 113145297Ssklower } 113245297Ssklower return 0; 113345297Ssklower abort: 113445574Ssklower if (wait) 113547271Ssklower panic ("pk_fragment null mbuf after wait"); 113645574Ssklower if (next) 113747271Ssklower m_freem (next); 113845574Ssklower for (m = head; m; m = next) { 113945297Ssklower next = m -> m_act; 114047271Ssklower m_freem (m); 114145297Ssklower } 114245297Ssklower return ENOBUFS; 114345297Ssklower } 1144