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