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