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*56530Sbostic * @(#)pk_subr.c 7.22 (Berkeley) 10/11/92 1341709Ssklower */ 1441593Ssklower 15*56530Sbostic #include <sys/param.h> 16*56530Sbostic #include <sys/systm.h> 17*56530Sbostic #include <sys/mbuf.h> 18*56530Sbostic #include <sys/socket.h> 19*56530Sbostic #include <sys/protosw.h> 20*56530Sbostic #include <sys/socketvar.h> 21*56530Sbostic #include <sys/errno.h> 22*56530Sbostic #include <sys/time.h> 23*56530Sbostic #include <sys/kernel.h> 2441593Ssklower 25*56530Sbostic #include <net/if.h> 2642277Ssklower 27*56530Sbostic #include <netccitt/x25.h> 28*56530Sbostic #include <netccitt/pk.h> 29*56530Sbostic #include <netccitt/pk_var.h> 30*56530Sbostic #include <netccitt/x25err.h> 3141593Ssklower 3241593Ssklower int pk_sendspace = 1024 * 2 + 8; 3341593Ssklower int pk_recvspace = 1024 * 2 + 8; 3441593Ssklower 3547271Ssklower struct pklcd_q pklcd_q = {&pklcd_q, &pklcd_q}; 3647271Ssklower 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; 5049018Ssklower int pk_output(); 5141593Ssklower 5247271Ssklower MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT); 5342277Ssklower if (lcp) { 5447271Ssklower bzero ((caddr_t)lcp, sizeof (*lcp)); 5547271Ssklower insque (&lcp -> lcd_q, &pklcd_q); 5649595Ssklower lcp -> lcd_state = READY; 5749595Ssklower lcp -> lcd_send = pk_output; 5842277Ssklower if (so) { 5942277Ssklower error = soreserve (so, pk_sendspace, pk_recvspace); 6042277Ssklower lcp -> lcd_so = so; 6142277Ssklower if (so -> so_options & SO_ACCEPTCONN) 6242277Ssklower lcp -> lcd_state = LISTEN; 6343361Ssklower } else 6445165Ssklower sbreserve (&lcp -> lcd_sb, pk_sendspace); 6542277Ssklower } 6642277Ssklower if (so) { 6742277Ssklower so -> so_pcb = (caddr_t) lcp; 6842277Ssklower so -> so_error = error; 6942277Ssklower } 7042277Ssklower return (lcp); 7141593Ssklower } 7241593Ssklower 7341593Ssklower /* 7441593Ssklower * Disconnect X.25 protocol from socket. 7541593Ssklower */ 7641593Ssklower 7741593Ssklower pk_disconnect (lcp) 7841593Ssklower register struct pklcd *lcp; 7941593Ssklower { 8041593Ssklower register struct socket *so = lcp -> lcd_so; 8141593Ssklower register struct pklcd *l, *p; 8241593Ssklower 8341593Ssklower switch (lcp -> lcd_state) { 8441593Ssklower case LISTEN: 8541593Ssklower for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen); 8641593Ssklower if (p == 0) { 8741593Ssklower if (l != 0) 8841593Ssklower pk_listenhead = l -> lcd_listen; 8941593Ssklower } 9041593Ssklower else 9141593Ssklower if (l != 0) 9241593Ssklower p -> lcd_listen = l -> lcd_listen; 9341593Ssklower pk_close (lcp); 9441593Ssklower break; 9541593Ssklower 9641593Ssklower case READY: 9741593Ssklower pk_acct (lcp); 9841593Ssklower pk_close (lcp); 9941593Ssklower break; 10041593Ssklower 10141593Ssklower case SENT_CLEAR: 10241593Ssklower case RECEIVED_CLEAR: 10341593Ssklower break; 10441593Ssklower 10541593Ssklower default: 10641593Ssklower pk_acct (lcp); 10742140Ssklower if (so) { 10842140Ssklower soisdisconnecting (so); 10942140Ssklower sbflush (&so -> so_rcv); 11042140Ssklower } 11145895Ssklower pk_clear (lcp, 241, 0); /* Normal Disconnect */ 11241593Ssklower 11341593Ssklower } 11441593Ssklower } 11541593Ssklower 11641593Ssklower /* 11741593Ssklower * Close an X.25 Logical Channel. Discard all space held by the 11841593Ssklower * connection and internal descriptors. Wake up any sleepers. 11941593Ssklower */ 12041593Ssklower 12141593Ssklower pk_close (lcp) 12241593Ssklower struct pklcd *lcp; 12341593Ssklower { 12441593Ssklower register struct socket *so = lcp -> lcd_so; 12541593Ssklower 12641593Ssklower pk_freelcd (lcp); 12741593Ssklower 12841593Ssklower if (so == NULL) 12941593Ssklower return; 13041593Ssklower 13141593Ssklower so -> so_pcb = 0; 13241593Ssklower soisdisconnected (so); 13345895Ssklower /* 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 14345895Ssklower struct mbuf * 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; 16149595Ssklower m -> m_pkthdr.len = 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 16945574Ssklower SET_LCN(xp, lcn); 17041593Ssklower xp -> packet_type = type; 17141593Ssklower 17245895Ssklower return (m); 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 { 18645895Ssklower register struct mbuf *m; 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) { 19545895Ssklower if (lcp -> lcd_so) { 19645297Ssklower lcp -> lcd_so -> so_error = ENETRESET; 19745895Ssklower pk_close (lcp); 19845895Ssklower } else { 19945895Ssklower pk_flush (lcp); 20045895Ssklower lcp -> lcd_state = READY; 20145895Ssklower if (lcp -> lcd_upper) 20247271Ssklower lcp -> lcd_upper (lcp, 0); 20345895Ssklower } 20441593Ssklower } 20541593Ssklower 20641593Ssklower if (restart_cause < 0) 20741593Ssklower return; 20841593Ssklower 20945297Ssklower pkp -> pk_state = DTE_SENT_RESTART; 21045297Ssklower lcp = pkp -> pk_chan[0]; 21145895Ssklower m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART); 21249595Ssklower m -> m_pkthdr.len = m -> m_len += 2; 21347271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; /* DTE only */ 21447271Ssklower mtod (m, octet *)[4] = restart_cause; 21541593Ssklower pk_output (lcp); 21641593Ssklower } 21741593Ssklower 21841593Ssklower 21941593Ssklower /* 22041593Ssklower * This procedure frees up the Logical Channel Descripter. 22141593Ssklower */ 22241593Ssklower 22341593Ssklower pk_freelcd (lcp) 22441593Ssklower register struct pklcd *lcp; 22541593Ssklower { 22641593Ssklower if (lcp == NULL) 22741593Ssklower return; 22841593Ssklower 22941593Ssklower if (lcp -> lcd_lcn > 0) 23041593Ssklower lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL; 23141593Ssklower 23247271Ssklower pk_flush (lcp); 23347271Ssklower remque (&lcp -> lcd_q); 23447271Ssklower free ((caddr_t)lcp, M_PCB); 23541593Ssklower } 23641593Ssklower 23741593Ssklower 23841593Ssklower /* 23941593Ssklower * Bind a address and protocol value to a socket. The important 24041593Ssklower * part is the protocol value - the first four characters of the 24141593Ssklower * Call User Data field. 24241593Ssklower */ 24341593Ssklower 24441593Ssklower pk_bind (lcp, nam) 24541593Ssklower struct pklcd *lcp; 24641593Ssklower struct mbuf *nam; 24741593Ssklower { 24841593Ssklower register struct pkcb *pkp; 24941593Ssklower register struct pklcd *pp; 25042277Ssklower register struct sockaddr_x25 *sa; 25141593Ssklower 25241593Ssklower if (nam == NULL) 25341593Ssklower return (EADDRNOTAVAIL); 25441593Ssklower if (lcp -> lcd_ceaddr) /* XXX */ 25541593Ssklower return (EADDRINUSE); 25645895Ssklower if (pk_checksockaddr (nam)) 25741593Ssklower return (EINVAL); 25841593Ssklower sa = mtod (nam, struct sockaddr_x25 *); 25941593Ssklower 26041593Ssklower /* 26141593Ssklower * If the user wishes to accept calls only from a particular 26241593Ssklower * net (net != 0), make sure the net is known 26341593Ssklower */ 26441593Ssklower 26541593Ssklower if (sa -> x25_net) 26641593Ssklower for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 26741593Ssklower if (pkp == 0) 26841593Ssklower return (ENETUNREACH); 26945165Ssklower if (pkp -> pk_xcp -> xc_addr.x25_net == sa -> x25_net) 27041593Ssklower break; 27141593Ssklower } 27241593Ssklower 27345895Ssklower /* 27445895Ssklower * For ISO's sake permit default listeners, but only one such . . . 27545895Ssklower */ 27645895Ssklower for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) { 27745895Ssklower register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr; 27845895Ssklower if ((sa2 -> x25_udlen == sa -> x25_udlen) && 27945895Ssklower (sa2 -> x25_udlen == 0 || 28045895Ssklower (bcmp (sa2 -> x25_udata, sa -> x25_udata, 28145895Ssklower min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0))) 28245895Ssklower return (EADDRINUSE); 28345895Ssklower } 28442277Ssklower lcp -> lcd_laddr = *sa; 28542277Ssklower lcp -> lcd_ceaddr = &lcp -> lcd_laddr; 28641593Ssklower return (0); 28741593Ssklower } 28841593Ssklower 28941593Ssklower /* 29045895Ssklower * Include a bound control block in the list of listeners. 29145895Ssklower */ 29245895Ssklower pk_listen (lcp) 29345895Ssklower register struct pklcd *lcp; 29445895Ssklower { 29545895Ssklower register struct pklcd **pp; 29645895Ssklower 29745895Ssklower if (lcp -> lcd_ceaddr == 0) 29845895Ssklower return (EDESTADDRREQ); 29945895Ssklower 30045895Ssklower lcp -> lcd_state = LISTEN; 30145895Ssklower /* 30245895Ssklower * Add default listener at end, any others at start. 30345895Ssklower */ 30445895Ssklower if (lcp -> lcd_ceaddr -> x25_udlen == 0) { 30545895Ssklower for (pp = &pk_listenhead; *pp; ) 30645895Ssklower pp = &((*pp) -> lcd_listen); 30745895Ssklower *pp = lcp; 30845895Ssklower } else { 30945895Ssklower lcp -> lcd_listen = pk_listenhead; 31045895Ssklower pk_listenhead = lcp; 31145895Ssklower } 31245895Ssklower return (0); 31345895Ssklower } 31445895Ssklower /* 31545895Ssklower * Include a listening control block for the benefit of other protocols. 31645895Ssklower */ 31745895Ssklower pk_protolisten (spi, spilen, callee) 31847271Ssklower int (*callee) (); 31945895Ssklower { 32045895Ssklower register struct pklcd *lcp = pk_attach ((struct socket *)0); 32145895Ssklower register struct mbuf *nam; 32245895Ssklower register struct sockaddr_x25 *sa; 32345895Ssklower int error = ENOBUFS; 32445895Ssklower 32545895Ssklower if (lcp) { 32647271Ssklower if (nam = m_getclr (MT_SONAME, M_DONTWAIT)) { 32747271Ssklower sa = mtod (nam, struct sockaddr_x25 *); 32845895Ssklower sa -> x25_family = AF_CCITT; 32945895Ssklower sa -> x25_len = nam -> m_len = sizeof (*sa); 33045895Ssklower sa -> x25_udlen = spilen; 33145895Ssklower sa -> x25_udata[0] = spi; 33245895Ssklower lcp -> lcd_upper = callee; 33345895Ssklower lcp -> lcd_flags = X25_MBS_HOLD; 33449929Ssklower if ((error = pk_bind (lcp, nam)) == 0) 33549929Ssklower error = pk_listen (lcp); 33645895Ssklower (void) m_free (nam); 33745895Ssklower } 33845895Ssklower if (error) 33947271Ssklower pk_freelcd (lcp); 34045895Ssklower } 34145895Ssklower return error; /* Hopefully Zero !*/ 34245895Ssklower } 34345895Ssklower 34445895Ssklower /* 34541593Ssklower * Associate a logical channel descriptor with a network. 34641593Ssklower * Fill in the default network specific parameters and then 34741593Ssklower * set any parameters explicitly specified by the user or 34841593Ssklower * by the remote DTE. 34941593Ssklower */ 35041593Ssklower 35141593Ssklower pk_assoc (pkp, lcp, sa) 35241593Ssklower register struct pkcb *pkp; 35341593Ssklower register struct pklcd *lcp; 35441593Ssklower register struct sockaddr_x25 *sa; 35541593Ssklower { 35641593Ssklower 35741593Ssklower lcp -> lcd_pkp = pkp; 35841593Ssklower lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize; 35941593Ssklower lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize; 36041593Ssklower lcp -> lcd_rsn = MODULUS - 1; 36141593Ssklower pkp -> pk_chan[lcp -> lcd_lcn] = lcp; 36241593Ssklower 36341593Ssklower if (sa -> x25_opts.op_psize) 36441593Ssklower lcp -> lcd_packetsize = sa -> x25_opts.op_psize; 36541593Ssklower else 36641593Ssklower sa -> x25_opts.op_psize = lcp -> lcd_packetsize; 36741593Ssklower if (sa -> x25_opts.op_wsize) 36841593Ssklower lcp -> lcd_windowsize = sa -> x25_opts.op_wsize; 36941593Ssklower else 37041593Ssklower sa -> x25_opts.op_wsize = lcp -> lcd_windowsize; 37145165Ssklower sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net; 37250020Ssklower lcp -> lcd_flags |= sa -> x25_opts.op_flags; 37341593Ssklower lcp -> lcd_stime = time.tv_sec; 37441593Ssklower } 37541593Ssklower 37645895Ssklower pk_connect (lcp, sa) 37741593Ssklower register struct pklcd *lcp; 37842277Ssklower register struct sockaddr_x25 *sa; 37941593Ssklower { 38041593Ssklower register struct pkcb *pkp; 38141593Ssklower 38241593Ssklower if (sa -> x25_addr[0] == '\0') 38341593Ssklower return (EDESTADDRREQ); 38445297Ssklower if (lcp -> lcd_pkp == 0) 38545297Ssklower for (pkp = pkcbhead; ; pkp = pkp -> pk_next) { 38641593Ssklower if (pkp == 0) 38741593Ssklower return (ENETUNREACH); 38841593Ssklower /* 38941593Ssklower * use first net configured (last in list 39041593Ssklower * headed by pkcbhead) if net is zero 39149929Ssklower * 39249929Ssklower * This is clearly bogus for many llc2's sharing 39349929Ssklower * the same xcp; we will replace this with a 39449929Ssklower * routing lookup. 39541593Ssklower */ 39641593Ssklower if (sa -> x25_net == 0 && pkp -> pk_next == 0) 39741593Ssklower break; 39845165Ssklower if (sa -> x25_net == pkp -> pk_xcp -> xc_addr.x25_net) 39941593Ssklower break; 40041593Ssklower } 40141593Ssklower 40241593Ssklower if (pkp -> pk_state != DTE_READY) 40341593Ssklower return (ENETDOWN); 40441593Ssklower if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0) 40541593Ssklower return (EMFILE); 40642277Ssklower lcp -> lcd_faddr = *sa; 40745297Ssklower lcp -> lcd_ceaddr = & lcp -> lcd_faddr; 40841593Ssklower pk_assoc (pkp, lcp, lcp -> lcd_ceaddr); 40945165Ssklower if (lcp -> lcd_so) 41042140Ssklower soisconnecting (lcp -> lcd_so); 41141593Ssklower lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL); 41242277Ssklower pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp); 41349929Ssklower return (*pkp -> pk_ia -> ia_start) (lcp); 41441593Ssklower } 41541593Ssklower 41649747Ssklower struct bcdinfo { 41749747Ssklower octet *cp; 41849747Ssklower unsigned posn; 41949747Ssklower }; 42041593Ssklower /* 42141593Ssklower * Build the rest of the CALL REQUEST packet. Fill in calling 42241593Ssklower * address, facilities fields and the user data field. 42341593Ssklower */ 42441593Ssklower 42542277Ssklower pk_callrequest (lcp, sa, xcp) 42641593Ssklower struct pklcd *lcp; 42742277Ssklower register struct sockaddr_x25 *sa; 42841593Ssklower register struct x25config *xcp; 42941593Ssklower { 43041593Ssklower register struct x25_calladdr *a; 43145895Ssklower register struct mbuf *m = lcp -> lcd_template; 43247271Ssklower register struct x25_packet *xp = mtod (m, struct x25_packet *); 43349747Ssklower struct bcdinfo b; 43441593Ssklower 43545574Ssklower if (lcp -> lcd_flags & X25_DBIT) 43645895Ssklower xp -> d_bit = 1; 43745895Ssklower a = (struct x25_calladdr *) &xp -> packet_data; 43849747Ssklower b.cp = (octet *) a -> address_field; 43949747Ssklower b.posn = 0; 44049747Ssklower a -> called_addrlen = to_bcd (&b, sa, xcp); 44149747Ssklower a -> calling_addrlen = to_bcd (&b, &xcp -> xc_addr, xcp); 44249747Ssklower if (b.posn & 0x01) 44349747Ssklower *b.cp++ &= 0xf0; 44449747Ssklower m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a; 44541593Ssklower 44645895Ssklower if (lcp -> lcd_facilities) { 44747271Ssklower m -> m_pkthdr.len += 44849747Ssklower (m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len; 44945895Ssklower lcp -> lcd_facilities = 0; 45045895Ssklower } else 45149747Ssklower pk_build_facilities (m, sa, (int)xcp -> xc_type); 45241593Ssklower 45347271Ssklower m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata); 45441593Ssklower } 45541593Ssklower 45649747Ssklower pk_build_facilities (m, sa, type) 45745895Ssklower register struct mbuf *m; 45841593Ssklower struct sockaddr_x25 *sa; 45941593Ssklower { 46045895Ssklower register octet *cp; 46141593Ssklower register octet *fcp; 46241593Ssklower register int revcharge; 46341593Ssklower 46447271Ssklower cp = mtod (m, octet *) + m -> m_len; 46545895Ssklower fcp = cp + 1; 46641593Ssklower revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0; 46741593Ssklower /* 46841593Ssklower * This is specific to Datapac X.25(1976) DTEs. International 46941593Ssklower * calls must have the "hi priority" bit on. 47041593Ssklower */ 47141593Ssklower if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128) 47241593Ssklower revcharge |= 02; 47341593Ssklower if (revcharge) { 47441593Ssklower *fcp++ = FACILITIES_REVERSE_CHARGE; 47541593Ssklower *fcp++ = revcharge; 47641593Ssklower } 47741593Ssklower switch (type) { 47841593Ssklower case X25_1980: 47941593Ssklower case X25_1984: 48041593Ssklower *fcp++ = FACILITIES_PACKETSIZE; 48141593Ssklower *fcp++ = sa -> x25_opts.op_psize; 48241593Ssklower *fcp++ = sa -> x25_opts.op_psize; 48341593Ssklower 48441593Ssklower *fcp++ = FACILITIES_WINDOWSIZE; 48541593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 48641593Ssklower *fcp++ = sa -> x25_opts.op_wsize; 48741593Ssklower } 48845895Ssklower *cp = fcp - cp - 1; 48945895Ssklower m -> m_pkthdr.len = (m -> m_len += *cp + 1); 49041593Ssklower } 49141593Ssklower 49249747Ssklower to_bcd (b, sa, xcp) 49349747Ssklower register struct bcdinfo *b; 49449747Ssklower struct sockaddr_x25 *sa; 49549747Ssklower register struct x25config *xcp; 49641593Ssklower { 49749747Ssklower register char *x = sa -> x25_addr; 49849747Ssklower unsigned start = b -> posn; 49949747Ssklower /* 50049747Ssklower * The nodnic and prepnd0 stuff looks tedious, 50149747Ssklower * but it does allow full X.121 addresses to be used, 50249747Ssklower * which is handy for routing info (& OSI type 37 addresses). 50349747Ssklower */ 50449747Ssklower if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) { 50549747Ssklower char dnicname[sizeof(long) * NBBY/3 + 2]; 50649747Ssklower register char *p = dnicname; 50749747Ssklower 50849747Ssklower sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff); 50949747Ssklower for (; *p; p++) /* *p == 0 means dnic matched */ 51049747Ssklower if ((*p ^ *x++) & 0x0f) 51149747Ssklower break; 51249747Ssklower if (*p || xcp -> xc_nodnic == 0) 51349747Ssklower x = sa -> x25_addr; 51449747Ssklower if (*p && xcp -> xc_prepnd0) { 51549747Ssklower if ((b -> posn)++ & 0x01) 51649747Ssklower *(b -> cp)++; 51749747Ssklower else 51849747Ssklower *(b -> cp) = 0; 51949747Ssklower } 52049747Ssklower } 52149747Ssklower while (*x) 52249747Ssklower if ((b -> posn)++ & 0x01) 52349747Ssklower *(b -> cp)++ |= *x++ & 0x0F; 52441593Ssklower else 52549747Ssklower *(b -> cp) = *x++ << 4; 52649747Ssklower return ((b -> posn) - start); 52741593Ssklower } 52841593Ssklower 52941593Ssklower /* 53041593Ssklower * This routine gets the first available logical channel number. The 53141593Ssklower * search is from the highest number to lowest number (DTE). 53241593Ssklower */ 53341593Ssklower 53441593Ssklower pk_getlcn (pkp) 53541593Ssklower register struct pkcb *pkp; 53641593Ssklower { 53741593Ssklower register int i; 53841593Ssklower 53945297Ssklower if (pkp -> pk_chan == 0) 54042140Ssklower return (0); 54141593Ssklower for (i = pkp -> pk_maxlcn; i > 0; --i) 54241593Ssklower if (pkp -> pk_chan[i] == NULL) 54341593Ssklower break; 54441593Ssklower return (i); 54541593Ssklower 54641593Ssklower } 54741593Ssklower 54841593Ssklower /* 54941593Ssklower * This procedure sends a CLEAR request packet. The lc state is 55041593Ssklower * set to "SENT_CLEAR". 55141593Ssklower */ 55241593Ssklower 55345895Ssklower pk_clear (lcp, diagnostic, abortive) 55445895Ssklower register struct pklcd *lcp; 55541593Ssklower { 55645895Ssklower register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR); 55741593Ssklower 55845895Ssklower m -> m_len += 2; 55951739Ssklower m -> m_pkthdr.len += 2; 56047271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; 56147271Ssklower mtod (m, octet *)[4] = diagnostic; 56245895Ssklower if (lcp -> lcd_facilities) { 56345895Ssklower m -> m_next = lcp -> lcd_facilities; 56445895Ssklower m -> m_pkthdr.len += m -> m_next -> m_len; 56545895Ssklower lcp -> lcd_facilities = 0; 56645895Ssklower } 56745895Ssklower if (abortive) 56845895Ssklower lcp -> lcd_template = m; 56945895Ssklower else { 57045895Ssklower struct socket *so = lcp -> lcd_so; 57145895Ssklower struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb; 57247271Ssklower sbappendrecord (sb, m); 57345895Ssklower } 57441593Ssklower pk_output (lcp); 57541593Ssklower 57641593Ssklower } 57741593Ssklower 57847271Ssklower /* 57947271Ssklower * This procedure generates RNR's or RR's to inhibit or enable 58047271Ssklower * inward data flow, if the current state changes (blocked ==> open or 58147271Ssklower * vice versa), or if forced to generate one. One forces RNR's to ack data. 58247271Ssklower */ 58347271Ssklower pk_flowcontrol (lcp, inhibit, forced) 58447271Ssklower register struct pklcd *lcp; 58547271Ssklower { 58647271Ssklower inhibit = (inhibit != 0); 58747271Ssklower if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER || 58847271Ssklower (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit)) 58947271Ssklower return; 59047271Ssklower lcp -> lcd_rxrnr_condition = inhibit; 59149929Ssklower lcp -> lcd_template = 59249929Ssklower pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR); 59347271Ssklower pk_output (lcp); 59447271Ssklower } 59547271Ssklower 59641593Ssklower /* 59747271Ssklower * This procedure sends a RESET request packet. It re-intializes 59841593Ssklower * virtual circuit. 59941593Ssklower */ 60041593Ssklower 60141593Ssklower static 60245895Ssklower pk_reset (lcp, diagnostic) 60341593Ssklower register struct pklcd *lcp; 60441593Ssklower { 60545895Ssklower register struct mbuf *m; 60645895Ssklower register struct socket *so = lcp -> lcd_so; 60741593Ssklower 60841593Ssklower if (lcp -> lcd_state != DATA_TRANSFER) 60941593Ssklower return; 61041593Ssklower 61145895Ssklower if (so) 61245895Ssklower so -> so_error = ECONNRESET; 61341593Ssklower lcp -> lcd_reset_condition = TRUE; 61441593Ssklower 61541593Ssklower /* Reset all the control variables for the channel. */ 61645895Ssklower pk_flush (lcp); 61741593Ssklower lcp -> lcd_window_condition = lcp -> lcd_rnr_condition = 61841593Ssklower lcp -> lcd_intrconf_pending = FALSE; 61941593Ssklower lcp -> lcd_rsn = MODULUS - 1; 62041593Ssklower lcp -> lcd_ssn = 0; 62141593Ssklower lcp -> lcd_output_window = lcp -> lcd_input_window = 62241593Ssklower lcp -> lcd_last_transmitted_pr = 0; 62345895Ssklower m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET); 62449595Ssklower m -> m_pkthdr.len = m -> m_len += 2; 62547271Ssklower mtod (m, struct x25_packet *) -> packet_data = 0; 62647271Ssklower mtod (m, octet *)[4] = diagnostic; 62745895Ssklower pk_output (lcp); 62845895Ssklower 62945895Ssklower } 63045895Ssklower 63145895Ssklower /* 63245895Ssklower * This procedure frees all data queued for output or delivery on a 63345895Ssklower * virtual circuit. 63445895Ssklower */ 63545895Ssklower 63645895Ssklower pk_flush (lcp) 63745895Ssklower register struct pklcd *lcp; 63845895Ssklower { 63945895Ssklower register struct socket *so; 64045895Ssklower 64145895Ssklower if (lcp -> lcd_template) 64245895Ssklower m_freem (lcp -> lcd_template); 64345895Ssklower 64445895Ssklower if (lcp -> lcd_cps) { 64547271Ssklower m_freem (lcp -> lcd_cps); 64645895Ssklower lcp -> lcd_cps = 0; 64745895Ssklower } 64847271Ssklower if (lcp -> lcd_facilities) { 64947271Ssklower m_freem (lcp -> lcd_facilities); 65047271Ssklower lcp -> lcd_facilities = 0; 65147271Ssklower } 65247271Ssklower if (so = lcp -> lcd_so) { 65342140Ssklower sbflush (&so -> so_snd); 65445895Ssklower } else 65545895Ssklower sbflush (&lcp -> lcd_sb); 65641593Ssklower } 65741593Ssklower 65841593Ssklower /* 65941593Ssklower * This procedure handles all local protocol procedure errors. 66041593Ssklower */ 66141593Ssklower 66245895Ssklower pk_procerror (error, lcp, errstr, diagnostic) 66341593Ssklower register struct pklcd *lcp; 66441593Ssklower char *errstr; 66541593Ssklower { 66641593Ssklower 66741593Ssklower pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr); 66841593Ssklower 66941593Ssklower switch (error) { 67041593Ssklower case CLEAR: 67145297Ssklower if (lcp -> lcd_so) { 67245297Ssklower lcp -> lcd_so -> so_error = ECONNABORTED; 67345297Ssklower soisdisconnecting (lcp -> lcd_so); 67441593Ssklower } 67545895Ssklower pk_clear (lcp, diagnostic, 1); 67641593Ssklower break; 67741593Ssklower 67841593Ssklower case RESET: 67945895Ssklower pk_reset (lcp, diagnostic); 68041593Ssklower } 68141593Ssklower } 68241593Ssklower 68341593Ssklower /* 68441593Ssklower * This procedure is called during the DATA TRANSFER state to check 68541593Ssklower * and process the P(R) values received in the DATA, RR OR RNR 68641593Ssklower * packets. 68741593Ssklower */ 68841593Ssklower 68941593Ssklower pk_ack (lcp, pr) 69041593Ssklower struct pklcd *lcp; 69141593Ssklower unsigned pr; 69241593Ssklower { 69341593Ssklower register struct socket *so = lcp -> lcd_so; 69441593Ssklower 69541593Ssklower if (lcp -> lcd_output_window == pr) 69641593Ssklower return (PACKET_OK); 69741593Ssklower if (lcp -> lcd_output_window < lcp -> lcd_ssn) { 69841593Ssklower if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) { 69945895Ssklower pk_procerror (RESET, lcp, 70045895Ssklower "p(r) flow control error", 2); 70141593Ssklower return (ERROR_PACKET); 70241593Ssklower } 70341593Ssklower } 70441593Ssklower else { 70541593Ssklower if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) { 70645895Ssklower pk_procerror (RESET, lcp, 70747271Ssklower "p(r) flow control error #2", 2); 70841593Ssklower return (ERROR_PACKET); 70941593Ssklower } 71041593Ssklower } 71141593Ssklower 71241593Ssklower lcp -> lcd_output_window = pr; /* Rotate window. */ 71341593Ssklower if (lcp -> lcd_window_condition == TRUE) 71441593Ssklower lcp -> lcd_window_condition = FALSE; 71541593Ssklower 71653744Ssklower if (so && (so -> so_snd.sb_flags & SB_NOTIFY)) 71741593Ssklower sowwakeup (so); 71841593Ssklower 71941593Ssklower return (PACKET_OK); 72041593Ssklower } 72141593Ssklower 72241593Ssklower /* 72341593Ssklower * This procedure decodes the X.25 level 3 packet returning a 72441593Ssklower * code to be used in switchs or arrays. 72541593Ssklower */ 72641593Ssklower 72741593Ssklower pk_decode (xp) 72841593Ssklower register struct x25_packet *xp; 72941593Ssklower { 73041593Ssklower register int type; 73141593Ssklower 73241593Ssklower if (xp -> fmt_identifier != 1) 73341593Ssklower return (INVALID_PACKET); 73445895Ssklower #ifdef ancient_history 73541593Ssklower /* 73641593Ssklower * Make sure that the logical channel group number is 0. 73741593Ssklower * This restriction may be removed at some later date. 73841593Ssklower */ 73941593Ssklower if (xp -> lc_group_number != 0) 74041593Ssklower return (INVALID_PACKET); 74145895Ssklower #endif 74241593Ssklower /* 74341593Ssklower * Test for data packet first. 74441593Ssklower */ 74541593Ssklower if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR)) 74641593Ssklower return (DATA); 74741593Ssklower 74841593Ssklower /* 74941593Ssklower * Test if flow control packet (RR or RNR). 75041593Ssklower */ 75141593Ssklower if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR)) 75247271Ssklower switch (xp -> packet_type & 0x1f) { 75347271Ssklower case X25_RR: 75441593Ssklower return (RR); 75547271Ssklower case X25_RNR: 75641593Ssklower return (RNR); 75747271Ssklower case X25_REJECT: 75847271Ssklower return (REJECT); 75947271Ssklower } 76041593Ssklower 76141593Ssklower /* 76241593Ssklower * Determine the rest of the packet types. 76341593Ssklower */ 76441593Ssklower switch (xp -> packet_type) { 76541593Ssklower case X25_CALL: 76641593Ssklower type = CALL; 76741593Ssklower break; 76841593Ssklower 76941593Ssklower case X25_CALL_ACCEPTED: 77041593Ssklower type = CALL_ACCEPTED; 77141593Ssklower break; 77241593Ssklower 77341593Ssklower case X25_CLEAR: 77441593Ssklower type = CLEAR; 77541593Ssklower break; 77641593Ssklower 77741593Ssklower case X25_CLEAR_CONFIRM: 77841593Ssklower type = CLEAR_CONF; 77941593Ssklower break; 78041593Ssklower 78141593Ssklower case X25_INTERRUPT: 78241593Ssklower type = INTERRUPT; 78341593Ssklower break; 78441593Ssklower 78541593Ssklower case X25_INTERRUPT_CONFIRM: 78641593Ssklower type = INTERRUPT_CONF; 78741593Ssklower break; 78841593Ssklower 78941593Ssklower case X25_RESET: 79041593Ssklower type = RESET; 79141593Ssklower break; 79241593Ssklower 79341593Ssklower case X25_RESET_CONFIRM: 79441593Ssklower type = RESET_CONF; 79541593Ssklower break; 79641593Ssklower 79741593Ssklower case X25_RESTART: 79841593Ssklower type = RESTART; 79941593Ssklower break; 80041593Ssklower 80141593Ssklower case X25_RESTART_CONFIRM: 80241593Ssklower type = RESTART_CONF; 80341593Ssklower break; 80441593Ssklower 80547271Ssklower case X25_DIAGNOSTIC: 80648873Ssklower type = DIAG_TYPE; 80747271Ssklower break; 80847271Ssklower 80941593Ssklower default: 81041593Ssklower type = INVALID_PACKET; 81141593Ssklower } 81241593Ssklower return (type); 81341593Ssklower } 81441593Ssklower 81541593Ssklower /* 81641593Ssklower * A restart packet has been received. Print out the reason 81741593Ssklower * for the restart. 81841593Ssklower */ 81941593Ssklower 82041593Ssklower pk_restartcause (pkp, xp) 82141593Ssklower struct pkcb *pkp; 82241593Ssklower register struct x25_packet *xp; 82341593Ssklower { 82441593Ssklower register struct x25config *xcp = pkp -> pk_xcp; 82545574Ssklower register int lcn = LCN(xp); 82641593Ssklower 82741593Ssklower switch (xp -> packet_data) { 82841593Ssklower case X25_RESTART_LOCAL_PROCEDURE_ERROR: 82941593Ssklower pk_message (lcn, xcp, "restart: local procedure error"); 83041593Ssklower break; 83141593Ssklower 83241593Ssklower case X25_RESTART_NETWORK_CONGESTION: 83341593Ssklower pk_message (lcn, xcp, "restart: network congestion"); 83441593Ssklower break; 83541593Ssklower 83641593Ssklower case X25_RESTART_NETWORK_OPERATIONAL: 83741593Ssklower pk_message (lcn, xcp, "restart: network operational"); 83841593Ssklower break; 83941593Ssklower 84041593Ssklower default: 84141593Ssklower pk_message (lcn, xcp, "restart: unknown cause"); 84241593Ssklower } 84341593Ssklower } 84441593Ssklower 84541593Ssklower #define MAXRESETCAUSE 7 84641593Ssklower 84741593Ssklower int Reset_cause[] = { 84841593Ssklower EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG 84941593Ssklower }; 85041593Ssklower 85141593Ssklower /* 85241593Ssklower * A reset packet has arrived. Return the cause to the user. 85341593Ssklower */ 85441593Ssklower 85541593Ssklower pk_resetcause (pkp, xp) 85641593Ssklower struct pkcb *pkp; 85741593Ssklower register struct x25_packet *xp; 85841593Ssklower { 85945297Ssklower register struct pklcd *lcp = 86045574Ssklower pkp -> pk_chan[LCN(xp)]; 86141593Ssklower register int code = xp -> packet_data; 86241593Ssklower 86341593Ssklower if (code > MAXRESETCAUSE) 86441593Ssklower code = 7; /* EXRNCG */ 86541593Ssklower 86647271Ssklower pk_message(LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x", 86747271Ssklower xp -> packet_data, 4[(u_char *)xp]); 86847271Ssklower 86949929Ssklower if (lcp -> lcd_so) 87049929Ssklower lcp -> lcd_so -> so_error = Reset_cause[code]; 87141593Ssklower } 87241593Ssklower 87341593Ssklower #define MAXCLEARCAUSE 25 87441593Ssklower 87541593Ssklower int Clear_cause[] = { 87641593Ssklower EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0, 87741593Ssklower 0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE, 87841593Ssklower 0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC 87941593Ssklower }; 88041593Ssklower 88141593Ssklower /* 88241593Ssklower * A clear packet has arrived. Return the cause to the user. 88341593Ssklower */ 88441593Ssklower 88541593Ssklower pk_clearcause (pkp, xp) 88641593Ssklower struct pkcb *pkp; 88741593Ssklower register struct x25_packet *xp; 88841593Ssklower { 88945297Ssklower register struct pklcd *lcp = 89045574Ssklower pkp -> pk_chan[LCN(xp)]; 89141593Ssklower register int code = xp -> packet_data; 89241593Ssklower 89341593Ssklower if (code > MAXCLEARCAUSE) 89441593Ssklower code = 5; /* EXRNCG */ 89549595Ssklower if (lcp -> lcd_so) 89649595Ssklower lcp -> lcd_so -> so_error = Clear_cause[code]; 89741593Ssklower } 89841593Ssklower 89941593Ssklower char * 90041593Ssklower format_ntn (xcp) 90141593Ssklower register struct x25config *xcp; 90241593Ssklower { 90341593Ssklower 90445165Ssklower return (xcp -> xc_addr.x25_addr); 90541593Ssklower } 90641593Ssklower 90741593Ssklower /* VARARGS1 */ 90841593Ssklower pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6) 90941593Ssklower struct x25config *xcp; 91041593Ssklower char *fmt; 91141593Ssklower { 91241593Ssklower 91341593Ssklower if (lcn) 91441593Ssklower if (pkcbhead -> pk_next) 91541593Ssklower printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn); 91641593Ssklower else 91741593Ssklower printf ("X.25: lcn %d: ", lcn); 91841593Ssklower else 91941593Ssklower if (pkcbhead -> pk_next) 92041593Ssklower printf ("X.25(%s): ", format_ntn (xcp)); 92141593Ssklower else 92241593Ssklower printf ("X.25: "); 92341593Ssklower 92441593Ssklower printf (fmt, a1, a2, a3, a4, a5, a6); 92541593Ssklower printf ("\n"); 92641593Ssklower } 92745297Ssklower 92847271Ssklower pk_fragment (lcp, m0, qbit, mbit, wait) 92945297Ssklower struct mbuf *m0; 93045297Ssklower register struct pklcd *lcp; 93145297Ssklower { 93245297Ssklower register struct mbuf *m = m0; 93345297Ssklower register struct x25_packet *xp; 93445297Ssklower register struct sockbuf *sb; 93547271Ssklower struct mbuf *head = 0, *next, **mp = &head, *m_split (); 93645297Ssklower int totlen, psize = 1 << (lcp -> lcd_packetsize); 93745297Ssklower 93845297Ssklower if (m == 0) 93949595Ssklower return 0; 94052433Ssklower if ((m -> m_flags & M_PKTHDR) == 0) 94147271Ssklower panic ("pk_fragment"); 94245297Ssklower totlen = m -> m_pkthdr.len; 94345574Ssklower m -> m_act = 0; 94445297Ssklower sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb; 94545297Ssklower do { 94645297Ssklower if (totlen > psize) { 94747271Ssklower if ((next = m_split (m, psize, wait)) == 0) 94845297Ssklower goto abort; 94945297Ssklower totlen -= psize; 95045574Ssklower } else 95145574Ssklower next = 0; 95245297Ssklower M_PREPEND(m, PKHEADERLN, wait); 95345297Ssklower if (m == 0) 95445297Ssklower goto abort; 95545574Ssklower *mp = m; 95645574Ssklower mp = & m -> m_act; 95745574Ssklower *mp = 0; 95847271Ssklower xp = mtod (m, struct x25_packet *); 95945297Ssklower 0[(char *)xp] = 0; 96045297Ssklower if (qbit) 96145574Ssklower xp -> q_bit = 1; 96245574Ssklower if (lcp -> lcd_flags & X25_DBIT) 96345574Ssklower xp -> d_bit = 1; 96445297Ssklower xp -> fmt_identifier = 1; 96545297Ssklower xp -> packet_type = X25_DATA; 96645574Ssklower SET_LCN(xp, lcp -> lcd_lcn); 96745574Ssklower if (next || (mbit && (totlen == psize || 96845574Ssklower (lcp -> lcd_flags & X25_DBIT)))) 96945297Ssklower MBIT(xp) = 1; 97045297Ssklower } while (m = next); 97145574Ssklower for (m = head; m; m = next) { 97245297Ssklower next = m -> m_act; 97345297Ssklower m -> m_act = 0; 97447271Ssklower sbappendrecord (sb, m); 97545297Ssklower } 97645297Ssklower return 0; 97745297Ssklower abort: 97845574Ssklower if (wait) 97947271Ssklower panic ("pk_fragment null mbuf after wait"); 98045574Ssklower if (next) 98147271Ssklower m_freem (next); 98245574Ssklower for (m = head; m; m = next) { 98345297Ssklower next = m -> m_act; 98447271Ssklower m_freem (m); 98545297Ssklower } 98645297Ssklower return ENOBUFS; 98745297Ssklower } 988