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