]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netiso/clnp_input.c
7bf537d7b280ec8bc00e519bbfbf42eae96a6270
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 * @(#)clnp_input.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
84 #include <sys/param.h>
86 #include <sys/domain.h>
87 #include <sys/protosw.h>
88 #include <sys/socket.h>
89 #include <sys/socketvar.h>
90 #include <sys/errno.h>
94 #include <net/if_types.h>
95 #include <net/route.h>
97 #include <netiso/iso.h>
98 #include <netiso/iso_var.h>
99 #include <netiso/iso_snpac.h>
100 #include <netiso/clnp.h>
101 #include <netiso/clnl.h>
102 #include <netiso/esis.h>
103 #include <netinet/in_systm.h>
104 #include <netinet/ip.h>
105 #include <netinet/if_ether.h>
106 #include <netiso/eonvar.h>
107 #include <netiso/clnp_stat.h>
108 #include <netiso/argo_debug.h>
111 u_char clnp_protox
[ISOPROTO_MAX
];
112 struct clnl_protosw clnl_protox
[256];
113 int clnpqmaxlen
= IFQ_MAXLEN
; /* RAH? why is this a variable */
114 struct mbuf
*clnp_data_ck();
122 #endif /* ISO_X25ESIS */
125 * FUNCTION: clnp_init
127 * PURPOSE: clnp initialization. Fill in clnp switch tables.
131 * SIDE EFFECTS: fills in clnp_protox table with correct offsets into
138 register struct protosw
*pr
;
141 * CLNP protox initialization
143 if ((pr
= pffindproto(PF_ISO
, ISOPROTO_RAW
, SOCK_RAW
)) == 0)
144 printf("clnl_init: no raw CLNP\n");
146 clnp_protox
[ISOPROTO_RAW
] = pr
- isosw
;
148 if ((pr
= pffindproto(PF_ISO
, ISOPROTO_TP
, SOCK_SEQPACKET
)) == 0)
149 printf("clnl_init: no tp/clnp\n");
151 clnp_protox
[ISOPROTO_TP
] = pr
- isosw
;
154 * CLNL protox initialization
156 clnl_protox
[ISO8473_CLNP
].clnl_input
= clnp_input
;
158 clnlintrq
.ifq_maxlen
= clnpqmaxlen
;
164 * PURPOSE: Process a packet on the clnl input queue
174 register struct mbuf
*m
; /* ptr to first mbuf of pkt */
175 register struct clnl_fixed
*clnl
; /* ptr to fixed part of clnl hdr */
176 int s
; /* save and restore priority */
177 struct clnl_protosw
*clnlsw
;/* ptr to protocol switch */
178 struct snpa_hdr sh
; /* subnetwork hdr */
181 * Get next datagram off clnl input queue
185 /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
186 IF_DEQUEUE(&clnlintrq
, m
);
190 if (m
== 0) /* nothing to do */
192 if ((m
->m_flags
& M_PKTHDR
) == 0 || m
->m_pkthdr
.rcvif
== 0) {
196 register struct ifaddr
*ifa
;
197 for (ifa
= m
->m_pkthdr
.rcvif
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
198 if (ifa
->ifa_addr
->sa_family
== AF_ISO
)
205 bzero((caddr_t
)&sh
, sizeof(sh
));
206 sh
.snh_flags
= m
->m_flags
& (M_MCAST
|M_BCAST
);
207 switch((sh
.snh_ifp
= m
->m_pkthdr
.rcvif
)->if_type
) {
208 extern int ether_output();
210 bcopy(mtod(m
, caddr_t
), (caddr_t
)sh
.snh_dhost
, sizeof(u_long
));
211 bcopy(sizeof(u_long
) + mtod(m
, caddr_t
),
212 (caddr_t
)sh
.snh_shost
, sizeof(u_long
));
213 sh
.snh_dhost
[4] = mtod(m
, u_char
*)[sizeof(struct ip
) +
214 _offsetof(struct eon_hdr
, eonh_class
)];
215 m
->m_data
+= EONIPLEN
;
216 m
->m_len
-= EONIPLEN
;
217 m
->m_pkthdr
.len
-= EONIPLEN
;
221 if (sh
.snh_ifp
->if_output
== ether_output
) {
222 bcopy((caddr_t
)(mtod(m
, struct ether_header
*)->ether_dhost
),
223 (caddr_t
)sh
.snh_dhost
, 2*sizeof(sh
.snh_dhost
));
224 m
->m_data
+= sizeof (struct ether_header
);
225 m
->m_len
-= sizeof (struct ether_header
);
226 m
->m_pkthdr
.len
-= sizeof (struct ether_header
);
231 printf("clnlintr: src:");
233 printf("%x%c", sh
.snh_shost
[i
] & 0xff, (i
<5) ? ':' : ' ');
236 printf("%x%c", sh
.snh_dhost
[i
] & 0xff, (i
<5) ? ':' : ' ');
241 * Get the fixed part of the clnl header into the first mbuf.
242 * Drop the packet if this fails.
243 * Do not call m_pullup if we have a cluster mbuf or the
246 if ((IS_CLUSTER(m
) || (m
->m_len
< sizeof(struct clnl_fixed
))) &&
247 ((m
= m_pullup(m
, sizeof(struct clnl_fixed
))) == 0)) {
248 INCSTAT(cns_toosmall
); /* TODO: use clnl stats */
249 goto next
; /* m_pullup discards mbuf */
252 clnl
= mtod(m
, struct clnl_fixed
*);
255 * Drop packet if the length of the header is not reasonable.
257 if ((clnl
->cnf_hdr_len
< CLNP_HDR_MIN
) ||
258 (clnl
->cnf_hdr_len
> CLNP_HDR_MAX
)) {
259 INCSTAT(cns_badhlen
); /* TODO: use clnl stats */
265 * If the header is not contained in this mbuf, make it so.
266 * Drop packet if this fails.
267 * Note: m_pullup will allocate a cluster mbuf if necessary
269 if (clnl
->cnf_hdr_len
> m
->m_len
) {
270 if ((m
= m_pullup(m
, (int)clnl
->cnf_hdr_len
)) == 0) {
271 INCSTAT(cns_badhlen
); /* TODO: use clnl stats */
272 goto next
; /* m_pullup discards mbuf */
274 clnl
= mtod(m
, struct clnl_fixed
*);
277 clnlsw
= &clnl_protox
[clnl
->cnf_proto_id
];
280 if (clnlsw
->clnl_input
)
281 (*clnlsw
->clnl_input
) (m
, &sh
);
289 * FUNCTION: clnp_input
291 * PURPOSE: process an incoming clnp packet
295 * SIDE EFFECTS: increments fields of clnp_stat structure.
298 * TODO: I would like to make seg_part a pointer into the mbuf, but
299 * will it be correctly aligned?
302 struct mbuf
*m
; /* ptr to first mbuf of pkt */
303 struct snpa_hdr
*shp
; /* subnetwork header */
305 register struct clnp_fixed
*clnp
; /* ptr to fixed part of header */
306 struct sockaddr_iso source
; /* source address of pkt */
307 struct sockaddr_iso target
; /* destination address of pkt */
308 #define src source.siso_addr
309 #define dst target.siso_addr
310 caddr_t hoff
; /* current offset in packet */
311 caddr_t hend
; /* address of end of header info */
312 struct clnp_segment seg_part
; /* segment part of hdr */
313 int seg_off
=0; /* offset of segment part of hdr */
314 int seg_len
;/* length of packet data&hdr in bytes */
315 struct clnp_optidx oidx
, *oidxp
= NULL
; /* option index */
316 extern int iso_systype
; /* used by ESIS config resp */
317 extern struct sockaddr_iso blank_siso
; /* used for initializing */
319 /* true if congestion experienced */
320 /* which means you need afrin nose */
321 /* spray. How clever! */
325 "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n",
326 m
->m_len
, m
->m_type
, IS_CLUSTER(m
) ? "cluster" : "normal");
331 * If no iso addresses have been set, there is nothing
332 * to do with the packet.
334 if (iso_ifaddr
== NULL
) {
335 clnp_discard(m
, ADDR_DESTUNREACH
);
340 clnp
= mtod(m
, struct clnp_fixed
*);
345 printf("clnp_input: clnp header:\n");
346 dump_buf(mtod(m
, caddr_t
), clnp
->cnf_hdr_len
);
347 printf("clnp_input: mbuf chain:\n");
348 for (mhead
= m
; mhead
!= NULL
; mhead
=mhead
->m_next
) {
349 printf("m x%x, len %d\n", mhead
, mhead
->m_len
);
350 total_len
+= mhead
->m_len
;
352 printf("clnp_input: total length of mbuf chain %d:\n", total_len
);
356 * Compute checksum (if necessary) and drop packet if
357 * checksum does not match
359 if (CKSUM_REQUIRED(clnp
) && iso_check_csum(m
, (int)clnp
->cnf_hdr_len
)) {
360 INCSTAT(cns_badcsum
);
361 clnp_discard(m
, GEN_BADCSUM
);
365 if (clnp
->cnf_vers
!= ISO8473_V1
) {
366 INCSTAT(cns_badvers
);
367 clnp_discard(m
, DISC_UNSUPPVERS
);
372 /* check mbuf data length: clnp_data_ck will free mbuf upon error */
373 CTOH(clnp
->cnf_seglen_msb
, clnp
->cnf_seglen_lsb
, seg_len
);
374 if ((m
= clnp_data_ck(m
, seg_len
)) == 0)
377 clnp
= mtod(m
, struct clnp_fixed
*);
378 hend
= (caddr_t
)clnp
+ clnp
->cnf_hdr_len
;
381 * extract the source and destination address
382 * drop packet on failure
384 source
= target
= blank_siso
;
386 hoff
= (caddr_t
)clnp
+ sizeof(struct clnp_fixed
);
387 CLNP_EXTRACT_ADDR(dst
, hoff
, hend
);
388 if (hoff
== (caddr_t
)0) {
389 INCSTAT(cns_badaddr
);
390 clnp_discard(m
, GEN_INCOMPLETE
);
393 CLNP_EXTRACT_ADDR(src
, hoff
, hend
);
394 if (hoff
== (caddr_t
)0) {
395 INCSTAT(cns_badaddr
);
396 clnp_discard(m
, GEN_INCOMPLETE
);
401 printf("clnp_input: from %s", clnp_iso_addrp(&src
));
402 printf(" to %s\n", clnp_iso_addrp(&dst
));
406 * extract the segmentation information, if it is present.
407 * drop packet on failure
409 if (((clnp
->cnf_type
& CNF_TYPE
) != CLNP_ER
) &&
410 (clnp
->cnf_type
& CNF_SEG_OK
)) {
411 if (hoff
+ sizeof(struct clnp_segment
) > hend
) {
413 clnp_discard(m
, GEN_INCOMPLETE
);
416 (void) bcopy(hoff
, (caddr_t
)&seg_part
, sizeof(struct clnp_segment
));
417 /* make sure segmentation fields are in host order */
418 seg_part
.cng_id
= ntohs(seg_part
.cng_id
);
419 seg_part
.cng_off
= ntohs(seg_part
.cng_off
);
420 seg_part
.cng_tot_len
= ntohs(seg_part
.cng_tot_len
);
421 seg_off
= hoff
- (caddr_t
)clnp
;
422 hoff
+= sizeof(struct clnp_segment
);
427 * process options if present. If clnp_opt_sanity returns
428 * false (indicating an error was found in the options) or
429 * an unsupported option was found
430 * then drop packet and emit an ER.
436 errcode
= clnp_opt_sanity(m
, hoff
, hend
-hoff
, oidxp
);
438 /* we do not support security */
439 if ((errcode
== 0) && (oidxp
->cni_securep
))
440 errcode
= DISC_UNSUPPSECURE
;
442 /* the er option is valid with ER pdus only */
443 if ((errcode
== 0) && (oidxp
->cni_er_reason
!= ER_INVALREAS
) &&
444 ((clnp
->cnf_type
& CNF_TYPE
) != CLNP_ER
))
445 errcode
= DISC_UNSUPPOPT
;
448 /* check if the congestion experienced bit is set */
449 if (oidxp
->cni_qos_formatp
) {
450 caddr_t qosp
= CLNP_OFFTOOPT(m
, oidxp
->cni_qos_formatp
);
453 need_afrin
= ((qos
& (CLNPOVAL_GLOBAL
|CLNPOVAL_CONGESTED
)) ==
454 (CLNPOVAL_GLOBAL
|CLNPOVAL_CONGESTED
));
456 INCSTAT(cns_congest_rcvd
);
461 clnp_discard(m
, (char)errcode
);
463 printf("clnp_input: dropped (err x%x) due to bad options\n",
471 * check if this packet is for us. if not, then forward
473 if (clnp_ours(&dst
) == 0) {
475 printf("clnp_input: forwarding packet not for us\n");
477 clnp_forward(m
, seg_len
, &dst
, oidxp
, seg_off
, shp
);
482 * ESIS Configuration Response Function
484 * If the packet received was sent to the multicast address
485 * all end systems, then send an esh to the source
487 if ((shp
->snh_flags
& M_MCAST
) && (iso_systype
== SNPA_ES
)) {
488 extern short esis_holding_time
;
490 esis_shoutput(shp
->snh_ifp
, ESIS_ESH
, esis_holding_time
,
491 shp
->snh_shost
, 6, &dst
);
495 * If this is a fragment, then try to reassemble it. If clnp_reass
496 * returns non NULL, the packet has been reassembled, and should
497 * be give to TP. Otherwise the fragment has been delt with
498 * by the reassembly code (either stored or deleted). In either case
499 * we should have nothing more to do with it.
501 if (((clnp
->cnf_type
& CNF_TYPE
) != CLNP_ER
) &&
502 (clnp
->cnf_type
& CNF_SEG_OK
) &&
503 (seg_len
!= seg_part
.cng_tot_len
)) {
506 if ((m0
= clnp_reass(m
, &src
, &dst
, &seg_part
)) != NULL
) {
508 clnp
= mtod(m
, struct clnp_fixed
*);
509 INCSTAT(cns_reassembled
);
516 * give the packet to the higher layer
518 * Note: the total length of packet
519 * is the total length field of the segmentation part,
520 * or, if absent, the segment length field of the
523 INCSTAT(cns_delivered
);
524 switch (clnp
->cnf_type
& CNF_TYPE
) {
527 * This ER must have the er option.
528 * If the option is not present, discard datagram.
530 if (oidxp
== NULL
|| oidxp
->cni_er_reason
== ER_INVALREAS
) {
531 clnp_discard(m
, GEN_HDRSYNTAX
);
533 clnp_er_input(m
, &src
, oidxp
->cni_er_reason
);
538 (*isosw
[clnp_protox
[ISOPROTO_TP
]].pr_input
)(m
, &source
, &target
,
539 clnp
->cnf_hdr_len
, need_afrin
);
545 printf("clnp_input: raw input of %d bytes\n",
546 clnp
->cnf_type
& CNF_SEG_OK
? seg_part
.cng_tot_len
: seg_len
);
548 (*isosw
[clnp_protox
[ISOPROTO_RAW
]].pr_input
)(m
, &source
, &target
,
554 printf("clnp_input: echoing packet\n");
556 (void)clnp_echoreply(m
,
557 (clnp
->cnf_type
& CNF_SEG_OK
? (int)seg_part
.cng_tot_len
: seg_len
),
558 &source
, &target
, oidxp
);
562 printf("clnp_input: unknown clnp pkt type %d\n",
563 clnp
->cnf_type
& CNF_TYPE
);
564 clnp_stat
.cns_delivered
--;
565 clnp_stat
.cns_noproto
++;
566 clnp_discard(m
, GEN_HDRSYNTAX
);