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 if (!sbreserve(&so->so_snd, size, so, p)) {
374 err = ENOBUFS;
375 ATM_OUTRO();
376 }
377
378 }
379
380 /*
381 * Now get the socket connected
382 */
383 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
384
385 ATM_OUTRO();
386 }
387
388
389 /*
390 * Accept pending connection
391 *
392 * Arguments:
393 * so pointer to socket
394 * addr pointer to pointer to contain protocol address
395 *
396 * Returns:
397 * 0 request processed
398 * errno error processing request - reason indicated
399 *
400 */
401 static int
402 atm_aal5_accept(so, addr)
403 struct socket *so;
404 struct sockaddr **addr;
405 {
406 ATM_INTRO("accept");
407
408 /*
409 * Everything is pretty much done already, we just need to
410 * return the caller's address to the user.
411 */
412 err = atm_sock_peeraddr(so, addr);
413
414 ATM_OUTRO();
415 }
416
417
418 /*
419 * Disconnect connected socket
420 *
421 * Arguments:
422 * so pointer to socket
423 *
424 * Returns:
425 * 0 request processed
426 * errno error processing request - reason indicated
427 *
428 */
429 static int
430 atm_aal5_disconnect(so)
431 struct socket *so;
432 {
433 ATM_INTRO("disconnect");
434
435 err = atm_sock_disconnect(so);
436
437 ATM_OUTRO();
438 }
439
440
441 /*
442 * Shut down socket data transmission
443 *
444 * Arguments:
445 * so pointer to socket
446 *
447 * Returns:
448 * 0 request processed
449 * errno error processing request - reason indicated
450 *
451 */
452 static int
453 atm_aal5_shutdown(so)
454 struct socket *so;
455 {
456 ATM_INTRO("shutdown");
457
458 socantsendmore(so);
459
460 ATM_OUTRO();
461 }
462
463
464 /*
465 * Send user data
466 *
467 * Arguments:
468 * so pointer to socket
469 * flags send data flags
470 * m pointer to buffer containing user data
471 * addr pointer to protocol address
472 * control pointer to buffer containing protocol control data
473 * p pointer to process
474 *
475 * Returns:
476 * 0 request processed
477 * errno error processing request - reason indicated
478 *
479 */
480 static int
481 atm_aal5_send(so, flags, m, addr, control, p)
482 struct socket *so;
483 int flags;
484 KBuffer *m;
485 struct sockaddr *addr;
486 KBuffer *control;
487 struct proc *p;
488 {
489 Atm_pcb *atp;
490
491 ATM_INTRO("send");
492
493 /*
494 * We don't support any control functions
495 */
496 if (control) {
497 int clen;
498
499 clen = KB_LEN(control);
500 KB_FREEALL(control);
501 if (clen) {
502 KB_FREEALL(m);
503 ATM_RETERR(EINVAL);
504 }
505 }
506
507 /*
508 * We also don't support any flags or send-level addressing
509 */
510 if (flags || addr) {
511 KB_FREEALL(m);
512 ATM_RETERR(EINVAL);
513 }
514
515 /*
516 * All we've got left is the data, so push it out
517 */
518 atp = sotoatmpcb(so);
519 err = atm_cm_cpcs_data(atp->atp_conn, m);
520 if (err) {
521 /*
522 * Output problem, drop packet
523 */
524 atm_sock_stat.as_outdrop[atp->atp_type]++;
525 KB_FREEALL(m);
526 }
527
528 out:
529 ATM_OUTRO();
530 }
531
532
533 /*
534 * Abnormally terminate service
535 *
536 * Arguments:
537 * so pointer to socket
538 *
539 * Returns:
540 * 0 request processed
541 * errno error processing request - reason indicated
542 *
543 */
544 static int
545 atm_aal5_abort(so)
546 struct socket *so;
547 {
548 ATM_INTRO("abort");
549
550 so->so_error = ECONNABORTED;
551 err = atm_sock_detach(so);
552
553 ATM_OUTRO();
554 }
555
556
557 /*
558 * Do control operation - ioctl system call
559 *
560 * Arguments:
561 * so pointer to socket
562 * cmd ioctl code
563 * data pointer to code specific parameter data area
564 * ifp pointer to ifnet structure if it's an interface ioctl
565 * p pointer to process
566 *
567 * Returns:
568 * 0 request processed
569 * errno error processing request - reason indicated
570 *
571 */
572 static int
573 atm_aal5_control(so, cmd, data, ifp, p)
574 struct socket *so;
575 u_long cmd;
576 caddr_t data;
577 struct ifnet *ifp;
578 struct proc *p;
579 {
580 ATM_INTRO("control");
581
582 switch (cmd) {
583
584 default:
585 err = EOPNOTSUPP;
586 }
587
588 ATM_OUTRO();
589 }
590
591 /*
592 * Sense socket status - fstat system call
593 *
594 * Arguments:
595 * so pointer to socket
596 * st pointer to file status structure
597 *
598 * Returns:
599 * 0 request processed
600 * errno error processing request - reason indicated
601 *
602 */
603 static int
604 atm_aal5_sense(so, st)
605 struct socket *so;
606 struct stat *st;
607 {
608 ATM_INTRO("sense");
609
610 /*
611 * Just return the max sdu size for the connection
612 */
613 st->st_blksize = so->so_snd.sb_hiwat;
614
615 ATM_OUTRO();
616 }
617
618
619 /*
620 * Retrieve local socket address
621 *
622 * Arguments:
623 * so pointer to socket
624 * addr pointer to pointer to contain protocol address
625 *
626 * Returns:
627 * 0 request processed
628 * errno error processing request - reason indicated
629 *
630 */
631 static int
632 atm_aal5_sockaddr(so, addr)
633 struct socket *so;
634 struct sockaddr **addr;
635 {
636 ATM_INTRO("sockaddr");
637
638 err = atm_sock_sockaddr(so, addr);
639
640 ATM_OUTRO();
641 }
642
643
644 /*
645 * Retrieve peer socket address
646 *
647 * Arguments:
648 * so pointer to socket
649 * addr pointer to pointer to contain protocol address
650 *
651 * Returns:
652 * 0 request processed
653 * errno error processing request - reason indicated
654 *
655 */
656 static int
657 atm_aal5_peeraddr(so, addr)
658 struct socket *so;
659 struct sockaddr **addr;
660 {
661 ATM_INTRO("peeraddr");
662
663 err = atm_sock_peeraddr(so, addr);
664
665 ATM_OUTRO();
666 }
667
668
669 /*
670 * Process Incoming Calls
671 *
672 * This function will receive control when an incoming call has been matched
673 * to one of our registered listen parameter blocks. Assuming the call passes
674 * acceptance criteria and all required resources are available, we will
675 * create a new protocol control block and socket association. We must
676 * then await notification of the final SVC setup results. If any
677 * problems are encountered, we will just tell the connection manager to
678 * reject the call.
679 *
680 * Called at splnet.
681 *
682 * Arguments:
683 * tok owner's matched listening token
684 * cop pointer to incoming call's connection block
685 * ap pointer to incoming call's attributes
686 * tokp pointer to location to store our connection token
687 *
688 * Returns:
689 * 0 call is accepted
690 * errno call rejected - reason indicated
691 *
692 */
693 static int
694 atm_aal5_incoming(tok, cop, ap, tokp)
695 void *tok;
696 Atm_connection *cop;
697 Atm_attributes *ap;
698 void **tokp;
699 {
700 Atm_pcb *atp0 = tok, *atp;
701 struct socket *so;
702 int err = 0;
703
704 /*
705 * Allocate a new socket and pcb for this connection.
706 *
707 * Note that our attach function will be called via sonewconn
708 * and it will allocate and setup most of the pcb.
709 */
710 atm_sock_stat.as_inconn[atp0->atp_type]++;
711 #if (defined(BSD) && (BSD >= 199103))
712 so = sonewconn(atp0->atp_socket, 0);
713 #else
714 so = sonewconn(atp0->atp_socket);
715 #endif
716
717 if (so) {
718 /*
719 * Finish pcb setup and pass pcb back to CM
720 */
721 atp = sotoatmpcb(so);
722 atp->atp_conn = cop;
723 atp->atp_attr = *atp0->atp_conn->co_lattr;
724 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
725 *tokp = atp;
726 } else {
727 err = ECONNABORTED;
728 atm_sock_stat.as_connfail[atp0->atp_type]++;
729 }
730
731 return (err);
732 }
733
734
735 /*
736 * Process Socket VCC Input Data
737 *
738 * Arguments:
739 * tok owner's connection token (atm_pcb)
740 * m pointer to input packet buffer chain
741 *
742 * Returns:
743 * none
744 *
745 */
746 static void
747 atm_aal5_cpcs_data(tok, m)
748 void *tok;
749 KBuffer *m;
750 {
751 Atm_pcb *atp = tok;
752 struct socket *so;
753 int len;
754
755 so = atp->atp_socket;
756
757 KB_PLENGET(m, len);
758
759 /*
760 * Ensure that the socket is able to receive data and
761 * that there's room in the socket buffer
762 */
763 if (((so->so_state & SS_ISCONNECTED) == 0) ||
764 (so->so_state & SS_CANTRCVMORE) ||
765 (len > sbspace(&so->so_rcv))) {
766 atm_sock_stat.as_indrop[atp->atp_type]++;
767 KB_FREEALL(m);
768 return;
769 }
770
771 /*
772 * Queue the data and notify the user
773 */
774 sbappendrecord(&so->so_rcv, m);
775 sorwakeup(so);
776
777 return;
778 }
779
780
781 /*
782 * Process getsockopt/setsockopt system calls
783 *
784 * Arguments:
785 * so pointer to socket
786 * sopt pointer to socket option info
787 *
788 * Returns:
789 * 0 request processed
790 * errno error processing request - reason indicated
791 *
792 */
793 int
794 atm_aal5_ctloutput(so, sopt)
795 struct socket *so;
796 struct sockopt *sopt;
797 {
798 Atm_pcb *atp;
799
800 ATM_INTRO("ctloutput");
801
802 /*
803 * Make sure this is for us
804 */
805 if (sopt->sopt_level != T_ATM_SIGNALING) {
806 ATM_RETERR(EINVAL);
807 }
808 atp = sotoatmpcb(so);
809 if (atp == NULL) {
810 ATM_RETERR(ENOTCONN);
811 }
812
813 switch (sopt->sopt_dir) {
814
815 case SOPT_SET:
816 /*
817 * setsockopt()
818 */
819
820 /*
821 * Validate socket state
822 */
823 switch (sopt->sopt_name) {
824
825 case T_ATM_ADD_LEAF:
826 case T_ATM_DROP_LEAF:
827 if ((so->so_state & SS_ISCONNECTED) == 0) {
828 ATM_RETERR(ENOTCONN);
829 }
830 break;
831
832 case T_ATM_CAUSE:
833 case T_ATM_APP_NAME:
834 break;
835
836 default:
837 if (so->so_state & SS_ISCONNECTED) {
838 ATM_RETERR(EISCONN);
839 }
840 break;
841 }
842
843 /*
844 * Validate and save user-supplied option data
845 */
846 err = atm_sock_setopt(so, sopt, atp);
847
848 break;
849
850 case SOPT_GET:
851 /*
852 * getsockopt()
853 */
854
855 /*
856 * Return option data
857 */
858 err = atm_sock_getopt(so, sopt, atp);
859
860 break;
861 }
862
863 out:
864 ATM_OUTRO();
865 }
866
867
868 /*
869 * Initialize AAL5 Sockets
870 *
871 * Arguments:
872 * none
873 *
874 * Returns:
875 * none
876 *
877 */
878 void
879 atm_aal5_init()
880 {
881 /*
882 * Register our endpoint
883 */
884 if (atm_endpoint_register(&atm_aal5_endpt))
885 panic("atm_aal5_init: register");
886
887 /*
888 * Set default connection attributes
889 */
890 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
891 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
892 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
893 }
894
895
896 /*
897 * Get Connection's Application/Owner Name
898 *
899 * Arguments:
900 * tok owner's connection token (atm_pcb)
901 *
902 * Returns:
903 * addr pointer to string containing our name
904 *
905 */
906 static caddr_t
907 atm_aal5_getname(tok)
908 void *tok;
909 {
910 Atm_pcb *atp = tok;
911
912 return (atp->atp_name);
913 }
914
Cache object: 168cf22af168b54578a0a5076e7ff30e
|