MFC r1.3 r1.13 r1.8 (HEAD):
[dragonfly.git] / sys / netproto / atm / atm_aal5.c
blobb1a761f50daf81fa4b15710d2ac51d6bba05eefa
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.13 2007/04/22 01:13:15 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 .pru_abort = atm_aal5_abort,
81 .pru_accept = atm_aal5_accept,
82 .pru_attach = atm_aal5_attach,
83 .pru_bind = atm_aal5_bind,
84 .pru_connect = atm_aal5_connect,
85 .pru_connect2 = pru_connect2_notsupp,
86 .pru_control = atm_aal5_control,
87 .pru_detach = atm_aal5_detach,
88 .pru_disconnect = atm_aal5_disconnect,
89 .pru_listen = atm_aal5_listen,
90 .pru_peeraddr = atm_aal5_peeraddr,
91 .pru_rcvd = pru_rcvd_notsupp,
92 .pru_rcvoob = pru_rcvoob_notsupp,
93 .pru_send = atm_aal5_send,
94 .pru_sense = atm_aal5_sense,
95 .pru_shutdown = atm_aal5_shutdown,
96 .pru_sockaddr = atm_aal5_sockaddr,
97 .pru_sosend = sosend,
98 .pru_soreceive = soreceive,
99 .pru_sopoll = 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(error) { \
206 err = error; \
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 * error error processing request - reason indicated
224 static int
225 atm_aal5_attach(struct socket *so, int proto, struct pru_attach_info *ai)
227 Atm_pcb *atp;
229 ATM_INTRO("attach");
232 * Do general attach stuff
234 err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace,
235 ai->sb_rlimit);
236 if (err)
237 ATM_RETERR(err);
240 * Finish up any protocol specific stuff
242 atp = sotoatmpcb(so);
243 atp->atp_type = ATPT_AAL5;
246 * Set default connection attributes
248 atp->atp_attr = atm_aal5_defattr;
249 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
251 out:
252 ATM_OUTRO();
257 * Detach protocol from socket
259 * Arguments:
260 * so pointer to socket
262 * Returns:
263 * 0 request processed
264 * error error processing request - reason indicated
267 static int
268 atm_aal5_detach(struct socket *so)
270 ATM_INTRO("detach");
272 err = atm_sock_detach(so);
274 ATM_OUTRO();
279 * Bind address to socket
281 * Arguments:
282 * so pointer to socket
283 * addr pointer to protocol address
284 * p pointer to process
286 * Returns:
287 * 0 request processed
288 * error error processing request - reason indicated
291 static int
292 atm_aal5_bind(struct socket *so, struct sockaddr *addr, struct thread *td)
294 ATM_INTRO("bind");
296 err = atm_sock_bind(so, addr);
298 ATM_OUTRO();
303 * Listen for incoming connections
305 * Arguments:
306 * so pointer to socket
307 * p pointer to process
309 * Returns:
310 * 0 request processed
311 * error error processing request - reason indicated
314 static int
315 atm_aal5_listen(struct socket *so, struct thread *td)
317 ATM_INTRO("listen");
319 err = atm_sock_listen(so, &atm_aal5_endpt);
321 ATM_OUTRO();
326 * Connect socket to peer
328 * Arguments:
329 * so pointer to socket
330 * addr pointer to protocol address
331 * p pointer to process
333 * Returns:
334 * 0 request processed
335 * error error processing request - reason indicated
338 static int
339 atm_aal5_connect(struct socket *so, struct sockaddr *addr, thread_t td)
341 Atm_pcb *atp;
343 ATM_INTRO("connect");
345 atp = sotoatmpcb(so);
348 * Resize send socket buffer to maximum sdu size
350 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
351 long size;
353 size = atp->atp_attr.aal.v.aal5.forward_max_SDU_size;
354 if (size != T_ATM_ABSENT)
355 if (!ssb_reserve(&so->so_snd, size, so,
356 &td->td_proc->p_rlimit[RLIMIT_SBSIZE])) {
357 err = ENOBUFS;
358 ATM_OUTRO();
364 * Now get the socket connected
366 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
368 ATM_OUTRO();
373 * Accept pending connection
375 * Arguments:
376 * so pointer to socket
377 * addr pointer to pointer to contain protocol address
379 * Returns:
380 * 0 request processed
381 * error error processing request - reason indicated
384 static int
385 atm_aal5_accept(struct socket *so, struct sockaddr **addr)
387 ATM_INTRO("accept");
390 * Everything is pretty much done already, we just need to
391 * return the caller's address to the user.
393 err = atm_sock_peeraddr(so, addr);
395 ATM_OUTRO();
400 * Disconnect connected socket
402 * Arguments:
403 * so pointer to socket
405 * Returns:
406 * 0 request processed
407 * error error processing request - reason indicated
410 static int
411 atm_aal5_disconnect(struct socket *so)
413 ATM_INTRO("disconnect");
415 err = atm_sock_disconnect(so);
417 ATM_OUTRO();
422 * Shut down socket data transmission
424 * Arguments:
425 * so pointer to socket
427 * Returns:
428 * 0 request processed
429 * error error processing request - reason indicated
432 static int
433 atm_aal5_shutdown(struct socket *so)
435 ATM_INTRO("shutdown");
437 socantsendmore(so);
439 ATM_OUTRO();
444 * Send user data
446 * Arguments:
447 * so pointer to socket
448 * flags send data flags
449 * m pointer to buffer containing user data
450 * addr pointer to protocol address
451 * control pointer to buffer containing protocol control data
452 * p pointer to process
454 * Returns:
455 * 0 request processed
456 * error error processing request - reason indicated
459 static int
460 atm_aal5_send(
461 struct socket *so,
462 int flags,
463 KBuffer *m,
464 struct sockaddr *addr,
465 KBuffer *control,
466 struct thread *td
468 Atm_pcb *atp;
470 ATM_INTRO("send");
473 * We don't support any control functions
475 if (control) {
476 int clen;
478 clen = KB_LEN(control);
479 KB_FREEALL(control);
480 if (clen) {
481 KB_FREEALL(m);
482 ATM_RETERR(EINVAL);
487 * We also don't support any flags or send-level addressing
489 if (flags || addr) {
490 KB_FREEALL(m);
491 ATM_RETERR(EINVAL);
495 * All we've got left is the data, so push it out
497 atp = sotoatmpcb(so);
498 err = atm_cm_cpcs_data(atp->atp_conn, m);
499 if (err) {
501 * Output problem, drop packet
503 atm_sock_stat.as_outdrop[atp->atp_type]++;
504 KB_FREEALL(m);
507 out:
508 ATM_OUTRO();
513 * Abnormally terminate service
515 * Arguments:
516 * so pointer to socket
518 * Returns:
519 * 0 request processed
520 * error error processing request - reason indicated
523 static int
524 atm_aal5_abort(struct socket *so)
526 ATM_INTRO("abort");
528 so->so_error = ECONNABORTED;
529 err = atm_sock_detach(so);
531 ATM_OUTRO();
536 * Do control operation - ioctl system call
538 * Arguments:
539 * so pointer to socket
540 * cmd ioctl code
541 * data pointer to code specific parameter data area
542 * ifp pointer to ifnet structure if it's an interface ioctl
543 * p pointer to process
545 * Returns:
546 * 0 request processed
547 * error error processing request - reason indicated
550 static int
551 atm_aal5_control(
552 struct socket *so,
553 u_long cmd,
554 caddr_t data,
555 struct ifnet *ifp,
556 struct thread *td
558 ATM_INTRO("control");
560 switch (cmd) {
562 default:
563 err = EOPNOTSUPP;
566 ATM_OUTRO();
570 * Sense socket status - fstat system call
572 * Arguments:
573 * so pointer to socket
574 * st pointer to file status structure
576 * Returns:
577 * 0 request processed
578 * error error processing request - reason indicated
581 static int
582 atm_aal5_sense(struct socket *so, struct stat *st)
584 ATM_INTRO("sense");
587 * Just return the max sdu size for the connection
589 st->st_blksize = so->so_snd.ssb_hiwat;
591 ATM_OUTRO();
596 * Retrieve local socket address
598 * Arguments:
599 * so pointer to socket
600 * addr pointer to pointer to contain protocol address
602 * Returns:
603 * 0 request processed
604 * error error processing request - reason indicated
607 static int
608 atm_aal5_sockaddr(struct socket *so, struct sockaddr **addr)
610 ATM_INTRO("sockaddr");
612 err = atm_sock_sockaddr(so, addr);
614 ATM_OUTRO();
619 * Retrieve peer socket address
621 * Arguments:
622 * so pointer to socket
623 * addr pointer to pointer to contain protocol address
625 * Returns:
626 * 0 request processed
627 * error error processing request - reason indicated
630 static int
631 atm_aal5_peeraddr(struct socket *so, struct sockaddr **addr)
633 ATM_INTRO("peeraddr");
635 err = atm_sock_peeraddr(so, addr);
637 ATM_OUTRO();
642 * Process Incoming Calls
644 * This function will receive control when an incoming call has been matched
645 * to one of our registered listen parameter blocks. Assuming the call passes
646 * acceptance criteria and all required resources are available, we will
647 * create a new protocol control block and socket association. We must
648 * then await notification of the final SVC setup results. If any
649 * problems are encountered, we will just tell the connection manager to
650 * reject the call.
652 * Called from a critical section.
654 * Arguments:
655 * tok owner's matched listening token
656 * cop pointer to incoming call's connection block
657 * ap pointer to incoming call's attributes
658 * tokp pointer to location to store our connection token
660 * Returns:
661 * 0 call is accepted
662 * error call rejected - reason indicated
665 static int
666 atm_aal5_incoming(void *tok, Atm_connection *cop, Atm_attributes *ap,
667 void **tokp)
669 Atm_pcb *atp0 = tok, *atp;
670 struct socket *so;
671 int err = 0;
674 * Allocate a new socket and pcb for this connection.
676 * Note that our attach function will be called via sonewconn
677 * and it will allocate and setup most of the pcb.
679 atm_sock_stat.as_inconn[atp0->atp_type]++;
680 so = sonewconn(atp0->atp_socket, 0);
682 if (so) {
684 * Finish pcb setup and pass pcb back to CM
686 atp = sotoatmpcb(so);
687 atp->atp_conn = cop;
688 atp->atp_attr = *atp0->atp_conn->co_lattr;
689 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
690 *tokp = atp;
691 } else {
692 err = ECONNABORTED;
693 atm_sock_stat.as_connfail[atp0->atp_type]++;
696 return (err);
701 * Process Socket VCC Input Data
703 * Arguments:
704 * tok owner's connection token (atm_pcb)
705 * m pointer to input packet buffer chain
707 * Returns:
708 * none
711 static void
712 atm_aal5_cpcs_data(void *tok, KBuffer *m)
714 Atm_pcb *atp = tok;
715 struct socket *so;
716 int len;
718 so = atp->atp_socket;
720 KB_PLENGET(m, len);
723 * Ensure that the socket is able to receive data and
724 * that there's room in the socket buffer
726 if (((so->so_state & SS_ISCONNECTED) == 0) ||
727 (so->so_state & SS_CANTRCVMORE) ||
728 (len > ssb_space(&so->so_rcv))) {
729 atm_sock_stat.as_indrop[atp->atp_type]++;
730 KB_FREEALL(m);
731 return;
735 * Queue the data and notify the user
737 ssb_appendrecord(&so->so_rcv, m);
738 sorwakeup(so);
740 return;
745 * Process getsockopt/setsockopt system calls
747 * Arguments:
748 * so pointer to socket
749 * sopt pointer to socket option info
751 * Returns:
752 * 0 request processed
753 * error error processing request - reason indicated
757 atm_aal5_ctloutput(struct socket *so, struct sockopt *sopt)
759 Atm_pcb *atp;
761 ATM_INTRO("ctloutput");
764 * Make sure this is for us
766 if (sopt->sopt_level != T_ATM_SIGNALING) {
767 ATM_RETERR(EINVAL);
769 atp = sotoatmpcb(so);
770 if (atp == NULL) {
771 ATM_RETERR(ENOTCONN);
774 switch (sopt->sopt_dir) {
776 case SOPT_SET:
778 * setsockopt()
782 * Validate socket state
784 switch (sopt->sopt_name) {
786 case T_ATM_ADD_LEAF:
787 case T_ATM_DROP_LEAF:
788 if ((so->so_state & SS_ISCONNECTED) == 0) {
789 ATM_RETERR(ENOTCONN);
791 break;
793 case T_ATM_CAUSE:
794 case T_ATM_APP_NAME:
795 break;
797 default:
798 if (so->so_state & SS_ISCONNECTED) {
799 ATM_RETERR(EISCONN);
801 break;
805 * Validate and save user-supplied option data
807 err = atm_sock_setopt(so, sopt, atp);
809 break;
811 case SOPT_GET:
813 * getsockopt()
817 * Return option data
819 err = atm_sock_getopt(so, sopt, atp);
821 break;
824 out:
825 ATM_OUTRO();
830 * Initialize AAL5 Sockets
832 * Arguments:
833 * none
835 * Returns:
836 * none
839 void
840 atm_aal5_init(void)
843 * Register our endpoint
845 if (atm_endpoint_register(&atm_aal5_endpt))
846 panic("atm_aal5_init: register");
849 * Set default connection attributes
851 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
852 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
853 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
858 * Get Connection's Application/Owner Name
860 * Arguments:
861 * tok owner's connection token (atm_pcb)
863 * Returns:
864 * addr pointer to string containing our name
867 static caddr_t
868 atm_aal5_getname(void *tok)
870 Atm_pcb *atp = tok;
872 return (atp->atp_name);