]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netiso/esis.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 * @(#)esis.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 #include <sys/param.h>
87 #include <sys/systm.h>
89 #include <sys/domain.h>
90 #include <sys/protosw.h>
91 #include <sys/socket.h>
92 #include <sys/socketvar.h>
93 #include <sys/errno.h>
94 #include <sys/kernel.h>
97 #include <net/if_dl.h>
98 #include <net/route.h>
99 #include <net/raw_cb.h>
101 #include <netiso/iso.h>
102 #include <netiso/iso_pcb.h>
103 #include <netiso/iso_var.h>
104 #include <netiso/iso_snpac.h>
105 #include <netiso/clnl.h>
106 #include <netiso/clnp.h>
107 #include <netiso/clnp_stat.h>
108 #include <netiso/esis.h>
109 #include <netiso/argo_debug.h>
112 * Global variables to esis implementation
114 * esis_holding_time - the holding time (sec) parameter for outgoing pdus
115 * esis_config_time - the frequency (sec) that hellos are generated
116 * esis_esconfig_time - suggested es configuration time placed in the
120 struct rawcb esis_pcb
;
121 void esis_config(), snpac_age();
122 int esis_sendspace
= 2048;
123 int esis_recvspace
= 2048;
124 short esis_holding_time
= ESIS_HT
;
125 short esis_config_time
= ESIS_CONFIG
;
126 short esis_esconfig_time
= ESIS_CONFIG
;
127 extern int iso_systype
;
128 struct sockaddr_dl esis_dl
= { sizeof(esis_dl
), AF_LINK
};
129 extern char all_es_snpa
[], all_is_snpa
[];
131 #define EXTEND_PACKET(m, mhdr, cp)\
132 if (((m)->m_next = m_getclr(M_DONTWAIT, MT_HEADER)) == NULL) {\
133 esis_stat.es_nomem++;\
138 (cp) = mtod((m), caddr_t);\
141 * FUNCTION: esis_init
143 * PURPOSE: Initialize the kernel portion of esis protocol
153 extern struct clnl_protosw clnl_protox
[256];
154 int esis_input(), isis_input();
157 #endif /* ISO_X25ESIS */
159 esis_pcb
.rcb_next
= esis_pcb
.rcb_prev
= &esis_pcb
;
160 llinfo_llc
.lc_next
= llinfo_llc
.lc_prev
= &llinfo_llc
;
162 timeout(snpac_age
, (caddr_t
)0, hz
);
163 timeout(esis_config
, (caddr_t
)0, hz
);
165 clnl_protox
[ISO9542_ESIS
].clnl_input
= esis_input
;
166 clnl_protox
[ISO10589_ISIS
].clnl_input
= isis_input
;
168 clnl_protox
[ISO9542X25_ESIS
].clnl_input
= x25esis_input
;
169 #endif /* ISO_X25ESIS */
173 * FUNCTION: esis_usrreq
175 * PURPOSE: Handle user level esis requests
177 * RETURNS: 0 or appropriate errno
183 esis_usrreq(so
, req
, m
, nam
, control
)
184 struct socket
*so
; /* socket: used only to get to this code */
185 int req
; /* request */
186 struct mbuf
*m
; /* data for request */
187 struct mbuf
*nam
; /* optional name */
188 struct mbuf
*control
; /* optional control */
190 struct rawcb
*rp
= sotorawcb(so
);
193 if ((so
->so_state
& SS_PRIV
) == 0) {
197 if (rp
== NULL
&& req
!= PRU_ATTACH
) {
208 MALLOC(rp
, struct rawcb
*, sizeof(*rp
), M_PCB
, M_WAITOK
);
209 if (so
->so_pcb
= (caddr_t
)rp
) {
210 bzero(so
->so_pcb
, sizeof(*rp
));
211 insque(rp
, &esis_pcb
);
213 error
= soreserve(so
, esis_sendspace
, esis_recvspace
);
223 /* error checking here */
224 error
= isis_output(mtod(nam
,struct sockaddr_dl
*), m
);
237 soisdisconnected(so
);
255 * FUNCTION: esis_input
257 * PURPOSE: Process an incoming esis packet
266 struct mbuf
*m0
; /* ptr to first mbuf of pkt */
267 struct snpa_hdr
*shp
; /* subnetwork header */
269 register struct esis_fixed
*pdu
= mtod(m0
, struct esis_fixed
*);
273 * check checksum if necessary
275 if (ESIS_CKSUM_REQUIRED(pdu
) && iso_check_csum(m0
, (int)pdu
->esis_hdr_len
)) {
276 esis_stat
.es_badcsum
++;
281 if (pdu
->esis_vers
!= ESIS_VERSION
) {
282 esis_stat
.es_badvers
++;
285 type
= pdu
->esis_type
& 0x1f;
288 esis_eshinput(m0
, shp
);
292 esis_ishinput(m0
, shp
);
296 esis_rdinput(m0
, shp
);
300 esis_stat
.es_badtype
++;
304 if (esis_pcb
.rcb_next
!= &esis_pcb
)
311 * FUNCTION: esis_rdoutput
313 * PURPOSE: Transmit a redirect pdu
319 * NOTES: Assumes there is enough space for fixed part of header,
320 * DA, BSNPA and NET in first mbuf.
322 esis_rdoutput(inbound_shp
, inbound_m
, inbound_oidx
, rd_dstnsap
, rt
)
323 struct snpa_hdr
*inbound_shp
; /* snpa hdr from incoming packet */
324 struct mbuf
*inbound_m
; /* incoming pkt itself */
325 struct clnp_optidx
*inbound_oidx
; /* clnp options assoc with incoming pkt */
326 struct iso_addr
*rd_dstnsap
; /* ultimate destination of pkt */
327 struct rtentry
*rt
; /* snpa cache info regarding next hop of
332 struct esis_fixed
*pdu
;
333 int len
, total_len
= 0;
334 struct sockaddr_iso siso
;
335 struct ifnet
*ifp
= inbound_shp
->snh_ifp
;
336 struct sockaddr_dl
*sdl
;
337 struct iso_addr
*rd_gwnsap
;
339 if (rt
->rt_flags
& RTF_GATEWAY
) {
340 rd_gwnsap
= &((struct sockaddr_iso
*)rt
->rt_gateway
)->siso_addr
;
341 rt
= rtalloc1(rt
->rt_gateway
, 0);
343 rd_gwnsap
= &((struct sockaddr_iso
*)rt_key(rt
))->siso_addr
;
344 if (rt
== 0 || (sdl
= (struct sockaddr_dl
*)rt
->rt_gateway
) == 0 ||
345 sdl
->sdl_family
!= AF_LINK
) {
346 /* maybe we should have a function that you
347 could put in the iso_ifaddr structure
348 which could translate iso_addrs into snpa's
349 where there is a known mapping for that address type */
350 esis_stat
.es_badtype
++;
353 esis_stat
.es_rdsent
++;
354 IFDEBUG(D_ESISOUTPUT
)
355 printf("esis_rdoutput: ifp x%x (%s%d), ht %d, m x%x, oidx x%x\n",
356 ifp
, ifp
->if_name
, ifp
->if_unit
, esis_holding_time
, inbound_m
,
358 printf("\tdestination: %s\n", clnp_iso_addrp(rd_dstnsap
));
359 printf("\tredirected toward:%s\n", clnp_iso_addrp(rd_gwnsap
));
362 if ((m0
= m
= m_gethdr(M_DONTWAIT
, MT_HEADER
)) == NULL
) {
363 esis_stat
.es_nomem
++;
366 bzero(mtod(m
, caddr_t
), MHLEN
);
368 pdu
= mtod(m
, struct esis_fixed
*);
369 cp
= (caddr_t
)(pdu
+ 1); /*pointer arith.; 1st byte after header */
370 len
= sizeof(struct esis_fixed
);
373 * Build fixed part of header
375 pdu
->esis_proto_id
= ISO9542_ESIS
;
376 pdu
->esis_vers
= ESIS_VERSION
;
377 pdu
->esis_type
= ESIS_RD
;
378 HTOC(pdu
->esis_ht_msb
, pdu
->esis_ht_lsb
, esis_holding_time
);
380 /* Insert destination address */
381 (void) esis_insert_addr(&cp
, &len
, rd_dstnsap
, m
, 0);
383 /* Insert the snpa of better next hop */
384 *cp
++ = sdl
->sdl_alen
;
385 bcopy(LLADDR(sdl
), cp
, sdl
->sdl_alen
);
387 len
+= (sdl
->sdl_alen
+ 1);
390 * If the next hop is not the destination, then it ought to be
391 * an IS and it should be inserted next. Else, set the
394 /* PHASE2 use mask from ifp of outgoing interface */
395 if (!iso_addrmatch1(rd_dstnsap
, rd_gwnsap
)) {
396 /* this should not happen:
397 if ((nhop_sc->sc_flags & SNPA_IS) == 0) {
398 printf("esis_rdoutput: next hop is not dst and not an IS\n");
402 (void) esis_insert_addr(&cp
, &len
, rd_gwnsap
, m
, 0);
404 *cp
++ = 0; /* NETL */
411 * If redirect is to an IS, add an address mask. The mask to be
412 * used should be the mask present in the routing entry used to
413 * forward the original data packet.
417 * Copy Qos, priority, or security options present in original npdu
420 /* THIS CODE IS CURRENTLY (mostly) UNTESTED */
422 if (inbound_oidx
->cni_qos_formatp
)
423 optlen
+= (inbound_oidx
->cni_qos_len
+ 2);
424 if (inbound_oidx
->cni_priorp
) /* priority option is 1 byte long */
426 if (inbound_oidx
->cni_securep
)
427 optlen
+= (inbound_oidx
->cni_secure_len
+ 2);
428 if (M_TRAILINGSPACE(m
) < optlen
) {
429 EXTEND_PACKET(m
, m0
, cp
);
431 /* assumes MLEN > optlen */
433 /* assume MLEN-len > optlen */
435 * When copying options, copy from ptr - 2 in order to grab
436 * the option code and length
438 if (inbound_oidx
->cni_qos_formatp
) {
439 bcopy(mtod(inbound_m
, caddr_t
) + inbound_oidx
->cni_qos_formatp
- 2,
440 cp
, (unsigned)(inbound_oidx
->cni_qos_len
+ 2));
441 cp
+= inbound_oidx
->cni_qos_len
+ 2;
443 if (inbound_oidx
->cni_priorp
) {
444 bcopy(mtod(inbound_m
, caddr_t
) + inbound_oidx
->cni_priorp
- 2,
448 if (inbound_oidx
->cni_securep
) {
449 bcopy(mtod(inbound_m
, caddr_t
) + inbound_oidx
->cni_securep
- 2, cp
,
450 (unsigned)(inbound_oidx
->cni_secure_len
+ 2));
451 cp
+= inbound_oidx
->cni_secure_len
+ 2;
457 pdu
->esis_hdr_len
= m0
->m_pkthdr
.len
= len
;
458 iso_gen_csum(m0
, ESIS_CKSUM_OFF
, (int)pdu
->esis_hdr_len
);
460 bzero((caddr_t
)&siso
, sizeof(siso
));
461 siso
.siso_family
= AF_ISO
;
462 siso
.siso_data
[0] = AFI_SNA
;
463 siso
.siso_nlen
= 6 + 1; /* should be taken from snpa_hdr */
465 bcopy(inbound_shp
->snh_shost
, siso
.siso_data
+ 1, 6);
466 (ifp
->if_output
)(ifp
, m0
, (struct sockaddr
*)&siso
, 0);
470 * FUNCTION: esis_insert_addr
472 * PURPOSE: Insert an iso_addr into a buffer
474 * RETURNS: true if buffer was big enough, else false
476 * SIDE EFFECTS: Increment buf & len according to size of iso_addr
478 * NOTES: Plus 1 here is for length byte
480 esis_insert_addr(buf
, len
, isoa
, m
, nsellen
)
481 register caddr_t
*buf
; /* ptr to buffer to put address into */
482 int *len
; /* ptr to length of buffer so far */
483 register struct iso_addr
*isoa
; /* ptr to address */
484 register struct mbuf
*m
; /* determine if there remains space */
487 register int newlen
, result
= 0;
489 isoa
->isoa_len
-= nsellen
;
490 newlen
= isoa
->isoa_len
+ 1;
491 if (newlen
<= M_TRAILINGSPACE(m
)) {
492 bcopy((caddr_t
)isoa
, *buf
, newlen
);
498 isoa
->isoa_len
+= nsellen
;
502 #define ESIS_EXTRACT_ADDR(d, b) { d = (struct iso_addr *)(b); b += (1 + *b); \
503 if (b > buflim) {esis_stat.es_toosmall++; goto bad;}}
504 #define ESIS_NEXT_OPTION(b) { b += (2 + b[1]); \
505 if (b > buflim) {esis_stat.es_toosmall++; goto bad;}}
510 * FUNCTION: esis_eshinput
512 * PURPOSE: Process an incoming ESH pdu
520 esis_eshinput(m
, shp
)
521 struct mbuf
*m
; /* esh pdu */
522 struct snpa_hdr
*shp
; /* subnetwork header */
524 struct esis_fixed
*pdu
= mtod(m
, struct esis_fixed
*);
525 u_short ht
; /* holding time */
526 struct iso_addr
*nsap
;
528 u_char
*buf
= (u_char
*)(pdu
+ 1);
529 u_char
*buflim
= pdu
->esis_hdr_len
+ (u_char
*)pdu
;
532 esis_stat
.es_eshrcvd
++;
534 CTOH(pdu
->esis_ht_msb
, pdu
->esis_ht_lsb
, ht
);
540 ESIS_EXTRACT_ADDR(nsap
, buf
);
541 new_entry
= snpac_add(shp
->snh_ifp
,
542 nsap
, shp
->snh_shost
, SNPA_ES
, ht
, 0);
544 int nsellength
= 0, nlen
= 0;
546 /* See if we want to compress out multiple nsaps differing
548 register struct ifaddr
*ifa
= shp
->snh_ifp
->if_addrlist
;
549 for (; ifa
; ifa
= ifa
->ifa_next
)
550 if (ifa
->ifa_addr
->sa_family
== AF_ISO
) {
551 nsellength
= ((struct iso_ifaddr
*)ifa
)->ia_addr
.siso_tlen
;
556 printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n",
557 ht
, naddr
, nsellength
);
559 while (naddr
-- > 0) {
560 struct iso_addr
*nsap2
; u_char
*buf2
;
561 ESIS_EXTRACT_ADDR(nsap
, buf
);
562 /* see if there is at least one more nsap in ESH differing
564 if (nsellength
!= 0) for (buf2
= buf
; buf2
< buflim
;) {
565 ESIS_EXTRACT_ADDR(nsap2
, buf2
);
567 printf("esis_eshinput: comparing %s ",
568 clnp_iso_addrp(nsap
));
569 printf("and %s\n", clnp_iso_addrp(nsap2
));
571 if (Bcmp(nsap
->isoa_genaddr
, nsap2
->isoa_genaddr
,
572 nsap
->isoa_len
- nsellength
) == 0) {
577 new_entry
|= snpac_add(shp
->snh_ifp
,
578 nsap
, shp
->snh_shost
, SNPA_ES
, ht
, nlen
);
583 printf("esis_eshinput: nsap %s is %s\n",
584 clnp_iso_addrp(nsap
), new_entry
? "new" : "old");
586 if (new_entry
&& (iso_systype
& SNPA_IS
))
587 esis_shoutput(shp
->snh_ifp
, ESIS_ISH
, esis_holding_time
,
588 shp
->snh_shost
, 6, (struct iso_addr
*)0);
594 * FUNCTION: esis_ishinput
596 * PURPOSE: process an incoming ISH pdu
604 esis_ishinput(m
, shp
)
605 struct mbuf
*m
; /* esh pdu */
606 struct snpa_hdr
*shp
; /* subnetwork header */
608 struct esis_fixed
*pdu
= mtod(m
, struct esis_fixed
*);
609 u_short ht
, newct
; /* holding time */
610 struct iso_addr
*nsap
; /* Network Entity Title */
611 register u_char
*buf
= (u_char
*) (pdu
+ 1);
612 register u_char
*buflim
= pdu
->esis_hdr_len
+ (u_char
*)pdu
;
615 esis_stat
.es_ishrcvd
++;
616 CTOH(pdu
->esis_ht_msb
, pdu
->esis_ht_lsb
, ht
);
619 printf("esis_ishinput: ish: ht %d\n", ht
);
624 ESIS_EXTRACT_ADDR(nsap
, buf
);
626 while (buf
< buflim
) {
629 if (iso_systype
& SNPA_IS
)
633 CTOH(buf
[2], buf
[3], newct
);
634 if (esis_config_time
!= newct
) {
635 untimeout(esis_config
,0);
636 esis_config_time
= newct
;
642 printf("Unknown ISH option: %x\n", *buf
);
644 ESIS_NEXT_OPTION(buf
);
646 new_entry
= snpac_add(shp
->snh_ifp
, nsap
, shp
->snh_shost
, SNPA_IS
, ht
, 0);
648 printf("esis_ishinput: nsap %s is %s\n",
649 clnp_iso_addrp(nsap
), new_entry
? "new" : "old");
653 esis_shoutput(shp
->snh_ifp
,
654 iso_systype
& SNPA_ES
? ESIS_ESH
: ESIS_ISH
,
655 esis_holding_time
, shp
->snh_shost
, 6, (struct iso_addr
*)0);
661 * FUNCTION: esis_rdinput
663 * PURPOSE: Process an incoming RD pdu
671 esis_rdinput(m0
, shp
)
672 struct mbuf
*m0
; /* esh pdu */
673 struct snpa_hdr
*shp
; /* subnetwork header */
675 struct esis_fixed
*pdu
= mtod(m0
, struct esis_fixed
*);
676 u_short ht
; /* holding time */
677 struct iso_addr
*da
, *net
= 0, *netmask
= 0, *snpamask
= 0;
678 register struct iso_addr
*bsnpa
;
679 register u_char
*buf
= (u_char
*)(pdu
+ 1);
680 register u_char
*buflim
= pdu
->esis_hdr_len
+ (u_char
*)pdu
;
682 esis_stat
.es_rdrcvd
++;
684 /* intermediate systems ignore redirects */
685 if (iso_systype
& SNPA_IS
)
690 CTOH(pdu
->esis_ht_msb
, pdu
->esis_ht_lsb
, ht
);
695 ESIS_EXTRACT_ADDR(da
, buf
);
697 /* Extract better snpa */
698 ESIS_EXTRACT_ADDR(bsnpa
, buf
);
700 /* Extract NET if present */
703 buf
++; /* no NET present, skip NETL anyway */
705 ESIS_EXTRACT_ADDR(net
, buf
);
708 /* process options */
709 while (buf
< buflim
) {
711 case ESISOVAL_SNPAMASK
:
712 if (snpamask
) /* duplicate */
714 snpamask
= (struct iso_addr
*)(buf
+ 1);
717 case ESISOVAL_NETMASK
:
718 if (netmask
) /* duplicate */
720 netmask
= (struct iso_addr
*)(buf
+ 1);
724 printf("Unknown option in ESIS RD (0x%x)\n", buf
[-1]);
726 ESIS_NEXT_OPTION(buf
);
730 printf("esis_rdinput: rd: ht %d, da %s\n", ht
, clnp_iso_addrp(da
));
732 printf("\t: net %s\n", clnp_iso_addrp(net
));
735 * If netl is zero, then redirect is to an ES. We need to add an entry
736 * to the snpa cache for (destination, better snpa).
737 * If netl is not zero, then the redirect is to an IS. In this
738 * case, add an snpa cache entry for (net, better snpa).
740 * If the redirect is to an IS, add a route entry towards that
743 if (net
== 0 || net
->isoa_len
== 0 || snpamask
) {
744 /* redirect to an ES */
745 snpac_add(shp
->snh_ifp
, da
,
746 bsnpa
->isoa_genaddr
, SNPA_ES
, ht
, 0);
748 snpac_add(shp
->snh_ifp
, net
,
749 bsnpa
->isoa_genaddr
, SNPA_IS
, ht
, 0);
750 snpac_addrt(shp
->snh_ifp
, da
, net
, netmask
);
752 bad
: ; /* Needed by ESIS_NEXT_OPTION */
756 * FUNCTION: esis_config
758 * PURPOSE: Report configuration
764 * NOTES: Called every esis_config_time seconds
769 register struct ifnet
*ifp
;
771 timeout(esis_config
, (caddr_t
)0, hz
* esis_config_time
);
774 * Report configuration for each interface that
776 * - has BROADCAST capability
777 * - has an ISO address
779 /* Todo: a better way would be to construct the esh or ish
780 * once and copy it out for all devices, possibly calling
781 * a method in the iso_ifaddr structure to encapsulate and
782 * transmit it. This could work to advantage for non-broadcast media
785 for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
) {
786 if ((ifp
->if_flags
& IFF_UP
) &&
787 (ifp
->if_flags
& IFF_BROADCAST
)) {
788 /* search for an ISO address family */
791 for (ia
= ifp
->if_addrlist
; ia
; ia
= ia
->ifa_next
) {
792 if (ia
->ifa_addr
->sa_family
== AF_ISO
) {
794 iso_systype
& SNPA_ES
? ESIS_ESH
: ESIS_ISH
,
796 (caddr_t
)(iso_systype
& SNPA_ES
? all_is_snpa
:
797 all_es_snpa
), 6, (struct iso_addr
*)0);
806 * FUNCTION: esis_shoutput
808 * PURPOSE: Transmit an esh or ish pdu
816 esis_shoutput(ifp
, type
, ht
, sn_addr
, sn_len
, isoa
)
822 struct iso_addr
*isoa
;
827 struct esis_fixed
*pdu
;
828 struct iso_ifaddr
*ia
;
830 struct sockaddr_iso siso
;
832 if (type
== ESIS_ESH
)
833 esis_stat
.es_eshsent
++;
834 else if (type
== ESIS_ISH
)
835 esis_stat
.es_ishsent
++;
837 printf("esis_shoutput: bad pdu type\n");
841 IFDEBUG(D_ESISOUTPUT
)
843 printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ",
844 ifp
, ifp
->if_name
, ifp
->if_unit
, type
== ESIS_ESH
? "esh" : "ish",
846 for (i
=0; i
<sn_len
; i
++)
847 printf("%x%c", *(sn_addr
+i
), i
< (sn_len
-1) ? ':' : ' ');
851 if ((m0
= m
= m_gethdr(M_DONTWAIT
, MT_HEADER
)) == NULL
) {
852 esis_stat
.es_nomem
++;
855 bzero(mtod(m
, caddr_t
), MHLEN
);
857 pdu
= mtod(m
, struct esis_fixed
*);
858 naddrp
= cp
= (caddr_t
)(pdu
+ 1);
859 len
= sizeof(struct esis_fixed
);
862 * Build fixed part of header
864 pdu
->esis_proto_id
= ISO9542_ESIS
;
865 pdu
->esis_vers
= ESIS_VERSION
;
866 pdu
->esis_type
= type
;
867 HTOC(pdu
->esis_ht_msb
, pdu
->esis_ht_lsb
, ht
);
869 if (type
== ESIS_ESH
) {
877 * Here we are responding to a clnp packet sent to an NSAP
878 * that is ours which was sent to the MAC addr all_es's.
879 * It is possible that we did not specifically advertise this
880 * NSAP, even though it is ours, so we will respond
881 * directly to the sender that we are here. If we do have
882 * multiple NSEL's we'll tack them on so he can compress them out.
884 (void) esis_insert_addr(&cp
, &len
, isoa
, m
, 0);
887 for (ia
= iso_ifaddr
; ia
; ia
= ia
->ia_next
) {
888 int nsellen
= (type
== ESIS_ISH
? ia
->ia_addr
.siso_tlen
: 0);
889 int n
= ia
->ia_addr
.siso_nlen
;
890 register struct iso_ifaddr
*ia2
;
892 if (type
== ESIS_ISH
&& naddr
> 0)
894 for (ia2
= iso_ifaddr
; ia2
!= ia
; ia2
= ia2
->ia_next
)
895 if (Bcmp(ia
->ia_addr
.siso_data
, ia2
->ia_addr
.siso_data
, n
) == 0)
898 continue; /* Means we have previously copied this nsap */
899 if (isoa
&& Bcmp(ia
->ia_addr
.siso_data
, isoa
->isoa_genaddr
, n
) == 0) {
901 continue; /* Ditto */
903 IFDEBUG(D_ESISOUTPUT
)
904 printf("esis_shoutput: adding NSAP %s\n",
905 clnp_iso_addrp(&ia
->ia_addr
.siso_addr
));
907 if (!esis_insert_addr(&cp
, &len
,
908 &ia
->ia_addr
.siso_addr
, m
, nsellen
)) {
909 EXTEND_PACKET(m
, m0
, cp
);
910 (void) esis_insert_addr(&cp
, &len
, &ia
->ia_addr
.siso_addr
, m
,
916 if (type
== ESIS_ESH
)
919 /* add suggested es config timer option to ISH */
920 if (M_TRAILINGSPACE(m
) < 4) {
921 printf("esis_shoutput: extending packet\n");
922 EXTEND_PACKET(m
, m0
, cp
);
924 *cp
++ = ESISOVAL_ESCT
;
926 HTOC(*cp
, *(cp
+1), esis_esconfig_time
);
929 IFDEBUG(D_ESISOUTPUT
)
930 printf("m0 0x%x, m 0x%x, data 0x%x, len %d, cp 0x%x\n",
931 m0
, m
, m
->m_data
, m
->m_len
, cp
);
935 m0
->m_pkthdr
.len
= len
;
936 pdu
->esis_hdr_len
= len
;
937 iso_gen_csum(m0
, ESIS_CKSUM_OFF
, (int)pdu
->esis_hdr_len
);
939 bzero((caddr_t
)&siso
, sizeof(siso
));
940 siso
.siso_family
= AF_ISO
;
941 siso
.siso_data
[0] = AFI_SNA
;
942 siso
.siso_nlen
= sn_len
+ 1;
943 bcopy(sn_addr
, siso
.siso_data
+ 1, (unsigned)sn_len
);
944 (ifp
->if_output
)(ifp
, m0
, (struct sockaddr
*)&siso
, 0);
948 * FUNCTION: isis_input
950 * PURPOSE: Process an incoming isis packet
959 struct mbuf
*m0
; /* ptr to first mbuf of pkt */
960 struct snpa_hdr
*shp
; /* subnetwork header */
963 register struct rawcb
*rp
, *first_rp
= 0;
964 struct ifnet
*ifp
= shp
->snh_ifp
;
971 printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp
,
972 ifp
->if_name
, ifp
->if_unit
);
974 printf("%x%c", shp
->snh_shost
[i
]&0xff, (i
<5) ? ':' : ' ');
977 printf("%x%c", shp
->snh_dhost
[i
]&0xff, (i
<5) ? ':' : ' ');
980 esis_dl
.sdl_alen
= ifp
->if_addrlen
;
981 esis_dl
.sdl_index
= ifp
->if_index
;
982 bcopy(shp
->snh_shost
, (caddr_t
)esis_dl
.sdl_data
, esis_dl
.sdl_alen
);
983 for (rp
= esis_pcb
.rcb_next
; rp
!= &esis_pcb
; rp
= rp
->rcb_next
) {
988 if (mm
= m_copy(m0
, 0, M_COPYALL
)) { /*can't block at interrupt level */
989 if (sbappendaddr(&rp
->rcb_socket
->so_rcv
,
990 &esis_dl
, mm
, (struct mbuf
*)0) != 0) {
991 sorwakeup(rp
->rcb_socket
);
994 printf("Error in sbappenaddr, mm = 0x%x\n", mm
);
1000 if (first_rp
&& sbappendaddr(&first_rp
->rcb_socket
->so_rcv
,
1001 &esis_dl
, m0
, (struct mbuf
*)0) != 0) {
1002 sorwakeup(first_rp
->rcb_socket
);
1009 register struct sockaddr_dl
*sdl
;
1012 register struct ifnet
*ifp
;
1013 struct ifaddr
*ifa
, *ifa_ifwithnet();
1014 struct sockaddr_iso siso
;
1018 ifa
= ifa_ifwithnet((struct sockaddr
*)sdl
); /* get ifp from sdl */
1020 IFDEBUG(D_ISISOUTPUT
)
1021 printf("isis_output: interface not found\n");
1027 sn_len
= sdl
->sdl_alen
;
1028 IFDEBUG(D_ISISOUTPUT
)
1029 u_char
*cp
= (u_char
*)LLADDR(sdl
), *cplim
= cp
+ sn_len
;
1030 printf("isis_output: ifp 0x%x (%s%d), to: ",
1031 ifp
, ifp
->if_name
, ifp
->if_unit
);
1032 while (cp
< cplim
) {
1033 printf("%x", *cp
++);
1034 printf("%c", (cp
< cplim
) ? ':' : ' ');
1038 bzero((caddr_t
)&siso
, sizeof(siso
));
1039 siso
.siso_family
= AF_ISO
; /* This convention may be useful for X.25 */
1040 siso
.siso_data
[0] = AFI_SNA
;
1041 siso
.siso_nlen
= sn_len
+ 1;
1042 bcopy(LLADDR(sdl
), siso
.siso_data
+ 1, sn_len
);
1043 error
= (ifp
->if_output
)(ifp
, m
, (struct sockaddr
*)&siso
, 0);
1045 IFDEBUG(D_ISISOUTPUT
)
1046 printf("isis_output: error from ether_output is %d\n", error
);
1059 * FUNCTION: esis_ctlinput
1061 * PURPOSE: Handle the PRC_IFDOWN transition
1067 * NOTES: Calls snpac_flush for interface specified.
1068 * The loop through iso_ifaddr is stupid because
1069 * back in if_down, we knew the ifp...
1071 esis_ctlinput(req
, siso
)
1072 int req
; /* request: we handle only PRC_IFDOWN */
1073 struct sockaddr_iso
*siso
; /* address of ifp */
1075 register struct iso_ifaddr
*ia
; /* scan through interface addresses */
1077 if (req
== PRC_IFDOWN
)
1078 for (ia
= iso_ifaddr
; ia
; ia
= ia
->ia_next
) {
1079 if (iso_addrmatch(IA_SIS(ia
), siso
))
1080 snpac_flushifp(ia
->ia_ifp
);