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*45895Ssklower * @(#)pk_subr.c 7.9 (Berkeley) 01/09/91 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 /* 3641593Ssklower * Attach X.25 protocol to socket, allocate logical channel descripter 3741593Ssklower * and buffer space, and enter LISTEN state if we are to accept 3841593Ssklower * IN-COMMING CALL packets. 3941593Ssklower * 4041593Ssklower */ 4141593Ssklower 4242277Ssklower struct pklcd * 4341593Ssklower pk_attach (so) 4441593Ssklower struct socket *so; 4541593Ssklower { 4641593Ssklower register struct pklcd *lcp; 4742277Ssklower register int error = ENOBUFS; 4841593Ssklower 4942277Ssklower MALLOC(lcp, struct pklcd *, sizeof(*lcp), M_PCB, M_NOWAIT); 5042277Ssklower if (lcp) { 5142277Ssklower bzero((caddr_t)lcp, sizeof(*lcp)); 5242277Ssklower if (so) { 5342277Ssklower error = soreserve (so, pk_sendspace, pk_recvspace); 5442277Ssklower lcp -> lcd_so = so; 5542277Ssklower if (so -> so_options & SO_ACCEPTCONN) 5642277Ssklower lcp -> lcd_state = LISTEN; 5742277Ssklower else 5842277Ssklower lcp -> lcd_state = READY; 5943361Ssklower } else 6045165Ssklower sbreserve (&lcp -> lcd_sb, pk_sendspace); 6142277Ssklower } 6242277Ssklower if (so) { 6342277Ssklower so -> so_pcb = (caddr_t) lcp; 6442277Ssklower so -> so_error = error; 6542277Ssklower } 6642277Ssklower return (lcp); 6741593Ssklower } 6841593Ssklower 6941593Ssklower /* 7041593Ssklower * Disconnect X.25 protocol from socket. 7141593Ssklower */ 7241593Ssklower 7341593Ssklower pk_disconnect (lcp) 7441593Ssklower register struct pklcd *lcp; 7541593Ssklower { 7641593Ssklower register struct socket *so = lcp -> lcd_so; 7741593Ssklower register struct pklcd *l, *p; 7841593Ssklower 7941593Ssklower switch (lcp -> lcd_state) { 8041593Ssklower case LISTEN: 8141593Ssklower for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen); 8241593Ssklower if (p == 0) { 8341593Ssklower if (l != 0) 8441593Ssklower pk_listenhead = l -> lcd_listen; 8541593Ssklower } 8641593Ssklower else 8741593Ssklower if (l != 0) 8841593Ssklower p -> lcd_listen = l -> lcd_listen; 8941593Ssklower pk_close (lcp); 9041593Ssklower break; 9141593Ssklower 9241593Ssklower case READY: 9341593Ssklower pk_acct (lcp); 9441593Ssklower pk_close (lcp); 9541593Ssklower break; 9641593Ssklower 9741593Ssklower case SENT_CLEAR: 9841593Ssklower case RECEIVED_CLEAR: 9941593Ssklower break; 10041593Ssklower 10141593Ssklower default: 10241593Ssklower pk_acct (lcp); 10342140Ssklower if (so) { 10442140Ssklower soisdisconnecting (so); 10542140Ssklower sbflush (&so -> so_rcv); 10642140Ssklower } 107*45895Ssklower pk_clear (lcp, 241, 0); /* Normal Disconnect */ 10841593Ssklower 10941593Ssklower } 11041593Ssklower } 11141593Ssklower 11241593Ssklower /* 11341593Ssklower * Close an X.25 Logical Channel. Discard all space held by the 11441593Ssklower * connection and internal descriptors. Wake up any sleepers. 11541593Ssklower */ 11641593Ssklower 11741593Ssklower pk_close (lcp) 11841593Ssklower struct pklcd *lcp; 11941593Ssklower { 12041593Ssklower register struct socket *so = lcp -> lcd_so; 12141593Ssklower 12241593Ssklower pk_freelcd (lcp); 12341593Ssklower 12441593Ssklower if (so == NULL) 12541593Ssklower return; 12641593Ssklower 12741593Ssklower so -> so_pcb = 0; 12841593Ssklower soisdisconnected (so); 129*45895Ssklower /* sofree (so); /* gak!!! you can't do that here */ 13041593Ssklower } 13141593Ssklower 13241593Ssklower /* 13341593Ssklower * Create a template to be used to send X.25 packets on a logical 13441593Ssklower * channel. It allocates an mbuf and fills in a skeletal packet 13541593Ssklower * depending on its type. This packet is passed to pk_output where 13641593Ssklower * the remainer of the packet is filled in. 13741593Ssklower */ 13841593Ssklower 139*45895Ssklower struct mbuf * 14041593Ssklower pk_template (lcn, type) 14141593Ssklower int lcn, type; 14241593Ssklower { 14341593Ssklower register struct mbuf *m; 14441593Ssklower register struct x25_packet *xp; 14541593Ssklower 14645297Ssklower MGETHDR (m, M_DONTWAIT, MT_HEADER); 14741593Ssklower if (m == 0) 14841593Ssklower panic ("pk_template"); 14941593Ssklower m -> m_act = 0; 15041593Ssklower 15141593Ssklower /* 15241593Ssklower * Efficiency hack: leave a four byte gap at the beginning 15341593Ssklower * of the packet level header with the hope that this will 15441593Ssklower * be enough room for the link level to insert its header. 15541593Ssklower */ 15645297Ssklower m -> m_data += max_linkhdr; 15741593Ssklower m -> m_len = PKHEADERLN; 15841593Ssklower 15941593Ssklower xp = mtod (m, struct x25_packet *); 16041593Ssklower *(long *)xp = 0; /* ugly, but fast */ 16141593Ssklower /* xp -> q_bit = 0;*/ 16241593Ssklower xp -> fmt_identifier = 1; 16341593Ssklower /* xp -> lc_group_number = 0;*/ 16441593Ssklower 16545574Ssklower SET_LCN(xp, lcn); 16641593Ssklower xp -> packet_type = type; 16741593Ssklower 168*45895Ssklower return (m); 16941593Ssklower } 17041593Ssklower 17141593Ssklower /* 17241593Ssklower * This routine restarts all the virtual circuits. Actually, 17341593Ssklower * the virtual circuits are not "restarted" as such. Instead, 17441593Ssklower * any active switched circuit is simply returned to READY 17541593Ssklower * state. 17641593Ssklower */ 17741593Ssklower 17841593Ssklower pk_restart (pkp, restart_cause) 17941593Ssklower register struct pkcb *pkp; 18041593Ssklower int restart_cause; 18141593Ssklower { 182*45895Ssklower register struct mbuf *m; 18341593Ssklower register struct pklcd *lcp; 18441593Ssklower register int i; 18541593Ssklower 18641593Ssklower /* Restart all logical channels. */ 18745297Ssklower if (pkp -> pk_chan == 0) 18842140Ssklower return; 18945297Ssklower for (i = 1; i <= pkp -> pk_maxlcn; ++i) 19045297Ssklower if ((lcp = pkp -> pk_chan[i]) != NULL) { 191*45895Ssklower if (lcp -> lcd_so) { 19245297Ssklower lcp -> lcd_so -> so_error = ENETRESET; 193*45895Ssklower pk_close (lcp); 194*45895Ssklower } else { 195*45895Ssklower pk_flush (lcp); 196*45895Ssklower lcp -> lcd_state = READY; 197*45895Ssklower if (lcp -> lcd_upper) 198*45895Ssklower lcp -> lcd_upper(lcp, 0); 199*45895Ssklower } 20041593Ssklower } 20141593Ssklower 20241593Ssklower if (restart_cause < 0) 20341593Ssklower return; 20441593Ssklower 20545297Ssklower pkp -> pk_state = DTE_SENT_RESTART; 20645297Ssklower lcp = pkp -> pk_chan[0]; 207*45895Ssklower m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART); 208*45895Ssklower m -> m_len += 2; 209*45895Ssklower mtod(m, struct x25_packet *) -> packet_data = 0; /* DTE only */ 210*45895Ssklower mtod(m, octet *)[4] = restart_cause; 21141593Ssklower pk_output (lcp); 21241593Ssklower } 21341593Ssklower 21441593Ssklower 21541593Ssklower /* 21641593Ssklower * This procedure frees up the Logical Channel Descripter. 21741593Ssklower */ 21841593Ssklower 21941593Ssklower pk_freelcd (lcp) 22041593Ssklower register struct pklcd *lcp; 22141593Ssklower { 22241593Ssklower if (lcp == NULL) 22341593Ssklower return; 22441593Ssklower 22541593Ssklower if (lcp -> lcd_lcn > 0) 22641593Ssklower lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL; 22741593Ssklower 228*45895Ssklower pk_flush(lcp); 22942277Ssklower free((caddr_t)lcp, M_PCB); 23041593Ssklower } 23141593Ssklower 23241593Ssklower 23341593Ssklower /* 23441593Ssklower * Bind a address and protocol value to a socket. The important 23541593Ssklower * part is the protocol value - the first four characters of the 23641593Ssklower * Call User Data field. 23741593Ssklower */ 23841593Ssklower 23941593Ssklower pk_bind (lcp, nam) 24041593Ssklower struct pklcd *lcp; 24141593Ssklower struct mbuf *nam; 24241593Ssklower { 24341593Ssklower register struct pkcb *pkp; 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); 251*45895Ssklower if (pk_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 268*45895Ssklower /* 269*45895Ssklower * For ISO's sake permit default listeners, but only one such . . . 270*45895Ssklower */ 271*45895Ssklower for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) { 272*45895Ssklower register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr; 273*45895Ssklower if ((sa2 -> x25_udlen == sa -> x25_udlen) && 274*45895Ssklower (sa2 -> x25_udlen == 0 || 275*45895Ssklower (bcmp (sa2 -> x25_udata, sa -> x25_udata, 276*45895Ssklower min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0))) 277*45895Ssklower return (EADDRINUSE); 278*45895Ssklower } 27942277Ssklower lcp -> lcd_laddr = *sa; 28042277Ssklower lcp -> lcd_ceaddr = &lcp -> lcd_laddr; 28141593Ssklower return (0); 28241593Ssklower } 28341593Ssklower 28441593Ssklower /* 285*45895Ssklower * Include a bound control block in the list of listeners. 286*45895Ssklower */ 287*45895Ssklower pk_listen (lcp) 288*45895Ssklower register struct pklcd *lcp; 289*45895Ssklower { 290*45895Ssklower register struct pklcd **pp; 291*45895Ssklower 292*45895Ssklower if (lcp -> lcd_ceaddr == 0) 293*45895Ssklower return (EDESTADDRREQ); 294*45895Ssklower 295*45895Ssklower lcp -> lcd_state = LISTEN; 296*45895Ssklower /* 297*45895Ssklower * Add default listener at end, any others at start. 298*45895Ssklower */ 299*45895Ssklower if (lcp -> lcd_ceaddr -> x25_udlen == 0) { 300*45895Ssklower for (pp = &pk_listenhead; *pp; ) 301*45895Ssklower pp = &((*pp) -> lcd_listen); 302*45895Ssklower *pp = lcp; 303*45895Ssklower } else { 304*45895Ssklower lcp -> lcd_listen = pk_listenhead; 305*45895Ssklower pk_listenhead = lcp; 306*45895Ssklower } 307*45895Ssklower return (0); 308*45895Ssklower } 309*45895Ssklower /* 310*45895Ssklower * Include a listening control block for the benefit of other protocols. 311*45895Ssklower */ 312*45895Ssklower pk_protolisten (spi, spilen, callee) 313*45895Ssklower int (*callee)(); 314*45895Ssklower { 315*45895Ssklower register struct pklcd *lcp = pk_attach ((struct socket *)0); 316*45895Ssklower register struct mbuf *nam; 317*45895Ssklower register struct sockaddr_x25 *sa; 318*45895Ssklower int error = ENOBUFS; 319*45895Ssklower 320*45895Ssklower if (lcp) { 321*45895Ssklower if (nam = m_getclr(MT_SONAME, M_DONTWAIT)) { 322*45895Ssklower sa = mtod(nam, struct sockaddr_x25 *); 323*45895Ssklower sa -> x25_family = AF_CCITT; 324*45895Ssklower sa -> x25_len = nam -> m_len = sizeof (*sa); 325*45895Ssklower sa -> x25_udlen = spilen; 326*45895Ssklower sa -> x25_udata[0] = spi; 327*45895Ssklower lcp -> lcd_upper = callee; 328*45895Ssklower lcp -> lcd_flags = X25_MBS_HOLD; 329*45895Ssklower error = pk_bind (lcp, nam) || pk_listen (lcp); 330*45895Ssklower (void) m_free (nam); 331*45895Ssklower } 332*45895Ssklower if (error) 333*45895Ssklower pk_freelcd(lcp); 334*45895Ssklower } 335*45895Ssklower return error; /* Hopefully Zero !*/ 336*45895Ssklower } 337*45895Ssklower 338*45895Ssklower /* 33941593Ssklower * Associate a logical channel descriptor with a network. 34041593Ssklower * Fill in the default network specific parameters and then 34141593Ssklower * set any parameters explicitly specified by the user or 34241593Ssklower * by the remote DTE. 34341593Ssklower */ 34441593Ssklower 34541593Ssklower pk_assoc (pkp, lcp, sa) 34641593Ssklower register struct pkcb *pkp; 34741593Ssklower register struct pklcd *lcp; 34841593Ssklower register struct sockaddr_x25 *sa; 34941593Ssklower { 35041593Ssklower 35141593Ssklower lcp -> lcd_pkp = pkp; 35241593Ssklower lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize; 35341593Ssklower lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize; 35441593Ssklower lcp -> lcd_rsn = MODULUS - 1; 35541593Ssklower pkp -> pk_chan[lcp -> lcd_lcn] = lcp; 35641593Ssklower 35741593Ssklower if (sa -> x25_opts.op_psize) 35841593Ssklower lcp -> lcd_packetsize = sa -> x25_opts.op_psize; 35941593Ssklower else 36041593Ssklower sa -> x25_opts.op_psize = lcp -> lcd_packetsize; 36141593Ssklower if (sa -> x25_opts.op_wsize) 36241593Ssklower lcp -> lcd_windowsize = sa -> x25_opts.op_wsize; 36341593Ssklower else 36441593Ssklower sa -> x25_opts.op_wsize = lcp -> lcd_windowsize; 36545165Ssklower sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net; 36641593Ssklower lcp -> lcd_flags = sa -> x25_opts.op_flags; 36741593Ssklower lcp -> lcd_stime = time.tv_sec; 36841593Ssklower } 36941593Ssklower 370*45895Ssklower pk_connect (lcp, sa) 37141593Ssklower register struct pklcd *lcp; 37242277Ssklower register struct sockaddr_x25 *sa; 37341593Ssklower { 37441593Ssklower register struct pkcb *pkp; 37541593Ssklower 37641593Ssklower if (sa -> x25_addr[0] == '\0') 37741593Ssklower return (EDESTADDRREQ); 37845297Ssklower if (lcp -> lcd_pkp == 0) 37945297Ssklower for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 38041593Ssklower if (pkp == 0) 38141593Ssklower return (ENETUNREACH); 38241593Ssklower /* 38341593Ssklower * use first net configured (last in list 38441593Ssklower * headed by pkcbhead) if net is zero 38541593Ssklower */ 38641593Ssklower if (sa -> x25_net == 0 && pkp -> pk_next == 0) 38741593Ssklower break; 38845165Ssklower if (sa -> x25_net == pkp -> pk_xcp -> xc_addr.x25_net) 38941593Ssklower break; 39041593Ssklower } 39141593Ssklower 39241593Ssklower if (pkp -> pk_state != DTE_READY) 39341593Ssklower return (ENETDOWN); 39441593Ssklower if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0) 39541593Ssklower return (EMFILE); 39642277Ssklower lcp -> lcd_faddr = *sa; 39745297Ssklower lcp -> lcd_ceaddr = & lcp -> lcd_faddr; 39841593Ssklower pk_assoc (pkp, lcp, lcp -> lcd_ceaddr); 39945165Ssklower if (lcp -> lcd_so) 40042140Ssklower soisconnecting (lcp -> lcd_so); 40141593Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL); 40242277Ssklower pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp); 40342277Ssklower return (*pkp -> pk_start)(lcp); 40441593Ssklower } 40541593Ssklower 40641593Ssklower /* 40741593Ssklower * Build the rest of the CALL REQUEST packet. Fill in calling 40841593Ssklower * address, facilities fields and the user data field. 40941593Ssklower */ 41041593Ssklower 41142277Ssklower pk_callrequest (lcp, sa, xcp) 41241593Ssklower struct pklcd *lcp; 41342277Ssklower register struct sockaddr_x25 *sa; 41441593Ssklower register struct x25config *xcp; 41541593Ssklower { 41641593Ssklower register struct x25_calladdr *a; 417*45895Ssklower register struct mbuf *m = lcp -> lcd_template; 418*45895Ssklower register struct x25_packet *xp = mtod(m, struct x25_packet *); 41941593Ssklower unsigned posn = 0; 42041593Ssklower octet *cp; 42141593Ssklower 42245574Ssklower if (lcp -> lcd_flags & X25_DBIT) 423*45895Ssklower xp -> d_bit = 1; 424*45895Ssklower a = (struct x25_calladdr *) &xp -> packet_data; 42545165Ssklower a -> calling_addrlen = strlen (xcp -> xc_addr.x25_addr); 42641593Ssklower a -> called_addrlen = strlen (sa -> x25_addr); 42741593Ssklower cp = (octet *) a -> address_field; 42841593Ssklower to_bcd (&cp, (int)a -> called_addrlen, sa -> x25_addr, &posn); 42945165Ssklower to_bcd (&cp, (int)a -> calling_addrlen, xcp -> xc_addr.x25_addr, &posn); 43041593Ssklower if (posn & 0x01) 43141593Ssklower *cp++ &= 0xf0; 432*45895Ssklower m -> m_len += cp - (octet *) a; 43341593Ssklower 434*45895Ssklower if (lcp -> lcd_facilities) { 435*45895Ssklower m -> m_next = lcp -> lcd_facilities; 436*45895Ssklower lcp -> lcd_facilities = 0; 437*45895Ssklower m -> m_pkthdr.len += m -> m_next -> m_len; 438*45895Ssklower } else 439*45895Ssklower build_facilities (m, sa, (int)xcp -> xc_type); 44041593Ssklower 441*45895Ssklower m_copyback(m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata); 44241593Ssklower #ifdef ANDREW 44341593Ssklower printf ("call: "); 44445297Ssklower for (cp = mtod (m, octet *), posn = 0; posn < m -> m_len; ++posn) 44541593Ssklower printf ("%x ", *cp++); 44641593Ssklower printf ("\n"); 44741593Ssklower #endif 44841593Ssklower } 44941593Ssklower 450*45895Ssklower build_facilities (m, sa, type) 451*45895Ssklower register struct mbuf *m; 45241593Ssklower struct sockaddr_x25 *sa; 45341593Ssklower { 454*45895Ssklower register octet *cp; 45541593Ssklower register octet *fcp; 45641593Ssklower register int revcharge; 45741593Ssklower 458*45895Ssklower cp = mtod(m, octet *) + m -> m_len; 459*45895Ssklower fcp = cp + 1; 46041593Ssklower revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0; 46141593Ssklower /* 46241593Ssklower * This is specific to Datapac X.25(1976) DTEs. International 46341593Ssklower * calls must have the "hi priority" bit on. 46441593Ssklower */ 46541593Ssklower if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128) 46641593Ssklower revcharge |= 02; 46741593Ssklower if (revcharge) { 46841593Ssklower *fcp++ = FACILITIES_REVERSE_CHARGE; 46941593Ssklower *fcp++ = revcharge; 47041593Ssklower } 47141593Ssklower switch (type) { 47241593Ssklower case X25_1980: 47341593Ssklower case X25_1984: 47441593Ssklower *fcp++ = FACILITIES_PACKETSIZE; 47541593Ssklower *fcp++ = sa -> x25_opts.op_psize; 47641593Ssklower *fcp++ = sa -> x25_opts.op_psize; 47741593Ssklower 47841593Ssklower *fcp++ = FACILITIES_WINDOWSIZE; 47941593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 48041593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 48141593Ssklower } 482*45895Ssklower *cp = fcp - cp - 1; 483*45895Ssklower m -> m_pkthdr.len = (m -> m_len += *cp + 1); 48441593Ssklower } 48541593Ssklower 48641593Ssklower to_bcd (a, len, x, posn) 48741593Ssklower register octet **a; 48841593Ssklower register char *x; 48941593Ssklower register int len; 49041593Ssklower register unsigned *posn; 49141593Ssklower { 49241593Ssklower while (--len >= 0) 49341593Ssklower if ((*posn)++ & 0x01) 49441593Ssklower *(*a)++ |= *x++ & 0x0F; 49541593Ssklower else 49641593Ssklower **a = *x++ << 4; 49741593Ssklower } 49841593Ssklower 49941593Ssklower /* 50041593Ssklower * This routine gets the first available logical channel number. The 50141593Ssklower * search is from the highest number to lowest number (DTE). 50241593Ssklower */ 50341593Ssklower 50441593Ssklower pk_getlcn (pkp) 50541593Ssklower register struct pkcb *pkp; 50641593Ssklower { 50741593Ssklower register int i; 50841593Ssklower 50945297Ssklower if (pkp -> pk_chan == 0) 51042140Ssklower return (0); 51141593Ssklower for (i = pkp -> pk_maxlcn; i > 0; --i) 51241593Ssklower if (pkp -> pk_chan[i] == NULL) 51341593Ssklower break; 51441593Ssklower return (i); 51541593Ssklower 51641593Ssklower } 51741593Ssklower 51841593Ssklower /* 51941593Ssklower * This procedure sends a CLEAR request packet. The lc state is 52041593Ssklower * set to "SENT_CLEAR". 52141593Ssklower */ 52241593Ssklower 523*45895Ssklower pk_clear (lcp, diagnostic, abortive) 524*45895Ssklower register struct pklcd *lcp; 52541593Ssklower { 526*45895Ssklower register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR); 52741593Ssklower 528*45895Ssklower m -> m_len += 2; 529*45895Ssklower mtod(m, struct x25_packet *) -> packet_data = 0; 530*45895Ssklower mtod(m, octet *)[4] = diagnostic; 531*45895Ssklower if (lcp -> lcd_facilities) { 532*45895Ssklower m -> m_next = lcp -> lcd_facilities; 533*45895Ssklower m -> m_pkthdr.len += m -> m_next -> m_len; 534*45895Ssklower lcp -> lcd_facilities = 0; 535*45895Ssklower } 536*45895Ssklower if (abortive) 537*45895Ssklower lcp -> lcd_template = m; 538*45895Ssklower else { 539*45895Ssklower struct socket *so = lcp -> lcd_so; 540*45895Ssklower struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb; 541*45895Ssklower sbappendrecord(sb, m); 542*45895Ssklower } 54341593Ssklower pk_output (lcp); 54441593Ssklower 54541593Ssklower } 54641593Ssklower 54741593Ssklower /* 54841593Ssklower * This procedure sends a RESET request packet. It re-intializes 54941593Ssklower * virtual circuit. 55041593Ssklower */ 55141593Ssklower 55241593Ssklower static 553*45895Ssklower pk_reset (lcp, diagnostic) 55441593Ssklower register struct pklcd *lcp; 55541593Ssklower { 556*45895Ssklower register struct mbuf *m; 557*45895Ssklower register struct socket *so = lcp -> lcd_so; 55841593Ssklower 55941593Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 56041593Ssklower return; 56141593Ssklower 562*45895Ssklower if (so) 563*45895Ssklower so -> so_error = ECONNRESET; 56441593Ssklower lcp -> lcd_reset_condition = TRUE; 56541593Ssklower 56641593Ssklower /* Reset all the control variables for the channel. */ 567*45895Ssklower pk_flush (lcp); 56841593Ssklower lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 56941593Ssklower lcp -> lcd_intrconf_pending = FALSE; 57041593Ssklower lcp -> lcd_rsn = MODULUS - 1; 57141593Ssklower lcp -> lcd_ssn = 0; 57241593Ssklower lcp -> lcd_output_window = lcp -> lcd_input_window = 57341593Ssklower lcp -> lcd_last_transmitted_pr = 0; 574*45895Ssklower m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET); 575*45895Ssklower m -> m_len += 2; 576*45895Ssklower mtod(m, struct x25_packet *) -> packet_data = 0; 577*45895Ssklower mtod(m, octet *)[4] = diagnostic; 578*45895Ssklower pk_output (lcp); 579*45895Ssklower 580*45895Ssklower } 581*45895Ssklower 582*45895Ssklower /* 583*45895Ssklower * This procedure frees all data queued for output or delivery on a 584*45895Ssklower * virtual circuit. 585*45895Ssklower */ 586*45895Ssklower 587*45895Ssklower pk_flush (lcp) 588*45895Ssklower register struct pklcd *lcp; 589*45895Ssklower { 590*45895Ssklower register struct socket *so; 591*45895Ssklower 592*45895Ssklower if (lcp -> lcd_template) 593*45895Ssklower m_freem (lcp -> lcd_template); 594*45895Ssklower 595*45895Ssklower if (lcp -> lcd_cps) { 596*45895Ssklower m_freem(lcp -> lcd_cps); 597*45895Ssklower lcp -> lcd_cps = 0; 598*45895Ssklower } 59942140Ssklower if (so = lcp -> lcd_so) { 60042140Ssklower sbflush (&so -> so_rcv); 60142140Ssklower sbflush (&so -> so_snd); 602*45895Ssklower } else 603*45895Ssklower sbflush (&lcp -> lcd_sb); 60441593Ssklower } 60541593Ssklower 60641593Ssklower 60741593Ssklower /* 60841593Ssklower * This procedure handles all local protocol procedure errors. 60941593Ssklower */ 61041593Ssklower 611*45895Ssklower pk_procerror (error, lcp, errstr, diagnostic) 61241593Ssklower register struct pklcd *lcp; 61341593Ssklower char *errstr; 61441593Ssklower { 61541593Ssklower 61641593Ssklower pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr); 61741593Ssklower 61841593Ssklower switch (error) { 61941593Ssklower case CLEAR: 62045297Ssklower if (lcp -> lcd_so) { 62145297Ssklower lcp -> lcd_so -> so_error = ECONNABORTED; 62245297Ssklower soisdisconnecting (lcp -> lcd_so); 62341593Ssklower } 624*45895Ssklower pk_clear (lcp, diagnostic, 1); 62541593Ssklower break; 62641593Ssklower 62741593Ssklower case RESET: 628*45895Ssklower pk_reset (lcp, diagnostic); 62941593Ssklower } 63041593Ssklower } 63141593Ssklower 63241593Ssklower /* 63341593Ssklower * This procedure is called during the DATA TRANSFER state to check 63441593Ssklower * and process the P(R) values received in the DATA, RR OR RNR 63541593Ssklower * packets. 63641593Ssklower */ 63741593Ssklower 63841593Ssklower pk_ack (lcp, pr) 63941593Ssklower struct pklcd *lcp; 64041593Ssklower unsigned pr; 64141593Ssklower { 64241593Ssklower register struct socket *so = lcp -> lcd_so; 64341593Ssklower 64441593Ssklower if (lcp -> lcd_output_window == pr) 64541593Ssklower return (PACKET_OK); 64641593Ssklower if (lcp -> lcd_output_window < lcp -> lcd_ssn) { 64741593Ssklower if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) { 648*45895Ssklower pk_procerror (RESET, lcp, 649*45895Ssklower "p(r) flow control error", 2); 65041593Ssklower return (ERROR_PACKET); 65141593Ssklower } 65241593Ssklower } 65341593Ssklower else { 65441593Ssklower if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) { 655*45895Ssklower pk_procerror (RESET, lcp, 656*45895Ssklower "p(r) flow control error", 2); 65741593Ssklower return (ERROR_PACKET); 65841593Ssklower } 65941593Ssklower } 66041593Ssklower 66141593Ssklower lcp -> lcd_output_window = pr; /* Rotate window. */ 66241593Ssklower if (lcp -> lcd_window_condition == TRUE) 66341593Ssklower lcp -> lcd_window_condition = FALSE; 66441593Ssklower 66542140Ssklower if (so && ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel)) 66641593Ssklower sowwakeup (so); 66743361Ssklower if (lcp -> lcd_upper) 66843361Ssklower (*lcp -> lcd_upper)(lcp, 0); 66941593Ssklower 67041593Ssklower return (PACKET_OK); 67141593Ssklower } 67241593Ssklower 67341593Ssklower /* 67441593Ssklower * This procedure decodes the X.25 level 3 packet returning a 67541593Ssklower * code to be used in switchs or arrays. 67641593Ssklower */ 67741593Ssklower 67841593Ssklower pk_decode (xp) 67941593Ssklower register struct x25_packet *xp; 68041593Ssklower { 68141593Ssklower register int type; 68241593Ssklower 68341593Ssklower if (xp -> fmt_identifier != 1) 68441593Ssklower return (INVALID_PACKET); 685*45895Ssklower #ifdef ancient_history 68641593Ssklower /* 68741593Ssklower * Make sure that the logical channel group number is 0. 68841593Ssklower * This restriction may be removed at some later date. 68941593Ssklower */ 69041593Ssklower if (xp -> lc_group_number != 0) 69141593Ssklower return (INVALID_PACKET); 692*45895Ssklower #endif 69341593Ssklower /* 69441593Ssklower * Test for data packet first. 69541593Ssklower */ 69641593Ssklower if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR)) 69741593Ssklower return (DATA); 69841593Ssklower 69941593Ssklower /* 70041593Ssklower * Test if flow control packet (RR or RNR). 70141593Ssklower */ 70241593Ssklower if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR)) 70341593Ssklower if (!(xp -> packet_type & RR_PACKET_DESIGNATOR)) 70441593Ssklower return (RR); 70541593Ssklower else 70641593Ssklower return (RNR); 70741593Ssklower 70841593Ssklower /* 70941593Ssklower * Determine the rest of the packet types. 71041593Ssklower */ 71141593Ssklower switch (xp -> packet_type) { 71241593Ssklower case X25_CALL: 71341593Ssklower type = CALL; 71441593Ssklower break; 71541593Ssklower 71641593Ssklower case X25_CALL_ACCEPTED: 71741593Ssklower type = CALL_ACCEPTED; 71841593Ssklower break; 71941593Ssklower 72041593Ssklower case X25_CLEAR: 72141593Ssklower type = CLEAR; 72241593Ssklower break; 72341593Ssklower 72441593Ssklower case X25_CLEAR_CONFIRM: 72541593Ssklower type = CLEAR_CONF; 72641593Ssklower break; 72741593Ssklower 72841593Ssklower case X25_INTERRUPT: 72941593Ssklower type = INTERRUPT; 73041593Ssklower break; 73141593Ssklower 73241593Ssklower case X25_INTERRUPT_CONFIRM: 73341593Ssklower type = INTERRUPT_CONF; 73441593Ssklower break; 73541593Ssklower 73641593Ssklower case X25_RESET: 73741593Ssklower type = RESET; 73841593Ssklower break; 73941593Ssklower 74041593Ssklower case X25_RESET_CONFIRM: 74141593Ssklower type = RESET_CONF; 74241593Ssklower break; 74341593Ssklower 74441593Ssklower case X25_RESTART: 74541593Ssklower type = RESTART; 74641593Ssklower break; 74741593Ssklower 74841593Ssklower case X25_RESTART_CONFIRM: 74941593Ssklower type = RESTART_CONF; 75041593Ssklower break; 75141593Ssklower 75241593Ssklower default: 75341593Ssklower type = INVALID_PACKET; 75441593Ssklower } 75541593Ssklower return (type); 75641593Ssklower } 75741593Ssklower 75841593Ssklower /* 75941593Ssklower * A restart packet has been received. Print out the reason 76041593Ssklower * for the restart. 76141593Ssklower */ 76241593Ssklower 76341593Ssklower pk_restartcause (pkp, xp) 76441593Ssklower struct pkcb *pkp; 76541593Ssklower register struct x25_packet *xp; 76641593Ssklower { 76741593Ssklower register struct x25config *xcp = pkp -> pk_xcp; 76845574Ssklower register int lcn = LCN(xp); 76941593Ssklower 77041593Ssklower switch (xp -> packet_data) { 77141593Ssklower case X25_RESTART_LOCAL_PROCEDURE_ERROR: 77241593Ssklower pk_message (lcn, xcp, "restart: local procedure error"); 77341593Ssklower break; 77441593Ssklower 77541593Ssklower case X25_RESTART_NETWORK_CONGESTION: 77641593Ssklower pk_message (lcn, xcp, "restart: network congestion"); 77741593Ssklower break; 77841593Ssklower 77941593Ssklower case X25_RESTART_NETWORK_OPERATIONAL: 78041593Ssklower pk_message (lcn, xcp, "restart: network operational"); 78141593Ssklower break; 78241593Ssklower 78341593Ssklower default: 78441593Ssklower pk_message (lcn, xcp, "restart: unknown cause"); 78541593Ssklower } 78641593Ssklower } 78741593Ssklower 78841593Ssklower #define MAXRESETCAUSE 7 78941593Ssklower 79041593Ssklower int Reset_cause[] = { 79141593Ssklower EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG 79241593Ssklower }; 79341593Ssklower 79441593Ssklower /* 79541593Ssklower * A reset packet has arrived. Return the cause to the user. 79641593Ssklower */ 79741593Ssklower 79841593Ssklower pk_resetcause (pkp, xp) 79941593Ssklower struct pkcb *pkp; 80041593Ssklower register struct x25_packet *xp; 80141593Ssklower { 80245297Ssklower register struct pklcd *lcp = 80345574Ssklower pkp -> pk_chan[LCN(xp)]; 80441593Ssklower register int code = xp -> packet_data; 80541593Ssklower 80641593Ssklower if (code > MAXRESETCAUSE) 80741593Ssklower code = 7; /* EXRNCG */ 80841593Ssklower 80945297Ssklower lcp -> lcd_so -> so_error = Reset_cause[code]; 81041593Ssklower } 81141593Ssklower 81241593Ssklower #define MAXCLEARCAUSE 25 81341593Ssklower 81441593Ssklower int Clear_cause[] = { 81541593Ssklower EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0, 81641593Ssklower 0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE, 81741593Ssklower 0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC 81841593Ssklower }; 81941593Ssklower 82041593Ssklower /* 82141593Ssklower * A clear packet has arrived. Return the cause to the user. 82241593Ssklower */ 82341593Ssklower 82441593Ssklower pk_clearcause (pkp, xp) 82541593Ssklower struct pkcb *pkp; 82641593Ssklower register struct x25_packet *xp; 82741593Ssklower { 82845297Ssklower register struct pklcd *lcp = 82945574Ssklower pkp -> pk_chan[LCN(xp)]; 83041593Ssklower register int code = xp -> packet_data; 83141593Ssklower 83241593Ssklower if (code > MAXCLEARCAUSE) 83341593Ssklower code = 5; /* EXRNCG */ 83445297Ssklower lcp -> lcd_so -> so_error = Clear_cause[code]; 83541593Ssklower } 83641593Ssklower 83741593Ssklower char * 83841593Ssklower format_ntn (xcp) 83941593Ssklower register struct x25config *xcp; 84041593Ssklower { 84141593Ssklower 84245165Ssklower return (xcp -> xc_addr.x25_addr); 84341593Ssklower } 84441593Ssklower 84541593Ssklower /* VARARGS1 */ 84641593Ssklower pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6) 84741593Ssklower struct x25config *xcp; 84841593Ssklower char *fmt; 84941593Ssklower { 85041593Ssklower 85141593Ssklower if (lcn) 85241593Ssklower if (pkcbhead -> pk_next) 85341593Ssklower printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn); 85441593Ssklower else 85541593Ssklower printf ("X.25: lcn %d: ", lcn); 85641593Ssklower else 85741593Ssklower if (pkcbhead -> pk_next) 85841593Ssklower printf ("X.25(%s): ", format_ntn (xcp)); 85941593Ssklower else 86041593Ssklower printf ("X.25: "); 86141593Ssklower 86241593Ssklower printf (fmt, a1, a2, a3, a4, a5, a6); 86341593Ssklower printf ("\n"); 86441593Ssklower } 86545297Ssklower 86645297Ssklower pk_ifattach(ia, lloutput, llnext) 86745297Ssklower register struct x25_ifaddr *ia; 86845297Ssklower int (*lloutput)(); 86945297Ssklower caddr_t llnext; 87045297Ssklower { 87145297Ssklower /* this is here because you can't include both pk_var and hd_var */ 87245297Ssklower /* this will probably be replace by a streams gluing mechanism */ 87345297Ssklower ia -> ia_pkcb.pk_lloutput = lloutput; 87445297Ssklower ia -> ia_pkcb.pk_llnext = llnext; 87545297Ssklower } 87645297Ssklower 87745297Ssklower pk_fragment(lcp, m0, qbit, mbit, wait) 87845297Ssklower struct mbuf *m0; 87945297Ssklower register struct pklcd *lcp; 88045297Ssklower { 88145297Ssklower register struct mbuf *m = m0; 88245297Ssklower register struct x25_packet *xp; 88345297Ssklower register struct sockbuf *sb; 884*45895Ssklower struct mbuf *head = 0, *next, **mp = &head, *m_split(); 88545297Ssklower int totlen, psize = 1 << (lcp -> lcd_packetsize); 88645297Ssklower 88745297Ssklower if (m == 0) 88845297Ssklower return; 889*45895Ssklower if (m -> m_flags & M_PKTHDR == 0) 89045297Ssklower panic("pk_fragment"); 89145297Ssklower totlen = m -> m_pkthdr.len; 89245574Ssklower m -> m_act = 0; 89345297Ssklower sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb; 89445297Ssklower do { 89545297Ssklower if (totlen > psize) { 896*45895Ssklower if ((next = m_split(m, psize, wait)) == 0) 89745297Ssklower goto abort; 89845297Ssklower totlen -= psize; 89945574Ssklower } else 90045574Ssklower next = 0; 90145297Ssklower M_PREPEND(m, PKHEADERLN, wait); 90245297Ssklower if (m == 0) 90345297Ssklower goto abort; 90445574Ssklower *mp = m; 90545574Ssklower mp = & m -> m_act; 90645574Ssklower *mp = 0; 90745297Ssklower xp = mtod(m, struct x25_packet *); 90845297Ssklower 0[(char *)xp] = 0; 90945297Ssklower if (qbit) 91045574Ssklower xp -> q_bit = 1; 91145574Ssklower if (lcp -> lcd_flags & X25_DBIT) 91245574Ssklower xp -> d_bit = 1; 91345297Ssklower xp -> fmt_identifier = 1; 91445297Ssklower xp -> packet_type = X25_DATA; 91545574Ssklower SET_LCN(xp, lcp -> lcd_lcn); 91645574Ssklower if (next || (mbit && (totlen == psize || 91745574Ssklower (lcp -> lcd_flags & X25_DBIT)))) 91845297Ssklower MBIT(xp) = 1; 91945297Ssklower } while (m = next); 92045574Ssklower for (m = head; m; m = next) { 92145297Ssklower next = m -> m_act; 92245297Ssklower m -> m_act = 0; 92345297Ssklower sbappendrecord(sb, m); 92445297Ssklower } 92545297Ssklower return 0; 92645297Ssklower abort: 92745574Ssklower if (wait) 92845574Ssklower panic("pk_fragment null mbuf after wait"); 92945574Ssklower if (next) 93045574Ssklower m_freem(next); 93145574Ssklower for (m = head; m; m = next) { 93245297Ssklower next = m -> m_act; 93345297Ssklower m_freem(m); 93445297Ssklower } 93545297Ssklower return ENOBUFS; 93645297Ssklower } 93745574Ssklower 93845574Ssklower struct mbuf * 93945574Ssklower m_split(m0, len0, wait) 94045574Ssklower register struct mbuf *m0; 94145574Ssklower int len0; 94245574Ssklower { 94345574Ssklower register struct mbuf *m, *n; 94445574Ssklower unsigned len = len0; 94545574Ssklower 94645574Ssklower for (m = m0; m && len > m -> m_len; m = m -> m_next) 94745574Ssklower len -= m -> m_len; 94845574Ssklower if (m == 0) 94945574Ssklower return (0); 95045574Ssklower if (m0 -> m_flags & M_PKTHDR) { 95145574Ssklower MGETHDR(n, wait, m0 -> m_type); 95245574Ssklower if (n == 0) 95345574Ssklower return (0); 95445574Ssklower n -> m_pkthdr.rcvif = m0 -> m_pkthdr.rcvif; 95545574Ssklower n -> m_pkthdr.len = m0 -> m_pkthdr.len - len0; 95645574Ssklower m0 -> m_pkthdr.len = len0; 95745574Ssklower if (m -> m_flags & M_EXT) 95845574Ssklower goto extpacket; 95945574Ssklower if (len > MHLEN) { 96045574Ssklower /* m can't be the lead packet */ 96145574Ssklower MH_ALIGN(n, 0); 96245574Ssklower n -> m_next = m_split(m, len, wait); 96345574Ssklower if (n -> m_next == 0) { 96445574Ssklower (void) m_free(n); 96545574Ssklower return (0); 96645574Ssklower } else 96745574Ssklower return (n); 96845574Ssklower } else 96945574Ssklower MH_ALIGN(n, len); 97045574Ssklower } else if (len == m -> m_len) { 97145574Ssklower n = m -> m_next; 97245574Ssklower m -> m_next = 0; 97345574Ssklower return (n); 97445574Ssklower } 97545574Ssklower extpacket: 97645574Ssklower len = m -> m_len - len; /* remainder to be copied */ 97745574Ssklower m -> m_len -= len; /* now equals original len */ 978*45895Ssklower if (m -> m_flags & M_EXT) { 97945574Ssklower n -> m_flags |= M_EXT; 98045574Ssklower n -> m_ext = m -> m_ext; 98145574Ssklower mclrefcnt[mtocl(m -> m_ext.ext_buf)]++; 98245574Ssklower n -> m_data = m -> m_data + m -> m_len; 98345574Ssklower } else { 98445574Ssklower MGET(n, wait, m -> m_type); 98545574Ssklower if (n == 0) { 98645574Ssklower m -> m_len += len; 98745574Ssklower return (0); 98845574Ssklower } 98945574Ssklower M_ALIGN(n, len); 99045574Ssklower bcopy(mtod(m, caddr_t), mtod(n, caddr_t), len); 99145574Ssklower } 99245574Ssklower n -> m_len = len; 99345574Ssklower n -> m_next = m -> m_next; 99445574Ssklower m -> m_next = 0; 99545574Ssklower return (n); 99645574Ssklower } 997