date and time created 88/12/14 15:29:49 by sklower
[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 $
30 *
31 * EON rfc
32 * Layer between IP and CLNL
33 *
34 * TODO:
35 * Put together a current rfc986 address format and get the right offset
36 * for the nsel
37 */
38#define RFC986_NSEL_OFFSET 5
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
44#include "eon.h"
45#if NEON>0
46
47#include "param.h"
48#include "systm.h"
49#include "types.h"
50#include "mbuf.h"
51#include "buf.h"
52#include "protosw.h"
53#include "socket.h"
54#include "ioctl.h"
55#include "errno.h"
56#include "types.h"
57
58#include "../machine/io.h"
59#include "../machineio/ioccvar.h"
60
61#include "../net/if.h"
62#include "../net/netisr.h"
63#include "../net/route.h"
64
65#include "../netinet/in.h"
66#include "../netinet/in_systm.h"
67#include "../netinet/ip.h"
68#include "../netinet/ip_var.h"
69#include "../netinet/if_ether.h"
70
71#include "../netiso/iso.h"
72#include "../netiso/argo_debug.h"
73#include "../netiso/iso_errno.h"
74#include "../netiso/eonvar.h"
75
76#define EOK 0
77
78int eoninput();
79int eonint();
80int eonoutput();
81int eonioctl();
82int eonprobe();
83int eonattach();
84int eoninit();
85extern int ip_output();
86struct ifnet eonif[NEON];
87
88#define EON_FAKE_CSR 0
89int eon_fakeautoconf[2]; /* need at least 2 ints */
90
91caddr_t eonstd[] = { (caddr_t) eon_fakeautoconf, 0 };
92struct iocc_device *eoninfo[NEON];
93
94struct iocc_driver eondriver = {
95 eonprobe, /* idr_probe */
96 0, /* idr_slave */
97 eonattach, /* idr_attach */
98 0, /* idr_dgo */
99 eonstd, /* idr_addr - list of standard addresses for device */
100 "eon", /* idr_dname */
101 eoninfo, /* idr_dinfo - backptrs to iodinit structs */
102 0, /* idr_mname - controller name */
103 0, /* idr_minfo -- backptrs to iominit structs */
104 eonint, /* idr_intr - interrupt rtn */
105 0, /* idr_csr - offset to read/write csr */
106 EON_FAKE_CSR, /* idr_chanrelse */
107 0, /* idr_flags */
108};
109
110
111/*
112 * entry in the EON address cache (list)
113 * (or pt-pt links list, however you view it)
114 */
115
116struct eon_centry {
117 struct qhdr eonc_q_LINK;
118#define eonc_nextLINK eonc_q_LINK.link
119#define eonc_prevLINK eonc_q_LINK.flink
120
121 struct qhdr eonc_q_IS;
122#define eonc_nextIS eonc_q_IS.link
123#define eonc_prevIS eonc_q_IS.flink
124
125 struct qhdr eonc_q_ES;
126#define eonc_nextES eonc_q_ES.link
127#define eonc_prevES eonc_q_ES.flink
128
129 struct in_addr eonc_addr;
130 u_short eonc_status;
131};
132
133/* kinda like mtod() but for eon_centries */
134#define qtocentry(q, off) ((struct eon_centry *) (((caddr_t)(q)) - off))
135#define centrytoq(c, off) ((struct qhdr *) (((caddr_t)(c)) + off))
136
137struct qhdr eon_LINK_hdr = {
138 (struct qhdr *)0,
139 (struct qhdr *)0,
140};
141static struct qhdr eon_IS_hdr = {
142 (struct qhdr *)0,
143 (struct qhdr *)0,
144};
145static struct qhdr eon_ES_hdr = {
146 (struct qhdr *)0,
147 (struct qhdr *)0,
148};
149static struct qhdr eon_FREE_hdr = {
150 (struct qhdr *)0,
151 (struct qhdr *)0,
152};
153
154#define INITQ(q) (q)->rlink = (q)->link = (q)
155
156/*
157 * FUNCTION: eon_dumpcache
158 *
159 * PURPOSE: dump the cache beginning with the argument given
160 *
161 * RETURNS: 0
162 */
163
164eon_dumpcache(which)
165 int which;
166{
167 register int off;
168 register struct eon_centry *ent;
169 struct qhdr *hdr;
170
171 switch (which) {
172 case E_FREE:
173 printf("FREE LIST\n");
174 off = _offsetof( struct eon_centry, eonc_q_LINK);
175 hdr = &eon_FREE_hdr;
176 ent = qtocentry( hdr->link,
177 _offsetof( struct eon_centry, eonc_q_LINK));
178 break;
179 case E_ES:
180 printf("ES LIST\n");
181 off = _offsetof( struct eon_centry, eonc_q_ES);
182 hdr = &eon_ES_hdr;
183 ent = qtocentry( hdr->link,
184 _offsetof( struct eon_centry, eonc_q_ES));
185 break;
186 case E_IS:
187 printf("IS LIST\n");
188 off = _offsetof( struct eon_centry, eonc_q_IS);
189 hdr = &eon_IS_hdr;
190 ent = qtocentry( hdr->link,
191 _offsetof( struct eon_centry, eonc_q_IS));
192 break;
193 case E_LINK:
194 printf("LINK LIST\n");
195 off = _offsetof( struct eon_centry, eonc_q_LINK);
196 hdr = &eon_LINK_hdr;
197 ent = qtocentry( hdr->link,
198 _offsetof( struct eon_centry, eonc_q_LINK));
199 break;
200 }
201 if(hdr == centrytoq(ent, off)->link )
202 printf("EMPTY\n");
203 else while(1) {
204 printf("0x%x: %d.%d.%d.%d, %s %s\n", ent,
205 (ent->eonc_addr.s_addr>>24)&0xff,
206 (ent->eonc_addr.s_addr>>16)&0xff,
207 (ent->eonc_addr.s_addr>>8)&0xff,
208 (ent->eonc_addr.s_addr)&0xff,
209 ((ent->eonc_status & EON_ESLINK_UP)?"ES^":
210 (ent->eonc_status & EON_ESLINK_DOWN)?"es*": " "),
211 ((ent->eonc_status & EON_ISLINK_UP)?"IS^":
212 (ent->eonc_status & EON_ISLINK_DOWN)?"is*": " ")
213 );
214 dump_buf(ent, sizeof(struct eon_centry) );
215
216 { /* ent = ent.next: */
217 register struct qhdr *q;
218
219 q = centrytoq(ent, off)->link;
220 if( q == hdr)
221 break;
222 if( q == (struct qhdr *)0) /* panic */ {
223 printf("eon0: BAD Q HDR or CENTRY! q 0x%x ent 0x%x off 0x%x\n",
224 q, ent, off);
225 break;
226 }
227 ent = qtocentry( q, off );
228 }
229 }
230}
231/*
232 * FUNCTION: eon_initcache
233 *
234 * PURPOSE: allocs a bunch of free cache entries
235 *
236 * RETURNS: 0
237 */
238
239eon_initcache()
240{
241 static struct eon_centry eoncache[EON_CACHESIZE];
242 register int i;
243 register struct eon_centry *ent;
244
245 bzero( eoncache, EON_CACHESIZE*sizeof(struct eon_centry));
246 INITQ( &eon_FREE_hdr );
247 INITQ( &eon_LINK_hdr );
248 INITQ( &eon_IS_hdr );
249 INITQ( &eon_ES_hdr );
250
251 ent = eoncache;
252
253 for(i=0; i< EON_CACHESIZE; i++,ent++) {
254 _insque( centrytoq(ent, _offsetof( struct eon_centry, eonc_q_LINK)),
255 &eon_FREE_hdr);
256 }
257 printf("eon0: cache initialized\n");
258}
259
260/*
261 * FUNCTION: eonprobe
262 *
263 * PURPOSE: filler for device configuration
264 *
265 * RETURNS: PROBE_OK
266 */
267
268eonprobe()
269{
270 extern int int_level, int_irq;
271
272 printf("eonprobe() \n");
273 int_level = int_irq = 0x3; /* pick something - anything but -1 */
274 return PROBE_OK;
275}
276
277/*
278 * FUNCTION: eonattach
279 *
280 * PURPOSE: autoconf attach routine
281 *
282 * RETURNS: void
283 */
284
285eonattach(iod)
286 register struct iocc_device *iod;
287{
288 register struct ifnet *ifp = &eonif[iod->iod_unit];
289
290 IFDEBUG(D_EON)
291 printf("eonattach()\n");
292 ENDDEBUG
293 ifp->if_unit = iod->iod_unit;
294 ifp->if_name = "eon";
295 ifp->if_mtu = ETHERMTU;
296 /* since everything will go out over ether or token ring */
297
298 ifp->if_init = eoninit;
299 ifp->if_ioctl = eonioctl; /* needed? */
300 ifp->if_output = eonoutput;
301 ifp->if_reset = 0;
302 ifp->if_flags = IFF_BROADCAST;
303 if_attach(ifp);
304
305 IFDEBUG(D_EON)
306 printf("eonattach()\n");
307 ENDDEBUG
308 eon_initcache();
309 IFDEBUG(D_EON)
310 printf("eon%d: attached\n", iod->iod_unit);
311 ENDDEBUG
312}
313
314static struct eon_centry *
315find_oldent( ea )
316 struct sockaddr_eon *ea;
317{
318 register int offset =
319 _offsetof( struct eon_centry, eonc_q_LINK);
320 register struct eon_centry *ent = qtocentry(eon_LINK_hdr.link, offset);
321
322 IFDEBUG(D_EON)
323 printf("eon: find_oldent() ipaddr: %d.%d.%d.%d\n",
324 (ea->seon_ipaddr>>24)&0xff,
325 (ea->seon_ipaddr>>16)&0xff,
326 (ea->seon_ipaddr>>8)&0xff,
327 (ea->seon_ipaddr)&0xff );
328 ENDDEBUG
329 for (; ent; ent = qtocentry(ent->eonc_nextLINK, offset) ) {
330 if( ent->eonc_addr.s_addr == ea->seon_ipaddr )
331 return ent;
332 }
333 return (struct eon_centry *)0;
334}
335
336/*
337 * FUNCTION: eonioctl
338 *
339 * PURPOSE: io controls - ifconfig
340 * need commands to
341 * link-UP (core addr) (flags: ES, IS)
342 * link-DOWN (core addr) (flags: ES, IS)
343 * must be callable from kernel or user
344 *
345 * RETURNS: nothing
346 */
347eonioctl(ifp, cmd, data)
348 register struct ifnet *ifp;
349 register int cmd;
350 register caddr_t data;
351{
352 struct ifreq *ifr = (struct ifreq *)data;
353 register struct sockaddr_eon *eoa =
354 (struct sockaddr_eon *)&(ifr->ifr_addr);
355 register int s = splimp();
356 register int error = 0;
357
358 IFDEBUG(D_EON)
359 printf("eonioctl (cmd 0x%x) \n", cmd);
360 ENDDEBUG
361
362 switch (cmd){
363 case SIOCSIFDSTADDR: {
364 /* add pt-pt link to the set of core addrs */
365 register struct eon_centry *ent, *oldent;
366 register u_short which;
367
368 /* "which" tells which lists to put these guys in - don't
369 * want to insert something in a list if it's already there
370 */
371#define LEGIT_EONADDR(a)\
372 ((a->seon_family == AF_ISO) && (a->seon_afi == 0x47) &&\
373 (a->seon_idi[0] == 0) && (a->seon_idi[1] == 6) \
374 )
375#ifdef notdef
376 /* GET THESE RIGHT AND ADD THEM */
377 && (a->seon_vers == 3) && (a->seon_adrlen == 0xa)
378#endif notdef
379
380 if( ! LEGIT_EONADDR(eoa) ) {
381 error = EADDRNOTAVAIL;
382 break;
383 }
384
385 oldent = find_oldent( eoa );
386 IFDEBUG(D_EON)
387 printf("eonioctl legit seon_status 0x%x oldent %s\n",
388 eoa->seon_status, oldent?"found":"not found");
389 ENDDEBUG
390
391 if( eoa->seon_status & UPBITS ) {
392 if (!oldent) {
393 /* doesn't exist - need to create one */
394 /* TODO : check for null free list */
395 ent = qtocentry(eon_FREE_hdr.link,
396 _offsetof( struct eon_centry, eonc_q_LINK));
397 remque( &(ent->eonc_q_LINK) );
398 ent->eonc_addr.s_addr = eoa->seon_ipaddr;
399 insque( &oldent->eonc_q_LINK, (&eon_LINK_hdr));
400 oldent = ent;
401 }
402
403 which = (eoa->seon_status ^ oldent->eonc_status) &
404 eoa->seon_status & UPBITS;
405
406 oldent->eonc_status |= (eoa->seon_status & UPBITS);
407
408 if( which & EON_ESLINK_UP )
409 insque( &oldent->eonc_q_ES, (&eon_ES_hdr));
410 if( which & EON_ISLINK_UP )
411 insque( &oldent->eonc_q_IS, (&eon_IS_hdr));
412 }
413
414 if( eoa->seon_status & DOWNBITS ) {
415 if(!oldent) {
416 return ENOENT; /* no such entry */
417 }
418 which = (eoa->seon_status ^ oldent->eonc_status) &
419 eoa->seon_status & DOWNBITS;
420
421 oldent->eonc_status |= (eoa->seon_status & DOWNBITS);
422
423 if( which & EON_ESLINK_DOWN )
424 remque( &(oldent->eonc_q_ES) );
425 if( which & EON_ISLINK_DOWN )
426 remque( &(oldent->eonc_q_IS) );
427 }
428
429 IFDEBUG(D_EON)
430 printf("at end status 0x%x\n", oldent->eonc_status);
431 ENDDEBUG
432 break;
433 }
434
435 case SIOCGIFDSTADDR:
436 {
437 register struct eon_centry *oldent;
438
439 oldent = find_oldent( eoa );
440 if( oldent == (struct eon_centry *)0 )
441 error = EADDRNOTAVAIL;
442 else
443 eoa->seon_status = oldent->eonc_status;
444 }
445 break;
446
447 case SIOCSIFADDR:
448 ifp->if_flags |= IFF_UP;
449 break;
450
451 case SIOCSIFFLAGS:
452 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags &
453 IFF_RUNNING){
454 ifp->if_flags &= ~IFF_RUNNING;
455 } else if (ifp->if_flags & IFF_UP && (ifp->if_flags &
456 IFF_RUNNING) == 0)
457 eoninit(ifp->if_unit);
458 break;
459 default:
460 error = EINVAL;
461 }
462 splx(s);
463 return(error);
464}
465
466/*
467 * FUNCTION: eoninit
468 *
469 * PURPOSE: initialization
470 *
471 * RETURNS: nothing
472 */
473
474eoninit(unit)
475 int unit;
476{
477 printf("eoninit ecn%d\n", unit);
478}
479
480
481/*
482 * FUNCTION: eonint
483 *
484 * PURPOSE: filler for device configuration
485 *
486 * RETURNS: nothing
487 *
488 * NOTES: *should* never get called - for debugging it's here
489 */
490
491eonint()
492{
493 /* silent - so no more stray interrupt messages from the aed! yay
494 printf("eonint() called - BOGUS INTERRUPT\n");
495 */
496}
497
498
499/*
500 * FUNCTION: eonoutput
501 *
502 * PURPOSE: prepend an eon header and hand to IP
503 * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device
504 * (m) is an mbuf *, *m is a CLNL packet
505 * (dst) is a destination address - have to interp. as
506 * multicast or broadcast or real address.
507 *
508 * RETURNS: unix error code
509 *
510 * NOTES:
511 *
512 */
513eonoutput(ifp, morig, dst)
514 register struct ifnet *ifp;
515 register struct mbuf *morig; /* packet */
516 struct sockaddr_iso *dst; /* destination addr */
517{
518 int s;
519 struct eon_hdr *eonhdr;
520 struct ip *iphdr;
521 struct mbuf *mh;
522 int error = 0;
523 register int datalen;
524 caddr_t dstipaddrloc;
525 int single=0;
526 int qoffset=0;
527 register struct eon_centry *ent;
528 struct qhdr *q;
529
530 IFDEBUG(D_EON)
531 printf("eonoutput \n" );
532 ENDDEBUG
533
534 if( dst->siso_family != AF_ISO )
535 return EINVAL;
536 if( dst->siso_addr.isoa_afi != AFI_RFC986 )
537 return EINVAL;
538
539 s = splnet();
540
541 /* Nsel tells what type of multicast address, if multicast */
542 switch( dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET]) {
543 case EON_NORMAL_ADDR:
544 IncStat(es_out_normal);
545 dstipaddrloc = (caddr_t)&(dst->siso_addr.rfc986_dsp[1]);
546 single = 1;
547 break;
548
549 case EON_BROADCAST:
550 IncStat(es_out_broad);
551 if( eon_LINK_hdr.link == (struct qhdr *)0 ) {
552 error = EADDRNOTAVAIL;
553 } else {
554 qoffset = _offsetof( struct eon_centry, eonc_q_LINK);
555 ent = qtocentry(eon_LINK_hdr.link, qoffset);
556 dstipaddrloc = (caddr_t) &(ent->eonc_addr);
557 }
558 break;
559 case EON_MULTICAST_ES:
560 IncStat(es_out_multi_es);
561 if( eon_ES_hdr.link == (struct qhdr *)0 ) {
562 error = EADDRNOTAVAIL;
563 } else {
564 qoffset = _offsetof( struct eon_centry, eonc_q_ES);
565 ent = qtocentry(eon_ES_hdr.link, qoffset);
566 dstipaddrloc = (caddr_t) &(ent->eonc_addr);
567 }
568 break;
569 case EON_MULTICAST_IS:
570 IncStat(es_out_multi_is);
571 if( eon_IS_hdr.link == (struct qhdr *)0 ) {
572 error = EADDRNOTAVAIL;
573 } else {
574 qoffset = _offsetof( struct eon_centry, eonc_q_LINK);
575 ent = qtocentry(eon_IS_hdr.link, qoffset);
576 dstipaddrloc = (caddr_t) &(ent->eonc_addr);
577 }
578 break;
579 default:
580 printf("NSEL bad value; treated as EON_NORMAL_ADDR\n");
581 dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET] = EON_NORMAL_ADDR;
582 single = 1;
583 break;
584 }
585 if( error )
586 goto done;
587
588 /* get data length -- needed later */
589 datalen = m_datalen( morig );
590 IFDEBUG(D_EON)
591 printf("eonoutput : m_datalen returns %d\n", datalen);
592 ENDDEBUG
593
594 mh = m_getclr( M_DONTWAIT, MT_HEADER);
595 if(mh == (struct mbuf *)0) {
596 goto done;
597 }
598
599 /* put an eon_hdr in the buffer, prepended by an ip header */
600 mh->m_act = (struct mbuf *)0;
601 mh->m_len = sizeof(struct eon_hdr);
602 mh->m_off = MMAXOFF - sizeof(struct eon_hdr);
603 mh->m_next = morig;
604 eonhdr = mtod(mh, struct eon_hdr *);
605 eonhdr->eonh_class =
606 dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET];
607 eonhdr->eonh_vers = EON_VERSION;
608
609 IFDEBUG(D_EON)
610 printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
611 mh, _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
612 ENDDEBUG
613 iso_gen_csum(mh,
614 _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
615
616 mh->m_len += sizeof(struct ip);
617 mh->m_off -= sizeof(struct ip);
618 iphdr = mtod(mh, struct ip *);
619
620 iphdr->ip_p = IPPROTO_EON;
621 iphdr->ip_len = (sizeof(struct eon_hdr) + sizeof(struct ip) + datalen);
622 iphdr->ip_ttl = MAXTTL;
623 iphdr->ip_src.s_addr = INADDR_ANY;
624
625 IFDEBUG(D_EON)
626 printf("eonoutput : after gen csum: ip_len %d/0x%x\n",
627 (sizeof(struct eon_hdr) + sizeof(struct ip) + datalen),
628 (sizeof(struct eon_hdr) + sizeof(struct ip) + datalen)
629 );
630 ENDDEBUG
631
632 morig = mh;
633
634 for(;;) {
635
636 if( !single ) {
637 /* make a copy to send */
638 IFDEBUG(D_EON)
639 printf("eonoutput : m_copy (0x%x, 0, 0x%x)\n",
640 morig, iphdr->ip_len);
641 ENDDEBUG
642 mh = m_copy(morig, 0, iphdr->ip_len);
643 mh = m_pullup(mh, sizeof(struct ip));
644 iphdr = mtod(mh, struct ip *);
645 }
646 IFDEBUG(D_EON)
647 printf("eonoutput : bcopy 0x%x to 0x%x length %d\n",
648 dstipaddrloc,
649 (caddr_t)&(iphdr->ip_dst.s_addr),
650 sizeof(iphdr->ip_dst.s_addr));
651 ENDDEBUG
652 bcopy(
653 dstipaddrloc,
654 (caddr_t)&(iphdr->ip_dst.s_addr), sizeof(iphdr->ip_dst.s_addr));
655 IFDEBUG(D_EON)
656 printf("eonoutput : dst ip addr : %d.%d.%d.%d",
657 (iphdr->ip_dst.s_addr>>24)&0xff,
658 (iphdr->ip_dst.s_addr>>16)&0xff,
659 (iphdr->ip_dst.s_addr>>8)&0xff,
660 (iphdr->ip_dst.s_addr)&0xff );
661 ENDDEBUG
662
663 IFDEBUG(D_EON)
664 printf("eonoutput ip_output : eon header:\n");
665 dump_buf(eonhdr, sizeof(struct eon_hdr));
666 printf("ip header:\n");
667 dump_buf(iphdr, sizeof(struct ip));
668 ENDDEBUG
669
670 IncStat(es_ipout);
671 if( error = ip_output(mh, (struct mbuf *)0, (struct route *)0, 0) )
672 break;
673
674 IFDEBUG(D_EON)
675 printf("eonoutput ip_output returns 0x%x; single %d\n",
676 error, single);
677 ENDDEBUG
678
679 if(single)
680 break;
681
682 q = centrytoq(ent, qoffset)->link;
683 if( q == (struct qhdr *)0)
684 break;
685 ent = qtocentry( q, qoffset );
686 IFDEBUG(D_EON)
687 printf("eonoutput : get next entry: 0x%x\n", ent);
688 ENDDEBUG
689 dstipaddrloc = (caddr_t) &(ent->eonc_addr);
690 IFDEBUG(D_EON)
691 printf("eonoutput : dump of eon_centry 0x%x:\n", ent );
692 dump_buf(ent, sizeof(struct eon_centry) );
693 ENDDEBUG
694 }
695done:
696 if( !single ) {
697 IFDEBUG(D_EON)
698 printf("eonoutput : freeing morig 0x%x\n", morig);
699 ENDDEBUG
700 m_freem(morig);
701 }
702 splx(s);
703 return error;
704}
705
706eoninput(m, ifp)
707 register struct mbuf *m;
708 struct ifnet *ifp; /* real ifp */
709{
710 int s;
711 register struct eon_hdr *eonhdr;
712 register struct ip *iphdr;
713 struct ifnet *eonifp;
714 register int datalen;
715
716 s = splnet();
717
718 eonifp = &eonif[0]; /* kludge - really want to give CLNP
719 * the ifp for eon, not for the real device
720 */
721
722 IFDEBUG(D_EON)
723 printf("eoninput() 0x%x m_off 0x%x m_len 0x%x dequeued\n",
724 m, m?m->m_off:0, m?m->m_len:0);
725 ENDDEBUG
726
727 if (m == 0) {
728 goto drop;
729 }
730 m = m_pullup(m, (sizeof(struct eon_hdr)+sizeof(struct ip)));
731 if (m == 0) {
732 IncStat(es_badhdr);
733 goto drop;
734 }
735
736 iphdr = mtod(m, struct ip *);
737
738 /* do a few checks for debugging */
739 if( iphdr->ip_p != IPPROTO_EON ) {
740 IncStat(es_badhdr);
741 goto drop;
742 }
743
744 /* drop ip header from the mbuf */
745 m->m_len -= sizeof(struct ip);
746 m->m_off += sizeof(struct ip);
747
748 eonhdr = mtod(m, struct eon_hdr *);
749
750 IFDEBUG(D_EON)
751 printf("eoninput: eon header:\n");
752 dump_buf(eonhdr, sizeof(struct eon_hdr));
753 ENDDEBUG
754
755 /* checks for debugging */
756 if( eonhdr->eonh_vers != EON_VERSION) {
757 IncStat(es_badhdr);
758 goto drop;
759 }
760
761 datalen = m_datalen( m );
762 if( iso_check_csum( m, sizeof(struct eon_hdr) ) != EOK ) {
763 IncStat(es_badcsum);
764 goto drop;
765 }
766
767 IFDEBUG(D_EON)
768 printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class );
769 ENDDEBUG
770 switch( eonhdr->eonh_class) {
771 case EON_BROADCAST:
772 IncStat(es_in_broad);
773 break;
774 case EON_NORMAL_ADDR:
775 IncStat(es_in_normal);
776 break;
777 case EON_MULTICAST_ES:
778 if( ( eonifp->if_flags & IFF_ES) == 0 )
779 goto drop;
780 IncStat(es_in_multi_es);
781 break;
782 case EON_MULTICAST_IS:
783 if( ( eonifp->if_flags & IFF_IS) == 0 )
784 goto drop;
785 IncStat(es_in_multi_is);
786 break;
787 }
788 eonifp->if_ipackets ++;
789
790 /* drop eonhdr from the mbuf */
791 m->m_len -= sizeof(struct eon_hdr);
792 m->m_off += sizeof(struct eon_hdr);
793
794 {
795 /* put it on the CLNP queue and set soft interrupt */
796 struct ifqueue *ifq;
797 extern struct ifqueue clnlintrq;
798 int len;
799
800 /* when acting as a subnet service, have to prepend a
801 * pointer to the ifnet before handing this to clnp (GAG)
802 */
803 len = sizeof(struct snpa_hdr);
804 if( ( m->m_off > MMINOFF + len) &&
805 ( m->m_off <= MMAXOFF )) {
806 m->m_off -= len;
807 m->m_len += len;
808 }
809 ( mtod(m, struct snpa_hdr *) )->snh_ifp = eonifp; /* KLUDGE */
810
811 /* this is cutting it close */
812 bcopy( &iphdr->ip_src, ( mtod(m, struct snpa_hdr *))->snh_shost,
813 sizeof(struct in_addr));
814 bcopy( &iphdr->ip_dst, ( mtod(m, struct snpa_hdr *))->snh_dhost,
815 sizeof(struct in_addr));
816
817 IFDEBUG(D_EON)
818 printf("eoninput to clnl IFQ\n");
819 ENDDEBUG
820 ifq = &clnlintrq;
821 splimp();
822 if (IF_QFULL(ifq)) {
823 IF_DROP(ifq);
824 m_freem(m);
825 splx(s);
826 eonifp->if_ierrors ++;
827 return;
828 }
829 IF_ENQUEUE(ifq, m);
830 IFDEBUG(D_EON)
831 printf(
832 "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_off 0x%x\n",
833 m, m->m_len, m->m_type, m->m_off);
834 dump_buf(mtod(m, caddr_t), m->m_len);
835 ENDDEBUG
836 schednetisr(NETISR_CLNP);
837 }
838done:
839 splx(s);
840 return 0;
841drop:
842 IFDEBUG(D_EON)
843 printf("eoninput: DROP \n" );
844 ENDDEBUG
845 eonifp->if_ierrors ++;
846 m_freem(m);
847 goto done;
848}
849
850int
851eonctlinput(cmd, sin)
852 int cmd;
853 struct sockaddr_in *sin;
854{
855 extern u_char inetctlerrmap[];
856
857 IFDEBUG(D_EON)
858 printf("eonctlinput: cmd 0x%x addr: ", cmd);
859 dump_isoaddr(sin);
860 printf("\n");
861 ENDDEBUG
862
863 if (cmd < 0 || cmd > PRC_NCMDS)
864 return 0;
865
866 IncStat(es_icmp[cmd]);
867 switch (cmd) {
868
869 case PRC_QUENCH2:
870 case PRC_QUENCH:
871 /* TODO: set the dec bit */
872 break;
873 case PRC_TIMXCEED_REASS:
874 case PRC_ROUTEDEAD:
875 case PRC_HOSTUNREACH:
876 case PRC_UNREACH_NET:
877 case PRC_IFDOWN:
878 case PRC_UNREACH_HOST:
879 case PRC_HOSTDEAD:
880 case PRC_TIMXCEED_INTRANS:
881 /* TODO: mark the link down */
882 break;
883
884 case PRC_UNREACH_PROTOCOL:
885 case PRC_UNREACH_PORT:
886 case PRC_UNREACH_NEEDFRAG:
887 case PRC_UNREACH_SRCFAIL:
888 case PRC_REDIRECT_NET:
889 case PRC_REDIRECT_HOST:
890 case PRC_REDIRECT_TOSNET:
891 case PRC_REDIRECT_TOSHOST:
892 case PRC_MSGSIZE:
893 case PRC_PARAMPROB:
894 printf("eonctlinput: ICMP cmd 0x%x\n", cmd );
895 break;
896 }
897 return 0;
898}
899
900#endif NEON>0