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