xref: /original-bsd/sys/netiso/tp_cons.c (revision 3705696b)
1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)tp_cons.c	8.1 (Berkeley) 06/10/93
8  */
9 
10 /***********************************************************
11 		Copyright IBM Corporation 1987
12 
13                       All Rights Reserved
14 
15 Permission to use, copy, modify, and distribute this software and its
16 documentation for any purpose and without fee is hereby granted,
17 provided that the above copyright notice appear in all copies and that
18 both that copyright notice and this permission notice appear in
19 supporting documentation, and that the name of IBM not be
20 used in advertising or publicity pertaining to distribution of the
21 software without specific, written prior permission.
22 
23 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29 SOFTWARE.
30 
31 ******************************************************************/
32 
33 /*
34  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
35  */
36 /*
37  * ARGO TP
38  * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $
39  * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $
40  *
41  * Here is where you find the iso- and cons-dependent code.  We've tried
42  * keep all net-level and (primarily) address-family-dependent stuff
43  * out of the tp source, and everthing here is reached indirectly
44  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
45  * (see tp_pcb.c).
46  * The routines here are:
47  *	tpcons_input: pullup and call tp_input w/ correct arguments
48  *	tpcons_output: package a pkt for cons given an isopcb & some data
49  *	cons_chan_to_tpcb: find a tpcb based on the channel #
50  */
51 
52 #ifdef ISO
53 #ifdef TPCONS
54 
55 #include <sys/param.h>
56 #include <sys/socket.h>
57 #include <sys/domain.h>
58 #include <sys/mbuf.h>
59 #include <sys/errno.h>
60 #include <sys/time.h>
61 
62 #include <net/if.h>
63 #include <net/route.h>
64 
65 #include <netiso/tp_param.h>
66 #include <netiso/argo_debug.h>
67 #include <netiso/tp_stat.h>
68 #include <netiso/tp_pcb.h>
69 #include <netiso/tp_trace.h>
70 #include <netiso/tp_stat.h>
71 #include <netiso/tp_tpdu.h>
72 #include <netiso/iso.h>
73 #include <netiso/iso_errno.h>
74 #include <netiso/iso_pcb.h>
75 #include <netiso/cons.h>
76 #include <netiso/tp_seq.h>
77 
78 #undef FALSE
79 #undef TRUE
80 #include <netccitt/x25.h>
81 #include <netccitt/pk.h>
82 #include <netccitt/pk_var.h>
83 
84 #include <netiso/if_cons.c>
85 int tpcons_output();
86 
87 /*
88  * CALLED FROM:
89  *  tp_route_to() for PRU_CONNECT
90  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
91  *  version of the previous procedure for X.25
92  */
93 
94 tpcons_pcbconnect(isop, nam)
95 struct isopcb *isop;
96 register struct mbuf *nam;
97 {
98 	int error;
99 	if (error = iso_pcbconnect(isop, nam))
100 		return error;
101 	if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) {
102 		IFDEBUG(D_CCONS)
103 			printf("tpcons_pcbconnect: no pklcd; returns 0x%x\n", error);
104 		ENDDEBUG
105 		return ENOBUFS;
106 	}
107 	if (error = cons_connect(isop)) { /* if it doesn't work */
108 		/* oh, dear, throw packet away */
109 		pk_disconnect((struct pklcd *)isop->isop_chan);
110 		isop->isop_chan = 0;
111 	} else
112 		isop->isop_refcnt = 1;
113 	return error;
114 }
115 
116 
117 /*
118  * CALLED FROM:
119  * 	cons
120  * FUNCTION and ARGUMENTS:
121  * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not -
122  */
123 ProtoHook
124 tpcons_ctlinput(cmd, siso, isop)
125 	int cmd;
126 	struct sockaddr_iso *siso;
127 	struct isopcb *isop;
128 {
129 	register struct tp_pcb *tpcb = 0;
130 
131 	if (isop->isop_socket)
132 		tpcb = (struct tp_pcb *)isop->isop_socket->so_pcb;
133 	switch (cmd) {
134 
135 	case PRC_CONS_SEND_DONE:
136 		if (tpcb) {
137 			struct 	tp_event 		E;
138 			int 					error = 0;
139 
140 			if (tpcb->tp_class == TP_CLASS_0) {
141 				/* only if class is exactly class zero, not
142 				 * still in class negotiation
143 				 */
144 				/* fake an ack */
145 				register SeqNum	seq =  SEQ_ADD(tpcb, tpcb->tp_snduna, 1);
146 
147 				IFTRACE(D_DATA)
148 					tptrace(TPPTmisc, "FAKE ACK seq cdt 1",
149 						seq, 0,0,0);
150 				ENDTRACE
151 				IFDEBUG(D_DATA)
152 					printf("FAKE ACK seq 0x%x cdt 1\n", seq );
153 				ENDDEBUG
154 				E.ATTR(AK_TPDU).e_cdt = 1;
155 				E.ATTR(AK_TPDU).e_seq = seq;
156 				E.ATTR(AK_TPDU).e_subseq = 0;
157 				E.ATTR(AK_TPDU).e_fcc_present = 0;
158 				error =  DoEvent(AK_TPDU);
159 				if( error ) {
160 					tpcb->tp_sock->so_error = error;
161 				}
162 			} /* else ignore it */
163 		}
164 		break;
165 	case PRC_ROUTEDEAD:
166 		if (tpcb && tpcb->tp_class == TP_CLASS_0) {
167 			tpiso_reset(isop);
168 			break;
169 		} /* else drop through */
170 	default:
171 		(void) tpclnp_ctlinput(cmd, siso);
172 		break;
173 	}
174 	return 0;
175 }
176 
177 /*
178  * CALLED FROM:
179  * 	cons's intr routine
180  * FUNCTION and ARGUMENTS:
181  * Take a packet (m) from cons, pullup m as required by tp,
182  *  ignore the socket argument, and call tp_input.
183  * No return value.
184  */
185 ProtoHook
186 tpcons_input(m, faddr, laddr, channel)
187 	struct mbuf 		*m;
188 	struct sockaddr_iso	*faddr, *laddr;
189 	caddr_t				channel;
190 {
191 	if( m == MNULL)
192 		return 0;
193 
194 	m = (struct mbuf *)tp_inputprep(m);
195 
196 	IFDEBUG(D_TPINPUT)
197 		printf("tpcons_input before tp_input(m 0x%x)\n", m);
198 		dump_buf( m, 12+ m->m_len);
199 	ENDDEBUG
200 	tp_input(m, faddr, laddr, channel, tpcons_output, 0);
201 	return 0;
202 }
203 
204 
205 /*
206  * CALLED FROM:
207  *  tp_emit()
208  * FUNCTION and ARGUMENTS:
209  *  Take a packet(m0) from tp and package it so that cons will accept it.
210  *  This means filling in a few of the fields.
211  *  inp is the isopcb structure; datalen is the length of the data in the
212  *  mbuf string m0.
213  * RETURN VALUE:
214  *  whatever (E*) is returned form the net layer output routine.
215  */
216 
217 int
218 tpcons_output(isop, m0, datalen, nochksum)
219 	struct isopcb		*isop;
220 	struct mbuf 		*m0;
221 	int 				datalen;
222 	int					nochksum;
223 {
224 	register	struct mbuf *m = m0;
225 	int					error;
226 
227 	IFDEBUG(D_EMIT)
228 		printf(
229 		"tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n",
230 			isop, m0, datalen, isop->isop_socket);
231 	ENDDEBUG
232 	if (m == MNULL)
233 		return 0;
234 	if ((m->m_flags & M_PKTHDR) == 0) {
235 		MGETHDR(m, M_DONTWAIT, MT_DATA);
236 		if (m == 0)
237 			return ENOBUFS;
238 		m->m_next = m0;
239 	}
240 	m->m_pkthdr.len = datalen;
241 	if (isop->isop_chan == 0) {
242 		/* got a restart maybe? */
243 		if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) {
244 			IFDEBUG(D_CCONS)
245 				printf("tpcons_output: no pklcd\n");
246 			ENDDEBUG
247 			error = ENOBUFS;
248 		}
249 		if (error = cons_connect(isop)) {
250 			pk_disconnect((struct pklcd *)isop->isop_chan);
251 			isop->isop_chan = 0;
252 			IFDEBUG(D_CCONS)
253 				printf("tpcons_output: can't reconnect\n");
254 			ENDDEBUG
255 		}
256 	} else {
257 		error = pk_send(isop->isop_chan, m);
258 		IncStat(ts_tpdu_sent);
259 	}
260 	return error;
261 }
262 /*
263  * CALLED FROM:
264  *  tp_error_emit()
265  * FUNCTION and ARGUMENTS:
266  *  Take a packet(m0) from tp and package it so that cons will accept it.
267  *  chan is the cons channel to use; datalen is the length of the data in the
268  *  mbuf string m0.
269  * RETURN VALUE:
270  *  whatever (E*) is returned form the net layer output routine.
271  */
272 
273 int
274 tpcons_dg_output(chan, m0, datalen)
275 	caddr_t				chan;
276 	struct mbuf 		*m0;
277 	int 				datalen;
278 {
279 	return tpcons_output(((struct pklcd *)chan)->lcd_upnext, m0, datalen, 0);
280 }
281 #endif /* TPCONS */
282 #endif /* ISO */
283