|
|
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) University of British Columbia, 1984
27: * Copyright (C) Computer Science Department IV,
28: * University of Erlangen-Nuremberg, Germany, 1992
29: * Copyright (c) 1991, 1992, 1993
30: * The Regents of the University of California. All rights reserved.
31: *
32: * This code is derived from software contributed to Berkeley by the
33: * Laboratory for Computation Vision and the Computer Science Department
34: * of the the University of British Columbia and the Computer Science
35: * Department (IV) of the University of Erlangen-Nuremberg, Germany.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
45: * 3. All advertising materials mentioning features or use of this software
46: * must display the following acknowledgement:
47: * This product includes software developed by the University of
48: * California, Berkeley and its contributors.
49: * 4. Neither the name of the University nor the names of its contributors
50: * may be used to endorse or promote products derived from this software
51: * without specific prior written permission.
52: *
53: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63: * SUCH DAMAGE.
64: *
65: * @(#)pk_subr.c 8.1 (Berkeley) 6/10/93
66: */
67:
68: #include <sys/param.h>
69: #include <sys/systm.h>
70: #include <sys/mbuf.h>
71: #include <sys/socket.h>
72: #include <sys/protosw.h>
73: #include <sys/socketvar.h>
74: #include <sys/errno.h>
75: #include <sys/time.h>
76: #include <sys/kernel.h>
77: #include <sys/malloc.h>
78:
79: #include <net/if.h>
80: #include <net/route.h>
81:
82: #include <netccitt/dll.h>
83: #include <netccitt/x25.h>
84: #include <netccitt/x25err.h>
85: #include <netccitt/pk.h>
86: #include <netccitt/pk_var.h>
87:
88: int pk_sendspace = 1024 * 2 + 8;
89: int pk_recvspace = 1024 * 2 + 8;
90:
91: struct pklcd_q pklcd_q = {&pklcd_q, &pklcd_q};
92:
93: struct x25bitslice x25_bitslice[] = {
94: /* mask, shift value */
95: { 0xf0, 0x4 },
96: { 0xf, 0x0 },
97: { 0x80, 0x7 },
98: { 0x40, 0x6 },
99: { 0x30, 0x4 },
100: { 0xe0, 0x5 },
101: { 0x10, 0x4 },
102: { 0xe, 0x1 },
103: { 0x1, 0x0 }
104: };
105:
106:
107: /*
108: * Attach X.25 protocol to socket, allocate logical channel descripter
109: * and buffer space, and enter LISTEN state if we are to accept
110: * IN-COMMING CALL packets.
111: *
112: */
113:
114: struct pklcd *
115: pk_attach (so)
116: struct socket *so;
117: {
118: register struct pklcd *lcp;
119: register int error = ENOBUFS;
120: int pk_output ();
121:
122: MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT);
123: if (lcp) {
124: bzero ((caddr_t)lcp, sizeof (*lcp));
125: insque (&lcp -> lcd_q, &pklcd_q);
126: lcp -> lcd_state = READY;
127: lcp -> lcd_send = pk_output;
128: if (so) {
129: error = soreserve (so, pk_sendspace, pk_recvspace);
130: lcp -> lcd_so = so;
131: if (so -> so_options & SO_ACCEPTCONN)
132: lcp -> lcd_state = LISTEN;
133: } else
134: sbreserve (&lcp -> lcd_sb, pk_sendspace);
135: }
136: if (so) {
137: so -> so_pcb = (caddr_t) lcp;
138: so -> so_error = error;
139: }
140: return (lcp);
141: }
142:
143: /*
144: * Disconnect X.25 protocol from socket.
145: */
146:
147: pk_disconnect (lcp)
148: register struct pklcd *lcp;
149: {
150: register struct socket *so = lcp -> lcd_so;
151: register struct pklcd *l, *p;
152:
153: switch (lcp -> lcd_state) {
154: case LISTEN:
155: for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen);
156: if (p == 0) {
157: if (l != 0)
158: pk_listenhead = l -> lcd_listen;
159: }
160: else
161: if (l != 0)
162: p -> lcd_listen = l -> lcd_listen;
163: pk_close (lcp);
164: break;
165:
166: case READY:
167: pk_acct (lcp);
168: pk_close (lcp);
169: break;
170:
171: case SENT_CLEAR:
172: case RECEIVED_CLEAR:
173: break;
174:
175: default:
176: pk_acct (lcp);
177: if (so) {
178: soisdisconnecting (so);
179: sbflush (&so -> so_rcv);
180: }
181: pk_clear (lcp, 241, 0); /* Normal Disconnect */
182:
183: }
184: }
185:
186: /*
187: * Close an X.25 Logical Channel. Discard all space held by the
188: * connection and internal descriptors. Wake up any sleepers.
189: */
190:
191: pk_close (lcp)
192: struct pklcd *lcp;
193: {
194: register struct socket *so = lcp -> lcd_so;
195:
196: /*
197: * If the X.25 connection is torn down due to link
198: * level failure (e.g. LLC2 FRMR) and at the same the user
199: * level is still filling up the socket send buffer that
200: * send buffer is locked. An attempt to sbflush () that send
201: * buffer will lead us into - no, not temptation but - panic!
202: * So - we'll just check wether the send buffer is locked
203: * and if that's the case we'll mark the lcp as zombie and
204: * have the pk_timer () do the cleaning ...
205: */
206:
207: if (so && so -> so_snd.sb_flags & SB_LOCK)
208: lcp -> lcd_state = LCN_ZOMBIE;
209: else
210: pk_freelcd (lcp);
211:
212: if (so == NULL)
213: return;
214:
215: so -> so_pcb = 0;
216: soisdisconnected (so);
217: /* sofree (so); /* gak!!! you can't do that here */
218: }
219:
220: /*
221: * Create a template to be used to send X.25 packets on a logical
222: * channel. It allocates an mbuf and fills in a skeletal packet
223: * depending on its type. This packet is passed to pk_output where
224: * the remainer of the packet is filled in.
225: */
226:
227: struct mbuf *
228: pk_template (lcn, type)
229: int lcn, type;
230: {
231: register struct mbuf *m;
232: register struct x25_packet *xp;
233:
234: MGETHDR (m, M_DONTWAIT, MT_HEADER);
235: if (m == 0)
236: panic ("pk_template");
237: m -> m_act = 0;
238:
239: /*
240: * Efficiency hack: leave a four byte gap at the beginning
241: * of the packet level header with the hope that this will
242: * be enough room for the link level to insert its header.
243: */
244: m -> m_data += max_linkhdr;
245: m -> m_pkthdr.len = m -> m_len = PKHEADERLN;
246:
247: xp = mtod (m, struct x25_packet *);
248: *(long *)xp = 0; /* ugly, but fast */
249: /* xp -> q_bit = 0;*/
250: X25SBITS(xp -> bits, fmt_identifier, 1);
251: /* xp -> lc_group_number = 0;*/
252:
253: SET_LCN(xp, lcn);
254: xp -> packet_type = type;
255:
256: return (m);
257: }
258:
259: /*
260: * This routine restarts all the virtual circuits. Actually,
261: * the virtual circuits are not "restarted" as such. Instead,
262: * any active switched circuit is simply returned to READY
263: * state.
264: */
265:
266: pk_restart (pkp, restart_cause)
267: register struct pkcb *pkp;
268: int restart_cause;
269: {
270: register struct mbuf *m;
271: register struct pklcd *lcp;
272: register int i;
273:
274: /* Restart all logical channels. */
275: if (pkp -> pk_chan == 0)
276: return;
277:
278: /*
279: * Don't do this if we're doing a restart issued from
280: * inside pk_connect () --- which is only done if and
281: * only if the X.25 link is down, i.e. a RESTART needs
282: * to be done to get it up.
283: */
284: if (!(pkp -> pk_dxerole & DTE_CONNECTPENDING)) {
285: for (i = 1; i <= pkp -> pk_maxlcn; ++i)
286: if ((lcp = pkp -> pk_chan[i]) != NULL) {
287: if (lcp -> lcd_so) {
288: lcp -> lcd_so -> so_error = ENETRESET;
289: pk_close (lcp);
290: } else {
291: pk_flush (lcp);
292: lcp -> lcd_state = READY;
293: if (lcp -> lcd_upper)
294: lcp -> lcd_upper (lcp, 0);
295: }
296: }
297: }
298:
299: if (restart_cause < 0)
300: return;
301:
302: pkp -> pk_state = DTE_SENT_RESTART;
303: pkp -> pk_dxerole &= ~(DTE_PLAYDCE | DTE_PLAYDTE);
304: lcp = pkp -> pk_chan[0];
305: m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART);
306: m -> m_pkthdr.len = m -> m_len += 2;
307: mtod (m, struct x25_packet *) -> packet_data = 0; /* DTE only */
308: mtod (m, octet *)[4] = restart_cause;
309: pk_output (lcp);
310: }
311:
312:
313: /*
314: * This procedure frees up the Logical Channel Descripter.
315: */
316:
317: pk_freelcd (lcp)
318: register struct pklcd *lcp;
319: {
320: if (lcp == NULL)
321: return;
322:
323: if (lcp -> lcd_lcn > 0)
324: lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL;
325:
326: pk_flush (lcp);
327: remque (&lcp -> lcd_q);
328: free ((caddr_t)lcp, M_PCB);
329: }
330:
331: static struct x25_ifaddr *
332: pk_ifwithaddr (sx)
333: struct sockaddr_x25 *sx;
334: {
335: struct ifnet *ifp;
336: struct ifaddr *ifa;
337: register struct x25_ifaddr *ia;
338: char *addr = sx -> x25_addr;
339:
340: for (ifp = ifnet; ifp; ifp = ifp -> if_next)
341: for (ifa = ifp -> if_addrlist; ifa; ifa = ifa -> ifa_next)
342: if (ifa -> ifa_addr -> sa_family == AF_CCITT) {
343: ia = (struct x25_ifaddr *)ifa;
344: if (bcmp (addr, ia -> ia_xc.xc_addr.x25_addr,
345: 16) == 0)
346: return (ia);
347:
348: }
349: return ((struct x25_ifaddr *)0);
350: }
351:
352:
353: /*
354: * Bind a address and protocol value to a socket. The important
355: * part is the protocol value - the first four characters of the
356: * Call User Data field.
357: */
358:
359: #define XTRACTPKP(rt) ((rt) -> rt_flags & RTF_GATEWAY ? \
360: ((rt) -> rt_llinfo ? \
361: (struct pkcb *) ((struct rtentry *)((rt) -> rt_llinfo)) -> rt_llinfo : \
362: (struct pkcb *) NULL) : \
363: (struct pkcb *)((rt) -> rt_llinfo))
364:
365: pk_bind (lcp, nam)
366: struct pklcd *lcp;
367: struct mbuf *nam;
368: {
369: register struct pklcd *pp;
370: register struct sockaddr_x25 *sa;
371:
372: if (nam == NULL)
373: return (EADDRNOTAVAIL);
374: if (lcp -> lcd_ceaddr) /* XXX */
375: return (EADDRINUSE);
376: if (pk_checksockaddr (nam))
377: return (EINVAL);
378: sa = mtod (nam, struct sockaddr_x25 *);
379:
380: /*
381: * If the user wishes to accept calls only from a particular
382: * net (net != 0), make sure the net is known
383: */
384:
385: if (sa -> x25_addr[0]) {
386: if (!pk_ifwithaddr (sa))
387: return (ENETUNREACH);
388: } else if (sa -> x25_net) {
389: if (!ifa_ifwithnet ((struct sockaddr *)sa))
390: return (ENETUNREACH);
391: }
392:
393: /*
394: * For ISO's sake permit default listeners, but only one such . . .
395: */
396: for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) {
397: register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr;
398: if ((sa2 -> x25_udlen == sa -> x25_udlen) &&
399: (sa2 -> x25_udlen == 0 ||
400: (bcmp (sa2 -> x25_udata, sa -> x25_udata,
401: min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0)))
402: return (EADDRINUSE);
403: }
404: lcp -> lcd_laddr = *sa;
405: lcp -> lcd_ceaddr = &lcp -> lcd_laddr;
406: return (0);
407: }
408:
409: /*
410: * Include a bound control block in the list of listeners.
411: */
412: pk_listen (lcp)
413: register struct pklcd *lcp;
414: {
415: register struct pklcd **pp;
416:
417: if (lcp -> lcd_ceaddr == 0)
418: return (EDESTADDRREQ);
419:
420: lcp -> lcd_state = LISTEN;
421: /*
422: * Add default listener at end, any others at start.
423: */
424: if (lcp -> lcd_ceaddr -> x25_udlen == 0) {
425: for (pp = &pk_listenhead; *pp; )
426: pp = &((*pp) -> lcd_listen);
427: *pp = lcp;
428: } else {
429: lcp -> lcd_listen = pk_listenhead;
430: pk_listenhead = lcp;
431: }
432: return (0);
433: }
434: /*
435: * Include a listening control block for the benefit of other protocols.
436: */
437: pk_protolisten (spi, spilen, callee)
438: int (*callee) ();
439: {
440: register struct pklcd *lcp = pk_attach ((struct socket *)0);
441: register struct mbuf *nam;
442: register struct sockaddr_x25 *sa;
443: int error = ENOBUFS;
444:
445: if (lcp) {
446: if (nam = m_getclr (MT_SONAME, M_DONTWAIT)) {
447: sa = mtod (nam, struct sockaddr_x25 *);
448: sa -> x25_family = AF_CCITT;
449: sa -> x25_len = nam -> m_len = sizeof (*sa);
450: sa -> x25_udlen = spilen;
451: sa -> x25_udata[0] = spi;
452: lcp -> lcd_upper = callee;
453: lcp -> lcd_flags = X25_MBS_HOLD;
454: if ((error = pk_bind (lcp, nam)) == 0)
455: error = pk_listen (lcp);
456: (void) m_free (nam);
457: }
458: if (error)
459: pk_freelcd (lcp);
460: }
461: return error; /* Hopefully Zero !*/
462: }
463:
464: /*
465: * Associate a logical channel descriptor with a network.
466: * Fill in the default network specific parameters and then
467: * set any parameters explicitly specified by the user or
468: * by the remote DTE.
469: */
470:
471: pk_assoc (pkp, lcp, sa)
472: register struct pkcb *pkp;
473: register struct pklcd *lcp;
474: register struct sockaddr_x25 *sa;
475: {
476:
477: lcp -> lcd_pkp = pkp;
478: lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize;
479: lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize;
480: lcp -> lcd_rsn = MODULUS - 1;
481: pkp -> pk_chan[lcp -> lcd_lcn] = lcp;
482:
483: if (sa -> x25_opts.op_psize)
484: lcp -> lcd_packetsize = sa -> x25_opts.op_psize;
485: else
486: sa -> x25_opts.op_psize = lcp -> lcd_packetsize;
487: if (sa -> x25_opts.op_wsize)
488: lcp -> lcd_windowsize = sa -> x25_opts.op_wsize;
489: else
490: sa -> x25_opts.op_wsize = lcp -> lcd_windowsize;
491: sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net;
492: lcp -> lcd_flags |= sa -> x25_opts.op_flags;
493: lcp -> lcd_stime = time.tv_sec;
494: }
495:
496: pk_connect (lcp, sa)
497: register struct pklcd *lcp;
498: register struct sockaddr_x25 *sa;
499: {
500: register struct pkcb *pkp;
501: register struct rtentry *rt;
502: register struct rtentry *nrt;
503:
504: struct rtentry *npaidb_enter ();
505: struct pkcb *pk_newlink ();
506:
507: if (sa -> x25_addr[0] == '\0')
508: return (EDESTADDRREQ);
509:
510: /*
511: * Is the destination address known?
512: */
513: if (!(rt = rtalloc1 ((struct sockaddr *)sa, 1)))
514: return (ENETUNREACH);
515:
516: if (!(pkp = XTRACTPKP(rt)))
517: pkp = pk_newlink ((struct x25_ifaddr *) (rt -> rt_ifa),
518: (caddr_t) 0);
519:
520: /*
521: * Have we entered the LLC address?
522: */
523: if (nrt = npaidb_enter (rt -> rt_gateway, rt_key (rt), rt, 0))
524: pkp -> pk_llrt = nrt;
525:
526: /*
527: * Have we allocated an LLC2 link yet?
528: */
529: if (pkp -> pk_llnext == (caddr_t)0 && pkp -> pk_llctlinput) {
530: struct dll_ctlinfo ctlinfo;
531:
532: ctlinfo.dlcti_rt = rt;
533: ctlinfo.dlcti_pcb = (caddr_t) pkp;
534: ctlinfo.dlcti_conf =
535: (struct dllconfig *) (&((struct x25_ifaddr *)(rt -> rt_ifa)) -> ia_xc);
536: pkp -> pk_llnext =
537: (pkp -> pk_llctlinput) (PRC_CONNECT_REQUEST, 0, &ctlinfo);
538: }
539:
540: if (pkp -> pk_state != DTE_READY && pkp -> pk_state != DTE_WAITING)
541: return (ENETDOWN);
542: if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0)
543: return (EMFILE);
544:
545: lcp -> lcd_faddr = *sa;
546: lcp -> lcd_ceaddr = & lcp -> lcd_faddr;
547: pk_assoc (pkp, lcp, lcp -> lcd_ceaddr);
548:
549: /*
550: * If the link is not up yet, initiate an X.25 RESTART
551: */
552: if (pkp -> pk_state == DTE_WAITING) {
553: pkp -> pk_dxerole |= DTE_CONNECTPENDING;
554: pk_ctlinput (PRC_LINKUP, (struct sockaddr *)0, pkp);
555: if (lcp -> lcd_so)
556: soisconnecting (lcp -> lcd_so);
557: return 0;
558: }
559:
560: if (lcp -> lcd_so)
561: soisconnecting (lcp -> lcd_so);
562: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
563: pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
564: return (*pkp -> pk_ia -> ia_start) (lcp);
565: }
566:
567: /*
568: * Complete all pending X.25 call requests --- this gets called after
569: * the X.25 link has been restarted.
570: */
571: #define RESHUFFLELCN(maxlcn, lcn) ((maxlcn) - (lcn) + 1)
572:
573: pk_callcomplete (pkp)
574: register struct pkcb *pkp;
575: {
576: register struct pklcd *lcp;
577: register int i;
578: register int ni;
579:
580:
581: if (pkp -> pk_dxerole & DTE_CONNECTPENDING)
582: pkp -> pk_dxerole &= ~DTE_CONNECTPENDING;
583: else return;
584:
585: if (pkp -> pk_chan == 0)
586: return;
587:
588: /*
589: * We pretended to be a DTE for allocating lcns, if
590: * it turns out that we are in reality performing as a
591: * DCE we need to reshuffle the lcps.
592: *
593: * /+---------------+-------- -
594: * / | a (maxlcn-1) | \
595: * / +---------------+ \
596: * +--- * | b (maxlcn-2) | \
597: * | \ +---------------+ \
598: * r | \ | c (maxlcn-3) | \
599: * e | \+---------------+ |
600: * s | | . |
601: * h | | . | m
602: * u | | . | a
603: * f | | . | x
604: * f | | . | l
605: * l | /+---------------+ | c
606: * e | / | c' ( 3 ) | | n
607: * | / +---------------+ |
608: * +--> * | b' ( 2 ) | /
609: * \ +---------------+ /
610: * \ | a' ( 1 ) | /
611: * \+---------------+ /
612: * | 0 | /
613: * +---------------+-------- -
614: *
615: */
616: if (pkp -> pk_dxerole & DTE_PLAYDCE) {
617: /* Sigh, reshuffle it */
618: for (i = pkp -> pk_maxlcn; i > 0; --i)
619: if (pkp -> pk_chan[i]) {
620: ni = RESHUFFLELCN(pkp -> pk_maxlcn, i);
621: pkp -> pk_chan[ni] = pkp -> pk_chan[i];
622: pkp -> pk_chan[i] = NULL;
623: pkp -> pk_chan[ni] -> lcd_lcn = ni;
624: }
625: }
626:
627: for (i = 1; i <= pkp -> pk_maxlcn; ++i)
628: if ((lcp = pkp -> pk_chan[i]) != NULL) {
629: /* if (lcp -> lcd_so)
630: soisconnecting (lcp -> lcd_so); */
631: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
632: pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
633: (*pkp -> pk_ia -> ia_start) (lcp);
634: }
635: }
636:
637: struct bcdinfo {
638: octet *cp;
639: unsigned posn;
640: };
641: /*
642: * Build the rest of the CALL REQUEST packet. Fill in calling
643: * address, facilities fields and the user data field.
644: */
645:
646: pk_callrequest (lcp, sa, xcp)
647: struct pklcd *lcp;
648: register struct sockaddr_x25 *sa;
649: register struct x25config *xcp;
650: {
651: register struct x25_calladdr *a;
652: register struct mbuf *m = lcp -> lcd_template;
653: register struct x25_packet *xp = mtod (m, struct x25_packet *);
654: struct bcdinfo b;
655:
656: if (lcp -> lcd_flags & X25_DBIT)
657: X25SBITS(xp -> bits, d_bit, 1);
658: a = (struct x25_calladdr *) &xp -> packet_data;
659: b.cp = (octet *) a -> address_field;
660: b.posn = 0;
661: X25SBITS(a -> addrlens, called_addrlen, to_bcd (&b, sa, xcp));
662: X25SBITS(a -> addrlens, calling_addrlen, to_bcd (&b, &xcp -> xc_addr, xcp));
663: if (b.posn & 0x01)
664: *b.cp++ &= 0xf0;
665: m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a;
666:
667: if (lcp -> lcd_facilities) {
668: m -> m_pkthdr.len +=
669: (m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len;
670: lcp -> lcd_facilities = 0;
671: } else
672: pk_build_facilities (m, sa, (int)xcp -> xc_type);
673:
674: m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata);
675: }
676:
677: pk_build_facilities (m, sa, type)
678: register struct mbuf *m;
679: struct sockaddr_x25 *sa;
680: {
681: register octet *cp;
682: register octet *fcp;
683: register int revcharge;
684:
685: cp = mtod (m, octet *) + m -> m_len;
686: fcp = cp + 1;
687: revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0;
688: /*
689: * This is specific to Datapac X.25(1976) DTEs. International
690: * calls must have the "hi priority" bit on.
691: */
692: if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128)
693: revcharge |= 02;
694: if (revcharge) {
695: *fcp++ = FACILITIES_REVERSE_CHARGE;
696: *fcp++ = revcharge;
697: }
698: switch (type) {
699: case X25_1980:
700: case X25_1984:
701: *fcp++ = FACILITIES_PACKETSIZE;
702: *fcp++ = sa -> x25_opts.op_psize;
703: *fcp++ = sa -> x25_opts.op_psize;
704:
705: *fcp++ = FACILITIES_WINDOWSIZE;
706: *fcp++ = sa -> x25_opts.op_wsize;
707: *fcp++ = sa -> x25_opts.op_wsize;
708: }
709: *cp = fcp - cp - 1;
710: m -> m_pkthdr.len = (m -> m_len += *cp + 1);
711: }
712:
713: to_bcd (b, sa, xcp)
714: register struct bcdinfo *b;
715: struct sockaddr_x25 *sa;
716: register struct x25config *xcp;
717: {
718: register char *x = sa -> x25_addr;
719: unsigned start = b -> posn;
720: /*
721: * The nodnic and prepnd0 stuff looks tedious,
722: * but it does allow full X.121 addresses to be used,
723: * which is handy for routing info (& OSI type 37 addresses).
724: */
725: if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {
726: char dnicname[sizeof (long) * NBBY/3 + 2];
727: register char *p = dnicname;
728:
729: sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff);
730: for (; *p; p++) /* *p == 0 means dnic matched */
731: if ((*p ^ *x++) & 0x0f)
732: break;
733: if (*p || xcp -> xc_nodnic == 0)
734: x = sa -> x25_addr;
735: if (*p && xcp -> xc_prepnd0) {
736: if ((b -> posn)++ & 0x01)
737: *(b -> cp)++;
738: else
739: *(b -> cp) = 0;
740: }
741: }
742: while (*x)
743: if ((b -> posn)++ & 0x01)
744: *(b -> cp)++ |= *x++ & 0x0F;
745: else
746: *(b -> cp) = *x++ << 4;
747: return ((b -> posn) - start);
748: }
749:
750: /*
751: * This routine gets the first available logical channel number. The
752: * search is
753: * - from the highest number to lowest number if playing DTE, and
754: * - from lowest to highest number if playing DCE.
755: */
756:
757: pk_getlcn (pkp)
758: register struct pkcb *pkp;
759: {
760: register int i;
761:
762: if (pkp -> pk_chan == 0)
763: return (0);
764: if ( pkp -> pk_dxerole & DTE_PLAYDCE ) {
765: for (i = 1; i <= pkp -> pk_maxlcn; ++i)
766: if (pkp -> pk_chan[i] == NULL)
767: break;
768: } else {
769: for (i = pkp -> pk_maxlcn; i > 0; --i)
770: if (pkp -> pk_chan[i] == NULL)
771: break;
772: }
773: i = ( i > pkp -> pk_maxlcn ? 0 : i );
774: return (i);
775: }
776:
777: /*
778: * This procedure sends a CLEAR request packet. The lc state is
779: * set to "SENT_CLEAR".
780: */
781:
782: pk_clear (lcp, diagnostic, abortive)
783: register struct pklcd *lcp;
784: {
785: register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR);
786:
787: m -> m_len += 2;
788: m -> m_pkthdr.len += 2;
789: mtod (m, struct x25_packet *) -> packet_data = 0;
790: mtod (m, octet *)[4] = diagnostic;
791: if (lcp -> lcd_facilities) {
792: m -> m_next = lcp -> lcd_facilities;
793: m -> m_pkthdr.len += m -> m_next -> m_len;
794: lcp -> lcd_facilities = 0;
795: }
796: if (abortive)
797: lcp -> lcd_template = m;
798: else {
799: struct socket *so = lcp -> lcd_so;
800: struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb;
801: sbappendrecord (sb, m);
802: }
803: pk_output (lcp);
804:
805: }
806:
807: /*
808: * This procedure generates RNR's or RR's to inhibit or enable
809: * inward data flow, if the current state changes (blocked ==> open or
810: * vice versa), or if forced to generate one. One forces RNR's to ack data.
811: */
812: pk_flowcontrol (lcp, inhibit, forced)
813: register struct pklcd *lcp;
814: {
815: inhibit = (inhibit != 0);
816: if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER ||
817: (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit))
818: return;
819: lcp -> lcd_rxrnr_condition = inhibit;
820: lcp -> lcd_template =
821: pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR);
822: pk_output (lcp);
823: }
824:
825: /*
826: * This procedure sends a RESET request packet. It re-intializes
827: * virtual circuit.
828: */
829:
830: static
831: pk_reset (lcp, diagnostic)
832: register struct pklcd *lcp;
833: {
834: register struct mbuf *m;
835: register struct socket *so = lcp -> lcd_so;
836:
837: if (lcp -> lcd_state != DATA_TRANSFER)
838: return;
839:
840: if (so)
841: so -> so_error = ECONNRESET;
842: lcp -> lcd_reset_condition = TRUE;
843:
844: /* Reset all the control variables for the channel. */
845: pk_flush (lcp);
846: lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =
847: lcp -> lcd_intrconf_pending = FALSE;
848: lcp -> lcd_rsn = MODULUS - 1;
849: lcp -> lcd_ssn = 0;
850: lcp -> lcd_output_window = lcp -> lcd_input_window =
851: lcp -> lcd_last_transmitted_pr = 0;
852: m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET);
853: m -> m_pkthdr.len = m -> m_len += 2;
854: mtod (m, struct x25_packet *) -> packet_data = 0;
855: mtod (m, octet *)[4] = diagnostic;
856: pk_output (lcp);
857:
858: }
859:
860: /*
861: * This procedure frees all data queued for output or delivery on a
862: * virtual circuit.
863: */
864:
865: pk_flush (lcp)
866: register struct pklcd *lcp;
867: {
868: register struct socket *so;
869:
870: if (lcp -> lcd_template)
871: m_freem (lcp -> lcd_template);
872:
873: if (lcp -> lcd_cps) {
874: m_freem (lcp -> lcd_cps);
875: lcp -> lcd_cps = 0;
876: }
877: if (lcp -> lcd_facilities) {
878: m_freem (lcp -> lcd_facilities);
879: lcp -> lcd_facilities = 0;
880: }
881: if (so = lcp -> lcd_so)
882: sbflush (&so -> so_snd);
883: else
884: sbflush (&lcp -> lcd_sb);
885: }
886:
887: /*
888: * This procedure handles all local protocol procedure errors.
889: */
890:
891: pk_procerror (error, lcp, errstr, diagnostic)
892: register struct pklcd *lcp;
893: char *errstr;
894: {
895:
896: pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr);
897:
898: switch (error) {
899: case CLEAR:
900: if (lcp -> lcd_so) {
901: lcp -> lcd_so -> so_error = ECONNABORTED;
902: soisdisconnecting (lcp -> lcd_so);
903: }
904: pk_clear (lcp, diagnostic, 1);
905: break;
906:
907: case RESET:
908: pk_reset (lcp, diagnostic);
909: }
910: }
911:
912: /*
913: * This procedure is called during the DATA TRANSFER state to check
914: * and process the P(R) values received in the DATA, RR OR RNR
915: * packets.
916: */
917:
918: pk_ack (lcp, pr)
919: struct pklcd *lcp;
920: unsigned pr;
921: {
922: register struct socket *so = lcp -> lcd_so;
923:
924: if (lcp -> lcd_output_window == pr)
925: return (PACKET_OK);
926: if (lcp -> lcd_output_window < lcp -> lcd_ssn) {
927: if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) {
928: pk_procerror (RESET, lcp,
929: "p(r) flow control error", 2);
930: return (ERROR_PACKET);
931: }
932: }
933: else {
934: if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) {
935: pk_procerror (RESET, lcp,
936: "p(r) flow control error #2", 2);
937: return (ERROR_PACKET);
938: }
939: }
940:
941: lcp -> lcd_output_window = pr; /* Rotate window. */
942: if (lcp -> lcd_window_condition == TRUE)
943: lcp -> lcd_window_condition = FALSE;
944:
945: if (so && ((so -> so_snd.sb_flags & SB_WAIT) ||
946: (so -> so_snd.sb_flags & SB_NOTIFY)))
947: sowwakeup (so);
948:
949: return (PACKET_OK);
950: }
951:
952: /*
953: * This procedure decodes the X.25 level 3 packet returning a
954: * code to be used in switchs or arrays.
955: */
956:
957: pk_decode (xp)
958: register struct x25_packet *xp;
959: {
960: register int type;
961:
962: if (X25GBITS(xp -> bits, fmt_identifier) != 1)
963: return (INVALID_PACKET);
964: #ifdef ancient_history
965: /*
966: * Make sure that the logical channel group number is 0.
967: * This restriction may be removed at some later date.
968: */
969: if (xp -> lc_group_number != 0)
970: return (INVALID_PACKET);
971: #endif
972: /*
973: * Test for data packet first.
974: */
975: if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR))
976: return (DATA);
977:
978: /*
979: * Test if flow control packet (RR or RNR).
980: */
981: if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR))
982: switch (xp -> packet_type & 0x1f) {
983: case X25_RR:
984: return (RR);
985: case X25_RNR:
986: return (RNR);
987: case X25_REJECT:
988: return (REJECT);
989: }
990:
991: /*
992: * Determine the rest of the packet types.
993: */
994: switch (xp -> packet_type) {
995: case X25_CALL:
996: type = CALL;
997: break;
998:
999: case X25_CALL_ACCEPTED:
1000: type = CALL_ACCEPTED;
1001: break;
1002:
1003: case X25_CLEAR:
1004: type = CLEAR;
1005: break;
1006:
1007: case X25_CLEAR_CONFIRM:
1008: type = CLEAR_CONF;
1009: break;
1010:
1011: case X25_INTERRUPT:
1012: type = INTERRUPT;
1013: break;
1014:
1015: case X25_INTERRUPT_CONFIRM:
1016: type = INTERRUPT_CONF;
1017: break;
1018:
1019: case X25_RESET:
1020: type = RESET;
1021: break;
1022:
1023: case X25_RESET_CONFIRM:
1024: type = RESET_CONF;
1025: break;
1026:
1027: case X25_RESTART:
1028: type = RESTART;
1029: break;
1030:
1031: case X25_RESTART_CONFIRM:
1032: type = RESTART_CONF;
1033: break;
1034:
1035: case X25_DIAGNOSTIC:
1036: type = DIAG_TYPE;
1037: break;
1038:
1039: default:
1040: type = INVALID_PACKET;
1041: }
1042: return (type);
1043: }
1044:
1045: /*
1046: * A restart packet has been received. Print out the reason
1047: * for the restart.
1048: */
1049:
1050: pk_restartcause (pkp, xp)
1051: struct pkcb *pkp;
1052: register struct x25_packet *xp;
1053: {
1054: register struct x25config *xcp = pkp -> pk_xcp;
1055: register int lcn = LCN(xp);
1056:
1057: switch (xp -> packet_data) {
1058: case X25_RESTART_LOCAL_PROCEDURE_ERROR:
1059: pk_message (lcn, xcp, "restart: local procedure error");
1060: break;
1061:
1062: case X25_RESTART_NETWORK_CONGESTION:
1063: pk_message (lcn, xcp, "restart: network congestion");
1064: break;
1065:
1066: case X25_RESTART_NETWORK_OPERATIONAL:
1067: pk_message (lcn, xcp, "restart: network operational");
1068: break;
1069:
1070: default:
1071: pk_message (lcn, xcp, "restart: unknown cause");
1072: }
1073: }
1074:
1075: #define MAXRESETCAUSE 7
1076:
1077: int Reset_cause[] = {
1078: EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG
1079: };
1080:
1081: /*
1082: * A reset packet has arrived. Return the cause to the user.
1083: */
1084:
1085: pk_resetcause (pkp, xp)
1086: struct pkcb *pkp;
1087: register struct x25_packet *xp;
1088: {
1089: register struct pklcd *lcp =
1090: pkp -> pk_chan[LCN(xp)];
1091: register int code = xp -> packet_data;
1092:
1093: if (code > MAXRESETCAUSE)
1094: code = 7; /* EXRNCG */
1095:
1096: pk_message (LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x",
1097: xp -> packet_data, 4[(u_char *)xp]);
1098:
1099: if (lcp -> lcd_so)
1100: lcp -> lcd_so -> so_error = Reset_cause[code];
1101: }
1102:
1103: #define MAXCLEARCAUSE 25
1104:
1105: int Clear_cause[] = {
1106: EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0,
1107: 0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE,
1108: 0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC
1109: };
1110:
1111: /*
1112: * A clear packet has arrived. Return the cause to the user.
1113: */
1114:
1115: pk_clearcause (pkp, xp)
1116: struct pkcb *pkp;
1117: register struct x25_packet *xp;
1118: {
1119: register struct pklcd *lcp =
1120: pkp -> pk_chan[LCN(xp)];
1121: register int code = xp -> packet_data;
1122:
1123: if (code > MAXCLEARCAUSE)
1124: code = 5; /* EXRNCG */
1125: if (lcp -> lcd_so)
1126: lcp -> lcd_so -> so_error = Clear_cause[code];
1127: }
1128:
1129: char *
1130: format_ntn (xcp)
1131: register struct x25config *xcp;
1132: {
1133:
1134: return (xcp -> xc_addr.x25_addr);
1135: }
1136:
1137: /* VARARGS1 */
1138: pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6)
1139: struct x25config *xcp;
1140: char *fmt;
1141: {
1142:
1143: if (lcn)
1144: if (!PQEMPTY)
1145: printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn);
1146: else
1147: printf ("X.25: lcn %d: ", lcn);
1148: else
1149: if (!PQEMPTY)
1150: printf ("X.25(%s): ", format_ntn (xcp));
1151: else
1152: printf ("X.25: ");
1153:
1154: printf (fmt, a1, a2, a3, a4, a5, a6);
1155: printf ("\n");
1156: }
1157:
1158: pk_fragment (lcp, m0, qbit, mbit, wait)
1159: struct mbuf *m0;
1160: register struct pklcd *lcp;
1161: {
1162: register struct mbuf *m = m0;
1163: register struct x25_packet *xp;
1164: register struct sockbuf *sb;
1165: struct mbuf *head = 0, *next, **mp = &head, *m_split ();
1166: int totlen, psize = 1 << (lcp -> lcd_packetsize);
1167:
1168: if (m == 0)
1169: return 0;
1170: if (m -> m_flags & M_PKTHDR == 0)
1171: panic ("pk_fragment");
1172: totlen = m -> m_pkthdr.len;
1173: m -> m_act = 0;
1174: sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb;
1175: do {
1176: if (totlen > psize) {
1177: if ((next = m_split (m, psize, wait)) == 0)
1178: goto abort;
1179: totlen -= psize;
1180: } else
1181: next = 0;
1182: M_PREPEND(m, PKHEADERLN, wait);
1183: if (m == 0)
1184: goto abort;
1185: *mp = m;
1186: mp = & m -> m_act;
1187: *mp = 0;
1188: xp = mtod (m, struct x25_packet *);
1189: 0[(char *)xp] = 0;
1190: if (qbit)
1191: X25SBITS(xp -> bits, q_bit, 1);
1192: if (lcp -> lcd_flags & X25_DBIT)
1193: X25SBITS(xp -> bits, d_bit, 1);
1194: X25SBITS(xp -> bits, fmt_identifier, 1);
1195: xp -> packet_type = X25_DATA;
1196: SET_LCN(xp, lcp -> lcd_lcn);
1197: if (next || (mbit && (totlen == psize ||
1198: (lcp -> lcd_flags & X25_DBIT))))
1199: SMBIT(xp, 1);
1200: } while (m = next);
1201: for (m = head; m; m = next) {
1202: next = m -> m_act;
1203: m -> m_act = 0;
1204: sbappendrecord (sb, m);
1205: }
1206: return 0;
1207: abort:
1208: if (wait)
1209: panic ("pk_fragment null mbuf after wait");
1210: if (next)
1211: m_freem (next);
1212: for (m = head; m; m = next) {
1213: next = m -> m_act;
1214: m_freem (m);
1215: }
1216: return ENOBUFS;
1217: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.