|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1990, 1993
27: * The Regents of the University of California. All rights reserved.
28: *
29: * Redistribution and use in source and binary forms, with or without
30: * modification, are permitted provided that the following conditions
31: * are met:
32: * 1. Redistributions of source code must retain the above copyright
33: * notice, this list of conditions and the following disclaimer.
34: * 2. Redistributions in binary form must reproduce the above copyright
35: * notice, this list of conditions and the following disclaimer in the
36: * documentation and/or other materials provided with the distribution.
37: * 3. All advertising materials mentioning features or use of this software
38: * must display the following acknowledgement:
39: * This product includes software developed by the University of
40: * California, Berkeley and its contributors.
41: * 4. Neither the name of the University nor the names of its contributors
42: * may be used to endorse or promote products derived from this software
43: * without specific prior written permission.
44: *
45: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55: * SUCH DAMAGE.
56: *
57: * @(#)if_x25subr.c 8.1 (Berkeley) 6/10/93
58: */
59:
60: #include <sys/param.h>
61: #include <sys/systm.h>
62: #include <sys/malloc.h>
63: #include <sys/mbuf.h>
64: #include <sys/protosw.h>
65: #include <sys/socket.h>
66: #include <sys/socketvar.h>
67: #include <sys/ioctl.h>
68: #include <sys/errno.h>
69: #include <sys/syslog.h>
70:
71: #include <net/if.h>
72: #include <net/if_types.h>
73: #include <net/netisr.h>
74: #include <net/route.h>
75:
76: #include <netccitt/x25.h>
77: #include <netccitt/x25err.h>
78: #include <netccitt/pk.h>
79: #include <netccitt/pk_var.h>
80:
81: #if INET
82: #include <netinet/in.h>
83: #include <netinet/in_var.h>
84: #endif
85:
86: #if NS
87: #include <netns/ns.h>
88: #include <netns/ns_if.h>
89: #endif
90:
91: #if ISO
92: int tp_incoming();
93: #include <netiso/argo_debug.h>
94: #include <netiso/iso.h>
95: #include <netiso/iso_var.h>
96: #endif
97:
98: extern struct ifnet loif;
99: struct llinfo_x25 llinfo_x25 = {&llinfo_x25, &llinfo_x25};
100: #ifndef _offsetof
101: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
102: #endif
103: struct sockaddr *x25_dgram_sockmask;
104: struct sockaddr_x25 x25_dgmask = {
105: _offsetof(struct sockaddr_x25, x25_udata[1]), /* _len */
106: 0, /* _family */
107: 0, /* _net */
108: { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, /* _addr */
109: {0}, /* opts */
110: -1, /* _udlen */
111: {-1} /* _udata */
112: };
113:
114: struct if_x25stats {
115: int ifx_wrongplen;
116: int ifx_nophdr;
117: } if_x25stats;
118: int x25_autoconnect = 0;
119:
120: #define senderr(x) {error = x; goto bad;}
121: /*
122: * Ancillary routines
123: */
124: static struct llinfo_x25 *
125: x25_lxalloc(rt)
126: register struct rtentry *rt;
127: {
128: register struct llinfo_x25 *lx;
129: register struct sockaddr *dst = rt_key(rt);
130: register struct ifaddr *ifa;
131:
132: MALLOC(lx, struct llinfo_x25 *, sizeof (*lx), M_PCB, M_NOWAIT);
133: if (lx == 0)
134: return lx;
135: Bzero(lx, sizeof(*lx));
136: lx->lx_rt = rt;
137: lx->lx_family = dst->sa_family;
1.1.1.2 ! root 138: RTHOLD(rt);
1.1 root 139: if (rt->rt_llinfo)
140: insque(lx, (struct llinfo_x25 *)rt->rt_llinfo);
141: else {
142: rt->rt_llinfo = (caddr_t)lx;
143: insque(lx, &llinfo_x25);
144: }
145: for (ifa = rt->rt_ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
146: if (ifa->ifa_addr->sa_family == AF_CCITT)
147: lx->lx_ia = (struct x25_ifaddr *)ifa;
148: }
149: return lx;
150: }
151: x25_lxfree(lx)
152: register struct llinfo_x25 *lx;
153: {
154: register struct rtentry *rt = lx->lx_rt;
155: register struct pklcd *lcp = lx->lx_lcd;
156:
157: if (lcp) {
158: lcp->lcd_upper = 0;
159: pk_disconnect(lcp);
160: }
161: if ((rt->rt_llinfo == (caddr_t)lx) && (lx->lx_next->lx_rt == rt))
162: rt->rt_llinfo = (caddr_t)lx->lx_next;
163: else
164: rt->rt_llinfo = 0;
165: RTFREE(rt);
166: remque(lx);
167: FREE(lx, M_PCB);
168: }
169: /*
170: * Process a x25 packet as datagram;
171: */
172: x25_ifinput(lcp, m)
173: struct pklcd *lcp;
174: register struct mbuf *m;
175: {
176: struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext;
177: register struct ifnet *ifp;
178: struct ifqueue *inq;
179: extern struct timeval time;
180: int s, len, isr;
181:
182: if (m == 0 || lcp->lcd_state != DATA_TRANSFER) {
183: x25_connect_callback(lcp, 0);
184: return;
185: }
186: pk_flowcontrol(lcp, 0, 1); /* Generate RR */
187: ifp = m->m_pkthdr.rcvif;
188: ifp->if_lastchange = time;
189: switch (m->m_type) {
190: default:
191: if (m)
192: m_freem(m);
193: return;
194:
195: case MT_DATA:
196: /* FALLTHROUGH */;
197: }
198: switch (lx->lx_family) {
199: #if INET
200: case AF_INET:
201: isr = NETISR_IP;
202: inq = &ipintrq;
203: break;
204:
205: #endif
206: #if NS
207: case AF_NS:
208: isr = NETISR_NS;
209: inq = &nsintrq;
210: break;
211:
212: #endif
213: #if ISO
214: case AF_ISO:
215: isr = NETISR_ISO;
216: inq = &clnlintrq;
217: break;
218: #endif
219: default:
220: m_freem(m);
221: ifp->if_noproto++;
222: return;
223: }
224: s = splimp();
225: schednetisr(isr);
226: if (IF_QFULL(inq)) {
227: IF_DROP(inq);
228: m_freem(m);
229: } else {
230: IF_ENQUEUE(inq, m);
231: ifp->if_ibytes += m->m_pkthdr.len;
232: }
233: splx(s);
234: }
235: x25_connect_callback(lcp, m)
236: register struct pklcd *lcp;
237: register struct mbuf *m;
238: {
239: register struct llinfo_x25 *lx = (struct llinfo_x25 *)lcp->lcd_upnext;
240: int do_clear = 1;
241: if (m == 0)
242: goto refused;
243: if (m->m_type != MT_CONTROL) {
244: printf("x25_connect_callback: should panic\n");
245: goto refused;
246: }
247: switch (pk_decode(mtod(m, struct x25_packet *))) {
248: case CALL_ACCEPTED:
249: lcp->lcd_upper = x25_ifinput;
250: if (lcp->lcd_sb.sb_mb)
251: lcp->lcd_send(lcp); /* XXX start queued packets */
252: return;
253: default:
254: do_clear = 0;
255: refused:
256: lcp->lcd_upper = 0;
257: lx->lx_lcd = 0;
258: if (do_clear)
259: pk_disconnect(lcp);
260: return;
261: }
262: }
263: #define SA(p) ((struct sockaddr *)(p))
264: #define RT(p) ((struct rtentry *)(p))
265:
266: x25_dgram_incoming(lcp, m0)
267: register struct pklcd *lcp;
268: struct mbuf *m0;
269: {
270: register struct rtentry *rt, *nrt;
271: register struct mbuf *m = m0->m_next; /* m0 has calling sockaddr_x25 */
272: void x25_rtrequest();
273:
274: rt = rtalloc1(SA(&lcp->lcd_faddr), 0);
275: if (rt == 0) {
276: refuse: lcp->lcd_upper = 0;
277: pk_close(lcp);
278: return;
279: }
280: rt->rt_refcnt--;
281: if ((nrt = RT(rt->rt_llinfo)) == 0 || rt_mask(rt) != x25_dgram_sockmask)
282: goto refuse;
283: if ((nrt->rt_flags & RTF_UP) == 0) {
284: rt->rt_llinfo = (caddr_t)rtalloc1(rt->rt_gateway, 0);
285: rtfree(nrt);
286: if ((nrt = RT(rt->rt_llinfo)) == 0)
287: goto refuse;
288: nrt->rt_refcnt--;
289: }
290: if (nrt->rt_ifa == 0 || nrt->rt_ifa->ifa_rtrequest != x25_rtrequest)
291: goto refuse;
292: lcp->lcd_send(lcp); /* confirm call */
293: x25_rtattach(lcp, nrt);
294: m_freem(m);
295: }
296:
297: /*
298: * X.25 output routine.
299: */
300: x25_ifoutput(ifp, m0, dst, rt)
301: struct ifnet *ifp;
302: struct mbuf *m0;
303: struct sockaddr *dst;
304: register struct rtentry *rt;
305: {
306: register struct mbuf *m = m0;
307: register struct llinfo_x25 *lx;
308: struct pklcd *lcp;
309: int s, error = 0;
310:
311: int plen;
312: for (plen = 0; m; m = m->m_next)
313: plen += m->m_len;
314: m = m0;
315:
316: if ((ifp->if_flags & IFF_UP) == 0)
317: senderr(ENETDOWN);
318: while (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) {
319: if (rt) {
320: if (rt->rt_llinfo) {
321: rt = (struct rtentry *)rt->rt_llinfo;
322: continue;
323: }
324: dst = rt->rt_gateway;
325: }
326: if ((rt = rtalloc1(dst, 1)) == 0)
327: senderr(EHOSTUNREACH);
328: rt->rt_refcnt--;
329: }
330: /*
331: * Sanity checks.
332: */
333: if ((rt->rt_ifp != ifp) ||
334: (rt->rt_flags & (RTF_CLONING | RTF_GATEWAY)) ||
335: ((lx = (struct llinfo_x25 *)rt->rt_llinfo) == 0)) {
336: senderr(ENETUNREACH);
337: }
338: if ((m->m_flags & M_PKTHDR) == 0) {
339: if_x25stats.ifx_nophdr++;
340: m = m_gethdr(M_NOWAIT, MT_HEADER);
341: if (m == 0)
342: senderr(ENOBUFS);
343: m->m_pkthdr.len = plen;
344: m->m_next = m0;
345: }
346: if (plen != m->m_pkthdr.len) {
347: if_x25stats.ifx_wrongplen++;
348: m->m_pkthdr.len = plen;
349: }
350: next_circuit:
351: lcp = lx->lx_lcd;
352: if (lcp == 0) {
353: lx->lx_lcd = lcp = pk_attach((struct socket *)0);
354: if (lcp == 0)
355: senderr(ENOBUFS);
356: lcp->lcd_upper = x25_connect_callback;
357: lcp->lcd_upnext = (caddr_t)lx;
358: lcp->lcd_packetsize = lx->lx_ia->ia_xc.xc_psize;
359: lcp->lcd_flags = X25_MBS_HOLD;
360: }
361: switch (lcp->lcd_state) {
362: case READY:
363: if (dst->sa_family == AF_INET &&
364: ifp->if_type == IFT_X25DDN &&
365: rt->rt_gateway->sa_family != AF_CCITT)
366: x25_ddnip_to_ccitt(dst, rt);
367: if (rt->rt_gateway->sa_family != AF_CCITT) {
368: if ((rt->rt_flags & RTF_XRESOLVE) == 0)
369: senderr(EHOSTUNREACH);
370: } else if (x25_autoconnect)
371: error = pk_connect(lcp,
372: (struct sockaddr_x25 *)rt->rt_gateway);
373: if (error)
374: senderr(error);
375: /* FALLTHROUGH */
376: case SENT_CALL:
377: case DATA_TRANSFER:
378: if (sbspace(&lcp->lcd_sb) < 0) {
379: lx = lx->lx_next;
380: if (lx->lx_rt != rt)
381: senderr(ENOSPC);
382: goto next_circuit;
383: }
384: if (lx->lx_ia)
385: lcp->lcd_dg_timer =
386: lx->lx_ia->ia_xc.xc_dg_idletimo;
387: pk_send(lcp, m);
388: break;
389: default:
390: /*
391: * We count on the timer routine to close idle
392: * connections, if there are not enough circuits to go
393: * around.
394: *
395: * So throw away data for now.
396: * After we get it all working, we'll rewrite to handle
397: * actively closing connections (other than by timers),
398: * when circuits get tight.
399: *
400: * In the DDN case, the imp itself closes connections
401: * under heavy load.
402: */
403: error = ENOBUFS;
404: bad:
405: if (m)
406: m_freem(m);
407: }
408: return (error);
409: }
410:
411: /*
412: * Simpleminded timer routine.
413: */
414: x25_iftimeout(ifp)
415: struct ifnet *ifp;
416: {
417: register struct pkcb *pkcb = 0;
418: register struct pklcd **lcpp, *lcp;
419: int s = splimp();
420:
421: FOR_ALL_PKCBS(pkcb)
422: if (pkcb->pk_ia->ia_ifp == ifp)
423: for (lcpp = pkcb->pk_chan + pkcb->pk_maxlcn;
424: --lcpp > pkcb->pk_chan;)
425: if ((lcp = *lcpp) &&
426: lcp->lcd_state == DATA_TRANSFER &&
427: (lcp->lcd_flags & X25_DG_CIRCUIT) &&
428: (lcp->lcd_dg_timer && --lcp->lcd_dg_timer == 0)) {
429: lcp->lcd_upper(lcp, 0);
430: }
431: splx(s);
432: }
433: /*
434: * This routine gets called when validating additions of new routes
435: * or deletions of old ones.
436: */
437: x25_rtrequest(cmd, rt, dst)
438: register struct rtentry *rt;
439: struct sockaddr *dst;
440: {
441: register struct llinfo_x25 *lx = (struct llinfo_x25 *)rt->rt_llinfo;
442: register struct sockaddr_x25 *sa =(struct sockaddr_x25 *)rt->rt_gateway;
443: register struct pklcd *lcp;
444:
445: /* would put this pk_init, except routing table doesn't
446: exist yet. */
447: if (x25_dgram_sockmask == 0) {
448: struct radix_node *rn_addmask();
449: x25_dgram_sockmask =
450: SA(rn_addmask((caddr_t)&x25_dgmask, 0, 4)->rn_key);
451: }
452: if (rt->rt_flags & RTF_GATEWAY) {
453: if (rt->rt_llinfo)
454: RTFREE((struct rtentry *)rt->rt_llinfo);
455: rt->rt_llinfo = (cmd == RTM_ADD) ?
456: (caddr_t)rtalloc1(rt->rt_gateway, 1) : 0;
457: return;
458: }
459: if ((rt->rt_flags & RTF_HOST) == 0)
460: return;
461: if (cmd == RTM_DELETE) {
462: while (rt->rt_llinfo)
463: x25_lxfree((struct llinfo *)rt->rt_llinfo);
464: x25_rtinvert(RTM_DELETE, rt->rt_gateway, rt);
465: return;
466: }
467: if (lx == 0 && (lx = x25_lxalloc(rt)) == 0)
468: return;
469: if ((lcp = lx->lx_lcd) && lcp->lcd_state != READY) {
470: /*
471: * This can only happen on a RTM_CHANGE operation
472: * though cmd will be RTM_ADD.
473: */
474: if (lcp->lcd_ceaddr &&
475: Bcmp(rt->rt_gateway, lcp->lcd_ceaddr,
476: lcp->lcd_ceaddr->x25_len) != 0) {
477: x25_rtinvert(RTM_DELETE, lcp->lcd_ceaddr, rt);
478: lcp->lcd_upper = 0;
479: pk_disconnect(lcp);
480: }
481: lcp = 0;
482: }
483: x25_rtinvert(RTM_ADD, rt->rt_gateway, rt);
484: }
485:
486: int x25_dont_rtinvert = 0;
487:
488: x25_rtinvert(cmd, sa, rt)
489: register struct sockaddr *sa;
490: register struct rtentry *rt;
491: {
492: struct rtentry *rt2 = 0;
493: /*
494: * rt_gateway contains PID indicating which proto
495: * family on the other end, so will be different
496: * from general host route via X.25.
497: */
498: if (rt->rt_ifp->if_type == IFT_X25DDN || x25_dont_rtinvert)
499: return;
500: if (sa->sa_family != AF_CCITT)
501: return;
502: if (cmd != RTM_DELETE) {
503: rtrequest(RTM_ADD, sa, rt_key(rt), x25_dgram_sockmask,
504: RTF_PROTO2, &rt2);
505: if (rt2) {
506: rt2->rt_llinfo = (caddr_t) rt;
1.1.1.2 ! root 507: RTHOLD(rt);
1.1 root 508: }
509: return;
510: }
511: rt2 = rt;
512: if ((rt = rtalloc1(sa, 0)) == 0 ||
513: (rt->rt_flags & RTF_PROTO2) == 0 ||
514: rt->rt_llinfo != (caddr_t)rt2) {
515: printf("x25_rtchange: inverse route screwup\n");
516: return;
517: } else
518: rt2->rt_refcnt--;
519: rtrequest(RTM_DELETE, sa, rt_key(rt2), x25_dgram_sockmask,
520: 0, (struct rtentry **) 0);
521: }
522:
523: static struct sockaddr_x25 blank_x25 = {sizeof blank_x25, AF_CCITT};
524: /*
525: * IP to X25 address routine copyright ACC, used by permission.
526: */
527: union imp_addr {
528: struct in_addr ip;
529: struct imp {
530: u_char s_net;
531: u_char s_host;
532: u_char s_lh;
533: u_char s_impno;
534: } imp;
535: };
536:
537: /*
538: * The following is totally bogus and here only to preserve
539: * the IP to X.25 translation.
540: */
541: x25_ddnip_to_ccitt(src, rt)
542: struct sockaddr_in *src;
543: register struct rtentry *rt;
544: {
545: register struct sockaddr_x25 *dst = (struct sockaddr_x25 *)rt->rt_gateway;
546: union imp_addr imp_addr;
547: int imp_no, imp_port, temp;
548: char *x25addr = dst->x25_addr;
549:
550:
551: imp_addr.ip = src->sin_addr;
552: *dst = blank_x25;
553: if ((imp_addr.imp.s_net & 0x80) == 0x00) { /* class A */
554: imp_no = imp_addr.imp.s_impno;
555: imp_port = imp_addr.imp.s_host;
556: } else if ((imp_addr.imp.s_net & 0xc0) == 0x80) { /* class B */
557: imp_no = imp_addr.imp.s_impno;
558: imp_port = imp_addr.imp.s_lh;
559: } else { /* class C */
560: imp_no = imp_addr.imp.s_impno / 32;
561: imp_port = imp_addr.imp.s_impno % 32;
562: }
563:
564: x25addr[0] = 12; /* length */
565: /* DNIC is cleared by struct copy above */
566:
567: if (imp_port < 64) { /* Physical: 0000 0 IIIHH00 [SS] *//* s_impno
568: * -> III, s_host -> HH */
569: x25addr[5] = 0; /* set flag bit */
570: x25addr[6] = imp_no / 100;
571: x25addr[7] = (imp_no % 100) / 10;
572: x25addr[8] = imp_no % 10;
573: x25addr[9] = imp_port / 10;
574: x25addr[10] = imp_port % 10;
575: } else { /* Logical: 0000 1 RRRRR00 [SS] *//* s
576: * _host * 256 + s_impno -> RRRRR */
577: temp = (imp_port << 8) + imp_no;
578: x25addr[5] = 1;
579: x25addr[6] = temp / 10000;
580: x25addr[7] = (temp % 10000) / 1000;
581: x25addr[8] = (temp % 1000) / 100;
582: x25addr[9] = (temp % 100) / 10;
583: x25addr[10] = temp % 10;
584: }
585: }
586:
587: /*
588: * This routine is a sketch and is not to be believed!!!!!
589: *
590: * This is a utility routine to be called by x25 devices when a
591: * call request is honored with the intent of starting datagram forwarding.
592: */
593: x25_dg_rtinit(dst, ia, af)
594: struct sockaddr_x25 *dst;
595: register struct x25_ifaddr *ia;
596: {
597: struct sockaddr *sa = 0;
598: struct rtentry *rt;
599: struct in_addr my_addr;
600: static struct sockaddr_in sin = {sizeof(sin), AF_INET};
601:
602: if (ia->ia_ifp->if_type == IFT_X25DDN && af == AF_INET) {
603: /*
604: * Inverse X25 to IP mapping copyright and courtesy ACC.
605: */
606: int imp_no, imp_port, temp;
607: union imp_addr imp_addr;
608: {
609: /*
610: * First determine our IP addr for network
611: */
612: register struct in_ifaddr *ina;
613: extern struct in_ifaddr *in_ifaddr;
614:
615: for (ina = in_ifaddr; ina; ina = ina->ia_next)
616: if (ina->ia_ifp == ia->ia_ifp) {
617: my_addr = ina->ia_addr.sin_addr;
618: break;
619: }
620: }
621: {
622:
623: register char *x25addr = dst->x25_addr;
624:
625: switch (x25addr[5] & 0x0f) {
626: case 0: /* Physical: 0000 0 IIIHH00 [SS] */
627: imp_no =
628: ((int) (x25addr[6] & 0x0f) * 100) +
629: ((int) (x25addr[7] & 0x0f) * 10) +
630: ((int) (x25addr[8] & 0x0f));
631:
632:
633: imp_port =
634: ((int) (x25addr[9] & 0x0f) * 10) +
635: ((int) (x25addr[10] & 0x0f));
636: break;
637: case 1: /* Logical: 0000 1 RRRRR00 [SS] */
638: temp = ((int) (x25addr[6] & 0x0f) * 10000)
639: + ((int) (x25addr[7] & 0x0f) * 1000)
640: + ((int) (x25addr[8] & 0x0f) * 100)
641: + ((int) (x25addr[9] & 0x0f) * 10)
642: + ((int) (x25addr[10] & 0x0f));
643:
644: imp_port = temp >> 8;
645: imp_no = temp & 0xff;
646: break;
647: default:
648: return (0L);
649: }
650: imp_addr.ip = my_addr;
651: if ((imp_addr.imp.s_net & 0x80) == 0x00) {
652: /* class A */
653: imp_addr.imp.s_host = imp_port;
654: imp_addr.imp.s_impno = imp_no;
655: imp_addr.imp.s_lh = 0;
656: } else if ((imp_addr.imp.s_net & 0xc0) == 0x80) {
657: /* class B */
658: imp_addr.imp.s_lh = imp_port;
659: imp_addr.imp.s_impno = imp_no;
660: } else {
661: /* class C */
662: imp_addr.imp.s_impno = (imp_no << 5) + imp_port;
663: }
664: }
665: sin.sin_addr = imp_addr.ip;
666: sa = (struct sockaddr *)&sin;
667: } else {
668: /*
669: * This uses the X25 routing table to do inverse
670: * lookup of x25 address to sockaddr.
671: */
672: if (rt = rtalloc1(SA(dst), 0)) {
673: sa = rt->rt_gateway;
674: rt->rt_refcnt--;
675: }
676: }
677: /*
678: * Call to rtalloc1 will create rtentry for reverse path
679: * to callee by virtue of cloning magic and will allocate
680: * space for local control block.
681: */
682: if (sa && (rt = rtalloc1(sa, 1)))
683: rt->rt_refcnt--;
684: }
685: int x25_startproto = 1;
686:
687: pk_init()
688: {
689: /*
690: * warning, sizeof (struct sockaddr_x25) > 32,
691: * but contains no data of interest beyond 32
692: */
693: if (x25_startproto) {
694: pk_protolisten(0xcc, 1, x25_dgram_incoming);
695: pk_protolisten(0x81, 1, x25_dgram_incoming);
696: }
697: }
698:
699: struct x25_dgproto {
700: u_char spi;
701: u_char spilen;
702: int (*f)();
703: } x25_dgprototab[] = {
704: #if (ISO) && (TPCONS)
705: { 0x0, 0, tp_incoming},
706: #endif
707: { 0xcc, 1, x25_dgram_incoming},
708: { 0xcd, 1, x25_dgram_incoming},
709: { 0x81, 1, x25_dgram_incoming},
710: };
711:
712: pk_user_protolisten(info)
713: register u_char *info;
714: {
715: register struct x25_dgproto *dp = x25_dgprototab
716: + ((sizeof x25_dgprototab) / (sizeof *dp));
717: register struct pklcd *lcp;
718:
719: while (dp > x25_dgprototab)
720: if ((--dp)->spi == info[0])
721: goto gotspi;
722: return ESRCH;
723:
724: gotspi: if (info[1])
725: return pk_protolisten(dp->spi, dp->spilen, dp->f);
726: for (lcp = pk_listenhead; lcp; lcp = lcp->lcd_listen)
727: if (lcp->lcd_laddr.x25_udlen == dp->spilen &&
728: Bcmp(&dp->spi, lcp->lcd_laddr.x25_udata, dp->spilen) == 0) {
729: pk_disconnect(lcp);
730: return 0;
731: }
732: return ESRCH;
733: }
734:
735: /*
736: * This routine transfers an X.25 circuit to or from a routing entry.
737: * If the supplied circuit is * in DATA_TRANSFER state, it is added to the
738: * routing entry. If freshly allocated, it glues back the vc from
739: * the rtentry to the socket.
740: */
741: pk_rtattach(so, m0)
742: register struct socket *so;
743: struct mbuf *m0;
744: {
745: register struct pklcd *lcp = (struct pklcd *)so->so_pcb;
746: register struct mbuf *m = m0;
747: struct sockaddr *dst = mtod(m, struct sockaddr *);
748: register struct rtentry *rt = rtalloc1(dst, 0);
749: register struct llinfo_x25 *lx;
750: caddr_t cp;
751: #define ROUNDUP(a) \
752: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
753: #define transfer_sockbuf(s, f, l) \
754: while (m = (s)->sb_mb)\
755: {(s)->sb_mb = m->m_act; m->m_act = 0; sbfree((s), m); f(l, m);}
756:
757: if (rt)
758: rt->rt_refcnt--;
759: cp = (dst->sa_len < m->m_len) ? ROUNDUP(dst->sa_len) + (caddr_t)dst : 0;
760: while (rt &&
761: ((cp == 0 && rt_mask(rt) != 0) ||
762: (cp != 0 && (rt_mask(rt) == 0 ||
763: Bcmp(cp, rt_mask(rt), rt_mask(rt)->sa_len)) != 0)))
764: rt = (struct rtentry *)rt->rt_nodes->rn_dupedkey;
765: if (rt == 0 || (rt->rt_flags & RTF_GATEWAY) ||
766: (lx = (struct llinfo_x25 *)rt->rt_llinfo) == 0)
767: return ESRCH;
768: if (lcp == 0)
769: return ENOTCONN;
770: switch (lcp->lcd_state) {
771: default:
772: return ENOTCONN;
773:
774: case READY:
775: /* Detach VC from rtentry */
776: if (lx->lx_lcd == 0)
777: return ENOTCONN;
778: lcp->lcd_so = 0;
779: pk_close(lcp);
780: lcp = lx->lx_lcd;
781: if (lx->lx_next->lx_rt == rt)
782: x25_lxfree(lx);
783: lcp->lcd_so = so;
784: lcp->lcd_upper = 0;
785: lcp->lcd_upnext = 0;
786: transfer_sockbuf(&lcp->lcd_sb, sbappendrecord, &so->so_snd);
787: soisconnected(so);
788: return 0;
789:
790: case DATA_TRANSFER:
791: /* Add VC to rtentry */
792: lcp->lcd_so = 0;
793: lcp->lcd_sb = so->so_snd; /* structure copy */
794: bzero((caddr_t)&so->so_snd, sizeof(so->so_snd)); /* XXXXXX */
795: so->so_pcb = 0;
796: x25_rtattach(lcp, rt);
797: transfer_sockbuf(&so->so_rcv, x25_ifinput, lcp);
798: soisdisconnected(so);
799: }
800: return 0;
801: }
802: x25_rtattach(lcp0, rt)
803: register struct pklcd *lcp0;
804: struct rtentry *rt;
805: {
806: register struct llinfo_x25 *lx = (struct llinfo_x25 *)rt->rt_llinfo;
807: register struct pklcd *lcp;
808: register struct mbuf *m;
809: if (lcp = lx->lx_lcd) { /* adding an additional VC */
810: if (lcp->lcd_state == READY) {
811: transfer_sockbuf(&lcp->lcd_sb, pk_output, lcp0);
812: lcp->lcd_upper = 0;
813: pk_close(lcp);
814: } else {
815: lx = x25_lxalloc(rt);
816: if (lx == 0)
817: return ENOBUFS;
818: }
819: }
820: lx->lx_lcd = lcp = lcp0;
821: lcp->lcd_upper = x25_ifinput;
822: lcp->lcd_upnext = (caddr_t)lx;
823: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.