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