1 /* $NetBSD: pk_subr.c,v 1.29 2005/02/26 22:45:10 perry 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.29 2005/02/26 22:45:10 perry 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|M_ZERO);
142 if (lcp) {
143 insque(&lcp->lcd_q, &pklcd_q);
144 lcp->lcd_state = READY;
145 lcp->lcd_send = pk_output;
146 if (so) {
147 error = soreserve(so, pk_sendspace, pk_recvspace);
148 lcp->lcd_so = so;
149 if (so->so_options & SO_ACCEPTCONN)
150 lcp->lcd_state = LISTEN;
151 } else
152 sbreserve(&lcp->lcd_sb, pk_sendspace, so);
153 }
154 if (so) {
155 so->so_pcb = lcp;
156 so->so_error = error;
157 }
158 return (lcp);
159 }
160
161 /*
162 * Disconnect X.25 protocol from socket.
163 */
164 void
165 pk_disconnect(lcp)
166 struct pklcd *lcp;
167 {
168 struct socket *so = lcp->lcd_so;
169
170 switch (lcp->lcd_state) {
171 case LISTEN:
172 TAILQ_REMOVE(&pk_listenhead, lcp, lcd_listen);
173 pk_close(lcp);
174 break;
175
176 case READY:
177 pk_acct(lcp);
178 pk_close(lcp);
179 break;
180
181 case SENT_CLEAR:
182 case RECEIVED_CLEAR:
183 break;
184
185 default:
186 pk_acct(lcp);
187 if (so) {
188 soisdisconnecting(so);
189 sbflush(&so->so_rcv);
190 }
191 pk_clear(lcp, 241, 0); /* Normal Disconnect */
192
193 }
194 }
195
196 /*
197 * Close an X.25 Logical Channel. Discard all space held by the connection
198 * and internal descriptors. Wake up any sleepers.
199 */
200
201 void
202 pk_close(lcp)
203 struct pklcd *lcp;
204 {
205 struct socket *so = lcp->lcd_so;
206
207 /*
208 * If the X.25 connection is torn down due to link
209 * level failure (e.g. LLC2 FRMR) and at the same the user
210 * level is still filling up the socket send buffer that
211 * send buffer is locked. An attempt to sbflush () that send
212 * buffer will lead us into - no, not temptation but - panic!
213 * So - we'll just check wether the send buffer is locked
214 * and if that's the case we'll mark the lcp as zombie and
215 * have the pk_timer () do the cleaning ...
216 */
217
218 if (so && so->so_snd.sb_flags & SB_LOCK)
219 lcp->lcd_state = LCN_ZOMBIE;
220 else
221 pk_freelcd(lcp);
222
223 if (so == NULL)
224 return;
225
226 so->so_pcb = 0;
227 soisdisconnected(so);
228 #if 0
229 sofree (so); /* gak!!! you can't do that here */
230 #endif
231 }
232
233 /*
234 * Create a template to be used to send X.25 packets on a logical channel. It
235 * allocates an mbuf and fills in a skeletal packet depending on its type.
236 * This packet is passed to pk_output where the remainer of the packet is
237 * filled in.
238 */
239
240 struct mbuf *
241 pk_template(lcn, type)
242 int lcn, type;
243 {
244 struct mbuf *m;
245 struct x25_packet *xp;
246
247 MGETHDR(m, M_DONTWAIT, MT_HEADER);
248 if (m == 0)
249 panic("pk_template");
250 m->m_nextpkt = 0;
251
252 /*
253 * Efficiency hack: leave a four byte gap at the beginning
254 * of the packet level header with the hope that this will
255 * be enough room for the link level to insert its header.
256 */
257 m->m_data += max_linkhdr;
258 m->m_pkthdr.len = m->m_len = PKHEADERLN;
259
260 xp = mtod(m, struct x25_packet *);
261 *(long *) xp = 0; /* ugly, but fast */
262 /* xp->q_bit = 0; */
263 X25SBITS(xp->bits, fmt_identifier, 1);
264 /* xp->lc_group_number = 0; */
265
266 SET_LCN(xp, lcn);
267 xp->packet_type = type;
268
269 return (m);
270 }
271
272 /*
273 * This routine restarts all the virtual circuits. Actually, the virtual
274 * circuits are not "restarted" as such. Instead, any active switched circuit
275 * is simply returned to READY state.
276 */
277
278 void
279 pk_restart(pkp, restart_cause)
280 struct pkcb *pkp;
281 int restart_cause;
282 {
283 struct mbuf *m;
284 struct pklcd *lcp;
285 int i;
286
287 /* Restart all logical channels. */
288 if (pkp->pk_chan == 0)
289 return;
290
291 /*
292 * Don't do this if we're doing a restart issued from
293 * inside pk_connect () --- which is only done if and
294 * only if the X.25 link is down, i.e. a RESTART needs
295 * to be done to get it up.
296 */
297 if (!(pkp->pk_dxerole & DTE_CONNECTPENDING)) {
298 for (i = 1; i <= pkp->pk_maxlcn; ++i)
299 if ((lcp = pkp->pk_chan[i]) != NULL) {
300 if (lcp->lcd_so) {
301 lcp->lcd_so->so_error = ENETRESET;
302 pk_close(lcp);
303 } else {
304 pk_flush(lcp);
305 lcp->lcd_state = READY;
306 if (lcp->lcd_upper)
307 (*lcp->lcd_upper)(NULL, lcp);
308 }
309 }
310 }
311 if (restart_cause < 0)
312 return;
313
314 pkp->pk_state = DTE_SENT_RESTART;
315 pkp->pk_dxerole &= ~(DTE_PLAYDCE | DTE_PLAYDTE);
316 lcp = pkp->pk_chan[0];
317 m = lcp->lcd_template = pk_template(lcp->lcd_lcn, X25_RESTART);
318 m->m_pkthdr.len = m->m_len += 2;
319 mtod(m, struct x25_packet *)->packet_data = 0; /* DTE only */
320 mtod(m, octet *)[4] = restart_cause;
321 pk_output(lcp);
322 }
323
324
325 /*
326 * This procedure frees up the Logical Channel Descripter.
327 */
328
329 void
330 pk_freelcd(lcp)
331 struct pklcd *lcp;
332 {
333 if (lcp == NULL)
334 return;
335
336 if (lcp->lcd_lcn > 0)
337 lcp->lcd_pkp->pk_chan[lcp->lcd_lcn] = NULL;
338
339 pk_flush(lcp);
340 remque(&lcp->lcd_q);
341 free((caddr_t) lcp, M_PCB);
342 }
343
344 static struct x25_ifaddr *
345 pk_ifwithaddr(sx)
346 struct sockaddr_x25 *sx;
347 {
348 struct ifnet *ifp;
349 struct ifaddr *ifa;
350 struct x25_ifaddr *ia;
351 char *addr = sx->x25_addr;
352
353 for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
354 for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
355 ifa = ifa->ifa_list.tqe_next)
356 if (ifa->ifa_addr->sa_family == AF_CCITT) {
357 ia = (struct x25_ifaddr *) ifa;
358 if (bcmp(addr, ia->ia_xc.xc_addr.x25_addr,
359 16) == 0)
360 return (ia);
361
362 }
363 return ((struct x25_ifaddr *) 0);
364 }
365
366
367 /*
368 * Bind a address and protocol value to a socket. The important part is the
369 * protocol value - the first four characters of the Call User Data field.
370 */
371
372 #define XTRACTPKP(rt) ((rt)->rt_flags & RTF_GATEWAY ? \
373 ((rt)->rt_llinfo ? \
374 (struct pkcb *) ((struct rtentry *)((rt)->rt_llinfo))->rt_llinfo : \
375 (struct pkcb *) NULL) : \
376 (struct pkcb *)((rt)->rt_llinfo))
377
378 int
379 pk_bind(lcp, nam)
380 struct pklcd *lcp;
381 struct mbuf *nam;
382 {
383 struct pklcd *pp;
384 struct sockaddr_x25 *sa;
385
386 if (nam == NULL)
387 return (EADDRNOTAVAIL);
388 if (lcp->lcd_ceaddr) /* XXX */
389 return (EADDRINUSE);
390 if (pk_checksockaddr(nam))
391 return (EINVAL);
392 sa = mtod(nam, struct sockaddr_x25 *);
393
394 /*
395 * If the user wishes to accept calls only from a particular
396 * net (net != 0), make sure the net is known
397 */
398
399 if (sa->x25_addr[0]) {
400 if (!pk_ifwithaddr(sa))
401 return (ENETUNREACH);
402 } else if (sa->x25_net) {
403 if (!ifa_ifwithnet((struct sockaddr *) sa))
404 return (ENETUNREACH);
405 }
406 /*
407 * For ISO's sake permit default listeners, but only one such . . .
408 */
409 for (pp = pk_listenhead.tqh_first; pp; pp = pp->lcd_listen.tqe_next) {
410 struct sockaddr_x25 *sa2 = pp->lcd_ceaddr;
411 if ((sa2->x25_udlen == sa->x25_udlen) &&
412 (sa2->x25_udlen == 0 ||
413 (bcmp(sa2->x25_udata, sa->x25_udata,
414 min(sa2->x25_udlen, sa->x25_udlen)) == 0)))
415 return (EADDRINUSE);
416 }
417 lcp->lcd_laddr = *sa;
418 lcp->lcd_ceaddr = &lcp->lcd_laddr;
419 return (0);
420 }
421
422 /*
423 * Include a bound control block in the list of listeners.
424 */
425 int
426 pk_listen(lcp)
427 struct pklcd *lcp;
428 {
429 if (lcp->lcd_ceaddr == 0)
430 return (EDESTADDRREQ);
431
432 lcp->lcd_state = LISTEN;
433 /*
434 * Add default listener at end, any others at start.
435 */
436 if (lcp->lcd_ceaddr->x25_udlen == 0) {
437 TAILQ_INSERT_TAIL(&pk_listenhead, lcp, lcd_listen);
438 } else {
439 TAILQ_INSERT_HEAD(&pk_listenhead, lcp, lcd_listen);
440 }
441 return (0);
442 }
443
444 /*
445 * Include a listening control block for the benefit of other protocols.
446 */
447 int
448 pk_protolisten(spi, spilen, callee)
449 int spi;
450 int spilen;
451 int (*callee) __P((struct mbuf *, void *));
452 {
453 struct pklcd *lcp = pk_attach((struct socket *) 0);
454 struct mbuf *nam;
455 struct sockaddr_x25 *sa;
456 int error = ENOBUFS;
457
458 if (lcp) {
459 if ((nam = m_getclr(M_DONTWAIT, MT_SONAME)) != NULL) {
460 sa = mtod(nam, struct sockaddr_x25 *);
461 sa->x25_family = AF_CCITT;
462 sa->x25_len = nam->m_len = sizeof(*sa);
463 sa->x25_udlen = spilen;
464 sa->x25_udata[0] = spi;
465 lcp->lcd_upper = callee;
466 lcp->lcd_flags = X25_MBS_HOLD;
467 if ((error = pk_bind(lcp, nam)) == 0)
468 error = pk_listen(lcp);
469 (void) m_free(nam);
470 }
471 if (error)
472 pk_freelcd(lcp);
473 }
474 return error; /* Hopefully Zero ! */
475 }
476
477 /*
478 * Associate a logical channel descriptor with a network.
479 * Fill in the default network specific parameters and then
480 * set any parameters explicitly specified by the user or
481 * by the remote DTE.
482 */
483
484 void
485 pk_assoc(pkp, lcp, sa)
486 struct pkcb *pkp;
487 struct pklcd *lcp;
488 struct sockaddr_x25 *sa;
489 {
490
491 lcp->lcd_pkp = pkp;
492 lcp->lcd_packetsize = pkp->pk_xcp->xc_psize;
493 lcp->lcd_windowsize = pkp->pk_xcp->xc_pwsize;
494 lcp->lcd_rsn = MODULUS - 1;
495 pkp->pk_chan[lcp->lcd_lcn] = lcp;
496
497 if (sa->x25_opts.op_psize)
498 lcp->lcd_packetsize = sa->x25_opts.op_psize;
499 else
500 sa->x25_opts.op_psize = lcp->lcd_packetsize;
501 if (sa->x25_opts.op_wsize)
502 lcp->lcd_windowsize = sa->x25_opts.op_wsize;
503 else
504 sa->x25_opts.op_wsize = lcp->lcd_windowsize;
505 sa->x25_net = pkp->pk_xcp->xc_addr.x25_net;
506 lcp->lcd_flags |= sa->x25_opts.op_flags;
507 lcp->lcd_stime = time.tv_sec;
508 }
509
510 int
511 pk_connect(lcp, sa)
512 struct pklcd *lcp;
513 struct sockaddr_x25 *sa;
514 {
515 struct pkcb *pkp;
516 struct rtentry *rt;
517 struct rtentry *nrt;
518
519 if (sa->x25_addr[0] == '\0')
520 return (EDESTADDRREQ);
521
522 /*
523 * Is the destination address known?
524 */
525 if (!(rt = rtalloc1((struct sockaddr *) sa, 1)))
526 return (ENETUNREACH);
527
528 if (!(pkp = XTRACTPKP(rt)))
529 pkp = pk_newlink((struct x25_ifaddr *) (rt->rt_ifa),
530 (caddr_t) 0);
531
532 /*
533 * Have we entered the LLC address?
534 */
535 if ((nrt = npaidb_enter((struct sockaddr_dl *) rt->rt_gateway,
536 rt_key(rt), rt, 0)) != NULL)
537 pkp->pk_llrt = nrt;
538
539 /*
540 * Have we allocated an LLC2 link yet?
541 */
542 if (pkp->pk_llnext == (caddr_t) 0 && pkp->pk_llctlinput) {
543 struct dll_ctlinfo ctlinfo;
544
545 ctlinfo.dlcti_rt = rt;
546 ctlinfo.dlcti_pcb = (caddr_t) pkp;
547 ctlinfo.dlcti_conf =
548 (struct dllconfig *) (&((struct x25_ifaddr *) (rt->rt_ifa))->ia_xc);
549 pkp->pk_llnext =
550 (*pkp->pk_llctlinput)(PRC_CONNECT_REQUEST,
551 NULL, &ctlinfo);
552 }
553 if (pkp->pk_state != DTE_READY && pkp->pk_state != DTE_WAITING)
554 return (ENETDOWN);
555 if ((lcp->lcd_lcn = pk_getlcn(pkp)) == 0)
556 return (EMFILE);
557
558 lcp->lcd_faddr = *sa;
559 lcp->lcd_ceaddr = &lcp->lcd_faddr;
560 pk_assoc(pkp, lcp, lcp->lcd_ceaddr);
561
562 /*
563 * If the link is not up yet, initiate an X.25 RESTART
564 */
565 if (pkp->pk_state == DTE_WAITING) {
566 pkp->pk_dxerole |= DTE_CONNECTPENDING;
567 pk_ctlinput(PRC_LINKUP, NULL, pkp);
568 if (lcp->lcd_so)
569 soisconnecting(lcp->lcd_so);
570 return 0;
571 }
572 if (lcp->lcd_so)
573 soisconnecting(lcp->lcd_so);
574 lcp->lcd_template = pk_template(lcp->lcd_lcn, X25_CALL);
575 pk_callrequest(lcp, lcp->lcd_ceaddr, pkp->pk_xcp);
576 return (*pkp->pk_ia->ia_start) (lcp);
577 }
578
579 /*
580 * Complete all pending X.25 call requests --- this gets called after
581 * the X.25 link has been restarted.
582 */
583 #define RESHUFFLELCN(maxlcn, lcn) ((maxlcn) - (lcn) + 1)
584
585 void
586 pk_callcomplete(pkp)
587 struct pkcb *pkp;
588 {
589 struct pklcd *lcp;
590 int i;
591 int ni;
592
593
594 if (pkp->pk_dxerole & DTE_CONNECTPENDING)
595 pkp->pk_dxerole &= ~DTE_CONNECTPENDING;
596 else
597 return;
598
599 if (pkp->pk_chan == 0)
600 return;
601
602 /*
603 * We pretended to be a DTE for allocating lcns, if
604 * it turns out that we are in reality performing as a
605 * DCE we need to reshuffle the lcps.
606 *
607 * /+---------------+-------- -
608 * / | a (maxlcn-1) | \
609 * / +---------------+ \
610 * +--- * | b (maxlcn-2) | \
611 * | \ +---------------+ \
612 * r | \ | c (maxlcn-3) | \
613 * e | \+---------------+ |
614 * s | | . |
615 * h | | . | m
616 * u | | . | a
617 * f | | . | x
618 * f | | . | l
619 * l | /+---------------+ | c
620 * e | / | c' ( 3 ) | | n
621 * | / +---------------+ |
622 * +--> * | b' ( 2 ) | /
623 * \ +---------------+ /
624 * \ | a' ( 1 ) | /
625 * \+---------------+ /
626 * | 0 | /
627 * +---------------+-------- -
628 *
629 */
630 if (pkp->pk_dxerole & DTE_PLAYDCE) {
631 /* Sigh, reshuffle it */
632 for (i = pkp->pk_maxlcn; i > 0; --i)
633 if (pkp->pk_chan[i]) {
634 ni = RESHUFFLELCN(pkp->pk_maxlcn, i);
635 pkp->pk_chan[ni] = pkp->pk_chan[i];
636 pkp->pk_chan[i] = NULL;
637 pkp->pk_chan[ni]->lcd_lcn = ni;
638 }
639 }
640 for (i = 1; i <= pkp->pk_maxlcn; ++i)
641 if ((lcp = pkp->pk_chan[i]) != NULL) {
642 /*
643 * if (lcp->lcd_so) soisconnecting (lcp->lcd_so);
644 */
645 lcp->lcd_template = pk_template(lcp->lcd_lcn, X25_CALL);
646 pk_callrequest(lcp, lcp->lcd_ceaddr, pkp->pk_xcp);
647 (*pkp->pk_ia->ia_start) (lcp);
648 }
649 }
650
651 struct bcdinfo {
652 octet *cp;
653 unsigned posn;
654 };
655
656 /*
657 * Build the rest of the CALL REQUEST packet. Fill in calling address,
658 * facilities fields and the user data field.
659 */
660
661 void
662 pk_callrequest(lcp, sa, xcp)
663 struct pklcd *lcp;
664 struct sockaddr_x25 *sa;
665 struct x25config *xcp;
666 {
667 struct x25_calladdr *a;
668 struct mbuf *m = lcp->lcd_template;
669 struct x25_packet *xp = mtod(m, struct x25_packet *);
670 struct bcdinfo b;
671
672 if (lcp->lcd_flags & X25_DBIT)
673 X25SBITS(xp->bits, d_bit, 1);
674 a = (struct x25_calladdr *) & xp->packet_data;
675 b.cp = (octet *) a->address_field;
676 b.posn = 0;
677 X25SBITS(a->addrlens, called_addrlen, to_bcd(&b, sa, xcp));
678 X25SBITS(a->addrlens, calling_addrlen, to_bcd(&b, &xcp->xc_addr, xcp));
679 if (b.posn & 0x01)
680 *b.cp++ &= 0xf0;
681 m->m_pkthdr.len = m->m_len += b.cp - (octet *) a;
682
683 if (lcp->lcd_facilities) {
684 m->m_pkthdr.len +=
685 (m->m_next = lcp->lcd_facilities)->m_pkthdr.len;
686 lcp->lcd_facilities = 0;
687 } else
688 pk_build_facilities(m, sa, (int) xcp->xc_type);
689
690 m_copyback(m, m->m_pkthdr.len, sa->x25_udlen, sa->x25_udata);
691 }
692
693 void
694 pk_build_facilities(m, sa, type)
695 struct mbuf *m;
696 struct sockaddr_x25 *sa;
697 int type;
698 {
699 octet *cp;
700 octet *fcp;
701 int revcharge;
702
703 cp = mtod(m, octet *) + m->m_len;
704 fcp = cp + 1;
705 revcharge = sa->x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0;
706 /*
707 * This is specific to Datapac X.25(1976) DTEs. International
708 * calls must have the "hi priority" bit on.
709 */
710 if (type == X25_1976 && sa->x25_opts.op_psize == X25_PS128)
711 revcharge |= 02;
712 if (revcharge) {
713 *fcp++ = FACILITIES_REVERSE_CHARGE;
714 *fcp++ = revcharge;
715 }
716 switch (type) {
717 case X25_1980:
718 case X25_1984:
719 *fcp++ = FACILITIES_PACKETSIZE;
720 *fcp++ = sa->x25_opts.op_psize;
721 *fcp++ = sa->x25_opts.op_psize;
722
723 *fcp++ = FACILITIES_WINDOWSIZE;
724 *fcp++ = sa->x25_opts.op_wsize;
725 *fcp++ = sa->x25_opts.op_wsize;
726 }
727 *cp = fcp - cp - 1;
728 m->m_pkthdr.len = (m->m_len += *cp + 1);
729 }
730
731 int
732 to_bcd(b, sa, xcp)
733 struct bcdinfo *b;
734 struct sockaddr_x25 *sa;
735 struct x25config *xcp;
736 {
737 char *x = sa->x25_addr;
738 unsigned start = b->posn;
739 /*
740 * The nodnic and prepnd0 stuff looks tedious,
741 * but it does allow full X.121 addresses to be used,
742 * which is handy for routing info (& OSI type 37 addresses).
743 */
744 if (xcp->xc_addr.x25_net && (xcp->xc_nodnic || xcp->xc_prepnd0)) {
745 char dnicname[sizeof(long) * NBBY / 3 + 2];
746 char *p = dnicname;
747
748 snprintf(p, sizeof(dnicname), "%d",
749 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 pk_message(int lcn, struct x25config * xcp, char * fmt,...)
1171 {
1172 va_list ap;
1173
1174 if (lcn)
1175 if (!PQEMPTY)
1176 printf("X.25(%s): lcn %d: ", format_ntn(xcp), lcn);
1177 else
1178 printf("X.25: lcn %d: ", lcn);
1179 else if (!PQEMPTY)
1180 printf("X.25(%s): ", format_ntn(xcp));
1181 else
1182 printf("X.25: ");
1183
1184 va_start(ap, fmt);
1185 vprintf(fmt, ap);
1186 printf("\n");
1187 va_end(ap);
1188 }
1189
1190 int
1191 pk_fragment(lcp, m0, qbit, mbit, wait)
1192 struct mbuf *m0;
1193 struct pklcd *lcp;
1194 int qbit, mbit, wait;
1195 {
1196 struct mbuf *m = m0;
1197 struct x25_packet *xp;
1198 struct sockbuf *sb;
1199 struct mbuf *head = 0, *next, **mp = &head;
1200 int totlen, psize = 1 << (lcp->lcd_packetsize);
1201
1202 if (m == 0)
1203 return 0;
1204 if ((m->m_flags & M_PKTHDR) == 0)
1205 panic("pk_fragment");
1206 totlen = m->m_pkthdr.len;
1207 m->m_nextpkt = 0;
1208 sb = lcp->lcd_so ? &lcp->lcd_so->so_snd : &lcp->lcd_sb;
1209 do {
1210 if (totlen > psize) {
1211 if ((next = m_split(m, psize, wait)) == 0)
1212 goto abort;
1213 totlen -= psize;
1214 } else
1215 next = 0;
1216 M_PREPEND(m, PKHEADERLN, wait);
1217 if (m == 0)
1218 goto abort;
1219 *mp = m;
1220 mp = &m->m_nextpkt;
1221 *mp = 0;
1222 xp = mtod(m, struct x25_packet *);
1223 0[(char *) xp] = 0;
1224 if (qbit)
1225 X25SBITS(xp->bits, q_bit, 1);
1226 if (lcp->lcd_flags & X25_DBIT)
1227 X25SBITS(xp->bits, d_bit, 1);
1228 X25SBITS(xp->bits, fmt_identifier, 1);
1229 xp->packet_type = X25_DATA;
1230 SET_LCN(xp, lcp->lcd_lcn);
1231 if (next || (mbit && (totlen == psize ||
1232 (lcp->lcd_flags & X25_DBIT))))
1233 SMBIT(xp, 1);
1234 } while ((m = next) != NULL);
1235 for (m = head; m; m = next) {
1236 next = m->m_nextpkt;
1237 m->m_nextpkt = 0;
1238 sbappendrecord(sb, m);
1239 }
1240 return 0;
1241 abort:
1242 if (wait)
1243 panic("pk_fragment null mbuf after wait");
1244 if (next)
1245 m_freem(next);
1246 for (m = head; m; m = next) {
1247 next = m->m_nextpkt;
1248 m_freem(m);
1249 }
1250 return ENOBUFS;
1251 }
Cache object: 8a91576b185c090d7424307b8a26e770
|