2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
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.
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.
20 * Copyright 1994-1998 Network Computing Services, Inc.
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
30 * ATM AAL5 socket protocol processing
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
38 #include <sys/protosw.h>
39 #include <sys/signalvar.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
44 #include <sys/systm.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>
61 u_long atm_aal5_sendspace = 64 * 1024; /* XXX */
62 u_long atm_aal5_recvspace = 64 * 1024; /* XXX */
68 static int atm_aal5_attach(struct socket *, int, struct thread *td);
69 static void atm_aal5_detach(struct socket *);
70 static int atm_aal5_bind(struct socket *, struct sockaddr *,
72 static int atm_aal5_listen(struct socket *, int backlog,
74 static int atm_aal5_connect(struct socket *, struct sockaddr *,
76 static int atm_aal5_accept(struct socket *, struct sockaddr **);
77 static int atm_aal5_disconnect(struct socket *);
78 static int atm_aal5_shutdown(struct socket *);
79 static int atm_aal5_send(struct socket *, int, KBuffer *,
80 struct sockaddr *, KBuffer *, struct thread *td);
81 static void atm_aal5_abort(struct socket *);
82 static int atm_aal5_control(struct socket *, u_long, caddr_t,
83 struct ifnet *, struct thread *td);
84 static int atm_aal5_sense(struct socket *, struct stat *);
85 static int atm_aal5_sockaddr(struct socket *, struct sockaddr **);
86 static int atm_aal5_peeraddr(struct socket *, struct sockaddr **);
87 static int atm_aal5_incoming(void *, Atm_connection *,
88 Atm_attributes *, void **);
89 static void atm_aal5_cpcs_data(void *, KBuffer *);
90 static caddr_t atm_aal5_getname(void *);
91 static void atm_aal5_close(struct socket *);
95 * New-style socket request routines
97 struct pr_usrreqs atm_aal5_usrreqs = {
98 .pru_abort = atm_aal5_abort,
99 .pru_accept = atm_aal5_accept,
100 .pru_attach = atm_aal5_attach,
101 .pru_bind = atm_aal5_bind,
102 .pru_connect = atm_aal5_connect,
103 .pru_control = atm_aal5_control,
104 .pru_detach = atm_aal5_detach,
105 .pru_disconnect = atm_aal5_disconnect,
106 .pru_listen = atm_aal5_listen,
107 .pru_peeraddr = atm_aal5_peeraddr,
108 .pru_send = atm_aal5_send,
109 .pru_sense = atm_aal5_sense,
110 .pru_shutdown = atm_aal5_shutdown,
111 .pru_sockaddr = atm_aal5_sockaddr,
112 .pru_close = atm_aal5_close,
118 static Atm_endpoint atm_aal5_endpt = {
136 static Atm_attributes atm_aal5_defattr = {
138 CMAPI_CPCS, /* api */
189 * Handy common code macros
192 #define ATM_INTRO(f) \
195 ATM_DEBUG2("aal5 socket %s (%p)\n", f, so); \
197 * Stack queue should have been drained \
199 if (atm_stackq_head != NULL) \
200 panic("atm_aal5: stack queue not empty"); \
202 #else /* !DIAGNOSTIC */
203 #define ATM_INTRO(f) \
207 #endif /* DIAGNOSTIC */
209 #define ATM_INTRO_NOERR(f) \
214 #define ATM_OUTRO() \
216 * Drain any deferred calls \
223 #define ATM_OUTRO_NOERR() \
225 * Drain any deferred calls \
231 #define ATM_RETERR(errno) { \
238 * Attach protocol to socket
241 * so pointer to socket
242 * proto protocol identifier
243 * p pointer to process
246 * 0 request processed
247 * errno error processing request - reason indicated
251 atm_aal5_attach(so, proto, td)
261 * Do general attach stuff
263 err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace);
268 * Finish up any protocol specific stuff
270 atp = sotoatmpcb(so);
271 atp->atp_type = ATPT_AAL5;
274 * Set default connection attributes
276 atp->atp_attr = atm_aal5_defattr;
277 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
285 * Detach protocol from socket
288 * so pointer to socket
291 * 0 request processed
292 * errno error processing request - reason indicated
299 ATM_INTRO_NOERR("detach");
308 * Bind address to socket
311 * so pointer to socket
312 * addr pointer to protocol address
313 * p pointer to process
316 * 0 request processed
317 * errno error processing request - reason indicated
321 atm_aal5_bind(so, addr, td)
323 struct sockaddr *addr;
328 err = atm_sock_bind(so, addr);
335 * Listen for incoming connections
338 * so pointer to socket
339 * p pointer to process
342 * 0 request processed
343 * errno error processing request - reason indicated
347 atm_aal5_listen(so, backlog, td)
354 err = atm_sock_listen(so, &atm_aal5_endpt, backlog);
361 * Connect socket to peer
364 * so pointer to socket
365 * addr pointer to protocol address
366 * p pointer to process
369 * 0 request processed
370 * errno error processing request - reason indicated
374 atm_aal5_connect(so, addr, td)
376 struct sockaddr *addr;
381 ATM_INTRO("connect");
383 atp = sotoatmpcb(so);
386 * Resize send socket buffer to maximum sdu size
388 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
391 size = atp->atp_attr.aal.v.aal5.forward_max_SDU_size;
392 if (size != T_ATM_ABSENT)
393 if (!sbreserve(&so->so_snd, size, so, td)) {
401 * Now get the socket connected
403 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
410 * Accept pending connection
413 * so pointer to socket
414 * addr pointer to pointer to contain protocol address
417 * 0 request processed
418 * errno error processing request - reason indicated
422 atm_aal5_accept(so, addr)
424 struct sockaddr **addr;
429 * Everything is pretty much done already, we just need to
430 * return the caller's address to the user.
432 err = atm_sock_peeraddr(so, addr);
439 * Disconnect connected socket
442 * so pointer to socket
445 * 0 request processed
446 * errno error processing request - reason indicated
450 atm_aal5_disconnect(so)
453 ATM_INTRO("disconnect");
455 err = atm_sock_disconnect(so);
462 * Shut down socket data transmission
465 * so pointer to socket
468 * 0 request processed
469 * errno error processing request - reason indicated
473 atm_aal5_shutdown(so)
476 ATM_INTRO("shutdown");
488 * so pointer to socket
489 * flags send data flags
490 * m pointer to buffer containing user data
491 * addr pointer to protocol address
492 * control pointer to buffer containing protocol control data
493 * p pointer to process
496 * 0 request processed
497 * errno error processing request - reason indicated
501 atm_aal5_send(so, flags, m, addr, control, td)
505 struct sockaddr *addr;
514 * We don't support any control functions
519 clen = KB_LEN(control);
528 * We also don't support any flags or send-level addressing
536 * All we've got left is the data, so push it out
538 atp = sotoatmpcb(so);
539 err = atm_cm_cpcs_data(atp->atp_conn, m);
542 * Output problem, drop packet
544 atm_sock_stat.as_outdrop[atp->atp_type]++;
554 * Abnormally terminate service
557 * so pointer to socket
560 * 0 request processed
561 * errno error processing request - reason indicated
568 ATM_INTRO_NOERR("abort");
570 (void)atm_sock_disconnect(so);
571 so->so_error = ECONNABORTED;
580 ATM_INTRO_NOERR("close");
582 (void)atm_sock_disconnect(so);
589 * Do control operation - ioctl system call
592 * so pointer to socket
594 * data pointer to code specific parameter data area
595 * ifp pointer to ifnet structure if it's an interface ioctl
596 * p pointer to process
599 * 0 request processed
600 * errno error processing request - reason indicated
604 atm_aal5_control(so, cmd, data, ifp, td)
611 ATM_INTRO("control");
623 * Sense socket status - fstat system call
626 * so pointer to socket
627 * st pointer to file status structure
630 * 0 request processed
631 * errno error processing request - reason indicated
635 atm_aal5_sense(so, st)
642 * Just return the max sdu size for the connection
644 st->st_blksize = so->so_snd.sb_hiwat;
651 * Retrieve local socket address
654 * so pointer to socket
655 * addr pointer to pointer to contain protocol address
658 * 0 request processed
659 * errno error processing request - reason indicated
663 atm_aal5_sockaddr(so, addr)
665 struct sockaddr **addr;
667 ATM_INTRO("sockaddr");
669 err = atm_sock_sockaddr(so, addr);
676 * Retrieve peer socket address
679 * so pointer to socket
680 * addr pointer to pointer to contain protocol address
683 * 0 request processed
684 * errno error processing request - reason indicated
688 atm_aal5_peeraddr(so, addr)
690 struct sockaddr **addr;
692 ATM_INTRO("peeraddr");
694 err = atm_sock_peeraddr(so, addr);
701 * Process Incoming Calls
703 * This function will receive control when an incoming call has been matched
704 * to one of our registered listen parameter blocks. Assuming the call passes
705 * acceptance criteria and all required resources are available, we will
706 * create a new protocol control block and socket association. We must
707 * then await notification of the final SVC setup results. If any
708 * problems are encountered, we will just tell the connection manager to
714 * tok owner's matched listening token
715 * cop pointer to incoming call's connection block
716 * ap pointer to incoming call's attributes
717 * tokp pointer to location to store our connection token
721 * errno call rejected - reason indicated
725 atm_aal5_incoming(tok, cop, ap, tokp)
731 Atm_pcb *atp0 = tok, *atp;
736 * Allocate a new socket and pcb for this connection.
738 * Note that our attach function will be called via sonewconn
739 * and it will allocate and setup most of the pcb.
741 atm_sock_stat.as_inconn[atp0->atp_type]++;
742 so = sonewconn(atp0->atp_socket, 0);
746 * Finish pcb setup and pass pcb back to CM
748 atp = sotoatmpcb(so);
750 atp->atp_attr = *atp0->atp_conn->co_lattr;
751 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
755 atm_sock_stat.as_connfail[atp0->atp_type]++;
763 * Process Socket VCC Input Data
766 * tok owner's connection token (atm_pcb)
767 * m pointer to input packet buffer chain
774 atm_aal5_cpcs_data(tok, m)
782 so = atp->atp_socket;
787 * Ensure that the socket is able to receive data and
788 * that there's room in the socket buffer
790 if (((so->so_state & SS_ISCONNECTED) == 0) ||
791 (so->so_rcv.sb_state & SBS_CANTRCVMORE) ||
792 (len > sbspace(&so->so_rcv))) {
793 atm_sock_stat.as_indrop[atp->atp_type]++;
799 * Queue the data and notify the user
801 sbappendrecord(&so->so_rcv, m);
809 * Process getsockopt/setsockopt system calls
812 * so pointer to socket
813 * sopt pointer to socket option info
816 * 0 request processed
817 * errno error processing request - reason indicated
821 atm_aal5_ctloutput(so, sopt)
823 struct sockopt *sopt;
827 ATM_INTRO("ctloutput");
830 * Make sure this is for us
832 if (sopt->sopt_level != T_ATM_SIGNALING) {
835 atp = sotoatmpcb(so);
837 ATM_RETERR(ENOTCONN);
840 switch (sopt->sopt_dir) {
848 * Validate socket state
850 switch (sopt->sopt_name) {
853 case T_ATM_DROP_LEAF:
854 if ((so->so_state & SS_ISCONNECTED) == 0) {
855 ATM_RETERR(ENOTCONN);
864 if (so->so_state & SS_ISCONNECTED) {
871 * Validate and save user-supplied option data
873 err = atm_sock_setopt(so, sopt, atp);
885 err = atm_sock_getopt(so, sopt, atp);
896 * Initialize AAL5 Sockets
909 * Register our endpoint
911 if (atm_endpoint_register(&atm_aal5_endpt))
912 panic("atm_aal5_init: register");
915 * Set default connection attributes
917 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
918 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
919 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
924 * Get Connection's Application/Owner Name
927 * tok owner's connection token (atm_pcb)
930 * addr pointer to string containing our name
934 atm_aal5_getname(tok)
939 return (atp->atp_name);