Include the fortran library sources from GCC 3.4.4.
[dragonfly/netmp.git] / sys / netproto / atm / atm_aal5.c
blob8d77ae24e5c332343be80da5431b35b45298a498
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/atm_aal5.c,v 1.6 1999/10/09 23:24:59 green Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/atm_aal5.c,v 1.9 2005/06/02 22:37:45 dillon Exp $
31 * Core ATM Services
32 * -----------------
34 * ATM AAL5 socket protocol processing
38 #include "kern_include.h"
39 #include <sys/stat.h>
42 * Global variables
44 u_long atm_aal5_sendspace = 64 * 1024; /* XXX */
45 u_long atm_aal5_recvspace = 64 * 1024; /* XXX */
49 * Local functions
51 static int atm_aal5_attach (struct socket *, int,
52 struct pru_attach_info *);
53 static int atm_aal5_detach (struct socket *);
54 static int atm_aal5_bind (struct socket *, struct sockaddr *,
55 struct thread *);
56 static int atm_aal5_listen (struct socket *, struct thread *);
57 static int atm_aal5_connect (struct socket *, struct sockaddr *,
58 struct thread *);
59 static int atm_aal5_accept (struct socket *, struct sockaddr **);
60 static int atm_aal5_disconnect (struct socket *);
61 static int atm_aal5_shutdown (struct socket *);
62 static int atm_aal5_send (struct socket *, int, KBuffer *,
63 struct sockaddr *, KBuffer *, struct thread *);
64 static int atm_aal5_abort (struct socket *);
65 static int atm_aal5_control (struct socket *, u_long, caddr_t,
66 struct ifnet *, struct thread *);
67 static int atm_aal5_sense (struct socket *, struct stat *);
68 static int atm_aal5_sockaddr (struct socket *, struct sockaddr **);
69 static int atm_aal5_peeraddr (struct socket *, struct sockaddr **);
70 static int atm_aal5_incoming (void *, Atm_connection *,
71 Atm_attributes *, void **);
72 static void atm_aal5_cpcs_data (void *, KBuffer *);
73 static caddr_t atm_aal5_getname (void *);
77 * New-style socket request routines
79 struct pr_usrreqs atm_aal5_usrreqs = {
80 atm_aal5_abort, /* pru_abort */
81 atm_aal5_accept, /* pru_accept */
82 atm_aal5_attach, /* pru_attach */
83 atm_aal5_bind, /* pru_bind */
84 atm_aal5_connect, /* pru_connect */
85 pru_connect2_notsupp, /* pru_connect2 */
86 atm_aal5_control, /* pru_control */
87 atm_aal5_detach, /* pru_detach */
88 atm_aal5_disconnect, /* pru_disconnect */
89 atm_aal5_listen, /* pru_listen */
90 atm_aal5_peeraddr, /* pru_peeraddr */
91 pru_rcvd_notsupp, /* pru_rcvd */
92 pru_rcvoob_notsupp, /* pru_rcvoob */
93 atm_aal5_send, /* pru_send */
94 atm_aal5_sense, /* pru_sense */
95 atm_aal5_shutdown, /* pru_shutdown */
96 atm_aal5_sockaddr, /* pru_sockaddr */
97 sosend, /* pru_sosend */
98 soreceive, /* pru_soreceive */
99 sopoll /* pru_sopoll */
103 * Local variables
105 static Atm_endpoint atm_aal5_endpt = {
106 NULL,
107 ENDPT_SOCK_AAL5,
108 NULL,
109 atm_aal5_getname,
110 atm_sock_connected,
111 atm_sock_cleared,
112 atm_aal5_incoming,
113 NULL,
114 NULL,
115 NULL,
116 atm_aal5_cpcs_data,
117 NULL,
118 NULL,
119 NULL,
120 NULL
123 static Atm_attributes atm_aal5_defattr = {
124 NULL, /* nif */
125 CMAPI_CPCS, /* api */
126 0, /* api_init */
127 0, /* headin */
128 0, /* headout */
129 { /* aal */
130 T_ATM_PRESENT,
131 ATM_AAL5
133 { /* traffic */
134 T_ATM_ABSENT,
136 { /* bearer */
137 T_ATM_ABSENT,
139 { /* bhli */
140 T_ATM_ABSENT
142 { /* blli */
143 T_ATM_ABSENT,
144 T_ATM_ABSENT,
146 { /* llc */
147 T_ATM_ABSENT,
149 { /* called */
150 T_ATM_ABSENT,
152 T_ATM_ABSENT,
156 T_ATM_ABSENT,
160 { /* calling */
161 T_ATM_ABSENT
163 { /* qos */
164 T_ATM_ABSENT,
166 { /* transit */
167 T_ATM_ABSENT
169 { /* cause */
170 T_ATM_ABSENT
176 * Handy common code macros
178 #ifdef DIAGNOSTIC
179 #define ATM_INTRO(f) \
180 int err = 0; \
181 crit_enter(); \
182 ATM_DEBUG2("aal5 socket %s (%p)\n", f, so); \
183 /* \
184 * Stack queue should have been drained \
185 */ \
186 if (atm_stackq_head != NULL) \
187 panic("atm_aal5: stack queue not empty"); \
189 #else /* !DIAGNOSTIC */
190 #define ATM_INTRO(f) \
191 int err = 0; \
192 crit_enter(); \
194 #endif /* DIAGNOSTIC */
196 #define ATM_OUTRO() \
197 /* \
198 * Drain any deferred calls \
199 */ \
200 STACK_DRAIN(); \
201 crit_exit(); \
202 return (err); \
205 #define ATM_RETERR(errno) { \
206 err = errno; \
207 goto out; \
212 * Attach protocol to socket
214 * Arguments:
215 * so pointer to socket
216 * proto protocol identifier
217 * p pointer to process
219 * Returns:
220 * 0 request processed
221 * errno error processing request - reason indicated
224 static int
225 atm_aal5_attach(so, proto, ai)
226 struct socket *so;
227 int proto;
228 struct pru_attach_info *ai;
230 Atm_pcb *atp;
232 ATM_INTRO("attach");
235 * Do general attach stuff
237 err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace,
238 ai->sb_rlimit);
239 if (err)
240 ATM_RETERR(err);
243 * Finish up any protocol specific stuff
245 atp = sotoatmpcb(so);
246 atp->atp_type = ATPT_AAL5;
249 * Set default connection attributes
251 atp->atp_attr = atm_aal5_defattr;
252 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
254 out:
255 ATM_OUTRO();
260 * Detach protocol from socket
262 * Arguments:
263 * so pointer to socket
265 * Returns:
266 * 0 request processed
267 * errno error processing request - reason indicated
270 static int
271 atm_aal5_detach(so)
272 struct socket *so;
274 ATM_INTRO("detach");
276 err = atm_sock_detach(so);
278 ATM_OUTRO();
283 * Bind address to socket
285 * Arguments:
286 * so pointer to socket
287 * addr pointer to protocol address
288 * p pointer to process
290 * Returns:
291 * 0 request processed
292 * errno error processing request - reason indicated
295 static int
296 atm_aal5_bind(so, addr, td)
297 struct socket *so;
298 struct sockaddr *addr;
299 struct thread *td;
301 ATM_INTRO("bind");
303 err = atm_sock_bind(so, addr);
305 ATM_OUTRO();
310 * Listen for incoming connections
312 * Arguments:
313 * so pointer to socket
314 * p pointer to process
316 * Returns:
317 * 0 request processed
318 * errno error processing request - reason indicated
321 static int
322 atm_aal5_listen(struct socket *so, struct thread *td)
324 ATM_INTRO("listen");
326 err = atm_sock_listen(so, &atm_aal5_endpt);
328 ATM_OUTRO();
333 * Connect socket to peer
335 * Arguments:
336 * so pointer to socket
337 * addr pointer to protocol address
338 * p pointer to process
340 * Returns:
341 * 0 request processed
342 * errno error processing request - reason indicated
345 static int
346 atm_aal5_connect(struct socket *so, struct sockaddr *addr, thread_t td)
348 Atm_pcb *atp;
350 ATM_INTRO("connect");
352 atp = sotoatmpcb(so);
355 * Resize send socket buffer to maximum sdu size
357 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
358 long size;
360 size = atp->atp_attr.aal.v.aal5.forward_max_SDU_size;
361 if (size != T_ATM_ABSENT)
362 if (!sbreserve(&so->so_snd, size, so,
363 &td->td_proc->p_rlimit[RLIMIT_SBSIZE])) {
364 err = ENOBUFS;
365 ATM_OUTRO();
371 * Now get the socket connected
373 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
375 ATM_OUTRO();
380 * Accept pending connection
382 * Arguments:
383 * so pointer to socket
384 * addr pointer to pointer to contain protocol address
386 * Returns:
387 * 0 request processed
388 * errno error processing request - reason indicated
391 static int
392 atm_aal5_accept(struct socket *so, struct sockaddr **addr)
394 ATM_INTRO("accept");
397 * Everything is pretty much done already, we just need to
398 * return the caller's address to the user.
400 err = atm_sock_peeraddr(so, addr);
402 ATM_OUTRO();
407 * Disconnect connected socket
409 * Arguments:
410 * so pointer to socket
412 * Returns:
413 * 0 request processed
414 * errno error processing request - reason indicated
417 static int
418 atm_aal5_disconnect(struct socket *so)
420 ATM_INTRO("disconnect");
422 err = atm_sock_disconnect(so);
424 ATM_OUTRO();
429 * Shut down socket data transmission
431 * Arguments:
432 * so pointer to socket
434 * Returns:
435 * 0 request processed
436 * errno error processing request - reason indicated
439 static int
440 atm_aal5_shutdown(struct socket *so)
442 ATM_INTRO("shutdown");
444 socantsendmore(so);
446 ATM_OUTRO();
451 * Send user data
453 * Arguments:
454 * so pointer to socket
455 * flags send data flags
456 * m pointer to buffer containing user data
457 * addr pointer to protocol address
458 * control pointer to buffer containing protocol control data
459 * p pointer to process
461 * Returns:
462 * 0 request processed
463 * errno error processing request - reason indicated
466 static int
467 atm_aal5_send(
468 struct socket *so,
469 int flags,
470 KBuffer *m,
471 struct sockaddr *addr,
472 KBuffer *control,
473 struct thread *td
475 Atm_pcb *atp;
477 ATM_INTRO("send");
480 * We don't support any control functions
482 if (control) {
483 int clen;
485 clen = KB_LEN(control);
486 KB_FREEALL(control);
487 if (clen) {
488 KB_FREEALL(m);
489 ATM_RETERR(EINVAL);
494 * We also don't support any flags or send-level addressing
496 if (flags || addr) {
497 KB_FREEALL(m);
498 ATM_RETERR(EINVAL);
502 * All we've got left is the data, so push it out
504 atp = sotoatmpcb(so);
505 err = atm_cm_cpcs_data(atp->atp_conn, m);
506 if (err) {
508 * Output problem, drop packet
510 atm_sock_stat.as_outdrop[atp->atp_type]++;
511 KB_FREEALL(m);
514 out:
515 ATM_OUTRO();
520 * Abnormally terminate service
522 * Arguments:
523 * so pointer to socket
525 * Returns:
526 * 0 request processed
527 * errno error processing request - reason indicated
530 static int
531 atm_aal5_abort(struct socket *so)
533 ATM_INTRO("abort");
535 so->so_error = ECONNABORTED;
536 err = atm_sock_detach(so);
538 ATM_OUTRO();
543 * Do control operation - ioctl system call
545 * Arguments:
546 * so pointer to socket
547 * cmd ioctl code
548 * data pointer to code specific parameter data area
549 * ifp pointer to ifnet structure if it's an interface ioctl
550 * p pointer to process
552 * Returns:
553 * 0 request processed
554 * errno error processing request - reason indicated
557 static int
558 atm_aal5_control(
559 struct socket *so,
560 u_long cmd,
561 caddr_t data,
562 struct ifnet *ifp,
563 struct thread *td
565 ATM_INTRO("control");
567 switch (cmd) {
569 default:
570 err = EOPNOTSUPP;
573 ATM_OUTRO();
577 * Sense socket status - fstat system call
579 * Arguments:
580 * so pointer to socket
581 * st pointer to file status structure
583 * Returns:
584 * 0 request processed
585 * errno error processing request - reason indicated
588 static int
589 atm_aal5_sense(struct socket *so, struct stat *st)
591 ATM_INTRO("sense");
594 * Just return the max sdu size for the connection
596 st->st_blksize = so->so_snd.sb_hiwat;
598 ATM_OUTRO();
603 * Retrieve local socket address
605 * Arguments:
606 * so pointer to socket
607 * addr pointer to pointer to contain protocol address
609 * Returns:
610 * 0 request processed
611 * errno error processing request - reason indicated
614 static int
615 atm_aal5_sockaddr(struct socket *so, struct sockaddr **addr)
617 ATM_INTRO("sockaddr");
619 err = atm_sock_sockaddr(so, addr);
621 ATM_OUTRO();
626 * Retrieve peer socket address
628 * Arguments:
629 * so pointer to socket
630 * addr pointer to pointer to contain protocol address
632 * Returns:
633 * 0 request processed
634 * errno error processing request - reason indicated
637 static int
638 atm_aal5_peeraddr(struct socket *so, struct sockaddr **addr)
640 ATM_INTRO("peeraddr");
642 err = atm_sock_peeraddr(so, addr);
644 ATM_OUTRO();
649 * Process Incoming Calls
651 * This function will receive control when an incoming call has been matched
652 * to one of our registered listen parameter blocks. Assuming the call passes
653 * acceptance criteria and all required resources are available, we will
654 * create a new protocol control block and socket association. We must
655 * then await notification of the final SVC setup results. If any
656 * problems are encountered, we will just tell the connection manager to
657 * reject the call.
659 * Called from a critical section.
661 * Arguments:
662 * tok owner's matched listening token
663 * cop pointer to incoming call's connection block
664 * ap pointer to incoming call's attributes
665 * tokp pointer to location to store our connection token
667 * Returns:
668 * 0 call is accepted
669 * errno call rejected - reason indicated
672 static int
673 atm_aal5_incoming(tok, cop, ap, tokp)
674 void *tok;
675 Atm_connection *cop;
676 Atm_attributes *ap;
677 void **tokp;
679 Atm_pcb *atp0 = tok, *atp;
680 struct socket *so;
681 int err = 0;
684 * Allocate a new socket and pcb for this connection.
686 * Note that our attach function will be called via sonewconn
687 * and it will allocate and setup most of the pcb.
689 atm_sock_stat.as_inconn[atp0->atp_type]++;
690 so = sonewconn(atp0->atp_socket, 0);
692 if (so) {
694 * Finish pcb setup and pass pcb back to CM
696 atp = sotoatmpcb(so);
697 atp->atp_conn = cop;
698 atp->atp_attr = *atp0->atp_conn->co_lattr;
699 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
700 *tokp = atp;
701 } else {
702 err = ECONNABORTED;
703 atm_sock_stat.as_connfail[atp0->atp_type]++;
706 return (err);
711 * Process Socket VCC Input Data
713 * Arguments:
714 * tok owner's connection token (atm_pcb)
715 * m pointer to input packet buffer chain
717 * Returns:
718 * none
721 static void
722 atm_aal5_cpcs_data(tok, m)
723 void *tok;
724 KBuffer *m;
726 Atm_pcb *atp = tok;
727 struct socket *so;
728 int len;
730 so = atp->atp_socket;
732 KB_PLENGET(m, len);
735 * Ensure that the socket is able to receive data and
736 * that there's room in the socket buffer
738 if (((so->so_state & SS_ISCONNECTED) == 0) ||
739 (so->so_state & SS_CANTRCVMORE) ||
740 (len > sbspace(&so->so_rcv))) {
741 atm_sock_stat.as_indrop[atp->atp_type]++;
742 KB_FREEALL(m);
743 return;
747 * Queue the data and notify the user
749 sbappendrecord(&so->so_rcv, m);
750 sorwakeup(so);
752 return;
757 * Process getsockopt/setsockopt system calls
759 * Arguments:
760 * so pointer to socket
761 * sopt pointer to socket option info
763 * Returns:
764 * 0 request processed
765 * errno error processing request - reason indicated
769 atm_aal5_ctloutput(struct socket *so, struct sockopt *sopt)
771 Atm_pcb *atp;
773 ATM_INTRO("ctloutput");
776 * Make sure this is for us
778 if (sopt->sopt_level != T_ATM_SIGNALING) {
779 ATM_RETERR(EINVAL);
781 atp = sotoatmpcb(so);
782 if (atp == NULL) {
783 ATM_RETERR(ENOTCONN);
786 switch (sopt->sopt_dir) {
788 case SOPT_SET:
790 * setsockopt()
794 * Validate socket state
796 switch (sopt->sopt_name) {
798 case T_ATM_ADD_LEAF:
799 case T_ATM_DROP_LEAF:
800 if ((so->so_state & SS_ISCONNECTED) == 0) {
801 ATM_RETERR(ENOTCONN);
803 break;
805 case T_ATM_CAUSE:
806 case T_ATM_APP_NAME:
807 break;
809 default:
810 if (so->so_state & SS_ISCONNECTED) {
811 ATM_RETERR(EISCONN);
813 break;
817 * Validate and save user-supplied option data
819 err = atm_sock_setopt(so, sopt, atp);
821 break;
823 case SOPT_GET:
825 * getsockopt()
829 * Return option data
831 err = atm_sock_getopt(so, sopt, atp);
833 break;
836 out:
837 ATM_OUTRO();
842 * Initialize AAL5 Sockets
844 * Arguments:
845 * none
847 * Returns:
848 * none
851 void
852 atm_aal5_init()
855 * Register our endpoint
857 if (atm_endpoint_register(&atm_aal5_endpt))
858 panic("atm_aal5_init: register");
861 * Set default connection attributes
863 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
864 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
865 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
870 * Get Connection's Application/Owner Name
872 * Arguments:
873 * tok owner's connection token (atm_pcb)
875 * Returns:
876 * addr pointer to string containing our name
879 static caddr_t
880 atm_aal5_getname(tok)
881 void *tok;
883 Atm_pcb *atp = tok;
885 return (atp->atp_name);