]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netiso/tp_iso.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1991, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * @(#)tp_iso.c 8.1 (Berkeley) 6/10/93
57 /***********************************************************
58 Copyright IBM Corporation 1987
62 Permission to use, copy, modify, and distribute this software and its
63 documentation for any purpose and without fee is hereby granted,
64 provided that the above copyright notice appear in all copies and that
65 both that copyright notice and this permission notice appear in
66 supporting documentation, and that the name of IBM not be
67 used in advertising or publicity pertaining to distribution of the
68 software without specific, written prior permission.
70 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
78 ******************************************************************/
81 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
86 * Here is where you find the iso-dependent code. We've tried
87 * keep all net-level and (primarily) address-family-dependent stuff
88 * out of the tp source, and everthing here is reached indirectly
89 * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
91 * The routines here are:
92 * iso_getsufx: gets transport suffix out of an isopcb structure.
93 * iso_putsufx: put transport suffix into an isopcb structure.
94 * iso_putnetaddr: put a whole net addr into an isopcb.
95 * iso_getnetaddr: get a whole net addr from an isopcb.
96 * iso_cmpnetaddr: compare a whole net addr from an isopcb.
97 * iso_recycle_suffix: clear suffix for reuse in isopcb
98 * tpclnp_ctlinput: handle ER CNLPdu : icmp-like stuff
99 * tpclnp_mtu: figure out what size tpdu to use
100 * tpclnp_input: take a pkt from clnp, strip off its clnp header,
102 * tpclnp_output_dg: package a pkt for clnp given 2 addresses & some data
103 * tpclnp_output: package a pkt for clnp given an isopcb & some data
108 #include <sys/param.h>
109 #include <sys/socket.h>
110 #include <sys/socketvar.h>
111 #include <sys/domain.h>
112 #include <sys/malloc.h>
113 #include <sys/mbuf.h>
114 #include <sys/errno.h>
115 #include <sys/time.h>
116 #include <sys/protosw.h>
119 #include <net/route.h>
121 #include <netiso/argo_debug.h>
122 #include <netiso/tp_param.h>
123 #include <netiso/tp_stat.h>
124 #include <netiso/tp_pcb.h>
125 #include <netiso/tp_trace.h>
126 #include <netiso/tp_stat.h>
127 #include <netiso/tp_tpdu.h>
128 #include <netiso/tp_clnp.h>
129 #include <netiso/cltp_var.h>
133 * pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR
134 * FUNCTION, ARGUMENTS:
135 * The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
138 iso_getsufx(isop
, lenp
, data_out
, which
)
144 register struct sockaddr_iso
*addr
= 0;
148 addr
= isop
->isop_laddr
;
152 addr
= isop
->isop_faddr
;
155 bcopy(TSEL(addr
), data_out
, (*lenp
= addr
->siso_tlen
));
159 * tp_newsocket(); i.e., when a connection is being established by an
162 * FUNCTION, ARGUMENTS:
163 * Put a transport suffix (found in name) into an isopcb structure (isop).
164 * The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
167 iso_putsufx(isop
, sufxloc
, sufxlen
, which
)
172 struct sockaddr_iso
**dst
, *backup
;
173 register struct sockaddr_iso
*addr
;
182 dst
= &isop
->isop_laddr
;
183 backup
= &isop
->isop_sladdr
;
187 dst
= &isop
->isop_faddr
;
188 backup
= &isop
->isop_sfaddr
;
190 if ((addr
= *dst
) == 0) {
191 addr
= *dst
= backup
;
195 printf("iso_putsufx on un-initialized isopcb\n");
197 len
= sufxlen
+ addr
->siso_nlen
+
198 (sizeof(*addr
) - sizeof(addr
->siso_data
));
199 if (addr
== backup
) {
200 if (len
> sizeof(*addr
)) {
201 m
= m_getclr(M_DONTWAIT
, MT_SONAME
);
204 addr
= *dst
= mtod(m
, struct sockaddr_iso
*);
209 bcopy(sufxloc
, TSEL(addr
), sufxlen
);
210 addr
->siso_tlen
= sufxlen
;
211 addr
->siso_len
= len
;
216 * tp.trans whenever we go into REFWAIT state.
217 * FUNCTION and ARGUMENT:
218 * Called when a ref is frozen, to allow the suffix to be reused.
219 * (isop) is the net level pcb. This really shouldn't have to be
220 * done in a NET level pcb but... for the internet world that just
221 * the way it is done in BSD...
222 * The alternative is to have the port unusable until the reference
226 iso_recycle_tsuffix(isop
)
229 isop
->isop_laddr
->siso_tlen
= isop
->isop_faddr
->siso_tlen
= 0;
234 * tp_newsocket(); i.e., when a connection is being established by an
237 * FUNCTION and ARGUMENTS:
238 * Copy a whole net addr from a struct sockaddr (name).
239 * into an isopcb (isop).
240 * The argument (which) takes values TP_LOCAL or TP_FOREIGN
243 iso_putnetaddr(isop
, name
, which
)
244 register struct isopcb
*isop
;
245 struct sockaddr_iso
*name
;
248 struct sockaddr_iso
**sisop
, *backup
;
249 register struct sockaddr_iso
*siso
;
253 printf("iso_putnetaddr: should panic\n");
256 sisop
= &isop
->isop_laddr
;
257 backup
= &isop
->isop_sladdr
;
260 sisop
= &isop
->isop_faddr
;
261 backup
= &isop
->isop_sfaddr
;
263 siso
= ((*sisop
== 0) ? (*sisop
= backup
) : *sisop
);
265 printf("ISO_PUTNETADDR\n");
266 dump_isoaddr(isop
->isop_faddr
);
268 siso
->siso_addr
= name
->siso_addr
;
273 * tp_input() when a connection is being established by an
274 * incoming CR_TPDU, and considered for interception.
276 * FUNCTION and ARGUMENTS:
277 * compare a whole net addr from a struct sockaddr (name),
278 * with that implicitly stored in an isopcb (isop).
279 * The argument (which) takes values TP_LOCAL or TP_FOREIGN.
281 iso_cmpnetaddr(isop
, name
, which
)
282 register struct isopcb
*isop
;
283 register struct sockaddr_iso
*name
;
286 struct sockaddr_iso
**sisop
, *backup
;
287 register struct sockaddr_iso
*siso
;
291 printf("iso_cmpnetaddr: should panic\n");
294 sisop
= &isop
->isop_laddr
;
295 backup
= &isop
->isop_sladdr
;
298 sisop
= &isop
->isop_faddr
;
299 backup
= &isop
->isop_sfaddr
;
301 siso
= ((*sisop
== 0) ? (*sisop
= backup
) : *sisop
);
303 printf("ISO_CMPNETADDR\n");
306 if (name
->siso_tlen
&& bcmp(TSEL(name
), TSEL(siso
), name
->siso_tlen
))
308 return (bcmp((caddr_t
)name
->siso_data
,
309 (caddr_t
)siso
->siso_data
, name
->siso_nlen
) == 0);
314 * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR
315 * FUNCTION and ARGUMENTS:
316 * Copy a whole net addr from an isopcb (isop) into
317 * a struct sockaddr (name).
318 * The argument (which) takes values TP_LOCAL or TP_FOREIGN.
322 iso_getnetaddr( isop
, name
, which
)
327 struct sockaddr_iso
*siso
=
328 (which
== TP_LOCAL
? isop
->isop_laddr
: isop
->isop_faddr
);
330 bcopy((caddr_t
)siso
, mtod(name
, caddr_t
),
331 (unsigned)(name
->m_len
= siso
->siso_len
));
339 * tp_route_to() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
341 * FUNCTION, ARGUMENTS, and RETURN VALUE:
343 * Perform subnetwork dependent part of determining MTU information.
344 * It appears that setting a double pointer to the rtentry associated with
345 * the destination, and returning the header size for the network protocol
349 * Sets tp_routep pointer in pcb.
354 register struct tp_pcb
*tpcb
;
356 struct isopcb
*isop
= (struct isopcb
*)tpcb
->tp_npcb
;
359 printf("tpclnp_mtu(tpcb)\n", tpcb
);
361 tpcb
->tp_routep
= &(isop
->isop_route
.ro_rt
);
362 if (tpcb
->tp_netservice
== ISO_CONS
)
365 return (sizeof(struct clnp_fixed
) + sizeof(struct clnp_segment
) +
366 2 * sizeof(struct iso_addr
));
373 * FUNCTION and ARGUMENTS:
374 * Take a packet(m0) from tp and package it so that clnp will accept it.
375 * This means prepending space for the clnp header and filling in a few
377 * isop is the isopcb structure; datalen is the length of the data in the
380 * whatever (E*) is returned form the net layer output routine.
384 tpclnp_output(isop
, m0
, datalen
, nochksum
)
390 register struct mbuf
*m
= m0
;
391 IncStat(ts_tpdu_sent
);
394 struct tpdu
*hdr
= mtod(m0
, struct tpdu
*);
397 "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n",
399 (int)hdr
->tpdu_li
, (int)hdr
->tpdu_type
, nochksum
);
400 dump_isoaddr(isop
->isop_faddr
);
401 printf("\nsrc addr:\n");
402 dump_isoaddr(isop
->isop_laddr
);
403 dump_mbuf(m0
, "at tpclnp_output");
407 clnp_output(m0
, isop
, datalen
, /* flags */nochksum
? CLNP_NO_CKSUM
: 0);
413 * FUNCTION and ARGUMENTS:
414 * This is a copy of tpclnp_output that takes the addresses
415 * instead of a pcb. It's used by the tp_error_emit, when we
416 * don't have an iso_pcb with which to call the normal output rtn.
419 * whatever (E*) is returned form the net layer output routine.
423 tpclnp_output_dg(laddr
, faddr
, m0
, datalen
, ro
, nochksum
)
424 struct iso_addr
*laddr
, *faddr
;
430 struct isopcb tmppcb
;
433 register struct mbuf
*m
= m0
;
436 printf("tpclnp_output_dg datalen 0x%x m0 0x%x\n", datalen
, m0
);
440 * Fill in minimal portion of isopcb so that clnp can send the
443 bzero((caddr_t
)&tmppcb
, sizeof(tmppcb
));
444 tmppcb
.isop_laddr
= &tmppcb
.isop_sladdr
;
445 tmppcb
.isop_laddr
->siso_addr
= *laddr
;
446 tmppcb
.isop_faddr
= &tmppcb
.isop_sfaddr
;
447 tmppcb
.isop_faddr
->siso_addr
= *faddr
;
450 printf("tpclnp_output_dg faddr: \n");
451 dump_isoaddr(&tmppcb
.isop_sfaddr
);
452 printf("\ntpclnp_output_dg laddr: \n");
453 dump_isoaddr(&tmppcb
.isop_sladdr
);
458 * Do not use packet cache since this is a one shot error packet
460 flags
= (CLNP_NOCACHE
|(nochksum
?CLNP_NO_CKSUM
:0));
462 IncStat(ts_tpdu_sent
);
464 err
= clnp_output(m0
, &tmppcb
, datalen
, flags
);
467 * Free route allocated by clnp (if the route was indeed allocated)
469 if (tmppcb
.isop_route
.ro_rt
)
470 RTFREE(tmppcb
.isop_route
.ro_rt
);
476 * clnp's input routine, indirectly through the protosw.
477 * FUNCTION and ARGUMENTS:
478 * Take a packet (m) from clnp, strip off the clnp header and give it to tp
482 tpclnp_input(m
, src
, dst
, clnp_len
, ce_bit
)
483 register struct mbuf
*m
;
484 struct sockaddr_iso
*src
, *dst
;
485 int clnp_len
, ce_bit
;
487 struct mbuf
*tp_inputprep();
488 int tp_input(), cltp_input(), (*input
)() = tp_input
;
490 IncStat(ts_pkt_rcvd
);
493 printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m
, clnp_len
);
494 dump_mbuf(m
, "at tpclnp_input");
497 * CLNP gives us an mbuf chain WITH the clnp header pulled up,
498 * and the length of the clnp header.
499 * First, strip off the Clnp header. leave the mbuf there for the
500 * pullup that follows.
502 m
->m_len
-= clnp_len
;
503 m
->m_data
+= clnp_len
;
504 m
->m_pkthdr
.len
-= clnp_len
;
505 /* XXXX: should probably be in clnp_input */
506 switch (dst
->siso_data
[dst
->siso_nlen
- 1]) {
509 return (tuba_tcpinput(m
, src
, dst
));
512 if (m
->m_len
== 0 && (m
= m_pullup(m
, 1)) == 0)
514 if (*(mtod(m
, u_char
*)) == ISO10747_IDRP
)
515 return (idrp_input(m
, src
, dst
));
520 if (mtod(m
, u_char
*)[1] == UD_TPDU_type
)
524 dump_mbuf(m
, "after tpclnp_input both pullups");
528 printf("calling %sinput : src 0x%x, dst 0x%x, src addr:\n",
529 (input
== tp_input
? "tp_" : "clts_"), src
, dst
);
531 printf(" dst addr:\n");
535 (void) (*input
)(m
, (struct sockaddr
*)src
, (struct sockaddr
*)dst
,
536 0, tpclnp_output_dg
, ce_bit
);
540 if(time
.tv_usec
& 0x4 && time
.tv_usec
& 0x40) {
541 printf("tpclnp_input: FAKING %s\n",
542 tp_stat
.ts_pkt_rcvd
& 0x1?"QUENCH":"QUENCH2");
543 if(tp_stat
.ts_pkt_rcvd
& 0x1) {
544 tpclnp_ctlinput(PRC_QUENCH
, &src
);
546 tpclnp_ctlinput(PRC_QUENCH2
, &src
);
564 * FUNCTION and ARGUMENTS:
565 * find the tpcb pointer and pass it to tp_quench
571 tp_quench((struct tp_pcb
*)isop
->isop_socket
->so_pcb
, PRC_QUENCH2
);
576 * FUNCTION and ARGUMENTS:
577 * find the tpcb pointer and pass it to tp_quench
583 tp_quench((struct tp_pcb
*)isop
->isop_socket
->so_pcb
, PRC_QUENCH
);
588 * The network layer through the protosw table.
589 * FUNCTION and ARGUMENTS:
590 * When clnp an ICMP-like msg this gets called.
591 * It either returns an error status to the user or
592 * it causes all connections on this address to be aborted
593 * by calling the appropriate xx_notify() routine.
594 * (cmd) is the type of ICMP error.
595 * (siso) is the address of the guy who sent the ER CLNPDU
598 tpclnp_ctlinput(cmd
, siso
)
600 struct sockaddr_iso
*siso
;
602 extern u_char inetctlerrmap
[];
603 extern ProtoHook
tpiso_abort();
604 extern ProtoHook
iso_rtchange();
605 extern ProtoHook
tpiso_reset();
606 void iso_pcbnotify();
609 printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd
);
613 if (cmd
< 0 || cmd
> PRC_NCMDS
)
615 if (siso
->siso_family
!= AF_ISO
)
620 iso_pcbnotify(&tp_isopcb
, siso
, 0, (int (*)())tpiso_decbit
);
624 iso_pcbnotify(&tp_isopcb
, siso
, 0, (int (*)())tpiso_quench
);
627 case PRC_TIMXCEED_REASS
:
629 iso_pcbnotify(&tp_isopcb
, siso
, 0, tpiso_reset
);
632 case PRC_HOSTUNREACH
:
633 case PRC_UNREACH_NET
:
636 iso_pcbnotify(&tp_isopcb
, siso
,
637 (int)inetctlerrmap
[cmd
], iso_rtchange
);
643 case PRC_UNREACH_HOST:
644 case PRC_UNREACH_PROTOCOL:
645 case PRC_UNREACH_PORT:
646 case PRC_UNREACH_NEEDFRAG:
647 case PRC_UNREACH_SRCFAIL:
648 case PRC_REDIRECT_NET:
649 case PRC_REDIRECT_HOST:
650 case PRC_REDIRECT_TOSNET:
651 case PRC_REDIRECT_TOSHOST:
652 case PRC_TIMXCEED_INTRANS:
655 iso_pcbnotify(&tp_isopcb
, siso
, (int)inetctlerrmap
[cmd
], tpiso_abort
);
661 * XXX - Variant which is called by clnp_er.c with an isoaddr rather
662 * than a sockaddr_iso.
665 static struct sockaddr_iso siso
= {sizeof(siso
), AF_ISO
};
666 tpclnp_ctlinput1(cmd
, isoa
)
668 struct iso_addr
*isoa
;
670 bzero((caddr_t
)&siso
.siso_addr
, sizeof(siso
.siso_addr
));
671 bcopy((caddr_t
)isoa
, (caddr_t
)&siso
.siso_addr
, isoa
->isoa_len
);
672 tpclnp_ctlinput(cmd
, &siso
);
676 * These next 2 routines are
678 * xxx_notify() from tp_ctlinput() when
679 * net level gets some ICMP-equiv. type event.
680 * FUNCTION and ARGUMENTS:
681 * Cause the connection to be aborted with some sort of error
682 * reason indicating that the network layer caused the abort.
683 * Fakes an ER TPDU so we can go through the driver.
684 * abort always aborts the TP connection.
685 * reset may or may not, depending on the TP class that's in use.
694 printf("tpiso_abort 0x%x\n", isop
);
696 e
.ev_number
= ER_TPDU
;
697 e
.ATTR(ER_TPDU
).e_reason
= ECONNABORTED
;
698 return tp_driver((struct tp_pcb
*)isop
->isop_socket
->so_pcb
, &e
);
707 e
.ev_number
= T_NETRESET
;
708 return tp_driver((struct tp_pcb
*)isop
->isop_socket
->so_pcb
, &e
);