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