xref: /csrg-svn/sys/netiso/tp_cons.c (revision 38841)
1 /***********************************************************
2 		Copyright IBM Corporation 1987
3 
4                       All Rights Reserved
5 
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of IBM not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
13 
14 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 SOFTWARE.
21 
22 ******************************************************************/
23 
24 /*
25  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26  */
27 /*
28  * ARGO TP
29  * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $
30  * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $
31  *	@(#)tp_cons.c	7.3 (Berkeley) 08/29/89 *
32  *
33  * Here is where you find the iso-dependent code.  We've tried
34  * keep all net-level and (primarily) address-family-dependent stuff
35  * out of the tp source, and everthing here is reached indirectly
36  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
37  * (see tp_pcb.c).
38  * The routines here are:
39  *		tpcons_mtu: figure out what size tpdu to use
40  *		tpcons_input: pullup and call tp_input w/ correct arguments
41  *		tpcons_output_dg: package a pkt for cons given 2 addresses & some data
42  *		tpcons_output: package a pkt for cons given an isopcb & some data
43  *		cons_chan_to_tpcb: find a tpcb based on the channel #
44  */
45 
46 #ifndef lint
47 static char *rcsid = "$Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $";
48 #endif lint
49 
50 #include "argoxtwentyfive.h"
51 
52 #ifdef ISO
53 #if NARGOXTWENTYFIVE > 0
54 
55 #include "param.h"
56 #include "socket.h"
57 #include "domain.h"
58 #include "mbuf.h"
59 #include "errno.h"
60 #include "time.h"
61 #include "../net/if.h"
62 
63 #include "tp_param.h"
64 #include "argo_debug.h"
65 #include "tp_stat.h"
66 #include "tp_pcb.h"
67 #include "tp_trace.h"
68 #include "tp_stat.h"
69 #include "tp_tpdu.h"
70 #include "../net/route.h"
71 #include "iso.h"
72 #include "iso_pcb.h"
73 #include "cons.h"
74 #include "tp_seq.h"
75 
76 int tpcons_output();
77 
78 /*
79  * CALLED FROM:
80  *  tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
81  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
82  *  version of the previous procedure for X.25
83  */
84 
85 void
86 tpcons_mtu(so, isop, size, negot)
87 	struct socket *so;
88 	struct isopcb *isop;
89 	int *size;
90 	u_char *negot;
91 {
92 	register struct ifnet *ifp;
93 	register int i=0;
94 	int windowsize = so->so_rcv.sb_hiwat;
95 	struct ifnet	*iso_routeifp();
96 
97 	IFTRACE(D_CONN)
98 		tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0);
99 	ENDTRACE
100 
101 
102 	*size = 1 << *negot;
103 	if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0)
104 		return;
105 
106 	if( *size > windowsize ) {
107 		*size = windowsize;
108 		i++;
109 	}
110 
111 	if(*size > ifp->if_mtu) {
112 		*size = ifp->if_mtu ;
113 		i++;
114 	}
115 	if(i) {
116 		/* size was changed by this routine - have to transform it to
117 		 * the log2 of size
118 		 */
119 		for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++)
120 			;
121 		/* are we on the same LAN? if so, negotiate one tpdu size larger,
122 		 * and actually send the real mtu size
123 		 */
124 		/* PHASE2: replace with iso_on_localnet(&isop->isop_faddr);
125 		 */
126 		if ( !iso_netmatch(&isop->isop_laddr, &isop->isop_faddr) ) {
127 			i--;
128 			*size = 1<<i;
129 		}
130 		*negot = i;
131 	}
132 
133 	IFDEBUG(D_CONN)
134 		printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
135 		ifp->if_name,	*size, *negot);
136 	ENDDEBUG
137 	IFTRACE(D_CONN)
138 		tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ",
139 		*size, *negot, 0, 0);
140 	ENDTRACE
141 }
142 
143 /*
144  * CALLED FROM:
145  * 	cons
146  * FUNCTION and ARGUMENTS:
147  * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not -
148  */
149 ProtoHook
150 tpcons_ctlinput(cmd, siso, isop)
151 	int cmd;
152 	struct sockaddr_iso *siso;
153 	struct isopcb *isop;
154 {
155 	switch (cmd) {
156 
157 	case PRC_CONS_SEND_DONE:
158 		if( isop->isop_socket ) { /* tp 0 only */
159 			register struct tp_pcb *tpcb =
160 				(struct tp_pcb *)isop->isop_socket->so_tpcb;
161 			struct 	tp_event 		E;
162 			int 					error = 0;
163 
164 			if( tpcb->tp_class == TP_CLASS_0 ) {
165 				/* only if class is exactly class zero, not
166 				 * still in class negotiation
167 				 */
168 				/* fake an ack */
169 				register SeqNum	seq =  SEQ_ADD(tpcb, tpcb->tp_snduna, 1);
170 
171 				IFTRACE(D_DATA)
172 					tptrace(TPPTmisc, "FAKE ACK seq cdt 1",
173 						seq, 0,0,0);
174 				ENDTRACE
175 				IFDEBUG(D_DATA)
176 					printf("FAKE ACK seq 0x%x cdt 1\n", seq );
177 				ENDDEBUG
178 				E.ATTR(AK_TPDU).e_cdt = 1;
179 				E.ATTR(AK_TPDU).e_seq = seq;
180 				E.ATTR(AK_TPDU).e_subseq = 0;
181 				E.ATTR(AK_TPDU).e_fcc_present = 0;
182 				error =  DoEvent(AK_TPDU);
183 				if( error ) {
184 					tpcb->tp_sock->so_error = error;
185 				}
186 			} /* else ignore it */
187 		}
188 		break;
189 	case PRC_ROUTEDEAD:
190 		if( isop->isop_socket ) { /* tp 0 only */
191 			tpiso_reset(isop);
192 			break;
193 		} /* else drop through */
194 	default:
195 		(void) tpclnp_ctlinput(cmd, siso);
196 		break;
197 	}
198 	return 0;
199 }
200 
201 /*
202  * CALLED FROM:
203  * 	cons's intr routine
204  * FUNCTION and ARGUMENTS:
205  * Take a packet (m) from cons, pullup m as required by tp,
206  *  ignore the socket argument, and call tp_input.
207  * No return value.
208  */
209 ProtoHook
210 tpcons_input(m, faddr, laddr, so, channel)
211 	struct mbuf 		*m;
212 	struct sockaddr_iso	*faddr, *laddr;
213 	struct socket 		*so; /* not used */
214 	int					channel;
215 {
216 	if( m == MNULL)
217 		return 0;
218 
219 	m = (struct mbuf *)tp_inputprep(m);
220 
221 	IFDEBUG(D_TPINPUT)
222 		printf("tpcons_input before tp_input(m 0x%x)\n", m);
223 		dump_buf( m, 12+ m->m_len);
224 	ENDDEBUG
225 	tp_input(m, faddr, laddr, channel, tpcons_output);
226 	return 0;
227 }
228 
229 
230 /*
231  * CALLED FROM:
232  *  tp_emit()
233  * FUNCTION and ARGUMENTS:
234  *  Take a packet(m0) from tp and package it so that cons will accept it.
235  *  This means filling in a few of the fields.
236  *  inp is the isopcb structure; datalen is the length of the data in the
237  *  mbuf string m0.
238  * RETURN VALUE:
239  *  whatever (E*) is returned form the net layer output routine.
240  */
241 
242 int
243 tpcons_output(isop, m0, datalen, nochksum)
244 	struct isopcb		*isop;
245 	struct mbuf 		*m0;
246 	int 				datalen;
247 	int					nochksum;
248 {
249 	struct tp_pcb 		*tpcb;
250 	int					error;
251 
252 	IFDEBUG(D_EMIT)
253 		printf(
254 		"tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n",
255 			isop, m0, datalen, isop->isop_socket);
256 	ENDDEBUG
257 	if(m0 == MNULL)
258 		return 0;
259 	ASSERT(m0->m_len > 0);
260 	tpcb = (struct tp_pcb *)isop->isop_socket->so_tpcb;
261 
262 	/* check is for class EQUAL to 4: if still in negotiation stage,
263 	 * cannot send as dgm
264 	 */
265 	error = cons_output(isop, m0,  datalen, (tpcb->tp_class == TP_CLASS_4));
266 	IncStat(ts_tpdu_sent);
267 
268 	IFTRACE(D_EMIT)
269 		tptrace( TPPTmisc,
270 		"tpcons_output( isop  m isdgm cons_output returns",
271 			isop, m0, (tpcb->tp_class == TP_CLASS_4), error );
272 	ENDTRACE
273 	return error;
274 }
275 
276 /*
277  * CALLED FROM:
278  *  tp_error_emit()
279  * FUNCTION and ARGUMENTS:
280  *  This is a copy of tpcons_output that takes the addresses
281  *  instead of a pcb.  It's used by the tp_error_emit, when we
282  *  don't have an iso_pcb with which to call the normal output rtn.
283  * RETURN VALUE:
284  *  ENOBUFS or
285  *  whatever (E*) is returned form the net layer output routine.
286  */
287 
288 int
289 tpcons_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
290 	struct iso_addr		*laddr, *faddr;
291 	struct mbuf 		*m0;
292 	int 				datalen;
293 	struct route 		*ro;
294 	int					nochksum;
295 {
296 	IFDEBUG(D_TPISO)
297 		printf("PANIC: tpcons_output_dg  datalen 0x%x m0 0x%x\n", datalen, m0);
298 	ENDDEBUG
299 
300 	return 0;
301 }
302 
303 struct tp_pcb *
304 cons_chan_to_tpcb(chan)
305 	int chan;
306 {
307 	extern struct isopcb *cons_chan_to_pcb ();
308 #ifdef ARGO_DEBUG
309 	struct isopcb *isop = cons_chan_to_pcb (chan, -1);
310 #else ARGO_DEBUG
311 	struct isopcb *isop = cons_chan_to_pcb (chan);
312 #endif ARGO_DEBUG
313 
314 	IFTRACE(D_CONN)
315 		tptrace(TPPTmisc, "vc->tpcb(chan) socket",
316 			chan, isop->isop_socket, 0, 0);
317 	ENDTRACE
318 	IFDEBUG(D_CONN)
319 		printf("vc->tpcb(0x%x) socket 0x%x, *ISOP dump:",
320 			chan, isop->isop_socket);
321 		dump_buf( isop, 32);
322 	ENDDEBUG
323 	if( isop->isop_socket == (struct socket *)0 )
324 		return (struct tp_pcb *) 0;
325 	else {
326 		return (struct tp_pcb *)(isop->isop_socket->so_tpcb);
327 }
328 }
329 #endif NARGOXTWENTYFIVE
330 #endif ISO
331