|
|
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_input.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/malloc.h>
76:
77: #include <net/if.h>
78: #include <net/if_dl.h>
79: #include <net/if_llc.h>
80: #include <net/route.h>
81:
82: #include <netccitt/dll.h>
83: #include <netccitt/x25.h>
84: #include <netccitt/pk.h>
85: #include <netccitt/pk_var.h>
86: #include <netccitt/llc_var.h>
87:
88: struct pkcb_q pkcb_q = {&pkcb_q, &pkcb_q};
89:
90: /*
91: * ccittintr() is the generic interrupt handler for HDLC, LLC2, and X.25. This
92: * allows to have kernel running X.25 but no HDLC or LLC2 or both (in case we
93: * employ boards that do all the stuff themselves, e.g. ADAX X.25 or TPS ISDN.)
94: */
95: void
96: ccittintr ()
97: {
98: extern struct ifqueue pkintrq;
99: extern struct ifqueue hdintrq;
100: extern struct ifqueue llcintrq;
101:
102: #if HDLC
103: if (hdintrq.ifq_len)
104: hdintr ();
105: #endif
106: #if LLC
107: if (llcintrq.ifq_len)
108: llcintr ();
109: #endif
110: if (pkintrq.ifq_len)
111: pkintr ();
112: }
113:
114: struct pkcb *
115: pk_newlink (ia, llnext)
116: struct x25_ifaddr *ia;
117: caddr_t llnext;
118: {
119: register struct x25config *xcp = &ia -> ia_xc;
120: register struct pkcb *pkp;
121: register struct pklcd *lcp;
122: register struct protosw *pp;
123: unsigned size;
124:
125: pp = pffindproto (AF_CCITT, (int) xcp -> xc_lproto, 0);
126: if (pp == 0 || pp -> pr_output == 0) {
127: pk_message (0, xcp, "link level protosw error");
128: return ((struct pkcb *)0);
129: }
130: /*
131: * Allocate a network control block structure
132: */
133: size = sizeof (struct pkcb);
134: // pkp = (struct pkcb *) malloc (size, M_PCB, M_WAITOK);
135: MALLOC(pkp, struct pkcb *, size, M_PCB, M_WAITOK);
136: if (pkp == 0)
137: return ((struct pkcb *)0);
138: bzero ((caddr_t) pkp, size);
139: pkp -> pk_lloutput = pp -> pr_output;
140: pkp -> pk_llctlinput = (caddr_t (*)()) pp -> pr_ctlinput;
141: pkp -> pk_xcp = xcp;
142: pkp -> pk_ia = ia;
143: pkp -> pk_state = DTE_WAITING;
144: pkp -> pk_llnext = llnext;
145: insque (pkp, &pkcb_q);
146:
147: /*
148: * set defaults
149: */
150:
151: if (xcp -> xc_pwsize == 0)
152: xcp -> xc_pwsize = DEFAULT_WINDOW_SIZE;
153: if (xcp -> xc_psize == 0)
154: xcp -> xc_psize = X25_PS128;
155: /*
156: * Allocate logical channel descriptor vector
157: */
158:
159: (void) pk_resize (pkp);
160: return (pkp);
161: }
162:
163:
164: pk_dellink (pkp)
165: register struct pkcb *pkp;
166: {
167: register int i;
168: register struct protosw *pp;
169:
170: /*
171: * Essentially we have the choice to
172: * (a) go ahead and let the route be deleted and
173: * leave the pkcb associated with that route
174: * as it is, i.e. the connections stay open
175: * (b) do a pk_disconnect() on all channels associated
176: * with the route via the pkcb and then proceed.
177: *
178: * For the time being we stick with (b)
179: */
180:
181: for (i = 1; i < pkp -> pk_maxlcn; ++i)
182: if (pkp -> pk_chan[i])
183: pk_disconnect (pkp -> pk_chan[i]);
184:
185: /*
186: * Free the pkcb
187: */
188:
189: /*
190: * First find the protoswitch to get hold of the link level
191: * protocol to be notified that the packet level entity is
192: * dissolving ...
193: */
194: pp = pffindproto (AF_CCITT, (int) pkp -> pk_xcp -> xc_lproto, 0);
195: if (pp == 0 || pp -> pr_output == 0) {
196: pk_message (0, pkp -> pk_xcp, "link level protosw error");
197: return (EPROTONOSUPPORT);
198: }
199:
200: pkp -> pk_refcount--;
201: if (!pkp -> pk_refcount) {
202: struct dll_ctlinfo ctlinfo;
203:
204: remque (pkp);
205: if (pkp -> pk_rt -> rt_llinfo == (caddr_t) pkp)
206: pkp -> pk_rt -> rt_llinfo = (caddr_t) NULL;
207:
208: /*
209: * Tell the link level that the pkcb is dissolving
210: */
211: if (pp -> pr_ctlinput && pkp -> pk_llnext) {
212: ctlinfo.dlcti_pcb = pkp -> pk_llnext;
213: ctlinfo.dlcti_rt = pkp -> pk_rt;
214: (pp -> pr_ctlinput)(PRC_DISCONNECT_REQUEST,
215: pkp -> pk_xcp, &ctlinfo);
216: }
217: free ((caddr_t) pkp -> pk_chan, M_IFADDR);
218: free ((caddr_t) pkp, M_PCB);
219: }
220:
221: return (0);
222: }
223:
224:
225: pk_resize (pkp)
226: register struct pkcb *pkp;
227: {
228: struct pklcd *dev_lcp = 0;
229: struct x25config *xcp = pkp -> pk_xcp;
230: if (pkp -> pk_chan &&
231: (pkp -> pk_maxlcn != xcp -> xc_maxlcn)) {
232: pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION);
233: dev_lcp = pkp -> pk_chan[0];
234: free ((caddr_t) pkp -> pk_chan, M_IFADDR);
235: pkp -> pk_chan = 0;
236: }
237: if (pkp -> pk_chan == 0) {
238: unsigned size;
239: pkp -> pk_maxlcn = xcp -> xc_maxlcn;
240: size = (pkp -> pk_maxlcn + 1) * sizeof (struct pklcd *);
241: // pkp -> pk_chan =
242: // (struct pklcd **) malloc (size, M_IFADDR, M_WAITOK);
243: MALLOC(pkp->pk_chan, struct pklcd **, size, M_IFADDR, M_WAITOK);
244: if (pkp -> pk_chan) {
245: bzero ((caddr_t) pkp -> pk_chan, size);
246: /*
247: * Allocate a logical channel descriptor for lcn 0
248: */
249: if (dev_lcp == 0 &&
250: (dev_lcp = pk_attach ((struct socket *)0)) == 0)
251: return (ENOBUFS);
252: dev_lcp -> lcd_state = READY;
253: dev_lcp -> lcd_pkp = pkp;
254: pkp -> pk_chan[0] = dev_lcp;
255: } else {
256: if (dev_lcp)
257: pk_close (dev_lcp);
258: return (ENOBUFS);
259: }
260: }
261: return 0;
262: }
263:
264: /*
265: * This procedure is called by the link level whenever the link
266: * becomes operational, is reset, or when the link goes down.
267: */
268: /*VARARGS*/
269: caddr_t
270: pk_ctlinput (code, src, addr)
271: int code;
272: struct sockaddr *src;
273: caddr_t addr;
274: {
275: register struct pkcb *pkp = (struct pkcb *) addr;
276:
277: switch (code) {
278: case PRC_LINKUP:
279: if (pkp -> pk_state == DTE_WAITING)
280: pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION);
281: break;
282:
283: case PRC_LINKDOWN:
284: pk_restart (pkp, -1); /* Clear all active circuits */
285: pkp -> pk_state = DTE_WAITING;
286: break;
287:
288: case PRC_LINKRESET:
289: pk_restart (pkp, X25_RESTART_NETWORK_CONGESTION);
290: break;
291:
292: case PRC_CONNECT_INDICATION: {
293: struct rtentry *llrt;
294:
295: if ((llrt = rtalloc1(src, 0)) == 0)
296: return 0;
297: else llrt -> rt_refcnt--;
298:
299: pkp = (((struct npaidbentry *) llrt -> rt_llinfo) -> np_rt) ?
300: (struct pkcb *)(((struct npaidbentry *) llrt -> rt_llinfo) -> np_rt -> rt_llinfo) : (struct pkcb *) 0;
301: if (pkp == (struct pkcb *) 0)
302: return 0;
303: pkp -> pk_llnext = addr;
304:
305: return ((caddr_t) pkp);
306: }
307: case PRC_DISCONNECT_INDICATION:
308: pk_restart (pkp, -1) ; /* Clear all active circuits */
309: pkp -> pk_state = DTE_WAITING;
310: pkp -> pk_llnext = (caddr_t) 0;
311: }
312: return (0);
313: }
314: struct ifqueue pkintrq;
315: /*
316: * This routine is called if there are semi-smart devices that do HDLC
317: * in hardware and want to queue the packet and call level 3 directly
318: */
319: pkintr ()
320: {
321: register struct mbuf *m;
322: register struct ifaddr *ifa;
323: register struct ifnet *ifp;
324: register int s;
325:
326: for (;;) {
327: s = splimp ();
328: IF_DEQUEUE (&pkintrq, m);
329: splx (s);
330: if (m == 0)
331: break;
332: if (m -> m_len < PKHEADERLN) {
333: printf ("pkintr: packet too short (len=%d)\n",
334: m -> m_len);
335: m_freem (m);
336: continue;
337: }
338: pk_input (m);
339: }
340: }
341: struct mbuf *pk_bad_packet;
342: struct mbuf_cache pk_input_cache = {0 };
343: /*
344: * X.25 PACKET INPUT
345: *
346: * This procedure is called by a link level procedure whenever
347: * an information frame is received. It decodes the packet and
348: * demultiplexes based on the logical channel number.
349: *
350: * We change the original conventions of the UBC code here --
351: * since there may be multiple pkcb's for a given interface
352: * of type 802.2 class 2, we retrieve which one it is from
353: * m_pkthdr.rcvif (which has been overwritten by lower layers);
354: * That field is then restored for the benefit of upper layers which
355: * may make use of it, such as CLNP.
356: *
357: */
358:
359: #define RESTART_DTE_ORIGINATED(xp) (((xp) -> packet_cause == X25_RESTART_DTE_ORIGINATED) || \
360: ((xp) -> packet_cause >= X25_RESTART_DTE_ORIGINATED2))
361:
362: pk_input (m)
363: register struct mbuf *m;
364: {
365: register struct x25_packet *xp;
366: register struct pklcd *lcp;
367: register struct socket *so = 0;
368: register struct pkcb *pkp;
369: int ptype, lcn, lcdstate = LISTEN;
370:
371: if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize)
372: mbuf_cache (&pk_input_cache, m);
373: if ((m -> m_flags & M_PKTHDR) == 0)
374: panic ("pkintr");
375:
376: if ((pkp = (struct pkcb *) m -> m_pkthdr.rcvif) == 0)
377: return;
378: xp = mtod (m, struct x25_packet *);
379: ptype = pk_decode (xp);
380: lcn = LCN(xp);
381: lcp = pkp -> pk_chan[lcn];
382:
383: /*
384: * If the DTE is in Restart state, then it will ignore data,
385: * interrupt, call setup and clearing, flow control and reset
386: * packets.
387: */
388: if (lcn < 0 || lcn > pkp -> pk_maxlcn) {
389: pk_message (lcn, pkp -> pk_xcp, "illegal lcn");
390: m_freem (m);
391: return;
392: }
393:
394: pk_trace (pkp -> pk_xcp, m, "P-In");
395:
396: if (pkp -> pk_state != DTE_READY && ptype != RESTART && ptype != RESTART_CONF) {
397: m_freem (m);
398: return;
399: }
400: if (lcp) {
401: so = lcp -> lcd_so;
402: lcdstate = lcp -> lcd_state;
403: } else {
404: if (ptype == CLEAR) { /* idle line probe (Datapac specific) */
405: /* send response on lcd 0's output queue */
406: lcp = pkp -> pk_chan[0];
407: lcp -> lcd_template = pk_template (lcn, X25_CLEAR_CONFIRM);
408: pk_output (lcp);
409: m_freem (m);
410: return;
411: }
412: if (ptype != CALL)
413: ptype = INVALID_PACKET;
414: }
415:
416: if (lcn == 0 && ptype != RESTART && ptype != RESTART_CONF) {
417: pk_message (0, pkp -> pk_xcp, "illegal ptype (%d, %s) on lcn 0",
418: ptype, pk_name[ptype / MAXSTATES]);
419: if (pk_bad_packet)
420: m_freem (pk_bad_packet);
421: pk_bad_packet = m;
422: return;
423: }
424:
425: m -> m_pkthdr.rcvif = pkp -> pk_ia -> ia_ifp;
426:
427: switch (ptype + lcdstate) {
428: /*
429: * Incoming Call packet received.
430: */
431: case CALL + LISTEN:
432: pk_incoming_call (pkp, m);
433: break;
434:
435: /*
436: * Call collision: Just throw this "incoming call" away since
437: * the DCE will ignore it anyway.
438: */
439: case CALL + SENT_CALL:
440: pk_message ((int) lcn, pkp -> pk_xcp,
441: "incoming call collision");
442: break;
443:
444: /*
445: * Call confirmation packet received. This usually means our
446: * previous connect request is now complete.
447: */
448: case CALL_ACCEPTED + SENT_CALL:
449: MCHTYPE(m, MT_CONTROL);
450: pk_call_accepted (lcp, m);
451: break;
452:
453: /*
454: * This condition can only happen if the previous state was
455: * SENT_CALL. Just ignore the packet, eventually a clear
456: * confirmation should arrive.
457: */
458: case CALL_ACCEPTED + SENT_CLEAR:
459: break;
460:
461: /*
462: * Clear packet received. This requires a complete tear down
463: * of the virtual circuit. Free buffers and control blocks.
464: * and send a clear confirmation.
465: */
466: case CLEAR + READY:
467: case CLEAR + RECEIVED_CALL:
468: case CLEAR + SENT_CALL:
469: case CLEAR + DATA_TRANSFER:
470: lcp -> lcd_state = RECEIVED_CLEAR;
471: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CLEAR_CONFIRM);
472: pk_output (lcp);
473: pk_clearcause (pkp, xp);
474: if (lcp -> lcd_upper) {
475: MCHTYPE(m, MT_CONTROL);
476: lcp -> lcd_upper (lcp, m);
477: }
478: pk_close (lcp);
479: lcp = 0;
480: break;
481:
482: /*
483: * Clear collision: Treat this clear packet as a confirmation.
484: */
485: case CLEAR + SENT_CLEAR:
486: pk_close (lcp);
487: break;
488:
489: /*
490: * Clear confirmation received. This usually means the virtual
491: * circuit is now completely removed.
492: */
493: case CLEAR_CONF + SENT_CLEAR:
494: pk_close (lcp);
495: break;
496:
497: /*
498: * A clear confirmation on an unassigned logical channel - just
499: * ignore it. Note: All other packets on an unassigned channel
500: * results in a clear.
501: */
502: case CLEAR_CONF + READY:
503: case CLEAR_CONF + LISTEN:
504: break;
505:
506: /*
507: * Data packet received. Pass on to next level. Move the Q and M
508: * bits into the data portion for the next level.
509: */
510: case DATA + DATA_TRANSFER:
511: if (lcp -> lcd_reset_condition) {
512: ptype = DELETE_PACKET;
513: break;
514: }
515:
516: /*
517: * Process the P(S) flow control information in this Data packet.
518: * Check that the packets arrive in the correct sequence and that
519: * they are within the "lcd_input_window". Input window rotation is
520: * initiated by the receive interface.
521: */
522:
523: if (PS(xp) != ((lcp -> lcd_rsn + 1) % MODULUS) ||
524: PS(xp) == ((lcp -> lcd_input_window + lcp -> lcd_windowsize) % MODULUS)) {
525: m_freem (m);
526: pk_procerror (RESET, lcp, "p(s) flow control error", 1);
527: break;
528: }
529: lcp -> lcd_rsn = PS(xp);
530:
531: if (pk_ack (lcp, PR(xp)) != PACKET_OK) {
532: m_freem (m);
533: break;
534: }
535: m -> m_data += PKHEADERLN;
536: m -> m_len -= PKHEADERLN;
537: m -> m_pkthdr.len -= PKHEADERLN;
538:
539: lcp -> lcd_rxcnt++;
540: if (lcp -> lcd_flags & X25_MBS_HOLD) {
541: register struct mbuf *n = lcp -> lcd_cps;
542: int mbit = MBIT(xp);
543: octet q_and_d_bits;
544:
545: if (n) {
546: n -> m_pkthdr.len += m -> m_pkthdr.len;
547: while (n -> m_next)
548: n = n -> m_next;
549: n -> m_next = m;
550: m = lcp -> lcd_cps;
551:
552: if (lcp -> lcd_cpsmax &&
553: n -> m_pkthdr.len > lcp -> lcd_cpsmax) {
554: pk_procerror (RESET, lcp,
555: "C.P.S. overflow", 128);
556: return;
557: }
558: q_and_d_bits = 0xc0 & *(octet *) xp;
559: xp = (struct x25_packet *)
560: (mtod (m, octet *) - PKHEADERLN);
561: *(octet *) xp |= q_and_d_bits;
562: }
563: if (mbit) {
564: lcp -> lcd_cps = m;
565: pk_flowcontrol (lcp, 0, 1);
566: return;
567: }
568: lcp -> lcd_cps = 0;
569: }
570: if (so == 0)
571: break;
572: if (lcp -> lcd_flags & X25_MQBIT) {
573: octet t = (X25GBITS(xp -> bits, q_bit)) ? t = 0x80 : 0;
574:
575: if (MBIT(xp))
576: t |= 0x40;
577: m -> m_data -= 1;
578: m -> m_len += 1;
579: m -> m_pkthdr.len += 1;
580: *mtod (m, octet *) = t;
581: }
582:
583: /*
584: * Discard Q-BIT packets if the application
585: * doesn't want to be informed of M and Q bit status
586: */
587: if (X25GBITS(xp -> bits, q_bit)
588: && (lcp -> lcd_flags & X25_MQBIT) == 0) {
589: m_freem (m);
590: /*
591: * NB. This is dangerous: sending a RR here can
592: * cause sequence number errors if a previous data
593: * packet has not yet been passed up to the application
594: * (RR's are normally generated via PRU_RCVD).
595: */
596: pk_flowcontrol (lcp, 0, 1);
597: } else {
598: sbappendrecord (&so -> so_rcv, m);
599: sorwakeup (so);
600: }
601: break;
602:
603: /*
604: * Interrupt packet received.
605: */
606: case INTERRUPT + DATA_TRANSFER:
607: if (lcp -> lcd_reset_condition)
608: break;
609: lcp -> lcd_intrdata = xp -> packet_data;
610: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_INTERRUPT_CONFIRM);
611: pk_output (lcp);
612: m -> m_data += PKHEADERLN;
613: m -> m_len -= PKHEADERLN;
614: m -> m_pkthdr.len -= PKHEADERLN;
615: MCHTYPE(m, MT_OOBDATA);
616: if (so) {
617: if (so -> so_options & SO_OOBINLINE)
618: sbinsertoob (&so -> so_rcv, m);
619: else
620: m_freem (m);
621: sohasoutofband (so);
622: }
623: break;
624:
625: /*
626: * Interrupt confirmation packet received.
627: */
628: case INTERRUPT_CONF + DATA_TRANSFER:
629: if (lcp -> lcd_reset_condition)
630: break;
631: if (lcp -> lcd_intrconf_pending == TRUE)
632: lcp -> lcd_intrconf_pending = FALSE;
633: else
634: pk_procerror (RESET, lcp, "unexpected packet", 43);
635: break;
636:
637: /*
638: * Receiver ready received. Rotate the output window and output
639: * any data packets waiting transmission.
640: */
641: case RR + DATA_TRANSFER:
642: if (lcp -> lcd_reset_condition ||
643: pk_ack (lcp, PR(xp)) != PACKET_OK) {
644: ptype = DELETE_PACKET;
645: break;
646: }
647: if (lcp -> lcd_rnr_condition == TRUE)
648: lcp -> lcd_rnr_condition = FALSE;
649: pk_output (lcp);
650: break;
651:
652: /*
653: * Receiver Not Ready received. Packets up to the P(R) can be
654: * be sent. Condition is cleared with a RR.
655: */
656: case RNR + DATA_TRANSFER:
657: if (lcp -> lcd_reset_condition ||
658: pk_ack (lcp, PR(xp)) != PACKET_OK) {
659: ptype = DELETE_PACKET;
660: break;
661: }
662: lcp -> lcd_rnr_condition = TRUE;
663: break;
664:
665: /*
666: * Reset packet received. Set state to FLOW_OPEN. The Input and
667: * Output window edges ar set to zero. Both the send and receive
668: * numbers are reset. A confirmation is returned.
669: */
670: case RESET + DATA_TRANSFER:
671: if (lcp -> lcd_reset_condition)
672: /* Reset collision. Just ignore packet. */
673: break;
674:
675: pk_resetcause (pkp, xp);
676: lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =
677: lcp -> lcd_intrconf_pending = FALSE;
678: lcp -> lcd_output_window = lcp -> lcd_input_window =
679: lcp -> lcd_last_transmitted_pr = 0;
680: lcp -> lcd_ssn = 0;
681: lcp -> lcd_rsn = MODULUS - 1;
682:
683: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET_CONFIRM);
684: pk_output (lcp);
685:
686: pk_flush (lcp);
687: if (so == 0)
688: break;
689: wakeup ((caddr_t) & so -> so_timeo);
690: sorwakeup (so);
691: sowwakeup (so);
692: break;
693:
694: /*
695: * Reset confirmation received.
696: */
697: case RESET_CONF + DATA_TRANSFER:
698: if (lcp -> lcd_reset_condition) {
699: lcp -> lcd_reset_condition = FALSE;
700: pk_output (lcp);
701: }
702: else
703: pk_procerror (RESET, lcp, "unexpected packet", 32);
704: break;
705:
706: case DATA + SENT_CLEAR:
707: ptype = DELETE_PACKET;
708: case RR + SENT_CLEAR:
709: case RNR + SENT_CLEAR:
710: case INTERRUPT + SENT_CLEAR:
711: case INTERRUPT_CONF + SENT_CLEAR:
712: case RESET + SENT_CLEAR:
713: case RESET_CONF + SENT_CLEAR:
714: /* Just ignore p if we have sent a CLEAR already.
715: */
716: break;
717:
718: /*
719: * Restart sets all the permanent virtual circuits to the "Data
720: * Transfer" stae and all the switched virtual circuits to the
721: * "Ready" state.
722: */
723: case RESTART + READY:
724: switch (pkp -> pk_state) {
725: case DTE_SENT_RESTART:
726: /*
727: * Restart collision.
728: * If case the restart cause is "DTE originated" we
729: * have a DTE-DTE situation and are trying to resolve
730: * who is going to play DTE/DCE [ISO 8208:4.2-4.5]
731: */
732: if (RESTART_DTE_ORIGINATED(xp)) {
733: pk_restart (pkp, X25_RESTART_DTE_ORIGINATED);
734: pk_message (0, pkp -> pk_xcp,
735: "RESTART collision");
736: if ((pkp -> pk_restartcolls++) > MAXRESTARTCOLLISIONS) {
737: pk_message (0, pkp -> pk_xcp,
738: "excessive RESTART collisions");
739: pkp -> pk_restartcolls = 0;
740: }
741: break;
742: }
743: pkp -> pk_state = DTE_READY;
744: pkp -> pk_dxerole |= DTE_PLAYDTE;
745: pkp -> pk_dxerole &= ~DTE_PLAYDCE;
746: pk_message (0, pkp -> pk_xcp,
747: "Packet level operational");
748: pk_message (0, pkp -> pk_xcp,
749: "Assuming DTE role");
750: if (pkp -> pk_dxerole & DTE_CONNECTPENDING)
751: pk_callcomplete (pkp);
752: break;
753:
754: default:
755: pk_restart (pkp, -1);
756: pk_restartcause (pkp, xp);
757: pkp -> pk_chan[0] -> lcd_template = pk_template (0,
758: X25_RESTART_CONFIRM);
759: pk_output (pkp -> pk_chan[0]);
760: pkp -> pk_state = DTE_READY;
761: pkp -> pk_dxerole |= RESTART_DTE_ORIGINATED(xp) ? DTE_PLAYDCE :
762: DTE_PLAYDTE;
763: if (pkp -> pk_dxerole & DTE_PLAYDTE) {
764: pkp -> pk_dxerole &= ~DTE_PLAYDCE;
765: pk_message (0, pkp -> pk_xcp,
766: "Assuming DTE role");
767: } else {
768: pkp -> pk_dxerole &= ~DTE_PLAYDTE;
769: pk_message (0, pkp -> pk_xcp,
770: "Assuming DCE role");
771: }
772: if (pkp -> pk_dxerole & DTE_CONNECTPENDING)
773: pk_callcomplete (pkp);
774: }
775: break;
776:
777: /*
778: * Restart confirmation received. All logical channels are set
779: * to READY.
780: */
781: case RESTART_CONF + READY:
782: switch (pkp -> pk_state) {
783: case DTE_SENT_RESTART:
784: pkp -> pk_state = DTE_READY;
785: pkp -> pk_dxerole |= DTE_PLAYDTE;
786: pkp -> pk_dxerole &= ~DTE_PLAYDCE;
787: pk_message (0, pkp -> pk_xcp,
788: "Packet level operational");
789: pk_message (0, pkp -> pk_xcp,
790: "Assuming DTE role");
791: if (pkp -> pk_dxerole & DTE_CONNECTPENDING)
792: pk_callcomplete (pkp);
793: break;
794:
795: default:
796: /* Restart local procedure error. */
797: pk_restart (pkp, X25_RESTART_LOCAL_PROCEDURE_ERROR);
798: pkp -> pk_state = DTE_SENT_RESTART;
799: pkp -> pk_dxerole &= ~(DTE_PLAYDTE | DTE_PLAYDCE);
800: }
801: break;
802:
803: default:
804: if (lcp) {
805: pk_procerror (CLEAR, lcp, "unknown packet error", 33);
806: pk_message (lcn, pkp -> pk_xcp,
807: "\"%s\" unexpected in \"%s\" state",
808: pk_name[ptype/MAXSTATES], pk_state[lcdstate]);
809: } else
810: pk_message (lcn, pkp -> pk_xcp,
811: "packet arrived on unassigned lcn");
812: break;
813: }
814: if (so == 0 && lcp && lcp -> lcd_upper && lcdstate == DATA_TRANSFER) {
815: if (ptype != DATA && ptype != INTERRUPT)
816: MCHTYPE(m, MT_CONTROL);
817: lcp -> lcd_upper (lcp, m);
818: } else if (ptype != DATA && ptype != INTERRUPT)
819: m_freem (m);
820: }
821:
822: static
823: prune_dnic (from, to, dnicname, xcp)
824: char *from, *to, *dnicname;
825: register struct x25config *xcp;
826: {
827: register char *cp1 = from, *cp2 = from;
828: if (xcp -> xc_prepnd0 && *cp1 == '0') {
829: from = ++cp1;
830: goto copyrest;
831: }
832: if (xcp -> xc_nodnic) {
833: for (cp1 = dnicname; *cp2 = *cp1++;)
834: cp2++;
835: cp1 = from;
836: }
837: copyrest:
838: for (cp1 = dnicname; *cp2 = *cp1++;)
839: cp2++;
840: }
841: /* static */
842: pk_simple_bsd (from, to, lower, len)
843: register octet *from, *to;
844: register len, lower;
845: {
846: register int c;
847: while (--len >= 0) {
848: c = *from;
849: if (lower & 0x01)
850: *from++;
851: else
852: c >>= 4;
853: c &= 0x0f; c |= 0x30; *to++ = c; lower++;
854: }
855: *to = 0;
856: }
857:
858: /*static octet * */
859: pk_from_bcd (a, iscalling, sa, xcp)
860: register struct x25_calladdr *a;
861: int iscalling;
862: register struct sockaddr_x25 *sa;
863: register struct x25config *xcp;
864: {
865: octet buf[MAXADDRLN+1];
866: octet *cp;
867: unsigned count;
868:
869: bzero ((caddr_t) sa, sizeof (*sa));
870: sa -> x25_len = sizeof (*sa);
871: sa -> x25_family = AF_CCITT;
872: if (iscalling) {
873: cp = a -> address_field + (X25GBITS(a -> addrlens, called_addrlen) / 2);
874: count = X25GBITS(a -> addrlens, calling_addrlen);
875: pk_simple_bsd (cp, buf, X25GBITS(a -> addrlens, called_addrlen), count);
876: } else {
877: count = X25GBITS(a -> addrlens, called_addrlen);
878: pk_simple_bsd (a -> address_field, buf, 0, count);
879: }
880: if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {
881: octet dnicname[sizeof (long) * NBBY/3 + 2];
882:
883: sprintf ((char *) dnicname, "%d", xcp -> xc_addr.x25_net);
884: prune_dnic ((char *) buf, sa -> x25_addr, dnicname, xcp);
885: } else
886: bcopy ((caddr_t) buf, (caddr_t) sa -> x25_addr, count + 1);
887: }
888:
889: static
890: save_extra (m0, fp, so)
891: struct mbuf *m0;
892: octet *fp;
893: struct socket *so;
894: {
895: register struct mbuf *m;
896: struct cmsghdr cmsghdr;
897: if (m = m_copy (m, 0, (int)M_COPYALL)) {
898: int off = fp - mtod (m0, octet *);
899: int len = m -> m_pkthdr.len - off + sizeof (cmsghdr);
900: cmsghdr.cmsg_len = len;
901: cmsghdr.cmsg_level = AF_CCITT;
902: cmsghdr.cmsg_type = PK_FACILITIES;
903: m_adj (m, off);
904: M_PREPEND (m, sizeof (cmsghdr), M_DONTWAIT);
905: if (m == 0)
906: return;
907: bcopy ((caddr_t)&cmsghdr, mtod (m, caddr_t), sizeof (cmsghdr));
908: MCHTYPE(m, MT_CONTROL);
909: sbappendrecord (&so -> so_rcv, m);
910: }
911: }
912:
913: /*
914: * This routine handles incoming call packets. It matches the protocol
915: * field on the Call User Data field (usually the first four bytes) with
916: * sockets awaiting connections.
917: */
918:
919: pk_incoming_call (pkp, m0)
920: struct mbuf *m0;
921: struct pkcb *pkp;
922: {
923: register struct pklcd *lcp = 0, *l;
924: register struct sockaddr_x25 *sa;
925: register struct x25_calladdr *a;
926: register struct socket *so = 0;
927: struct x25_packet *xp = mtod (m0, struct x25_packet *);
928: struct mbuf *m;
929: struct x25config *xcp = pkp -> pk_xcp;
930: int len = m0 -> m_pkthdr.len;
931: int udlen;
932: char *errstr = "server unavailable";
933: octet *u, *facp;
934: int lcn = LCN(xp);
935:
936: /* First, copy the data from the incoming call packet to a X25 address
937: descriptor. It is to be regretted that you have
938: to parse the facilities into a sockaddr to determine
939: if reverse charging is being requested */
940: if ((m = m_get (M_DONTWAIT, MT_SONAME)) == 0)
941: return;
942: sa = mtod (m, struct sockaddr_x25 *);
943: a = (struct x25_calladdr *) &xp -> packet_data;
944: facp = u = (octet *) (a -> address_field +
945: ((X25GBITS(a -> addrlens, called_addrlen) + X25GBITS(a -> addrlens, calling_addrlen) + 1) / 2));
946: u += *u + 1;
947: udlen = min (16, ((octet *) xp) + len - u);
948: if (udlen < 0)
949: udlen = 0;
950: pk_from_bcd (a, 1, sa, pkp -> pk_xcp); /* get calling address */
951: pk_parse_facilities (facp, sa);
952: bcopy ((caddr_t) u, sa -> x25_udata, udlen);
953: sa -> x25_udlen = udlen;
954:
955: /*
956: * Now, loop through the listen sockets looking for a match on the
957: * PID. That is the first few octets of the user data field.
958: * This is the closest thing to a port number for X.25 packets.
959: * It does provide a way of multiplexing services at the user level.
960: */
961:
962: for (l = pk_listenhead; l; l = l -> lcd_listen) {
963: struct sockaddr_x25 *sxp = l -> lcd_ceaddr;
964:
965: if (bcmp (sxp -> x25_udata, u, sxp -> x25_udlen))
966: continue;
967: if (sxp -> x25_net &&
968: sxp -> x25_net != xcp -> xc_addr.x25_net)
969: continue;
970: /*
971: * don't accept incoming calls with the D-Bit on
972: * unless the server agrees
973: */
974: if (X25GBITS(xp -> bits, d_bit) && !(sxp -> x25_opts.op_flags & X25_DBIT)) {
975: errstr = "incoming D-Bit mismatch";
976: break;
977: }
978: /*
979: * don't accept incoming collect calls unless
980: * the server sets the reverse charging option.
981: */
982: if ((sxp -> x25_opts.op_flags & (X25_OLDSOCKADDR|X25_REVERSE_CHARGE)) == 0 &&
983: sa -> x25_opts.op_flags & X25_REVERSE_CHARGE) {
984: errstr = "incoming collect call refused";
985: break;
986: }
987: if (l -> lcd_so) {
988: if (so = sonewconn (l -> lcd_so, SS_ISCONNECTED))
989: lcp = (struct pklcd *) so -> so_pcb;
990: } else
991: lcp = pk_attach ((struct socket *) 0);
992: if (lcp == 0) {
993: /*
994: * Insufficient space or too many unaccepted
995: * connections. Just throw the call away.
996: */
997: errstr = "server malfunction";
998: break;
999: }
1000: lcp -> lcd_upper = l -> lcd_upper;
1001: lcp -> lcd_upnext = l -> lcd_upnext;
1002: lcp -> lcd_lcn = lcn;
1003: lcp -> lcd_state = RECEIVED_CALL;
1004: sa -> x25_opts.op_flags |= (sxp -> x25_opts.op_flags &
1005: ~X25_REVERSE_CHARGE) | l -> lcd_flags;
1006: pk_assoc (pkp, lcp, sa);
1007: lcp -> lcd_faddr = *sa;
1008: lcp -> lcd_laddr.x25_udlen = sxp -> x25_udlen;
1009: lcp -> lcd_craddr = &lcp -> lcd_faddr;
1010: lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL_ACCEPTED);
1011: if (lcp -> lcd_flags & X25_DBIT) {
1012: if (X25GBITS(xp -> bits, d_bit))
1013: X25SBITS(mtod (lcp -> lcd_template,
1014: struct x25_packet *) -> bits, d_bit, 1);
1015: else
1016: lcp -> lcd_flags &= ~X25_DBIT;
1017: }
1018: if (so) {
1019: pk_output (lcp);
1020: soisconnected (so);
1021: if (so -> so_options & SO_OOBINLINE)
1022: save_extra (m0, facp, so);
1023: } else if (lcp -> lcd_upper) {
1024: (*lcp -> lcd_upper) (lcp, m0);
1025: }
1026: (void) m_free (m);
1027: return;
1028: }
1029:
1030: /*
1031: * If the call fails for whatever reason, we still need to build a
1032: * skeleton LCD in order to be able to properly receive the CLEAR
1033: * CONFIRMATION.
1034: */
1035: #ifdef WATERLOO /* be explicit */
1036: if (l == 0 && bcmp (sa -> x25_udata, "ean", 3) == 0)
1037: pk_message (lcn, pkp -> pk_xcp, "host=%s ean%c: %s",
1038: sa -> x25_addr, sa -> x25_udata[3] & 0xff, errstr);
1039: else if (l == 0 && bcmp (sa -> x25_udata, "\1\0\0\0", 4) == 0)
1040: pk_message (lcn, pkp -> pk_xcp, "host=%s x29d: %s",
1041: sa -> x25_addr, errstr);
1042: else
1043: #endif
1044: pk_message (lcn, pkp -> pk_xcp, "host=%s pid=%x %x %x %x: %s",
1045: sa -> x25_addr, sa -> x25_udata[0] & 0xff,
1046: sa -> x25_udata[1] & 0xff, sa -> x25_udata[2] & 0xff,
1047: sa -> x25_udata[3] & 0xff, errstr);
1048: if ((lcp = pk_attach ((struct socket *)0)) == 0) {
1049: (void) m_free (m);
1050: return;
1051: }
1052: lcp -> lcd_lcn = lcn;
1053: lcp -> lcd_state = RECEIVED_CALL;
1054: pk_assoc (pkp, lcp, sa);
1055: (void) m_free (m);
1056: pk_clear (lcp, 0, 1);
1057: }
1058:
1059: pk_call_accepted (lcp, m)
1060: struct pklcd *lcp;
1061: struct mbuf *m;
1062: {
1063: register struct x25_calladdr *ap;
1064: register octet *fcp;
1065: struct x25_packet *xp = mtod (m, struct x25_packet *);
1066: int len = m -> m_len;
1067:
1068: lcp -> lcd_state = DATA_TRANSFER;
1069: if (lcp -> lcd_so)
1070: soisconnected (lcp -> lcd_so);
1071: if ((lcp -> lcd_flags & X25_DBIT) && (X25GBITS(xp -> bits, d_bit) == 0))
1072: lcp -> lcd_flags &= ~X25_DBIT;
1073: if (len > 3) {
1074: ap = (struct x25_calladdr *) &xp -> packet_data;
1075: fcp = (octet *) ap -> address_field + (X25GBITS(ap -> addrlens, calling_addrlen) +
1076: X25GBITS(ap -> addrlens, called_addrlen) + 1) / 2;
1077: if (fcp + *fcp <= ((octet *) xp) + len)
1078: pk_parse_facilities (fcp, lcp -> lcd_ceaddr);
1079: }
1080: pk_assoc (lcp -> lcd_pkp, lcp, lcp -> lcd_ceaddr);
1081: if (lcp -> lcd_so == 0 && lcp -> lcd_upper)
1082: lcp -> lcd_upper (lcp, m);
1083: }
1084:
1085: pk_parse_facilities (fcp, sa)
1086: register octet *fcp;
1087: register struct sockaddr_x25 *sa;
1088: {
1089: register octet *maxfcp;
1090:
1091: maxfcp = fcp + *fcp;
1092: fcp++;
1093: while (fcp < maxfcp) {
1094: /*
1095: * Ignore national DCE or DTE facilities
1096: */
1097: if (*fcp == 0 || *fcp == 0xff)
1098: break;
1099: switch (*fcp) {
1100: case FACILITIES_WINDOWSIZE:
1101: sa -> x25_opts.op_wsize = fcp[1];
1102: fcp += 3;
1103: break;
1104:
1105: case FACILITIES_PACKETSIZE:
1106: sa -> x25_opts.op_psize = fcp[1];
1107: fcp += 3;
1108: break;
1109:
1110: case FACILITIES_THROUGHPUT:
1111: sa -> x25_opts.op_speed = fcp[1];
1112: fcp += 2;
1113: break;
1114:
1115: case FACILITIES_REVERSE_CHARGE:
1116: if (fcp[1] & 01)
1117: sa -> x25_opts.op_flags |= X25_REVERSE_CHARGE;
1118: /*
1119: * Datapac specific: for a X.25(1976) DTE, bit 2
1120: * indicates a "hi priority" (eg. international) call.
1121: */
1122: if (fcp[1] & 02 && sa -> x25_opts.op_psize == 0)
1123: sa -> x25_opts.op_psize = X25_PS128;
1124: fcp += 2;
1125: break;
1126:
1127: default:
1128: /*printf("unknown facility %x, class=%d\n", *fcp, (*fcp & 0xc0) >> 6);*/
1129: switch ((*fcp & 0xc0) >> 6) {
1130: case 0: /* class A */
1131: fcp += 2;
1132: break;
1133:
1134: case 1:
1135: fcp += 3;
1136: break;
1137:
1138: case 2:
1139: fcp += 4;
1140: break;
1141:
1142: case 3:
1143: fcp++;
1144: fcp += *fcp;
1145: }
1146: }
1147: }
1148: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.