FreeBSD/Linux Kernel Cross Reference
sys/netatm/atm_aal5.c
1 /*
2 *
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
6 *
7 *
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
12 *
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
20 *
21 * Copyright 1994-1998 Network Computing Services, Inc.
22 *
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
25 *
26 * @(#) $FreeBSD$
27 *
28 */
29
30 /*
31 * Core ATM Services
32 * -----------------
33 *
34 * ATM AAL5 socket protocol processing
35 *
36 */
37
38 #include <netatm/kern_include.h>
39 #include <sys/stat.h>
40
41 #ifndef lint
42 __RCSID("@(#) $FreeBSD$");
43 #endif
44
45
46 /*
47 * Global variables
48 */
49 u_long atm_aal5_sendspace = 64 * 1024; /* XXX */
50 u_long atm_aal5_recvspace = 64 * 1024; /* XXX */
51
52
53 /*
54 * Local functions
55 */
56 static int atm_aal5_attach __P((struct socket *, int, struct proc *));
57 static int atm_aal5_detach __P((struct socket *));
58 static int atm_aal5_bind __P((struct socket *, struct sockaddr *,
59 struct proc *));
60 static int atm_aal5_listen __P((struct socket *, struct proc *));
61 static int atm_aal5_connect __P((struct socket *, struct sockaddr *,
62 struct proc *));
63 static int atm_aal5_accept __P((struct socket *, struct sockaddr **));
64 static int atm_aal5_disconnect __P((struct socket *));
65 static int atm_aal5_shutdown __P((struct socket *));
66 static int atm_aal5_send __P((struct socket *, int, KBuffer *,
67 struct sockaddr *, KBuffer *, struct proc *));
68 static int atm_aal5_abort __P((struct socket *));
69 static int atm_aal5_control __P((struct socket *, u_long, caddr_t,
70 struct ifnet *, struct proc *));
71 static int atm_aal5_sense __P((struct socket *, struct stat *));
72 static int atm_aal5_sockaddr __P((struct socket *, struct sockaddr **));
73 static int atm_aal5_peeraddr __P((struct socket *, struct sockaddr **));
74 static int atm_aal5_incoming __P((void *, Atm_connection *,
75 Atm_attributes *, void **));
76 static void atm_aal5_cpcs_data __P((void *, KBuffer *));
77 static caddr_t atm_aal5_getname __P((void *));
78
79
80 #if (defined(__FreeBSD__) && (BSD >= 199506))
81 /*
82 * New-style socket request routines
83 */
84 struct pr_usrreqs atm_aal5_usrreqs = {
85 atm_aal5_abort, /* pru_abort */
86 atm_aal5_accept, /* pru_accept */
87 atm_aal5_attach, /* pru_attach */
88 atm_aal5_bind, /* pru_bind */
89 atm_aal5_connect, /* pru_connect */
90 pru_connect2_notsupp, /* pru_connect2 */
91 atm_aal5_control, /* pru_control */
92 atm_aal5_detach, /* pru_detach */
93 atm_aal5_disconnect, /* pru_disconnect */
94 atm_aal5_listen, /* pru_listen */
95 atm_aal5_peeraddr, /* pru_peeraddr */
96 pru_rcvd_notsupp, /* pru_rcvd */
97 pru_rcvoob_notsupp, /* pru_rcvoob */
98 atm_aal5_send, /* pru_send */
99 atm_aal5_sense, /* pru_sense */
100 atm_aal5_shutdown, /* pru_shutdown */
101 atm_aal5_sockaddr, /* pru_sockaddr */
102 sosend, /* pru_sosend */
103 soreceive, /* pru_soreceive */
104 sopoll /* pru_sopoll */
105 };
106 #endif
107
108
109 /*
110 * Local variables
111 */
112 static Atm_endpoint atm_aal5_endpt = {
113 NULL,
114 ENDPT_SOCK_AAL5,
115 NULL,
116 atm_aal5_getname,
117 atm_sock_connected,
118 atm_sock_cleared,
119 atm_aal5_incoming,
120 NULL,
121 NULL,
122 NULL,
123 atm_aal5_cpcs_data,
124 NULL,
125 NULL,
126 NULL,
127 NULL
128 };
129
130 static Atm_attributes atm_aal5_defattr = {
131 NULL, /* nif */
132 CMAPI_CPCS, /* api */
133 0, /* api_init */
134 0, /* headin */
135 0, /* headout */
136 { /* aal */
137 T_ATM_PRESENT,
138 ATM_AAL5
139 },
140 { /* traffic */
141 T_ATM_ABSENT,
142 },
143 { /* bearer */
144 T_ATM_ABSENT,
145 },
146 { /* bhli */
147 T_ATM_ABSENT
148 },
149 { /* blli */
150 T_ATM_ABSENT,
151 T_ATM_ABSENT,
152 },
153 { /* llc */
154 T_ATM_ABSENT,
155 },
156 { /* called */
157 T_ATM_ABSENT,
158 {
159 T_ATM_ABSENT,
160 0
161 },
162 {
163 T_ATM_ABSENT,
164 0
165 }
166 },
167 { /* calling */
168 T_ATM_ABSENT
169 },
170 { /* qos */
171 T_ATM_ABSENT,
172 },
173 { /* transit */
174 T_ATM_ABSENT
175 },
176 { /* cause */
177 T_ATM_ABSENT
178 }
179 };
180
181
182 /*
183 * Handy common code macros
184 */
185 #ifdef DIAGNOSTIC
186 #define ATM_INTRO(f) \
187 int s, err = 0; \
188 s = splnet(); \
189 ATM_DEBUG2("aal5 socket %s (%p)\n", f, so); \
190 /* \
191 * Stack queue should have been drained \
192 */ \
193 if (atm_stackq_head != NULL) \
194 panic("atm_aal5: stack queue not empty"); \
195 ;
196 #else /* !DIAGNOSTIC */
197 #define ATM_INTRO(f) \
198 int s, err = 0; \
199 s = splnet(); \
200 ;
201 #endif /* DIAGNOSTIC */
202
203 #define ATM_OUTRO() \
204 /* \
205 * Drain any deferred calls \
206 */ \
207 STACK_DRAIN(); \
208 (void) splx(s); \
209 return (err); \
210 ;
211
212 #define ATM_RETERR(errno) { \
213 err = errno; \
214 goto out; \
215 }
216
217
218 /*
219 * Attach protocol to socket
220 *
221 * Arguments:
222 * so pointer to socket
223 * proto protocol identifier
224 * p pointer to process
225 *
226 * Returns:
227 * 0 request processed
228 * errno error processing request - reason indicated
229 *
230 */
231 static int
232 atm_aal5_attach(so, proto, p)
233 struct socket *so;
234 int proto;
235 struct proc *p;
236 {
237 Atm_pcb *atp;
238
239 ATM_INTRO("attach");
240
241 /*
242 * Do general attach stuff
243 */
244 err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace);
245 if (err)
246 ATM_RETERR(err);
247
248 /*
249 * Finish up any protocol specific stuff
250 */
251 atp = sotoatmpcb(so);
252 atp->atp_type = ATPT_AAL5;
253
254 /*
255 * Set default connection attributes
256 */
257 atp->atp_attr = atm_aal5_defattr;
258 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
259
260 out:
261 ATM_OUTRO();
262 }
263
264
265 /*
266 * Detach protocol from socket
267 *
268 * Arguments:
269 * so pointer to socket
270 *
271 * Returns:
272 * 0 request processed
273 * errno error processing request - reason indicated
274 *
275 */
276 static int
277 atm_aal5_detach(so)
278 struct socket *so;
279 {
280 ATM_INTRO("detach");
281
282 err = atm_sock_detach(so);
283
284 ATM_OUTRO();
285 }
286
287
288 /*
289 * Bind address to socket
290 *
291 * Arguments:
292 * so pointer to socket
293 * addr pointer to protocol address
294 * p pointer to process
295 *
296 * Returns:
297 * 0 request processed
298 * errno error processing request - reason indicated
299 *
300 */
301 static int
302 atm_aal5_bind(so, addr, p)
303 struct socket *so;
304 struct sockaddr *addr;
305 struct proc *p;
306 {
307 ATM_INTRO("bind");
308
309 err = atm_sock_bind(so, addr);
310
311 ATM_OUTRO();
312 }
313
314
315 /*
316 * Listen for incoming connections
317 *
318 * Arguments:
319 * so pointer to socket
320 * p pointer to process
321 *
322 * Returns:
323 * 0 request processed
324 * errno error processing request - reason indicated
325 *
326 */
327 static int
328 atm_aal5_listen(so, p)
329 struct socket *so;
330 struct proc *p;
331 {
332 ATM_INTRO("listen");
333
334 err = atm_sock_listen(so, &atm_aal5_endpt);
335
336 ATM_OUTRO();
337 }
338
339
340 /*
341 * Connect socket to peer
342 *
343 * Arguments:
344 * so pointer to socket
345 * addr pointer to protocol address
346 * p pointer to process
347 *
348 * Returns:
349 * 0 request processed
350 * errno error processing request - reason indicated
351 *
352 */
353 static int
354 atm_aal5_connect(so, addr, p)
355 struct socket *so;
356 struct sockaddr *addr;
357 struct proc *p;
358 {
359 Atm_pcb *atp;
360
361 ATM_INTRO("connect");
362
363 atp = sotoatmpcb(so);
364
365 /*
366 * Resize send socket buffer to maximum sdu size
367 */
368 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
369 long size;
370
371 size = atp->atp_attr.aal.v.aal5.forward_max_SDU_size;
372 if (size != T_ATM_ABSENT)
373 (void) sbreserve(&so->so_snd, size);
374 }
375
376 /*
377 * Now get the socket connected
378 */
379 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
380
381 ATM_OUTRO();
382 }
383
384
385 /*
386 * Accept pending connection
387 *
388 * Arguments:
389 * so pointer to socket
390 * addr pointer to pointer to contain protocol address
391 *
392 * Returns:
393 * 0 request processed
394 * errno error processing request - reason indicated
395 *
396 */
397 static int
398 atm_aal5_accept(so, addr)
399 struct socket *so;
400 struct sockaddr **addr;
401 {
402 ATM_INTRO("accept");
403
404 /*
405 * Everything is pretty much done already, we just need to
406 * return the caller's address to the user.
407 */
408 err = atm_sock_peeraddr(so, addr);
409
410 ATM_OUTRO();
411 }
412
413
414 /*
415 * Disconnect connected socket
416 *
417 * Arguments:
418 * so pointer to socket
419 *
420 * Returns:
421 * 0 request processed
422 * errno error processing request - reason indicated
423 *
424 */
425 static int
426 atm_aal5_disconnect(so)
427 struct socket *so;
428 {
429 ATM_INTRO("disconnect");
430
431 err = atm_sock_disconnect(so);
432
433 ATM_OUTRO();
434 }
435
436
437 /*
438 * Shut down socket data transmission
439 *
440 * Arguments:
441 * so pointer to socket
442 *
443 * Returns:
444 * 0 request processed
445 * errno error processing request - reason indicated
446 *
447 */
448 static int
449 atm_aal5_shutdown(so)
450 struct socket *so;
451 {
452 ATM_INTRO("shutdown");
453
454 socantsendmore(so);
455
456 ATM_OUTRO();
457 }
458
459
460 /*
461 * Send user data
462 *
463 * Arguments:
464 * so pointer to socket
465 * flags send data flags
466 * m pointer to buffer containing user data
467 * addr pointer to protocol address
468 * control pointer to buffer containing protocol control data
469 * p pointer to process
470 *
471 * Returns:
472 * 0 request processed
473 * errno error processing request - reason indicated
474 *
475 */
476 static int
477 atm_aal5_send(so, flags, m, addr, control, p)
478 struct socket *so;
479 int flags;
480 KBuffer *m;
481 struct sockaddr *addr;
482 KBuffer *control;
483 struct proc *p;
484 {
485 Atm_pcb *atp;
486
487 ATM_INTRO("send");
488
489 /*
490 * We don't support any control functions
491 */
492 if (control) {
493 int clen;
494
495 clen = KB_LEN(control);
496 KB_FREEALL(control);
497 if (clen) {
498 KB_FREEALL(m);
499 ATM_RETERR(EINVAL);
500 }
501 }
502
503 /*
504 * We also don't support any flags or send-level addressing
505 */
506 if (flags || addr) {
507 KB_FREEALL(m);
508 ATM_RETERR(EINVAL);
509 }
510
511 /*
512 * All we've got left is the data, so push it out
513 */
514 atp = sotoatmpcb(so);
515 err = atm_cm_cpcs_data(atp->atp_conn, m);
516 if (err) {
517 /*
518 * Output problem, drop packet
519 */
520 atm_sock_stat.as_outdrop[atp->atp_type]++;
521 KB_FREEALL(m);
522 }
523
524 out:
525 ATM_OUTRO();
526 }
527
528
529 /*
530 * Abnormally terminate service
531 *
532 * Arguments:
533 * so pointer to socket
534 *
535 * Returns:
536 * 0 request processed
537 * errno error processing request - reason indicated
538 *
539 */
540 static int
541 atm_aal5_abort(so)
542 struct socket *so;
543 {
544 ATM_INTRO("abort");
545
546 so->so_error = ECONNABORTED;
547 err = atm_sock_detach(so);
548
549 ATM_OUTRO();
550 }
551
552
553 /*
554 * Do control operation - ioctl system call
555 *
556 * Arguments:
557 * so pointer to socket
558 * cmd ioctl code
559 * data pointer to code specific parameter data area
560 * ifp pointer to ifnet structure if it's an interface ioctl
561 * p pointer to process
562 *
563 * Returns:
564 * 0 request processed
565 * errno error processing request - reason indicated
566 *
567 */
568 static int
569 atm_aal5_control(so, cmd, data, ifp, p)
570 struct socket *so;
571 u_long cmd;
572 caddr_t data;
573 struct ifnet *ifp;
574 struct proc *p;
575 {
576 ATM_INTRO("control");
577
578 switch (cmd) {
579
580 default:
581 err = EOPNOTSUPP;
582 }
583
584 ATM_OUTRO();
585 }
586
587 /*
588 * Sense socket status - fstat system call
589 *
590 * Arguments:
591 * so pointer to socket
592 * st pointer to file status structure
593 *
594 * Returns:
595 * 0 request processed
596 * errno error processing request - reason indicated
597 *
598 */
599 static int
600 atm_aal5_sense(so, st)
601 struct socket *so;
602 struct stat *st;
603 {
604 ATM_INTRO("sense");
605
606 /*
607 * Just return the max sdu size for the connection
608 */
609 st->st_blksize = so->so_snd.sb_hiwat;
610
611 ATM_OUTRO();
612 }
613
614
615 /*
616 * Retrieve local socket address
617 *
618 * Arguments:
619 * so pointer to socket
620 * addr pointer to pointer to contain protocol address
621 *
622 * Returns:
623 * 0 request processed
624 * errno error processing request - reason indicated
625 *
626 */
627 static int
628 atm_aal5_sockaddr(so, addr)
629 struct socket *so;
630 struct sockaddr **addr;
631 {
632 ATM_INTRO("sockaddr");
633
634 err = atm_sock_sockaddr(so, addr);
635
636 ATM_OUTRO();
637 }
638
639
640 /*
641 * Retrieve peer socket address
642 *
643 * Arguments:
644 * so pointer to socket
645 * addr pointer to pointer to contain protocol address
646 *
647 * Returns:
648 * 0 request processed
649 * errno error processing request - reason indicated
650 *
651 */
652 static int
653 atm_aal5_peeraddr(so, addr)
654 struct socket *so;
655 struct sockaddr **addr;
656 {
657 ATM_INTRO("peeraddr");
658
659 err = atm_sock_peeraddr(so, addr);
660
661 ATM_OUTRO();
662 }
663
664
665 /*
666 * Process Incoming Calls
667 *
668 * This function will receive control when an incoming call has been matched
669 * to one of our registered listen parameter blocks. Assuming the call passes
670 * acceptance criteria and all required resources are available, we will
671 * create a new protocol control block and socket association. We must
672 * then await notification of the final SVC setup results. If any
673 * problems are encountered, we will just tell the connection manager to
674 * reject the call.
675 *
676 * Called at splnet.
677 *
678 * Arguments:
679 * tok owner's matched listening token
680 * cop pointer to incoming call's connection block
681 * ap pointer to incoming call's attributes
682 * tokp pointer to location to store our connection token
683 *
684 * Returns:
685 * 0 call is accepted
686 * errno call rejected - reason indicated
687 *
688 */
689 static int
690 atm_aal5_incoming(tok, cop, ap, tokp)
691 void *tok;
692 Atm_connection *cop;
693 Atm_attributes *ap;
694 void **tokp;
695 {
696 Atm_pcb *atp0 = tok, *atp;
697 struct socket *so;
698 int err = 0;
699
700 /*
701 * Allocate a new socket and pcb for this connection.
702 *
703 * Note that our attach function will be called via sonewconn
704 * and it will allocate and setup most of the pcb.
705 */
706 atm_sock_stat.as_inconn[atp0->atp_type]++;
707 #if (defined(BSD) && (BSD >= 199103))
708 so = sonewconn(atp0->atp_socket, 0);
709 #else
710 so = sonewconn(atp0->atp_socket);
711 #endif
712
713 if (so) {
714 /*
715 * Finish pcb setup and pass pcb back to CM
716 */
717 atp = sotoatmpcb(so);
718 atp->atp_conn = cop;
719 atp->atp_attr = *atp0->atp_conn->co_lattr;
720 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
721 *tokp = atp;
722 } else {
723 err = ECONNABORTED;
724 atm_sock_stat.as_connfail[atp0->atp_type]++;
725 }
726
727 return (err);
728 }
729
730
731 /*
732 * Process Socket VCC Input Data
733 *
734 * Arguments:
735 * tok owner's connection token (atm_pcb)
736 * m pointer to input packet buffer chain
737 *
738 * Returns:
739 * none
740 *
741 */
742 static void
743 atm_aal5_cpcs_data(tok, m)
744 void *tok;
745 KBuffer *m;
746 {
747 Atm_pcb *atp = tok;
748 struct socket *so;
749 int len;
750
751 so = atp->atp_socket;
752
753 KB_PLENGET(m, len);
754
755 /*
756 * Ensure that the socket is able to receive data and
757 * that there's room in the socket buffer
758 */
759 if (((so->so_state & SS_ISCONNECTED) == 0) ||
760 (so->so_state & SS_CANTRCVMORE) ||
761 (len > sbspace(&so->so_rcv))) {
762 atm_sock_stat.as_indrop[atp->atp_type]++;
763 KB_FREEALL(m);
764 return;
765 }
766
767 /*
768 * Queue the data and notify the user
769 */
770 sbappendrecord(&so->so_rcv, m);
771 sorwakeup(so);
772
773 return;
774 }
775
776
777 /*
778 * Process getsockopt/setsockopt system calls
779 *
780 * Arguments:
781 * so pointer to socket
782 * sopt pointer to socket option info
783 *
784 * Returns:
785 * 0 request processed
786 * errno error processing request - reason indicated
787 *
788 */
789 int
790 atm_aal5_ctloutput(so, sopt)
791 struct socket *so;
792 struct sockopt *sopt;
793 {
794 Atm_pcb *atp;
795
796 ATM_INTRO("ctloutput");
797
798 /*
799 * Make sure this is for us
800 */
801 if (sopt->sopt_level != T_ATM_SIGNALING) {
802 ATM_RETERR(EINVAL);
803 }
804 atp = sotoatmpcb(so);
805 if (atp == NULL) {
806 ATM_RETERR(ENOTCONN);
807 }
808
809 switch (sopt->sopt_dir) {
810
811 case SOPT_SET:
812 /*
813 * setsockopt()
814 */
815
816 /*
817 * Validate socket state
818 */
819 switch (sopt->sopt_name) {
820
821 case T_ATM_ADD_LEAF:
822 case T_ATM_DROP_LEAF:
823 if ((so->so_state & SS_ISCONNECTED) == 0) {
824 ATM_RETERR(ENOTCONN);
825 }
826 break;
827
828 case T_ATM_CAUSE:
829 case T_ATM_APP_NAME:
830 break;
831
832 default:
833 if (so->so_state & SS_ISCONNECTED) {
834 ATM_RETERR(EISCONN);
835 }
836 break;
837 }
838
839 /*
840 * Validate and save user-supplied option data
841 */
842 err = atm_sock_setopt(so, sopt, atp);
843
844 break;
845
846 case SOPT_GET:
847 /*
848 * getsockopt()
849 */
850
851 /*
852 * Return option data
853 */
854 err = atm_sock_getopt(so, sopt, atp);
855
856 break;
857 }
858
859 out:
860 ATM_OUTRO();
861 }
862
863
864 /*
865 * Initialize AAL5 Sockets
866 *
867 * Arguments:
868 * none
869 *
870 * Returns:
871 * none
872 *
873 */
874 void
875 atm_aal5_init()
876 {
877 /*
878 * Register our endpoint
879 */
880 if (atm_endpoint_register(&atm_aal5_endpt))
881 panic("atm_aal5_init: register");
882
883 /*
884 * Set default connection attributes
885 */
886 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
887 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
888 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
889 }
890
891
892 /*
893 * Get Connection's Application/Owner Name
894 *
895 * Arguments:
896 * tok owner's connection token (atm_pcb)
897 *
898 * Returns:
899 * addr pointer to string containing our name
900 *
901 */
902 static caddr_t
903 atm_aal5_getname(tok)
904 void *tok;
905 {
906 Atm_pcb *atp = tok;
907
908 return (atp->atp_name);
909 }
910
Cache object: 888977720a3b5c899169d888b8e8e1de
|