xref: /original-bsd/sys/netiso/tp_cons.c (revision 3588a932)
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.4 (Berkeley) 01/09/91 *
32  *
33  * Here is where you find the iso- and cons-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: 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 
50 #ifdef ISO
51 #ifdef TPCONS
52 
53 #include "param.h"
54 #include "socket.h"
55 #include "domain.h"
56 #include "mbuf.h"
57 #include "errno.h"
58 #include "time.h"
59 
60 #include "../net/if.h"
61 #include "../net/route.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 "iso.h"
71 #include "iso_errno.h"
72 #include "iso_pcb.h"
73 #include "cons.h"
74 #include "tp_seq.h"
75 
76 #undef FALSE
77 #undef TRUE
78 #include "../netccitt/x25.h"
79 #include "../netccitt/pk.h"
80 #include "../netccitt/pk_var.h"
81 
82 #include "if_cons.c"
83 int tpcons_output();
84 
85 /*
86  * CALLED FROM:
87  *  tp_route_to() for PRU_CONNECT
88  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
89  *  version of the previous procedure for X.25
90  */
91 
92 tpcons_pcbconnect(isop, nam)
93 struct isopcb *isop;
94 register struct mbuf *nam;
95 {
96 	int error;
97 	if (error = iso_pcbconnect(isop, nam))
98 		return error;
99 	if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) {
100 		IFDEBUG(D_CCONS)
101 			printf("tpcons_pcbconnect: no pklcd; returns 0x%x\n", error);
102 		ENDDEBUG
103 		return ENOBUFS;
104 	}
105 	if (error = cons_connect(isop)) { /* if it doesn't work */
106 		/* oh, dear, throw packet away */
107 		pk_disconnect((struct pklcd *)isop->isop_chan);
108 		isop->isop_chan = 0;
109 		return error;
110 	}
111 }
112 
113 
114 /*
115  * CALLED FROM:
116  *  tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
117  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
118  *  version of the previous procedure for X.25
119  */
120 
121 void
122 tpcons_mtu(so, isop, size, negot)
123 	struct socket *so;
124 	struct isopcb *isop;
125 	int *size;
126 	u_char *negot;
127 {
128 	register struct ifnet *ifp;
129 	register int i=0, isize;
130 	int windowsize = so->so_rcv.sb_hiwat;
131 
132 	IFTRACE(D_CONN)
133 		tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0);
134 	ENDTRACE
135 
136 	isize = *size = 1 << *negot;
137 #ifdef ancient_history
138 	if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0)
139 		return;
140 #endif
141 
142 	if (isize > windowsize) {
143 		isize = windowsize;
144 		i++;
145 	}
146 	if (isize > ifp->if_mtu) {
147 		isize = ifp->if_mtu;
148 		i++;
149 	}
150 	if (i) {
151 		/* size was changed by this routine - have to transform it to
152 		 * the log2 of size
153 		 */
154 		for (i = TP_MIN_TPDUSIZE; i < TP_MAX_TPDUSIZE; i++) {
155 			if (isize <  (1 << (1 + i)))
156 				break;
157 		}
158 		*negot = i;
159 		*size = 1 << i;
160 	}
161 
162 	IFDEBUG(D_CONN)
163 		printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
164 		ifp->if_name,	*size, *negot);
165 	ENDDEBUG
166 	IFTRACE(D_CONN)
167 		tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ",
168 		*size, *negot, 0, 0);
169 	ENDTRACE
170 }
171 
172 /*
173  * CALLED FROM:
174  * 	cons
175  * FUNCTION and ARGUMENTS:
176  * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not -
177  */
178 ProtoHook
179 tpcons_ctlinput(cmd, siso, isop)
180 	int cmd;
181 	struct sockaddr_iso *siso;
182 	struct isopcb *isop;
183 {
184 	switch (cmd) {
185 
186 	case PRC_CONS_SEND_DONE:
187 		if( isop->isop_socket ) { /* tp 0 only */
188 			register struct tp_pcb *tpcb =
189 				(struct tp_pcb *)isop->isop_socket->so_tpcb;
190 			struct 	tp_event 		E;
191 			int 					error = 0;
192 
193 			if( tpcb->tp_class == TP_CLASS_0 ) {
194 				/* only if class is exactly class zero, not
195 				 * still in class negotiation
196 				 */
197 				/* fake an ack */
198 				register SeqNum	seq =  SEQ_ADD(tpcb, tpcb->tp_snduna, 1);
199 
200 				IFTRACE(D_DATA)
201 					tptrace(TPPTmisc, "FAKE ACK seq cdt 1",
202 						seq, 0,0,0);
203 				ENDTRACE
204 				IFDEBUG(D_DATA)
205 					printf("FAKE ACK seq 0x%x cdt 1\n", seq );
206 				ENDDEBUG
207 				E.ATTR(AK_TPDU).e_cdt = 1;
208 				E.ATTR(AK_TPDU).e_seq = seq;
209 				E.ATTR(AK_TPDU).e_subseq = 0;
210 				E.ATTR(AK_TPDU).e_fcc_present = 0;
211 				error =  DoEvent(AK_TPDU);
212 				if( error ) {
213 					tpcb->tp_sock->so_error = error;
214 				}
215 			} /* else ignore it */
216 		}
217 		break;
218 	case PRC_ROUTEDEAD:
219 		if( isop->isop_socket ) { /* tp 0 only */
220 			tpiso_reset(isop);
221 			break;
222 		} /* else drop through */
223 	default:
224 		(void) tpclnp_ctlinput(cmd, siso);
225 		break;
226 	}
227 	return 0;
228 }
229 
230 /*
231  * CALLED FROM:
232  * 	cons's intr routine
233  * FUNCTION and ARGUMENTS:
234  * Take a packet (m) from cons, pullup m as required by tp,
235  *  ignore the socket argument, and call tp_input.
236  * No return value.
237  */
238 ProtoHook
239 tpcons_input(m, faddr, laddr, channel)
240 	struct mbuf 		*m;
241 	struct sockaddr_iso	*faddr, *laddr;
242 	caddr_t				channel;
243 {
244 	if( m == MNULL)
245 		return 0;
246 
247 	m = (struct mbuf *)tp_inputprep(m);
248 
249 	IFDEBUG(D_TPINPUT)
250 		printf("tpcons_input before tp_input(m 0x%x)\n", m);
251 		dump_buf( m, 12+ m->m_len);
252 	ENDDEBUG
253 	tp_input(m, faddr, laddr, channel, tpcons_output);
254 	return 0;
255 }
256 
257 
258 /*
259  * CALLED FROM:
260  *  tp_emit()
261  * FUNCTION and ARGUMENTS:
262  *  Take a packet(m0) from tp and package it so that cons will accept it.
263  *  This means filling in a few of the fields.
264  *  inp is the isopcb structure; datalen is the length of the data in the
265  *  mbuf string m0.
266  * RETURN VALUE:
267  *  whatever (E*) is returned form the net layer output routine.
268  */
269 
270 int
271 tpcons_output(isop, m0, datalen, nochksum)
272 	struct isopcb		*isop;
273 	struct mbuf 		*m0;
274 	int 				datalen;
275 	int					nochksum;
276 {
277 	register	struct mbuf *m = m0;
278 	int					error;
279 
280 	IFDEBUG(D_EMIT)
281 		printf(
282 		"tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n",
283 			isop, m0, datalen, isop->isop_socket);
284 	ENDDEBUG
285 	if (m == MNULL)
286 		return 0;
287 	if (m->m_flags & M_PKTHDR == 0) {
288 		MGETHDR(m, M_DONTWAIT, MT_DATA);
289 		if (m == 0)
290 			return ENOBUFS;
291 		m->m_next = m0;
292 	}
293 	m->m_pkthdr.len = datalen;
294 	error = pk_send(isop->isop_chan, m);
295 	IncStat(ts_tpdu_sent);
296 
297 	return error;
298 }
299 /*
300  * CALLED FROM:
301  *  tp_error_emit()
302  * FUNCTION and ARGUMENTS:
303  *  Take a packet(m0) from tp and package it so that cons will accept it.
304  *  chan is the cons channel to use; datalen is the length of the data in the
305  *  mbuf string m0.
306  * RETURN VALUE:
307  *  whatever (E*) is returned form the net layer output routine.
308  */
309 
310 int
311 tpcons_dg_output(chan, m0, datalen)
312 	caddr_t				chan;
313 	struct mbuf 		*m0;
314 	int 				datalen;
315 {
316 	return tpcons_output(((struct pklcd *)chan)->lcd_upnext, m0, datalen, 0);
317 }
318 #endif TPCONS
319 #endif ISO
320