149268Sbostic /*-
2*63222Sbostic * Copyright (c) 1991, 1993
3*63222Sbostic * The Regents of the University of California. All rights reserved.
449268Sbostic *
549268Sbostic * %sccs.include.redist.c%
649268Sbostic *
7*63222Sbostic * @(#)tp_cons.c 8.1 (Berkeley) 06/10/93
849268Sbostic */
949268Sbostic
1036398Ssklower /***********************************************************
1136398Ssklower Copyright IBM Corporation 1987
1236398Ssklower
1336398Ssklower All Rights Reserved
1436398Ssklower
1536398Ssklower Permission to use, copy, modify, and distribute this software and its
1636398Ssklower documentation for any purpose and without fee is hereby granted,
1736398Ssklower provided that the above copyright notice appear in all copies and that
1836398Ssklower both that copyright notice and this permission notice appear in
1936398Ssklower supporting documentation, and that the name of IBM not be
2036398Ssklower used in advertising or publicity pertaining to distribution of the
2136398Ssklower software without specific, written prior permission.
2236398Ssklower
2336398Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436398Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536398Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636398Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736398Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836398Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936398Ssklower SOFTWARE.
3036398Ssklower
3136398Ssklower ******************************************************************/
3236398Ssklower
3336398Ssklower /*
3436398Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536398Ssklower */
3636398Ssklower /*
3736398Ssklower * ARGO TP
3836398Ssklower * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $
3936398Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $
4036398Ssklower *
4145900Ssklower * Here is where you find the iso- and cons-dependent code. We've tried
4236398Ssklower * keep all net-level and (primarily) address-family-dependent stuff
4336398Ssklower * out of the tp source, and everthing here is reached indirectly
4436398Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
4536398Ssklower * (see tp_pcb.c).
4636398Ssklower * The routines here are:
4749268Sbostic * tpcons_input: pullup and call tp_input w/ correct arguments
4849268Sbostic * tpcons_output: package a pkt for cons given an isopcb & some data
4949268Sbostic * cons_chan_to_tpcb: find a tpcb based on the channel #
5036398Ssklower */
5136398Ssklower
5236398Ssklower #ifdef ISO
5345900Ssklower #ifdef TPCONS
5436398Ssklower
5556533Sbostic #include <sys/param.h>
5656533Sbostic #include <sys/socket.h>
5756533Sbostic #include <sys/domain.h>
5856533Sbostic #include <sys/mbuf.h>
5956533Sbostic #include <sys/errno.h>
6056533Sbostic #include <sys/time.h>
6145900Ssklower
6256533Sbostic #include <net/if.h>
6356533Sbostic #include <net/route.h>
6436398Ssklower
6556533Sbostic #include <netiso/tp_param.h>
6656533Sbostic #include <netiso/argo_debug.h>
6756533Sbostic #include <netiso/tp_stat.h>
6856533Sbostic #include <netiso/tp_pcb.h>
6956533Sbostic #include <netiso/tp_trace.h>
7056533Sbostic #include <netiso/tp_stat.h>
7156533Sbostic #include <netiso/tp_tpdu.h>
7256533Sbostic #include <netiso/iso.h>
7356533Sbostic #include <netiso/iso_errno.h>
7456533Sbostic #include <netiso/iso_pcb.h>
7556533Sbostic #include <netiso/cons.h>
7656533Sbostic #include <netiso/tp_seq.h>
7736398Ssklower
7845900Ssklower #undef FALSE
7945900Ssklower #undef TRUE
8056533Sbostic #include <netccitt/x25.h>
8156533Sbostic #include <netccitt/pk.h>
8256533Sbostic #include <netccitt/pk_var.h>
8345900Ssklower
8456533Sbostic #include <netiso/if_cons.c>
8536398Ssklower int tpcons_output();
8636398Ssklower
8736398Ssklower /*
8836398Ssklower * CALLED FROM:
8945900Ssklower * tp_route_to() for PRU_CONNECT
9045900Ssklower * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
9145900Ssklower * version of the previous procedure for X.25
9245900Ssklower */
9345900Ssklower
9445900Ssklower tpcons_pcbconnect(isop, nam)
9545900Ssklower struct isopcb *isop;
9645900Ssklower register struct mbuf *nam;
9745900Ssklower {
9845900Ssklower int error;
9945900Ssklower if (error = iso_pcbconnect(isop, nam))
10045900Ssklower return error;
10145900Ssklower if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) {
10245900Ssklower IFDEBUG(D_CCONS)
10345900Ssklower printf("tpcons_pcbconnect: no pklcd; returns 0x%x\n", error);
10445900Ssklower ENDDEBUG
10545900Ssklower return ENOBUFS;
10645900Ssklower }
10745900Ssklower if (error = cons_connect(isop)) { /* if it doesn't work */
10845900Ssklower /* oh, dear, throw packet away */
10945900Ssklower pk_disconnect((struct pklcd *)isop->isop_chan);
11045900Ssklower isop->isop_chan = 0;
11149257Ssklower } else
11249257Ssklower isop->isop_refcnt = 1;
11349257Ssklower return error;
11445900Ssklower }
11545900Ssklower
11645900Ssklower
11745900Ssklower /*
11845900Ssklower * CALLED FROM:
11936398Ssklower * cons
12036398Ssklower * FUNCTION and ARGUMENTS:
12136398Ssklower * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not -
12236398Ssklower */
12336398Ssklower ProtoHook
tpcons_ctlinput(cmd,siso,isop)12436398Ssklower tpcons_ctlinput(cmd, siso, isop)
12536398Ssklower int cmd;
12636398Ssklower struct sockaddr_iso *siso;
12736398Ssklower struct isopcb *isop;
12836398Ssklower {
12950648Ssklower register struct tp_pcb *tpcb = 0;
13050648Ssklower
13150648Ssklower if (isop->isop_socket)
13250648Ssklower tpcb = (struct tp_pcb *)isop->isop_socket->so_pcb;
13336398Ssklower switch (cmd) {
13436398Ssklower
13536398Ssklower case PRC_CONS_SEND_DONE:
13650648Ssklower if (tpcb) {
13736398Ssklower struct tp_event E;
13836398Ssklower int error = 0;
13936398Ssklower
14050648Ssklower if (tpcb->tp_class == TP_CLASS_0) {
14136398Ssklower /* only if class is exactly class zero, not
14236398Ssklower * still in class negotiation
14336398Ssklower */
14436398Ssklower /* fake an ack */
14536398Ssklower register SeqNum seq = SEQ_ADD(tpcb, tpcb->tp_snduna, 1);
14636398Ssklower
14736398Ssklower IFTRACE(D_DATA)
14836398Ssklower tptrace(TPPTmisc, "FAKE ACK seq cdt 1",
14936398Ssklower seq, 0,0,0);
15036398Ssklower ENDTRACE
15136398Ssklower IFDEBUG(D_DATA)
15236398Ssklower printf("FAKE ACK seq 0x%x cdt 1\n", seq );
15336398Ssklower ENDDEBUG
15436398Ssklower E.ATTR(AK_TPDU).e_cdt = 1;
15536398Ssklower E.ATTR(AK_TPDU).e_seq = seq;
15636398Ssklower E.ATTR(AK_TPDU).e_subseq = 0;
15736398Ssklower E.ATTR(AK_TPDU).e_fcc_present = 0;
15836398Ssklower error = DoEvent(AK_TPDU);
15936398Ssklower if( error ) {
16036398Ssklower tpcb->tp_sock->so_error = error;
16136398Ssklower }
16236398Ssklower } /* else ignore it */
16350648Ssklower }
16436398Ssklower break;
16536398Ssklower case PRC_ROUTEDEAD:
16650648Ssklower if (tpcb && tpcb->tp_class == TP_CLASS_0) {
16736398Ssklower tpiso_reset(isop);
16836398Ssklower break;
16936398Ssklower } /* else drop through */
17036398Ssklower default:
17136398Ssklower (void) tpclnp_ctlinput(cmd, siso);
17236398Ssklower break;
17336398Ssklower }
17436398Ssklower return 0;
17536398Ssklower }
17636398Ssklower
17736398Ssklower /*
17836398Ssklower * CALLED FROM:
17936398Ssklower * cons's intr routine
18036398Ssklower * FUNCTION and ARGUMENTS:
18136398Ssklower * Take a packet (m) from cons, pullup m as required by tp,
18236398Ssklower * ignore the socket argument, and call tp_input.
18336398Ssklower * No return value.
18436398Ssklower */
18536398Ssklower ProtoHook
tpcons_input(m,faddr,laddr,channel)18645900Ssklower tpcons_input(m, faddr, laddr, channel)
18736398Ssklower struct mbuf *m;
18836398Ssklower struct sockaddr_iso *faddr, *laddr;
18945900Ssklower caddr_t channel;
19036398Ssklower {
19136398Ssklower if( m == MNULL)
19236398Ssklower return 0;
19336398Ssklower
19436398Ssklower m = (struct mbuf *)tp_inputprep(m);
19536398Ssklower
19636398Ssklower IFDEBUG(D_TPINPUT)
19736398Ssklower printf("tpcons_input before tp_input(m 0x%x)\n", m);
19836398Ssklower dump_buf( m, 12+ m->m_len);
19936398Ssklower ENDDEBUG
20048743Ssklower tp_input(m, faddr, laddr, channel, tpcons_output, 0);
20136398Ssklower return 0;
20236398Ssklower }
20336398Ssklower
20436398Ssklower
20536398Ssklower /*
20636398Ssklower * CALLED FROM:
20736398Ssklower * tp_emit()
20836398Ssklower * FUNCTION and ARGUMENTS:
20936398Ssklower * Take a packet(m0) from tp and package it so that cons will accept it.
21036398Ssklower * This means filling in a few of the fields.
21136398Ssklower * inp is the isopcb structure; datalen is the length of the data in the
21236398Ssklower * mbuf string m0.
21336398Ssklower * RETURN VALUE:
21436398Ssklower * whatever (E*) is returned form the net layer output routine.
21536398Ssklower */
21636398Ssklower
21736398Ssklower int
tpcons_output(isop,m0,datalen,nochksum)21836398Ssklower tpcons_output(isop, m0, datalen, nochksum)
21936398Ssklower struct isopcb *isop;
22036398Ssklower struct mbuf *m0;
22136398Ssklower int datalen;
22236398Ssklower int nochksum;
22336398Ssklower {
22445900Ssklower register struct mbuf *m = m0;
22536398Ssklower int error;
22636398Ssklower
22736398Ssklower IFDEBUG(D_EMIT)
22836398Ssklower printf(
22936398Ssklower "tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n",
23036398Ssklower isop, m0, datalen, isop->isop_socket);
23136398Ssklower ENDDEBUG
23245900Ssklower if (m == MNULL)
23336398Ssklower return 0;
23449586Ssklower if ((m->m_flags & M_PKTHDR) == 0) {
23545900Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA);
23645900Ssklower if (m == 0)
23745900Ssklower return ENOBUFS;
23845900Ssklower m->m_next = m0;
23945900Ssklower }
24045900Ssklower m->m_pkthdr.len = datalen;
24150648Ssklower if (isop->isop_chan == 0) {
24250648Ssklower /* got a restart maybe? */
24350648Ssklower if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) {
24450648Ssklower IFDEBUG(D_CCONS)
24550648Ssklower printf("tpcons_output: no pklcd\n");
24650648Ssklower ENDDEBUG
24750648Ssklower error = ENOBUFS;
24850648Ssklower }
24950648Ssklower if (error = cons_connect(isop)) {
25050648Ssklower pk_disconnect((struct pklcd *)isop->isop_chan);
25150648Ssklower isop->isop_chan = 0;
25250648Ssklower IFDEBUG(D_CCONS)
25350648Ssklower printf("tpcons_output: can't reconnect\n");
25450648Ssklower ENDDEBUG
25550648Ssklower }
25650648Ssklower } else {
25750648Ssklower error = pk_send(isop->isop_chan, m);
25850648Ssklower IncStat(ts_tpdu_sent);
25950648Ssklower }
26036398Ssklower return error;
26136398Ssklower }
26236398Ssklower /*
26336398Ssklower * CALLED FROM:
26436398Ssklower * tp_error_emit()
26536398Ssklower * FUNCTION and ARGUMENTS:
26645900Ssklower * Take a packet(m0) from tp and package it so that cons will accept it.
26745900Ssklower * chan is the cons channel to use; datalen is the length of the data in the
26845900Ssklower * mbuf string m0.
26936398Ssklower * RETURN VALUE:
27036398Ssklower * whatever (E*) is returned form the net layer output routine.
27136398Ssklower */
27236398Ssklower
27336398Ssklower int
tpcons_dg_output(chan,m0,datalen)27445900Ssklower tpcons_dg_output(chan, m0, datalen)
27545900Ssklower caddr_t chan;
27636398Ssklower struct mbuf *m0;
27736398Ssklower int datalen;
27836398Ssklower {
27945900Ssklower return tpcons_output(((struct pklcd *)chan)->lcd_upnext, m0, datalen, 0);
28036398Ssklower }
28160359Sbostic #endif /* TPCONS */
28260359Sbostic #endif /* ISO */
283