rdir and cdir move into file descriptor structure
[unix-history] / usr / src / sys / netiso / if_eon.c
CommitLineData
109874b6
KS
1/***********************************************************
2 Copyright IBM Corporation 1987
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of IBM not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
21
22******************************************************************/
23
24/*
25 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26 */
27/*
28 * $Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $
29 * $Source: /usr/argo/sys/netiso/RCS/if_eon.c,v $
0b8bdcc2 30 * @(#)if_eon.c 7.11 (Berkeley) %G% *
109874b6
KS
31 *
32 * EON rfc
33 * Layer between IP and CLNL
34 *
35 * TODO:
36 * Put together a current rfc986 address format and get the right offset
37 * for the nsel
38 */
109874b6
KS
39
40#ifndef lint
41static char *rcsid = "$Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $";
42#endif lint
43
a50e2bc0
KS
44#ifdef EON
45#define NEON 1
46
109874b6
KS
47
48#include "param.h"
49#include "systm.h"
50#include "types.h"
51#include "mbuf.h"
52#include "buf.h"
53#include "protosw.h"
54#include "socket.h"
55#include "ioctl.h"
56#include "errno.h"
57#include "types.h"
58
109874b6 59#include "../net/if.h"
4f565be6 60#include "../net/if_types.h"
6ffae239 61#include "../net/if_dl.h"
109874b6
KS
62#include "../net/netisr.h"
63#include "../net/route.h"
d301d150 64#include "machine/mtpr.h"
109874b6
KS
65
66#include "../netinet/in.h"
67#include "../netinet/in_systm.h"
6ffae239 68#include "../netinet/in_var.h"
109874b6
KS
69#include "../netinet/ip.h"
70#include "../netinet/ip_var.h"
71#include "../netinet/if_ether.h"
72
a50e2bc0
KS
73#include "iso.h"
74#include "iso_var.h"
75#include "iso_snpac.h"
a50e2bc0
KS
76#include "argo_debug.h"
77#include "iso_errno.h"
78#include "eonvar.h"
4f565be6 79extern struct timeval time;
109874b6
KS
80
81#define EOK 0
82
83int eoninput();
109874b6
KS
84int eonoutput();
85int eonioctl();
109874b6
KS
86int eonattach();
87int eoninit();
6ffae239 88int eonrtrequest();
109874b6 89extern int ip_output();
6ffae239 90struct ifnet eonif[1];
a50e2bc0
KS
91
92eonprotoinit() {
6ffae239 93 (void) eonattach();
a50e2bc0 94}
109874b6 95
6ffae239
KS
96struct eon_llinfo eon_llinfo;
97#define PROBE_OK 0;
109874b6 98
109874b6
KS
99
100/*
101 * FUNCTION: eonattach
102 *
103 * PURPOSE: autoconf attach routine
104 *
105 * RETURNS: void
106 */
107
6ffae239 108eonattach()
109874b6 109{
6ffae239 110 register struct ifnet *ifp = eonif;
109874b6
KS
111
112 IFDEBUG(D_EON)
113 printf("eonattach()\n");
114 ENDDEBUG
6ffae239 115 ifp->if_unit = 0;
109874b6
KS
116 ifp->if_name = "eon";
117 ifp->if_mtu = ETHERMTU;
118 /* since everything will go out over ether or token ring */
119
120 ifp->if_init = eoninit;
a50e2bc0 121 ifp->if_ioctl = eonioctl;
109874b6 122 ifp->if_output = eonoutput;
a50e2bc0
KS
123 ifp->if_type = IFT_EON;
124 ifp->if_addrlen = 5;
125 ifp->if_hdrlen = EONIPLEN;
109874b6
KS
126 ifp->if_flags = IFF_BROADCAST;
127 if_attach(ifp);
6ffae239
KS
128 eonioctl(ifp, SIOCSIFADDR, (caddr_t)ifp->if_addrlist);
129 eon_llinfo.el_qhdr.link =
130 eon_llinfo.el_qhdr.rlink = &(eon_llinfo.el_qhdr);
109874b6
KS
131
132 IFDEBUG(D_EON)
133 printf("eonattach()\n");
134 ENDDEBUG
109874b6
KS
135}
136
109874b6
KS
137
138/*
139 * FUNCTION: eonioctl
140 *
141 * PURPOSE: io controls - ifconfig
142 * need commands to
143 * link-UP (core addr) (flags: ES, IS)
144 * link-DOWN (core addr) (flags: ES, IS)
145 * must be callable from kernel or user
146 *
147 * RETURNS: nothing
148 */
149eonioctl(ifp, cmd, data)
150 register struct ifnet *ifp;
6ffae239 151 int cmd;
109874b6
KS
152 register caddr_t data;
153{
6ffae239 154 int s = splimp();
109874b6
KS
155 register int error = 0;
156
157 IFDEBUG(D_EON)
158 printf("eonioctl (cmd 0x%x) \n", cmd);
159 ENDDEBUG
160
6ffae239
KS
161 switch (cmd) {
162 register struct ifaddr *ifa;
109874b6
KS
163
164 case SIOCSIFADDR:
6ffae239
KS
165 if (ifa = (struct ifaddr *)data) {
166 ifp->if_flags |= IFF_UP;
9f05a572
KS
167 if (ifa->ifa_addr->sa_family != AF_LINK)
168 ifa->ifa_rtrequest = eonrtrequest;
6ffae239 169 ifa->ifa_llinfolen = sizeof(struct eon_llinfo);
9f05a572 170 }
109874b6 171 break;
109874b6
KS
172 }
173 splx(s);
174 return(error);
175}
176
6ffae239
KS
177
178eoniphdr(hdr, loc, ro, class, zero)
179struct route *ro;
180register struct eon_iphdr *hdr;
181caddr_t loc;
182{
183 struct mbuf mhead;
184 register struct sockaddr_in *sin = (struct sockaddr_in *)&ro->ro_dst;
185 if (zero) {
186 bzero((caddr_t)hdr, sizeof (*hdr));
187 bzero((caddr_t)ro, sizeof (*ro));
188 }
189 sin->sin_family = AF_INET;
190 sin->sin_len = sizeof (*sin);
191 bcopy(loc, (caddr_t)&sin->sin_addr, sizeof(struct in_addr));
192 hdr->ei_ip.ip_dst = sin->sin_addr;
193 hdr->ei_ip.ip_p = IPPROTO_EON;
194 hdr->ei_ip.ip_ttl = MAXTTL;
195 hdr->ei_eh.eonh_class = class;
196 hdr->ei_eh.eonh_vers = EON_VERSION;
197 hdr->ei_eh.eonh_csum = 0;
198 mhead.m_data = (caddr_t) &hdr->ei_eh;
199 mhead.m_len = sizeof(struct eon_hdr);
200 mhead.m_next = 0;
201 IFDEBUG(D_EON)
202 printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
203 &mhead,
204 _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
205 ENDDEBUG
206 iso_gen_csum(&mhead,
207 _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
208}
109874b6 209/*
6ffae239 210 * FUNCTION: eonrtrequest
109874b6 211 *
6ffae239
KS
212 * PURPOSE: maintains list of direct eon recipients.
213 * sets up IP route for rest.
109874b6
KS
214 *
215 * RETURNS: nothing
216 */
6ffae239
KS
217eonrtrequest(cmd, rt, gate)
218register struct rtentry *rt;
6712b8a1 219register struct sockaddr *gate;
109874b6 220{
6712b8a1
KS
221 unsigned long zerodst = 0;
222 caddr_t ipaddrloc = (caddr_t) &zerodst;
6ffae239 223 register struct eon_llinfo *el = (struct eon_llinfo *)rt->rt_llinfo;
6ffae239 224
6ffae239
KS
225 /*
226 * Common Housekeeping
227 */
228 switch (cmd) {
c2bb180a
KS
229 case RTM_DELETE:
230 if (el) {
231 remque(&(el->el_qhdr));
232 if (el->el_iproute.ro_rt)
233 RTFREE(el->el_iproute.ro_rt);
234 Free(el);
235 rt->rt_llinfo = 0;
236 }
237 return;
6ffae239 238
c2bb180a 239 case RTM_RESOLVE:
6ffae239 240 case RTM_ADD:
c2bb180a
KS
241 R_Malloc(el, struct eon_llinfo *, sizeof(*el));
242 rt->rt_llinfo = (caddr_t)el;
243 if (el == 0)
244 return;
245 Bzero(el, sizeof(*el));
6ffae239
KS
246 insque(&(el->el_qhdr), &eon_llinfo.el_qhdr);
247 el->el_rt = rt;
248 break;
6ffae239
KS
249 }
250 if (gate || (gate = rt->rt_gateway)) switch (gate->sa_family) {
251 case AF_LINK:
6712b8a1
KS
252#define SDL(x) ((struct sockaddr_dl *)x)
253 if (SDL(gate)->sdl_alen = 1)
254 el->el_snpaoffset = *(u_char *)LLADDR(SDL(gate));
255 else
256 ipaddrloc = LLADDR(SDL(gate));
6ffae239
KS
257 break;
258 case AF_INET:
6712b8a1
KS
259#define SIN(x) ((struct sockaddr_in *)x)
260 ipaddrloc = (caddr_t) &SIN(gate)->sin_addr;
6ffae239
KS
261 break;
262 default:
263 return;
264 }
265 el->el_flags |= RTF_UP;
55617903 266 eoniphdr(&el->el_ei, ipaddrloc, &el->el_iproute, EON_NORMAL_ADDR, 0);
6ffae239 267}
109874b6
KS
268
269/*
6ffae239 270 * FUNCTION: eoninit
109874b6 271 *
6ffae239 272 * PURPOSE: initialization
109874b6
KS
273 *
274 * RETURNS: nothing
109874b6
KS
275 */
276
6ffae239
KS
277eoninit(unit)
278 int unit;
109874b6 279{
6ffae239 280 printf("eon driver-init eon%d\n", unit);
109874b6
KS
281}
282
283
284/*
285 * FUNCTION: eonoutput
286 *
287 * PURPOSE: prepend an eon header and hand to IP
288 * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device
289 * (m) is an mbuf *, *m is a CLNL packet
290 * (dst) is a destination address - have to interp. as
291 * multicast or broadcast or real address.
292 *
293 * RETURNS: unix error code
294 *
295 * NOTES:
296 *
297 */
6ffae239 298eonoutput(ifp, m, dst, rt)
a50e2bc0 299 struct ifnet *ifp;
6ffae239 300 register struct mbuf *m; /* packet */
109874b6 301 struct sockaddr_iso *dst; /* destination addr */
6ffae239 302 struct rtentry *rt;
109874b6 303{
6ffae239
KS
304 register struct eon_llinfo *el;
305 register struct eon_iphdr *ei;
306 struct route *ro;
307 int datalen;
308 struct mbuf *mh;
0b8bdcc2
KS
309 int error = 0, class = 0, alen = 0;
310 caddr_t ipaddrloc;
6ffae239
KS
311 static struct eon_iphdr eon_iphdr;
312 static struct route route;
109874b6
KS
313
314 IFDEBUG(D_EON)
315 printf("eonoutput \n" );
316 ENDDEBUG
317
4f565be6
KS
318 ifp->if_lastchange = time;
319 ifp->if_opackets++;
6ffae239
KS
320 if (rt == 0 || (el = (struct eon_llinfo *)rt->rt_llinfo) == 0) {
321 if (dst->siso_family == AF_LINK) {
322 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)dst;
0b8bdcc2
KS
323
324 ipaddrloc = LLADDR(sdl);
325 alen = sdl->sdl_alen;
326 } else if (dst->siso_family == AF_ISO && dst->siso_data[0] == AFI_SNA) {
327 alen = dst->siso_nlen - 1;
328 ipaddrloc = (caddr_t) dst->siso_data + 1;
329 }
330 switch (alen) {
331 case 5:
332 class = 4[(u_char *)ipaddrloc];
333 case 4:
334 ro = &route;
335 ei = &eon_iphdr;
336 eoniphdr(ei, ipaddrloc, ro, class, 1);
337 goto send;
6ffae239
KS
338 }
339einval:
a50e2bc0
KS
340 error = EINVAL;
341 goto flush;
342 }
6ffae239
KS
343 if ((el->el_flags & RTF_UP) == 0) {
344 eonrtrequest(RTM_CHANGE, rt, (struct sockaddr *)0);
345 if ((el->el_flags & RTF_UP) == 0) {
346 error = EHOSTUNREACH;
347 goto flush;
348 }
349 }
350 if ((m->m_flags & M_PKTHDR) == 0) {
a50e2bc0
KS
351 printf("eon: got non headered packet\n");
352 goto einval;
353 }
6ffae239
KS
354 ei = &el->el_ei;
355 ro = &el->el_iproute;
6712b8a1
KS
356 if (el->el_snpaoffset) {
357 if (dst->siso_family == AF_ISO) {
358 bcopy((caddr_t) &dst->siso_data[el->el_snpaoffset],
359 (caddr_t) &ei->ei_ip.ip_dst, sizeof(ei->ei_ip.ip_dst));
360 } else
361 goto einval;
362 }
6ffae239
KS
363send:
364 /* put an eon_hdr in the buffer, prepended by an ip header */
365 datalen = m->m_pkthdr.len + EONIPLEN;
a50e2bc0
KS
366 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
367 if(mh == (struct mbuf *)0)
6ffae239
KS
368 goto flush;
369 mh->m_next = m;
370 m = mh;
371 MH_ALIGN(m, sizeof(struct eon_iphdr));
372 m->m_len = sizeof(struct eon_iphdr);
4f565be6 373 ifp->if_obytes +=
6ffae239
KS
374 (ei->ei_ip.ip_len = (u_short)(m->m_pkthdr.len = datalen));
375 *mtod(m, struct eon_iphdr *) = *ei;
109874b6
KS
376
377 IFDEBUG(D_EON)
6ffae239
KS
378 printf("eonoutput dst ip addr : %x\n", ei->ei_ip.ip_dst.s_addr);
379 printf("eonoutput ip_output : eonip header:\n");
380 dump_buf(ei, sizeof(struct eon_iphdr));
109874b6
KS
381 ENDDEBUG
382
6ffae239
KS
383 error = ip_output(m, (struct mbuf *)0, ro, 0);
384 m = 0;
4f565be6
KS
385 if (error) {
386 ifp->if_oerrors++;
387 ifp->if_opackets--;
6ffae239 388 ifp->if_obytes -= datalen;
4f565be6 389 }
6ffae239
KS
390flush:
391 if (m)
392 m_freem(m);
109874b6
KS
393 return error;
394}
395
a50e2bc0 396eoninput(m, iphlen)
109874b6 397 register struct mbuf *m;
a50e2bc0 398 int iphlen;
109874b6 399{
109874b6
KS
400 register struct eon_hdr *eonhdr;
401 register struct ip *iphdr;
402 struct ifnet *eonifp;
a50e2bc0 403 int s;
109874b6
KS
404
405 eonifp = &eonif[0]; /* kludge - really want to give CLNP
406 * the ifp for eon, not for the real device
407 */
408
409 IFDEBUG(D_EON)
a50e2bc0
KS
410 printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n",
411 m, m?m->m_data:0, m?m->m_len:0);
109874b6
KS
412 ENDDEBUG
413
a50e2bc0
KS
414 if (m == 0)
415 return;
416 if (iphlen > sizeof (struct ip))
417 ip_stripoptions(m, (struct mbuf *)0);
418 if (m->m_len < EONIPLEN) {
419 if ((m = m_pullup(m, EONIPLEN)) == 0) {
420 IncStat(es_badhdr);
421drop:
422 IFDEBUG(D_EON)
423 printf("eoninput: DROP \n" );
424 ENDDEBUG
425 eonifp->if_ierrors ++;
426 m_freem(m);
427 return;
428 }
109874b6 429 }
4f565be6
KS
430 eonif->if_ibytes += m->m_pkthdr.len;
431 eonif->if_lastchange = time;
109874b6 432 iphdr = mtod(m, struct ip *);
109874b6
KS
433 /* do a few checks for debugging */
434 if( iphdr->ip_p != IPPROTO_EON ) {
435 IncStat(es_badhdr);
436 goto drop;
437 }
a50e2bc0
KS
438 /* temporarily drop ip header from the mbuf */
439 m->m_data += sizeof(struct ip);
109874b6 440 eonhdr = mtod(m, struct eon_hdr *);
a50e2bc0
KS
441 if( iso_check_csum( m, sizeof(struct eon_hdr) ) != EOK ) {
442 IncStat(es_badcsum);
443 goto drop;
444 }
445 m->m_data -= sizeof(struct ip);
446
109874b6 447 IFDEBUG(D_EON)
a50e2bc0 448 printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class );
109874b6
KS
449 printf("eoninput: eon header:\n");
450 dump_buf(eonhdr, sizeof(struct eon_hdr));
451 ENDDEBUG
452
453 /* checks for debugging */
454 if( eonhdr->eonh_vers != EON_VERSION) {
455 IncStat(es_badhdr);
456 goto drop;
457 }
a50e2bc0 458 m->m_flags &= ~(M_BCAST|M_MCAST);
109874b6
KS
459 switch( eonhdr->eonh_class) {
460 case EON_BROADCAST:
461 IncStat(es_in_broad);
a50e2bc0 462 m->m_flags |= M_BCAST;
109874b6
KS
463 break;
464 case EON_NORMAL_ADDR:
465 IncStat(es_in_normal);
466 break;
467 case EON_MULTICAST_ES:
109874b6 468 IncStat(es_in_multi_es);
a50e2bc0 469 m->m_flags |= M_MCAST;
109874b6
KS
470 break;
471 case EON_MULTICAST_IS:
109874b6 472 IncStat(es_in_multi_is);
a50e2bc0 473 m->m_flags |= M_MCAST;
109874b6
KS
474 break;
475 }
4f565be6 476 eonifp->if_ipackets++;
109874b6 477
109874b6
KS
478 {
479 /* put it on the CLNP queue and set soft interrupt */
480 struct ifqueue *ifq;
481 extern struct ifqueue clnlintrq;
109874b6 482
a50e2bc0 483 m->m_pkthdr.rcvif = eonifp; /* KLUDGE */
109874b6
KS
484 IFDEBUG(D_EON)
485 printf("eoninput to clnl IFQ\n");
486 ENDDEBUG
487 ifq = &clnlintrq;
a50e2bc0 488 s = splimp();
109874b6
KS
489 if (IF_QFULL(ifq)) {
490 IF_DROP(ifq);
491 m_freem(m);
4f565be6
KS
492 eonifp->if_iqdrops++;
493 eonifp->if_ipackets--;
a50e2bc0 494 splx(s);
109874b6
KS
495 return;
496 }
497 IF_ENQUEUE(ifq, m);
498 IFDEBUG(D_EON)
499 printf(
a50e2bc0
KS
500 "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n",
501 m, m->m_len, m->m_type, m->m_data);
109874b6
KS
502 dump_buf(mtod(m, caddr_t), m->m_len);
503 ENDDEBUG
a50e2bc0
KS
504 schednetisr(NETISR_ISO);
505 splx(s);
109874b6 506 }
109874b6
KS
507}
508
509int
510eonctlinput(cmd, sin)
511 int cmd;
512 struct sockaddr_in *sin;
513{
514 extern u_char inetctlerrmap[];
515
516 IFDEBUG(D_EON)
517 printf("eonctlinput: cmd 0x%x addr: ", cmd);
518 dump_isoaddr(sin);
519 printf("\n");
520 ENDDEBUG
521
522 if (cmd < 0 || cmd > PRC_NCMDS)
523 return 0;
524
525 IncStat(es_icmp[cmd]);
526 switch (cmd) {
527
109874b6 528 case PRC_QUENCH:
a50e2bc0 529 case PRC_QUENCH2:
109874b6
KS
530 /* TODO: set the dec bit */
531 break;
532 case PRC_TIMXCEED_REASS:
533 case PRC_ROUTEDEAD:
534 case PRC_HOSTUNREACH:
535 case PRC_UNREACH_NET:
536 case PRC_IFDOWN:
537 case PRC_UNREACH_HOST:
538 case PRC_HOSTDEAD:
539 case PRC_TIMXCEED_INTRANS:
540 /* TODO: mark the link down */
541 break;
542
543 case PRC_UNREACH_PROTOCOL:
544 case PRC_UNREACH_PORT:
109874b6
KS
545 case PRC_UNREACH_SRCFAIL:
546 case PRC_REDIRECT_NET:
547 case PRC_REDIRECT_HOST:
548 case PRC_REDIRECT_TOSNET:
549 case PRC_REDIRECT_TOSHOST:
550 case PRC_MSGSIZE:
551 case PRC_PARAMPROB:
0b8bdcc2 552 /* printf("eonctlinput: ICMP cmd 0x%x\n", cmd );*/
109874b6
KS
553 break;
554 }
555 return 0;
556}
557
a50e2bc0 558#endif