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