xref: /original-bsd/sys/netiso/tp_iso.c (revision 92d853e2)
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_iso.c,v 5.3 88/11/18 17:27:57 nhall Exp $
30  * $Source: /usr/argo/sys/netiso/RCS/tp_iso.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  * 		iso_getsufx: gets transport suffix out of an isopcb structure.
39  * 		iso_putsufx: put transport suffix into an isopcb structure.
40  *		iso_putnetaddr: put a whole net addr into an isopcb.
41  *		iso_getnetaddr: get a whole net addr from an isopcb.
42  *		iso_recycle_suffix: clear suffix for reuse in isopcb
43  * 		tpclnp_ctlinput: handle ER CNLPdu : icmp-like stuff
44  * 		tpclnp_mtu: figure out what size tpdu to use
45  *		tpclnp_input: take a pkt from clnp, strip off its clnp header,
46  *				give to tp
47  *		tpclnp_output_dg: package a pkt for clnp given 2 addresses & some data
48  *		tpclnp_output: package a pkt for clnp given an isopcb & some data
49  */
50 
51 #ifndef lint
52 static char *rcsid = "$Header: tp_iso.c,v 5.3 88/11/18 17:27:57 nhall Exp $";
53 #endif lint
54 
55 #ifdef ISO
56 
57 #include "../h/types.h"
58 #include "../h/socket.h"
59 #include "../h/socketvar.h"
60 #include "../h/domain.h"
61 #include "../h/mbuf.h"
62 #include "../h/errno.h"
63 #include "../h/time.h"
64 #include "../net/if.h"
65 #include "../net/route.h"
66 #include "../h/protosw.h"
67 
68 #include "../netiso/tp_param.h"
69 #include "../netiso/argo_debug.h"
70 #include "../netiso/tp_stat.h"
71 #include "../netiso/tp_pcb.h"
72 #include "../netiso/tp_trace.h"
73 #include "../netiso/tp_stat.h"
74 #include "../netiso/tp_tpdu.h"
75 #include "../netiso/tp_clnp.h"
76 
77 /*
78  * CALLED FROM:
79  * 	pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR
80  * FUNCTION, ARGUMENTS, and RETURN VALUE:
81  * 	Return a transport suffix from an isopcb structure (inp).
82  *  (CAST TO AN INT)
83  * 	The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
84  */
85 
86 short
87 iso_getsufx(isop,  which)
88 	struct isopcb *isop;
89 	int which;
90 {
91 	switch (which) {
92 	case TP_LOCAL:
93 		return  htons(isop->isop_laddr.siso_tsuffix);
94 
95 	case TP_FOREIGN:
96 		return  htons(isop->isop_faddr.siso_tsuffix);
97 	}
98 }
99 
100 /* CALLED FROM:
101  * 	tp_newsocket(); i.e., when a connection is being established by an
102  * 	incoming CR_TPDU.
103  *
104  * FUNCTION, ARGUMENTS:
105  * 	Put a transport suffix (found in name) into an isopcb structure (isop).
106  * 	The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
107  */
108 void
109 iso_putsufx(isop, name, which)
110 	struct isopcb *isop;
111 	struct sockaddr_iso *name;
112 	int which;
113 {
114 	switch (which) {
115 	case TP_LOCAL:
116 		isop->isop_lport = ntohs(name->siso_tsuffix);
117 		break;
118 	case TP_FOREIGN:
119 		isop->isop_fport = ntohs(name->siso_tsuffix);
120 		break;
121 	}
122 }
123 
124 /*
125  * CALLED FROM:
126  * 	tp.trans whenever we go into REFWAIT state.
127  * FUNCTION and ARGUMENT:
128  *	 Called when a ref is frozen, to allow the suffix to be reused.
129  * 	(isop) is the net level pcb.  This really shouldn't have to be
130  * 	done in a NET level pcb but... for the internet world that just
131  * 	the way it is done in BSD...
132  * 	The alternative is to have the port unusable until the reference
133  * 	timer goes off.
134  */
135 void
136 iso_recycle_tsuffix(isop)
137 	struct isopcb	*isop;
138 {
139 	isop->isop_laddr.siso_tsuffix = isop->isop_faddr.siso_tsuffix = 0;
140 }
141 
142 /*
143  * CALLED FROM:
144  * 	tp_newsocket(); i.e., when a connection is being established by an
145  * 	incoming CR_TPDU.
146  *
147  * FUNCTION and ARGUMENTS:
148  * 	Copy a whole net addr from a struct sockaddr (name).
149  * 	into an isopcb (isop).
150  * 	The argument (which) takes values TP_LOCAL or TP_FOREIGN
151  */
152 void
153 iso_putnetaddr(isop, name, which)
154 	register struct isopcb	*isop;
155 	struct sockaddr_iso	*name;
156 	int which;
157 {
158 	switch (which) {
159 	case TP_LOCAL:
160 		isop->isop_laddr.siso_family = AF_ISO;
161 		bcopy((caddr_t)&name->siso_addr,
162 			(caddr_t)&isop->isop_laddr.siso_addr, sizeof(struct iso_addr));
163 		IFDEBUG(D_TPISO)
164 			printf("PUT TP_LOCAL addr\n");
165 			dump_isoaddr(&isop->isop_laddr);
166 		ENDDEBUG
167 		break;
168 	case TP_FOREIGN:
169 		isop->isop_faddr.siso_family = AF_ISO;
170 		if( name != (struct sockaddr_iso *)0 ) {
171 			bcopy((caddr_t)&name->siso_addr,
172 				(caddr_t)&isop->isop_faddr.siso_addr, sizeof(struct iso_addr));
173 		}
174 		IFDEBUG(D_TPISO)
175 			printf("PUT TP_FOREIGN addr\n");
176 			dump_isoaddr(&isop->isop_faddr);
177 		ENDDEBUG
178 	}
179 }
180 
181 /*
182  * CALLED FROM:
183  *  pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR
184  * FUNCTION and ARGUMENTS:
185  * 	Copy a whole net addr from an isopcb (isop) into
186  * 	a struct sockaddr (name).
187  * 	The argument (which) takes values TP_LOCAL or TP_FOREIGN.
188  */
189 
190 void
191 iso_getnetaddr( isop, name, which)
192 	struct isopcb *isop;
193 	struct sockaddr_iso *name;
194 	int which;
195 {
196 	switch (which) {
197 	case TP_LOCAL:
198 		bcopy( (caddr_t)&isop->isop_laddr.siso_addr,
199 			(caddr_t)&name->siso_addr, sizeof(struct iso_addr));
200 		break;
201 
202 	case TP_FOREIGN:
203 		bcopy( (caddr_t)&isop->isop_faddr.siso_addr,
204 			(caddr_t)&name->siso_addr, sizeof(struct iso_addr));
205 		break;
206 	}
207 }
208 
209 /*
210  * CALLED FROM:
211  *  tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
212  * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE:
213  * Determine the proper maximum transmission unit, i.e., MTU, to use, given
214  * a) the header size for the network protocol and the max transmission
215  *	  unit on the subnet interface, determined from the information in (isop),
216  * b) the max size negotiated so far (negot)
217  * c) the window size used by the tp connection (found in so),
218  *
219  * The result is put in the integer *size in its integer form and in
220  * *negot in its logarithmic form.
221  *
222  * The rules are:
223  * a) can only negotiate down from the value found in *negot.
224  * b) the MTU must be < the windowsize,
225  * c) If src and dest are on the same net,
226  * 	  we will negotiate the closest size larger than  MTU but really USE
227  *    the actual device mtu - ll hdr sizes.
228  *   otherwise we negotiate the closest size smaller than MTU - ll hdr sizes.
229  */
230 
231 void
232 tpclnp_mtu(so, isop, size, negot )
233 	struct socket *so;
234 	struct isopcb *isop;
235 	int *size;
236 	u_char *negot;
237 {
238 	struct ifnet *ifp;
239 	register int i;
240 	int windowsize = so->so_rcv.sb_hiwat;
241 	int clnp_size;
242 	int sizeismtu = 0;
243 
244 	struct ifnet	*iso_routeifp();
245 
246 	IFDEBUG(D_CONN)
247 		printf("tpclnp_mtu(0x%x,0x%x,0x%x,0x%x)\n", so, isop, size, negot);
248 	ENDDEBUG
249 	IFTRACE(D_CONN)
250 		tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0);
251 	ENDTRACE
252 
253 	*size = 1 << *negot;
254 
255 	if( *size > windowsize ) {
256 		*size = windowsize;
257 	}
258 
259 	if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0)
260 		return;
261 
262 	/* TODO - make this indirect off the socket structure to the
263 	 * network layer to get headersize
264 	 */
265 	clnp_size = clnp_hdrsize(isop->isop_laddr.siso_addr.isoa_len);
266 
267 	if(*size > ifp->if_mtu - clnp_size) {
268 		*size = ifp->if_mtu - clnp_size;
269 		sizeismtu = 1;
270 	}
271 	IFTRACE(D_CONN)
272 		tptrace(TPPTmisc, "GET MTU MID: tpcb size negot i \n",
273 		*size, *negot, i, 0);
274 	ENDTRACE
275 
276 	/* have to transform size to the log2 of size */
277 	for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i) <= *size)) ; i++)
278 		;
279 	i--;
280 
281 	/* are we on the same LAN? if so, negotiate one tpdu size larger,
282 	 * and actually send the real mtu size
283 	 */
284 	/* PHASE2: replace with iso_on_localnet(&isop->isop_faddr);
285 	 * or something along those lines
286 	 */
287 	if ( iso_netmatch(&isop->isop_laddr, &isop->isop_faddr) && sizeismtu ) {
288 		i++;
289 	} else {
290 		*size = 1<<i;
291 	}
292 	*negot = i;
293 
294 	IFDEBUG(D_CONN)
295 		printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n",
296 		ifp->if_name,	*size, *negot);
297 	ENDDEBUG
298 	IFTRACE(D_CONN)
299 		tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n",
300 		*size, *negot, 0, 0);
301 	ENDTRACE
302 }
303 
304 
305 /*
306  * CALLED FROM:
307  *  tp_emit()
308  * FUNCTION and ARGUMENTS:
309  *  Take a packet(m0) from tp and package it so that clnp will accept it.
310  *  This means prepending space for the clnp header and filling in a few
311  *  of the fields.
312  *  inp is the isopcb structure; datalen is the length of the data in the
313  *  mbuf string m0.
314  * RETURN VALUE:
315  *  whatever (E*) is returned form the net layer output routine.
316  */
317 
318 int
319 tpclnp_output(isop, m0, datalen, nochksum)
320 	struct isopcb		*isop;
321 	struct mbuf 		*m0;
322 	int 				datalen;
323 	int					nochksum;
324 {
325 	IncStat(ts_tpdu_sent);
326 
327 	IFDEBUG(D_TPISO)
328 		struct tpdu *hdr = mtod(m0, struct tpdu *);
329 
330 		printf(
331 "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n",
332 			datalen,
333 			(int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum);
334 		dump_isoaddr(&isop->isop_faddr);
335 		printf("\nsrc addr:\n");
336 		dump_isoaddr(&isop->isop_laddr);
337 		dump_mbuf(m0, "at tpclnp_output");
338 	ENDDEBUG
339 
340 	return
341 		clnp_output(m0, isop, datalen, nochksum?CLNP_NO_CKSUM:0 /* flags */);
342 }
343 
344 /*
345  * CALLED FROM:
346  *  tp_error_emit()
347  * FUNCTION and ARGUMENTS:
348  *  This is a copy of tpclnp_output that takes the addresses
349  *  instead of a pcb.  It's used by the tp_error_emit, when we
350  *  don't have an iso_pcb with which to call the normal output rtn.
351  * RETURN VALUE:
352  *  ENOBUFS or
353  *  whatever (E*) is returned form the net layer output routine.
354  */
355 
356 int
357 tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
358 	struct iso_addr		*laddr, *faddr;
359 	struct mbuf 		*m0;
360 	int 				datalen;
361 	struct route 		*ro;
362 	int					nochksum;
363 {
364 	struct isopcb		tmppcb;
365 	struct iso_addr		*isoa;
366 	int					err;
367 	int					flags;
368 
369 	IFDEBUG(D_TPISO)
370 		printf("tpclnp_output_dg  datalen 0x%x m0 0x%x\n", datalen, m0);
371 	ENDDEBUG
372 
373 	/*
374 	 *	Fill in minimal portion of isopcb so that clnp can send the
375 	 *	packet.
376 	 */
377 	bzero((caddr_t)&tmppcb, sizeof(tmppcb));
378 	isoa = &(tmppcb.isop_laddr.siso_addr);
379 	bcopy((caddr_t)laddr, (caddr_t)isoa, sizeof (struct iso_addr));
380 	isoa = &(tmppcb.isop_faddr.siso_addr);
381 	bcopy((caddr_t)faddr, (caddr_t)isoa, sizeof (struct iso_addr));
382 
383 	IFDEBUG(D_TPISO)
384 		printf("tpclnp_output_dg  faddr: \n");
385 		dump_isoaddr(&tmppcb.isop_faddr);
386 		printf("\ntpclnp_output_dg  laddr: \n");
387 		dump_isoaddr(&tmppcb.isop_laddr);
388 		printf("\n");
389 	ENDDEBUG
390 
391 	/*
392 	 *	Do not use packet cache since this is a one shot error packet
393 	 */
394 	flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0));
395 
396 	IncStat(ts_tpdu_sent);
397 
398 	err = clnp_output(m0, &tmppcb, datalen, flags);
399 
400 	/*
401 	 *	Free route allocated by clnp (if the route was indeed allocated)
402 	 */
403 	if (tmppcb.isop_route.ro_rt)
404 		RTFREE(tmppcb.isop_route.ro_rt);
405 
406 	return(err);
407 }
408 
409 /*
410  * CALLED FROM:
411  * 	clnp's input routine, indirectly through the protosw.
412  * FUNCTION and ARGUMENTS:
413  * Take a packet (m) from clnp, strip off the clnp header and give it to tp
414  * No return value.
415  */
416 ProtoHook
417 tpclnp_input(m, faddr, laddr, clnp_len)
418 	struct mbuf *m;
419 	struct iso_addr *faddr, *laddr;
420 	int clnp_len;
421 {
422 	struct sockaddr_iso src, dst;
423 	int s = splnet();
424 
425 	IncStat(ts_pkt_rcvd);
426 
427 	IFDEBUG(D_TPINPUT)
428 		printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len);
429 		dump_mbuf(m, "at tpclnp_input");
430 	ENDDEBUG
431 	/*
432 	 * CLNP gives us an mbuf chain WITH the clnp header pulled up,
433 	 * and the length of the clnp header.
434 	 * First, strip off the Clnp header. leave the mbuf there for the
435 	 * pullup that follows.
436 	 */
437 
438 	m->m_len -= clnp_len;
439 	m->m_off += clnp_len;
440 
441 	m = (struct mbuf *)tp_inputprep(m);
442 
443 	IFDEBUG(D_TPINPUT)
444 		dump_mbuf(m, "after tpclnp_input both pullups");
445 	ENDDEBUG
446 
447 	src.siso_family = dst.siso_family = AF_ISO;
448 	bcopy(faddr, &src.siso_addr, sizeof(struct iso_addr));
449 	bcopy(laddr, &dst.siso_addr, sizeof(struct iso_addr));
450 
451 	IFDEBUG(D_TPISO)
452 		printf("calling tp_input: &src 0x%x  &dst 0x%x, src addr:\n",
453 			&src, &dst);
454 		printf(" dst addr:\n");
455 		dump_isoaddr(&src);
456 		dump_isoaddr(&dst);
457 	ENDDEBUG
458 
459 	(void) tp_input(m, &src, &dst, 0, tpclnp_output_dg);
460 
461 	IFDEBUG(D_QUENCH)
462 		{
463 			if(time.tv_usec & 0x4 && time.tv_usec & 0x40) {
464 				printf("tpclnp_input: FAKING %s\n",
465 					tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2");
466 				if(tp_stat.ts_pkt_rcvd & 0x1) {
467 					tpclnp_ctlinput(PRC_QUENCH, &src);
468 				} else {
469 					tpclnp_ctlinput(PRC_QUENCH2, &src);
470 				}
471 			}
472 		}
473 	ENDDEBUG
474 
475 	splx(s);
476 	return 0;
477 
478 discard:
479 	IFDEBUG(D_TPINPUT)
480 		printf("tpclnp_input DISCARD\n");
481 	ENDDEBUG
482 	IFTRACE(D_TPINPUT)
483 		tptrace(TPPTmisc, "tpclnp_input DISCARD m",  m,0,0,0);
484 	ENDTRACE
485 	m_freem(m);
486 	IncStat(ts_recv_drop);
487 	splx(s);
488 
489 	return 0;
490 }
491 
492 ProtoHook
493 iso_rtchange()
494 {
495 	return 0;
496 }
497 
498 /*
499  * CALLED FROM:
500  *  tpclnp_ctlinput()
501  * FUNCTION and ARGUMENTS:
502  *  find the tpcb pointer and pass it to tp_quench
503  */
504 void
505 tpiso_decbit(isop)
506 	struct isopcb *isop;
507 {
508 	tp_quench( isop->isop_socket->so_tpcb, PRC_QUENCH2 );
509 }
510 /*
511  * CALLED FROM:
512  *  tpclnp_ctlinput()
513  * FUNCTION and ARGUMENTS:
514  *  find the tpcb pointer and pass it to tp_quench
515  */
516 void
517 tpiso_quench(isop)
518 	struct isopcb *isop;
519 {
520 	tp_quench( isop->isop_socket->so_tpcb, PRC_QUENCH );
521 }
522 
523 /*
524  * CALLED FROM:
525  *  The network layer through the protosw table.
526  * FUNCTION and ARGUMENTS:
527  *	When clnp an ICMP-like msg this gets called.
528  *	It either returns an error status to the user or
529  *	it causes all connections on this address to be aborted
530  *	by calling the appropriate xx_notify() routine.
531  *	(cmd) is the type of ICMP error.
532  * 	(siso) is the address of the guy who sent the ER CLNPDU
533  */
534 ProtoHook
535 tpclnp_ctlinput(cmd, siso)
536 	int cmd;
537 	struct sockaddr_iso *siso;
538 {
539 	extern u_char inetctlerrmap[];
540 	extern ProtoHook tpiso_abort();
541 	extern ProtoHook iso_rtchange();
542 	extern ProtoHook tpiso_reset();
543 
544 	IFDEBUG(D_TPINPUT)
545 		printf("tpclnp_ctlinput: cmd 0x%x addr: ", cmd);
546 		dump_isoaddr(siso);
547 		printf("\n");
548 	ENDDEBUG
549 
550 	if (cmd < 0 || cmd > PRC_NCMDS)
551 		return 0;
552 	switch (cmd) {
553 
554 		case	PRC_QUENCH2:
555 			iso_pcbnotify(&tp_isopcb, &siso->siso_addr, 0, tpiso_decbit);
556 			break;
557 
558 		case	PRC_QUENCH:
559 			iso_pcbnotify(&tp_isopcb, &siso->siso_addr, 0, tpiso_quench);
560 			break;
561 
562 		case	PRC_TIMXCEED_REASS:
563 		case	PRC_ROUTEDEAD:
564 			iso_pcbnotify(&tp_isopcb, &siso->siso_addr, 0, tpiso_reset);
565 			break;
566 
567 		case	PRC_HOSTUNREACH:
568 		case	PRC_UNREACH_NET:
569 		case	PRC_IFDOWN:
570 		case	PRC_HOSTDEAD:
571 			iso_pcbnotify(&tp_isopcb, &siso->siso_addr,
572 					(int)inetctlerrmap[cmd], iso_rtchange);
573 			break;
574 
575 		default:
576 		/*
577 		case	PRC_MSGSIZE:
578 		case	PRC_UNREACH_HOST:
579 		case	PRC_UNREACH_PROTOCOL:
580 		case	PRC_UNREACH_PORT:
581 		case	PRC_UNREACH_NEEDFRAG:
582 		case	PRC_UNREACH_SRCFAIL:
583 		case	PRC_REDIRECT_NET:
584 		case	PRC_REDIRECT_HOST:
585 		case	PRC_REDIRECT_TOSNET:
586 		case	PRC_REDIRECT_TOSHOST:
587 		case	PRC_TIMXCEED_INTRANS:
588 		case	PRC_PARAMPROB:
589 		*/
590 		iso_pcbnotify(&tp_isopcb, &siso->siso_addr,
591 			(int)inetctlerrmap[cmd], tpiso_abort);
592 		break;
593 	}
594 	return 0;
595 }
596 
597 /*
598  * These next 2 routines are
599  * CALLED FROM:
600  *	xxx_notify() from tp_ctlinput() when
601  *  net level gets some ICMP-equiv. type event.
602  * FUNCTION and ARGUMENTS:
603  *  Cause the connection to be aborted with some sort of error
604  *  reason indicating that the network layer caused the abort.
605  *  Fakes an ER TPDU so we can go through the driver.
606  *  abort always aborts the TP connection.
607  *  reset may or may not, depending on the TP class that's in use.
608  */
609 ProtoHook
610 tpiso_abort(isop)
611 	struct isopcb *isop;
612 {
613 	struct tp_event e;
614 
615 	IFDEBUG(D_CONN)
616 		printf("tpiso_abort 0x%x\n", isop);
617 	ENDDEBUG
618 	e.ev_number = ER_TPDU;
619 	e.ATTR(ER_TPDU).e_reason = ECONNABORTED;
620 	return  tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e);
621 }
622 
623 ProtoHook
624 tpiso_reset(isop)
625 	struct isopcb *isop;
626 {
627 	struct tp_event e;
628 
629 	e.ev_number = T_NETRESET;
630 	return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e);
631 
632 }
633 
634 #endif ISO
635