Checkpoint as of first successful tp connection, before posix, &
[unix-history] / usr / src / sys / netiso / tp_cons.c
CommitLineData
47f37345
KS
1/***********************************************************
2 Copyright IBM Corporation 1987
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of IBM not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
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
46static 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
a50e2bc0 54#include "param.h"
47f37345
KS
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
a50e2bc0
KS
62#include "tp_param.h"
63#include "argo_debug.h"
64#include "tp_stat.h"
65#include "tp_pcb.h"
66#include "tp_trace.h"
67#include "tp_stat.h"
68#include "tp_tpdu.h"
47f37345 69#include "../net/route.h"
a50e2bc0
KS
70#include "iso.h"
71#include "iso_pcb.h"
72#include "cons.h"
73#include "tp_seq.h"
47f37345
KS
74
75int 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
84void
85tpcons_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 */
148ProtoHook
149tpcons_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 */
208ProtoHook
209tpcons_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
241int
242tpcons_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
287int
288tpcons_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
302struct tp_pcb *
303cons_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