]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netiso/if_eon.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 * @(#)if_eon.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
85 * Layer between IP and CLNL
88 * Put together a current rfc986 address format and get the right offset
96 #include <sys/param.h>
97 #include <sys/systm.h>
100 #include <sys/protosw.h>
101 #include <sys/socket.h>
102 #include <sys/ioctl.h>
103 #include <sys/errno.h>
104 #include <sys/types.h>
107 #include <net/if_types.h>
108 #include <net/if_dl.h>
109 #include <net/netisr.h>
110 #include <net/route.h>
111 #include <machine/mtpr.h>
113 #include <netinet/in.h>
114 #include <netinet/in_systm.h>
115 #include <netinet/in_var.h>
116 #include <netinet/ip.h>
117 #include <netinet/ip_var.h>
118 #include <netinet/if_ether.h>
120 #include <netiso/iso.h>
121 #include <netiso/iso_var.h>
122 #include <netiso/iso_snpac.h>
123 #include <netiso/argo_debug.h>
124 #include <netiso/iso_errno.h>
125 #include <netiso/eonvar.h>
127 extern struct timeval time
;
128 extern struct ifnet loif
;
138 struct ifnet eonif
[1];
144 struct eon_llinfo eon_llinfo
;
149 * FUNCTION: eonattach
151 * PURPOSE: autoconf attach routine
158 register struct ifnet
*ifp
= eonif
;
161 printf("eonattach()\n");
164 ifp
->if_name
= "eon";
165 ifp
->if_mtu
= ETHERMTU
;
166 /* since everything will go out over ether or token ring */
168 ifp
->if_init
= eoninit
;
169 ifp
->if_ioctl
= eonioctl
;
170 ifp
->if_output
= eonoutput
;
171 ifp
->if_type
= IFT_EON
;
173 ifp
->if_hdrlen
= EONIPLEN
;
174 ifp
->if_flags
= IFF_BROADCAST
;
176 eonioctl(ifp
, SIOCSIFADDR
, (caddr_t
)ifp
->if_addrlist
);
177 eon_llinfo
.el_qhdr
.link
=
178 eon_llinfo
.el_qhdr
.rlink
= &(eon_llinfo
.el_qhdr
);
181 printf("eonattach()\n");
189 * PURPOSE: io controls - ifconfig
191 * link-UP (core addr) (flags: ES, IS)
192 * link-DOWN (core addr) (flags: ES, IS)
193 * must be callable from kernel or user
197 eonioctl(ifp
, cmd
, data
)
198 register struct ifnet
*ifp
;
200 register caddr_t data
;
203 register int error
= 0;
206 printf("eonioctl (cmd 0x%x) \n", cmd
);
210 register struct ifaddr
*ifa
;
213 if (ifa
= (struct ifaddr
*)data
) {
214 ifp
->if_flags
|= IFF_UP
;
215 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
)
216 ifa
->ifa_rtrequest
= eonrtrequest
;
225 eoniphdr(hdr
, loc
, ro
, class, zero
)
227 register struct eon_iphdr
*hdr
;
231 register struct sockaddr_in
*sin
= (struct sockaddr_in
*)&ro
->ro_dst
;
233 bzero((caddr_t
)hdr
, sizeof (*hdr
));
234 bzero((caddr_t
)ro
, sizeof (*ro
));
236 sin
->sin_family
= AF_INET
;
237 sin
->sin_len
= sizeof (*sin
);
238 bcopy(loc
, (caddr_t
)&sin
->sin_addr
, sizeof(struct in_addr
));
240 * If there is a cached route,
241 * check that it is to the same destination
242 * and is still up. If not, free it and try again.
245 struct sockaddr_in
*dst
=
246 (struct sockaddr_in
*)rt_key(ro
->ro_rt
);
247 if ((ro
->ro_rt
->rt_flags
& RTF_UP
) == 0 ||
248 sin
->sin_addr
.s_addr
!= dst
->sin_addr
.s_addr
) {
250 ro
->ro_rt
= (struct rtentry
*)0;
256 hdr
->ei_ip
.ip_dst
= sin
->sin_addr
;
257 hdr
->ei_ip
.ip_p
= IPPROTO_EON
;
258 hdr
->ei_ip
.ip_ttl
= MAXTTL
;
259 hdr
->ei_eh
.eonh_class
= class;
260 hdr
->ei_eh
.eonh_vers
= EON_VERSION
;
261 hdr
->ei_eh
.eonh_csum
= 0;
262 mhead
.m_data
= (caddr_t
) &hdr
->ei_eh
;
263 mhead
.m_len
= sizeof(struct eon_hdr
);
266 printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
268 _offsetof(struct eon_hdr
, eonh_csum
), sizeof(struct eon_hdr
));
271 _offsetof(struct eon_hdr
, eonh_csum
), sizeof(struct eon_hdr
));
274 * FUNCTION: eonrtrequest
276 * PURPOSE: maintains list of direct eon recipients.
277 * sets up IP route for rest.
282 eonrtrequest(cmd
, rt
, gate
)
283 register struct rtentry
*rt
;
284 register struct sockaddr
*gate
;
286 unsigned long zerodst
= 0;
287 caddr_t ipaddrloc
= (caddr_t
) &zerodst
;
288 register struct eon_llinfo
*el
= (struct eon_llinfo
*)rt
->rt_llinfo
;
291 * Common Housekeeping
296 remque(&(el
->el_qhdr
));
297 if (el
->el_iproute
.ro_rt
)
298 RTFREE(el
->el_iproute
.ro_rt
);
306 rt
->rt_rmx
.rmx_mtu
= loif
.if_mtu
; /* unless better below */
307 R_Malloc(el
, struct eon_llinfo
*, sizeof(*el
));
308 rt
->rt_llinfo
= (caddr_t
)el
;
311 Bzero(el
, sizeof(*el
));
312 insque(&(el
->el_qhdr
), &eon_llinfo
.el_qhdr
);
316 if (gate
|| (gate
= rt
->rt_gateway
)) switch (gate
->sa_family
) {
318 #define SDL(x) ((struct sockaddr_dl *)x)
319 if (SDL(gate
)->sdl_alen
== 1)
320 el
->el_snpaoffset
= *(u_char
*)LLADDR(SDL(gate
));
322 ipaddrloc
= LLADDR(SDL(gate
));
325 #define SIN(x) ((struct sockaddr_in *)x)
326 ipaddrloc
= (caddr_t
) &SIN(gate
)->sin_addr
;
331 el
->el_flags
|= RTF_UP
;
332 eoniphdr(&el
->el_ei
, ipaddrloc
, &el
->el_iproute
, EON_NORMAL_ADDR
, 0);
333 if (el
->el_iproute
.ro_rt
)
334 rt
->rt_rmx
.rmx_mtu
= el
->el_iproute
.ro_rt
->rt_rmx
.rmx_mtu
341 * PURPOSE: initialization
349 printf("eon driver-init eon%d\n", unit
);
354 * FUNCTION: eonoutput
356 * PURPOSE: prepend an eon header and hand to IP
357 * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device
358 * (m) is an mbuf *, *m is a CLNL packet
359 * (dst) is a destination address - have to interp. as
360 * multicast or broadcast or real address.
362 * RETURNS: unix error code
367 eonoutput(ifp
, m
, dst
, rt
)
369 register struct mbuf
*m
; /* packet */
370 struct sockaddr_iso
*dst
; /* destination addr */
373 register struct eon_llinfo
*el
;
374 register struct eon_iphdr
*ei
;
378 int error
= 0, class = 0, alen
= 0;
380 static struct eon_iphdr eon_iphdr
;
381 static struct route route
;
384 printf("eonoutput \n" );
387 ifp
->if_lastchange
= time
;
389 if (rt
== 0 || (el
= (struct eon_llinfo
*)rt
->rt_llinfo
) == 0) {
390 if (dst
->siso_family
== AF_LINK
) {
391 register struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)dst
;
393 ipaddrloc
= LLADDR(sdl
);
394 alen
= sdl
->sdl_alen
;
395 } else if (dst
->siso_family
== AF_ISO
&& dst
->siso_data
[0] == AFI_SNA
) {
396 alen
= dst
->siso_nlen
- 1;
397 ipaddrloc
= (caddr_t
) dst
->siso_data
+ 1;
401 class = 4[(u_char
*)ipaddrloc
];
405 eoniphdr(ei
, ipaddrloc
, ro
, class, 1);
412 if ((el
->el_flags
& RTF_UP
) == 0) {
413 eonrtrequest(RTM_CHANGE
, rt
, (struct sockaddr
*)0);
414 if ((el
->el_flags
& RTF_UP
) == 0) {
415 error
= EHOSTUNREACH
;
419 if ((m
->m_flags
& M_PKTHDR
) == 0) {
420 printf("eon: got non headered packet\n");
424 ro
= &el
->el_iproute
;
425 if (el
->el_snpaoffset
) {
426 if (dst
->siso_family
== AF_ISO
) {
427 bcopy((caddr_t
) &dst
->siso_data
[el
->el_snpaoffset
],
428 (caddr_t
) &ei
->ei_ip
.ip_dst
, sizeof(ei
->ei_ip
.ip_dst
));
433 /* put an eon_hdr in the buffer, prepended by an ip header */
434 datalen
= m
->m_pkthdr
.len
+ EONIPLEN
;
435 MGETHDR(mh
, M_DONTWAIT
, MT_HEADER
);
436 if(mh
== (struct mbuf
*)0)
440 MH_ALIGN(m
, sizeof(struct eon_iphdr
));
441 m
->m_len
= sizeof(struct eon_iphdr
);
443 (ei
->ei_ip
.ip_len
= (u_short
)(m
->m_pkthdr
.len
= datalen
));
444 *mtod(m
, struct eon_iphdr
*) = *ei
;
447 printf("eonoutput dst ip addr : %x\n", ei
->ei_ip
.ip_dst
.s_addr
);
448 printf("eonoutput ip_output : eonip header:\n");
449 dump_buf(ei
, sizeof(struct eon_iphdr
));
452 error
= ip_output(m
, (struct mbuf
*)0, ro
, 0, NULL
);
457 ifp
->if_obytes
-= datalen
;
466 register struct mbuf
*m
;
469 register struct eon_hdr
*eonhdr
;
470 register struct ip
*iphdr
;
471 struct ifnet
*eonifp
;
474 eonifp
= &eonif
[0]; /* kludge - really want to give CLNP
475 * the ifp for eon, not for the real device
479 printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n",
480 m
, m
?m
->m_data
:0, m
?m
->m_len
:0);
485 if (iphlen
> sizeof (struct ip
))
486 ip_stripoptions(m
, (struct mbuf
*)0);
487 if (m
->m_len
< EONIPLEN
) {
488 if ((m
= m_pullup(m
, EONIPLEN
)) == 0) {
492 printf("eoninput: DROP \n" );
494 eonifp
->if_ierrors
++;
499 eonif
->if_ibytes
+= m
->m_pkthdr
.len
;
500 eonif
->if_lastchange
= time
;
501 iphdr
= mtod(m
, struct ip
*);
502 /* do a few checks for debugging */
503 if( iphdr
->ip_p
!= IPPROTO_EON
) {
507 /* temporarily drop ip header from the mbuf */
508 m
->m_data
+= sizeof(struct ip
);
509 eonhdr
= mtod(m
, struct eon_hdr
*);
510 if( iso_check_csum( m
, sizeof(struct eon_hdr
) ) != EOK
) {
514 m
->m_data
-= sizeof(struct ip
);
517 printf("eoninput csum ok class 0x%x\n", eonhdr
->eonh_class
);
518 printf("eoninput: eon header:\n");
519 dump_buf(eonhdr
, sizeof(struct eon_hdr
));
522 /* checks for debugging */
523 if( eonhdr
->eonh_vers
!= EON_VERSION
) {
527 m
->m_flags
&= ~(M_BCAST
|M_MCAST
);
528 switch( eonhdr
->eonh_class
) {
530 IncStat(es_in_broad
);
531 m
->m_flags
|= M_BCAST
;
533 case EON_NORMAL_ADDR
:
534 IncStat(es_in_normal
);
536 case EON_MULTICAST_ES
:
537 IncStat(es_in_multi_es
);
538 m
->m_flags
|= M_MCAST
;
540 case EON_MULTICAST_IS
:
541 IncStat(es_in_multi_is
);
542 m
->m_flags
|= M_MCAST
;
545 eonifp
->if_ipackets
++;
548 /* put it on the CLNP queue and set soft interrupt */
550 extern struct ifqueue clnlintrq
;
552 m
->m_pkthdr
.rcvif
= eonifp
; /* KLUDGE */
554 printf("eoninput to clnl IFQ\n");
561 eonifp
->if_iqdrops
++;
562 eonifp
->if_ipackets
--;
569 "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n",
570 m
, m
->m_len
, m
->m_type
, m
->m_data
);
571 dump_buf(mtod(m
, caddr_t
), m
->m_len
);
573 schednetisr(NETISR_ISO
);
579 eonctlinput(cmd
, sin
)
581 struct sockaddr_in
*sin
;
583 extern u_char inetctlerrmap
[];
586 printf("eonctlinput: cmd 0x%x addr: ", cmd
);
591 if (cmd
< 0 || cmd
> PRC_NCMDS
)
594 IncStat(es_icmp
[cmd
]);
599 /* TODO: set the dec bit */
601 case PRC_TIMXCEED_REASS
:
603 case PRC_HOSTUNREACH
:
604 case PRC_UNREACH_NET
:
606 case PRC_UNREACH_HOST
:
608 case PRC_TIMXCEED_INTRANS
:
609 /* TODO: mark the link down */
612 case PRC_UNREACH_PROTOCOL
:
613 case PRC_UNREACH_PORT
:
614 case PRC_UNREACH_SRCFAIL
:
615 case PRC_REDIRECT_NET
:
616 case PRC_REDIRECT_HOST
:
617 case PRC_REDIRECT_TOSNET
:
618 case PRC_REDIRECT_TOSHOST
:
621 /* printf("eonctlinput: ICMP cmd 0x%x\n", cmd );*/