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*45574Ssklower * @(#)pk_subr.c 7.8 (Berkeley) 11/13/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; 6143361Ssklower } else 6245165Ssklower sbreserve (&lcp -> lcd_sb, pk_sendspace); 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 15045297Ssklower MGETHDR (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 */ 16045297Ssklower m -> m_data += max_linkhdr; 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 169*45574Ssklower SET_LCN(xp, 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. */ 19145297Ssklower if (pkp -> pk_chan == 0) 19242140Ssklower return; 19345297Ssklower for (i = 1; i <= pkp -> pk_maxlcn; ++i) 19445297Ssklower if ((lcp = pkp -> pk_chan[i]) != NULL) { 19541593Ssklower if (lcp -> lcd_so) 19645297Ssklower lcp -> lcd_so -> so_error = ENETRESET; 19741593Ssklower pk_close (lcp); 19841593Ssklower } 19941593Ssklower 20041593Ssklower if (restart_cause < 0) 20141593Ssklower return; 20241593Ssklower 20345297Ssklower pkp -> pk_state = DTE_SENT_RESTART; 20445297Ssklower 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); 26445165Ssklower if (pkp -> pk_xcp -> xc_addr.x25_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, 27045297Ssklower 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; 30545165Ssklower sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_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); 32645297Ssklower if (lcp -> lcd_pkp == 0) 32745297Ssklower 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; 33645165Ssklower if (sa -> x25_net == pkp -> pk_xcp -> xc_addr.x25_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; 34545297Ssklower lcp -> lcd_ceaddr = & lcp -> lcd_faddr; 34641593Ssklower pk_assoc (pkp, lcp, lcp -> lcd_ceaddr); 34745165Ssklower if (lcp -> lcd_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 369*45574Ssklower if (lcp -> lcd_flags & X25_DBIT) 370*45574Ssklower lcp -> lcd_template -> d_bit = 1; 37141593Ssklower a = (struct x25_calladdr *) &lcp -> lcd_template -> packet_data; 37245165Ssklower a -> calling_addrlen = strlen (xcp -> xc_addr.x25_addr); 37341593Ssklower a -> called_addrlen = strlen (sa -> x25_addr); 37441593Ssklower cp = (octet *) a -> address_field; 37541593Ssklower to_bcd (&cp, (int)a -> called_addrlen, sa -> x25_addr, &posn); 37645165Ssklower to_bcd (&cp, (int)a -> calling_addrlen, xcp -> xc_addr.x25_addr, &posn); 37741593Ssklower if (posn & 0x01) 37841593Ssklower *cp++ &= 0xf0; 37941593Ssklower 38041593Ssklower build_facilities (&cp, sa, (int)xcp -> xc_type); 38141593Ssklower 38241593Ssklower bcopy (sa -> x25_udata, (caddr_t)cp, (unsigned)sa -> x25_udlen); 38341593Ssklower cp += sa -> x25_udlen; 38441593Ssklower 38541593Ssklower m -> m_len += cp - (octet *) a; 38641593Ssklower 38741593Ssklower #ifdef ANDREW 38841593Ssklower printf ("call: "); 38945297Ssklower for (cp = mtod (m, octet *), posn = 0; posn < m -> m_len; ++posn) 39041593Ssklower printf ("%x ", *cp++); 39141593Ssklower printf ("\n"); 39241593Ssklower #endif 39341593Ssklower } 39441593Ssklower 39541593Ssklower build_facilities (cp, sa, type) 39641593Ssklower register octet **cp; 39741593Ssklower struct sockaddr_x25 *sa; 39841593Ssklower { 39941593Ssklower register octet *fcp; 40041593Ssklower register int revcharge; 40141593Ssklower 40241593Ssklower fcp = *cp + 1; 40341593Ssklower revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0; 40441593Ssklower /* 40541593Ssklower * This is specific to Datapac X.25(1976) DTEs. International 40641593Ssklower * calls must have the "hi priority" bit on. 40741593Ssklower */ 40841593Ssklower if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128) 40941593Ssklower revcharge |= 02; 41041593Ssklower if (revcharge) { 41141593Ssklower *fcp++ = FACILITIES_REVERSE_CHARGE; 41241593Ssklower *fcp++ = revcharge; 41341593Ssklower } 41441593Ssklower switch (type) { 41541593Ssklower case X25_1980: 41641593Ssklower case X25_1984: 41741593Ssklower *fcp++ = FACILITIES_PACKETSIZE; 41841593Ssklower *fcp++ = sa -> x25_opts.op_psize; 41941593Ssklower *fcp++ = sa -> x25_opts.op_psize; 42041593Ssklower 42141593Ssklower *fcp++ = FACILITIES_WINDOWSIZE; 42241593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 42341593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 42441593Ssklower } 42541593Ssklower **cp = fcp - *cp - 1; 42641593Ssklower *cp = fcp; 42741593Ssklower } 42841593Ssklower 42941593Ssklower to_bcd (a, len, x, posn) 43041593Ssklower register octet **a; 43141593Ssklower register char *x; 43241593Ssklower register int len; 43341593Ssklower register unsigned *posn; 43441593Ssklower { 43541593Ssklower while (--len >= 0) 43641593Ssklower if ((*posn)++ & 0x01) 43741593Ssklower *(*a)++ |= *x++ & 0x0F; 43841593Ssklower else 43941593Ssklower **a = *x++ << 4; 44041593Ssklower } 44141593Ssklower 44241593Ssklower /* 44341593Ssklower * This routine gets the first available logical channel number. The 44441593Ssklower * search is from the highest number to lowest number (DTE). 44541593Ssklower */ 44641593Ssklower 44741593Ssklower pk_getlcn (pkp) 44841593Ssklower register struct pkcb *pkp; 44941593Ssklower { 45041593Ssklower register int i; 45141593Ssklower 45245297Ssklower if (pkp -> pk_chan == 0) 45342140Ssklower return (0); 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; 52342140Ssklower if (so = lcp -> lcd_so) { 52442140Ssklower so -> so_error = ECONNRESET; 52542140Ssklower sbflush (&so -> so_rcv); 52642140Ssklower sbflush (&so -> so_snd); 52742140Ssklower } 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: 54945297Ssklower if (lcp -> lcd_so) { 55045297Ssklower lcp -> lcd_so -> so_error = ECONNABORTED; 55145297Ssklower 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 59242140Ssklower if (so && ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel)) 59341593Ssklower sowwakeup (so); 59443361Ssklower if (lcp -> lcd_upper) 59543361Ssklower (*lcp -> lcd_upper)(lcp, 0); 59641593Ssklower 59741593Ssklower return (PACKET_OK); 59841593Ssklower } 59941593Ssklower 60041593Ssklower /* 60141593Ssklower * This procedure decodes the X.25 level 3 packet returning a 60241593Ssklower * code to be used in switchs or arrays. 60341593Ssklower */ 60441593Ssklower 60541593Ssklower pk_decode (xp) 60641593Ssklower register struct x25_packet *xp; 60741593Ssklower { 60841593Ssklower register int type; 60941593Ssklower 61041593Ssklower if (xp -> fmt_identifier != 1) 61141593Ssklower return (INVALID_PACKET); 61241593Ssklower 61341593Ssklower /* 61441593Ssklower * Make sure that the logical channel group number is 0. 61541593Ssklower * This restriction may be removed at some later date. 61641593Ssklower */ 61741593Ssklower if (xp -> lc_group_number != 0) 61841593Ssklower return (INVALID_PACKET); 61941593Ssklower 62041593Ssklower /* 62141593Ssklower * Test for data packet first. 62241593Ssklower */ 62341593Ssklower if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR)) 62441593Ssklower return (DATA); 62541593Ssklower 62641593Ssklower /* 62741593Ssklower * Test if flow control packet (RR or RNR). 62841593Ssklower */ 62941593Ssklower if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR)) 63041593Ssklower if (!(xp -> packet_type & RR_PACKET_DESIGNATOR)) 63141593Ssklower return (RR); 63241593Ssklower else 63341593Ssklower return (RNR); 63441593Ssklower 63541593Ssklower /* 63641593Ssklower * Determine the rest of the packet types. 63741593Ssklower */ 63841593Ssklower switch (xp -> packet_type) { 63941593Ssklower case X25_CALL: 64041593Ssklower type = CALL; 64141593Ssklower break; 64241593Ssklower 64341593Ssklower case X25_CALL_ACCEPTED: 64441593Ssklower type = CALL_ACCEPTED; 64541593Ssklower break; 64641593Ssklower 64741593Ssklower case X25_CLEAR: 64841593Ssklower type = CLEAR; 64941593Ssklower break; 65041593Ssklower 65141593Ssklower case X25_CLEAR_CONFIRM: 65241593Ssklower type = CLEAR_CONF; 65341593Ssklower break; 65441593Ssklower 65541593Ssklower case X25_INTERRUPT: 65641593Ssklower type = INTERRUPT; 65741593Ssklower break; 65841593Ssklower 65941593Ssklower case X25_INTERRUPT_CONFIRM: 66041593Ssklower type = INTERRUPT_CONF; 66141593Ssklower break; 66241593Ssklower 66341593Ssklower case X25_RESET: 66441593Ssklower type = RESET; 66541593Ssklower break; 66641593Ssklower 66741593Ssklower case X25_RESET_CONFIRM: 66841593Ssklower type = RESET_CONF; 66941593Ssklower break; 67041593Ssklower 67141593Ssklower case X25_RESTART: 67241593Ssklower type = RESTART; 67341593Ssklower break; 67441593Ssklower 67541593Ssklower case X25_RESTART_CONFIRM: 67641593Ssklower type = RESTART_CONF; 67741593Ssklower break; 67841593Ssklower 67941593Ssklower default: 68041593Ssklower type = INVALID_PACKET; 68141593Ssklower } 68241593Ssklower return (type); 68341593Ssklower } 68441593Ssklower 68541593Ssklower /* 68641593Ssklower * A restart packet has been received. Print out the reason 68741593Ssklower * for the restart. 68841593Ssklower */ 68941593Ssklower 69041593Ssklower pk_restartcause (pkp, xp) 69141593Ssklower struct pkcb *pkp; 69241593Ssklower register struct x25_packet *xp; 69341593Ssklower { 69441593Ssklower register struct x25config *xcp = pkp -> pk_xcp; 695*45574Ssklower register int lcn = LCN(xp); 69641593Ssklower 69741593Ssklower switch (xp -> packet_data) { 69841593Ssklower case X25_RESTART_LOCAL_PROCEDURE_ERROR: 69941593Ssklower pk_message (lcn, xcp, "restart: local procedure error"); 70041593Ssklower break; 70141593Ssklower 70241593Ssklower case X25_RESTART_NETWORK_CONGESTION: 70341593Ssklower pk_message (lcn, xcp, "restart: network congestion"); 70441593Ssklower break; 70541593Ssklower 70641593Ssklower case X25_RESTART_NETWORK_OPERATIONAL: 70741593Ssklower pk_message (lcn, xcp, "restart: network operational"); 70841593Ssklower break; 70941593Ssklower 71041593Ssklower default: 71141593Ssklower pk_message (lcn, xcp, "restart: unknown cause"); 71241593Ssklower } 71341593Ssklower } 71441593Ssklower 71541593Ssklower #define MAXRESETCAUSE 7 71641593Ssklower 71741593Ssklower int Reset_cause[] = { 71841593Ssklower EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG 71941593Ssklower }; 72041593Ssklower 72141593Ssklower /* 72241593Ssklower * A reset packet has arrived. Return the cause to the user. 72341593Ssklower */ 72441593Ssklower 72541593Ssklower pk_resetcause (pkp, xp) 72641593Ssklower struct pkcb *pkp; 72741593Ssklower register struct x25_packet *xp; 72841593Ssklower { 72945297Ssklower register struct pklcd *lcp = 730*45574Ssklower pkp -> pk_chan[LCN(xp)]; 73141593Ssklower register int code = xp -> packet_data; 73241593Ssklower 73341593Ssklower if (code > MAXRESETCAUSE) 73441593Ssklower code = 7; /* EXRNCG */ 73541593Ssklower 73645297Ssklower 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 { 75545297Ssklower register struct pklcd *lcp = 756*45574Ssklower pkp -> pk_chan[LCN(xp)]; 75741593Ssklower register int code = xp -> packet_data; 75841593Ssklower 75941593Ssklower if (code > MAXCLEARCAUSE) 76041593Ssklower code = 5; /* EXRNCG */ 76145297Ssklower lcp -> lcd_so -> so_error = Clear_cause[code]; 76241593Ssklower } 76341593Ssklower 76441593Ssklower char * 76541593Ssklower format_ntn (xcp) 76641593Ssklower register struct x25config *xcp; 76741593Ssklower { 76841593Ssklower 76945165Ssklower return (xcp -> xc_addr.x25_addr); 77041593Ssklower } 77141593Ssklower 77241593Ssklower /* VARARGS1 */ 77341593Ssklower pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6) 77441593Ssklower struct x25config *xcp; 77541593Ssklower char *fmt; 77641593Ssklower { 77741593Ssklower 77841593Ssklower if (lcn) 77941593Ssklower if (pkcbhead -> pk_next) 78041593Ssklower printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn); 78141593Ssklower else 78241593Ssklower printf ("X.25: lcn %d: ", lcn); 78341593Ssklower else 78441593Ssklower if (pkcbhead -> pk_next) 78541593Ssklower printf ("X.25(%s): ", format_ntn (xcp)); 78641593Ssklower else 78741593Ssklower printf ("X.25: "); 78841593Ssklower 78941593Ssklower printf (fmt, a1, a2, a3, a4, a5, a6); 79041593Ssklower printf ("\n"); 79141593Ssklower } 79245297Ssklower 79345297Ssklower pk_ifattach(ia, lloutput, llnext) 79445297Ssklower register struct x25_ifaddr *ia; 79545297Ssklower int (*lloutput)(); 79645297Ssklower caddr_t llnext; 79745297Ssklower { 79845297Ssklower /* this is here because you can't include both pk_var and hd_var */ 79945297Ssklower /* this will probably be replace by a streams gluing mechanism */ 80045297Ssklower ia -> ia_pkcb.pk_lloutput = lloutput; 80145297Ssklower ia -> ia_pkcb.pk_llnext = llnext; 80245297Ssklower } 80345297Ssklower 80445297Ssklower pk_fragment(lcp, m0, qbit, mbit, wait) 80545297Ssklower struct mbuf *m0; 80645297Ssklower register struct pklcd *lcp; 80745297Ssklower { 80845297Ssklower register struct mbuf *m = m0; 80945297Ssklower register struct x25_packet *xp; 81045297Ssklower register struct sockbuf *sb; 811*45574Ssklower struct mbuf *head = 0, *next, **mp = &head; 81245297Ssklower int totlen, psize = 1 << (lcp -> lcd_packetsize); 81345297Ssklower 81445297Ssklower if (m == 0) 81545297Ssklower return; 81645297Ssklower if (m->m_flags & M_PKTHDR == 0) 81745297Ssklower panic("pk_fragment"); 81845297Ssklower totlen = m -> m_pkthdr.len; 819*45574Ssklower m -> m_act = 0; 82045297Ssklower sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb; 82145297Ssklower do { 82245297Ssklower if (totlen > psize) { 82345297Ssklower next = m; 82445297Ssklower m = m_copym(m, 0, psize, wait); 82545297Ssklower if (m == 0) 82645297Ssklower goto abort; 82745297Ssklower m_adj(next, psize); 82845297Ssklower totlen -= psize; 829*45574Ssklower } else 830*45574Ssklower next = 0; 83145297Ssklower M_PREPEND(m, PKHEADERLN, wait); 83245297Ssklower if (m == 0) 83345297Ssklower goto abort; 834*45574Ssklower *mp = m; 835*45574Ssklower mp = & m -> m_act; 836*45574Ssklower *mp = 0; 83745297Ssklower xp = mtod(m, struct x25_packet *); 83845297Ssklower 0[(char *)xp] = 0; 83945297Ssklower if (qbit) 840*45574Ssklower xp -> q_bit = 1; 841*45574Ssklower if (lcp -> lcd_flags & X25_DBIT) 842*45574Ssklower xp -> d_bit = 1; 84345297Ssklower xp -> fmt_identifier = 1; 84445297Ssklower xp -> packet_type = X25_DATA; 845*45574Ssklower SET_LCN(xp, lcp -> lcd_lcn); 846*45574Ssklower if (next || (mbit && (totlen == psize || 847*45574Ssklower (lcp -> lcd_flags & X25_DBIT)))) 84845297Ssklower MBIT(xp) = 1; 84945297Ssklower } while (m = next); 850*45574Ssklower for (m = head; m; m = next) { 85145297Ssklower next = m -> m_act; 85245297Ssklower m -> m_act = 0; 85345297Ssklower sbappendrecord(sb, m); 85445297Ssklower } 85545297Ssklower return 0; 85645297Ssklower abort: 857*45574Ssklower if (wait) 858*45574Ssklower panic("pk_fragment null mbuf after wait"); 859*45574Ssklower if (next) 860*45574Ssklower m_freem(next); 861*45574Ssklower for (m = head; m; m = next) { 86245297Ssklower next = m -> m_act; 86345297Ssklower m_freem(m); 86445297Ssklower } 86545297Ssklower return ENOBUFS; 86645297Ssklower } 867*45574Ssklower 868*45574Ssklower struct mbuf * 869*45574Ssklower m_split(m0, len0, wait) 870*45574Ssklower register struct mbuf *m0; 871*45574Ssklower int len0; 872*45574Ssklower { 873*45574Ssklower register struct mbuf *m, *n; 874*45574Ssklower unsigned len = len0; 875*45574Ssklower 876*45574Ssklower for (m = m0; m && len > m -> m_len; m = m -> m_next) 877*45574Ssklower len -= m -> m_len; 878*45574Ssklower if (m == 0) 879*45574Ssklower return (0); 880*45574Ssklower if (m0 -> m_flags & M_PKTHDR) { 881*45574Ssklower MGETHDR(n, wait, m0 -> m_type); 882*45574Ssklower if (n == 0) 883*45574Ssklower return (0); 884*45574Ssklower n -> m_pkthdr.rcvif = m0 -> m_pkthdr.rcvif; 885*45574Ssklower n -> m_pkthdr.len = m0 -> m_pkthdr.len - len0; 886*45574Ssklower m0 -> m_pkthdr.len = len0; 887*45574Ssklower if (m -> m_flags & M_EXT) 888*45574Ssklower goto extpacket; 889*45574Ssklower if (len > MHLEN) { 890*45574Ssklower /* m can't be the lead packet */ 891*45574Ssklower MH_ALIGN(n, 0); 892*45574Ssklower n -> m_next = m_split(m, len, wait); 893*45574Ssklower if (n -> m_next == 0) { 894*45574Ssklower (void) m_free(n); 895*45574Ssklower return (0); 896*45574Ssklower } else 897*45574Ssklower return (n); 898*45574Ssklower } else 899*45574Ssklower MH_ALIGN(n, len); 900*45574Ssklower } else if (len == m -> m_len) { 901*45574Ssklower n = m -> m_next; 902*45574Ssklower m -> m_next = 0; 903*45574Ssklower return (n); 904*45574Ssklower } 905*45574Ssklower extpacket: 906*45574Ssklower len = m -> m_len - len; /* remainder to be copied */ 907*45574Ssklower m -> m_len -= len; /* now equals original len */ 908*45574Ssklower if (m -> m>flags & M_EXT) { 909*45574Ssklower n -> m_flags |= M_EXT; 910*45574Ssklower n -> m_ext = m -> m_ext; 911*45574Ssklower mclrefcnt[mtocl(m -> m_ext.ext_buf)]++; 912*45574Ssklower n -> m_data = m -> m_data + m -> m_len; 913*45574Ssklower } else { 914*45574Ssklower MGET(n, wait, m -> m_type); 915*45574Ssklower if (n == 0) { 916*45574Ssklower m -> m_len += len; 917*45574Ssklower return (0); 918*45574Ssklower } 919*45574Ssklower M_ALIGN(n, len); 920*45574Ssklower bcopy(mtod(m, caddr_t), mtod(n, caddr_t), len); 921*45574Ssklower } 922*45574Ssklower n -> m_len = len; 923*45574Ssklower n -> m_next = m -> m_next; 924*45574Ssklower m -> m_next = 0; 925*45574Ssklower return (n); 926*45574Ssklower } 927