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