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