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