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.
34 * ATM AAL5 socket protocol processing
38 #include <netatm/kern_include.h>
42 __RCSID("@(#) $FreeBSD$");
49 u_long atm_aal5_sendspace = 64 * 1024; /* XXX */
50 u_long atm_aal5_recvspace = 64 * 1024; /* XXX */
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 *,
60 static int atm_aal5_listen __P((struct socket *, struct proc *));
61 static int atm_aal5_connect __P((struct socket *, struct sockaddr *,
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 *));
80 #if (defined(__FreeBSD__) && (BSD >= 199506))
82 * New-style socket request routines
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 */
112 static Atm_endpoint atm_aal5_endpt = {
130 static Atm_attributes atm_aal5_defattr = {
132 CMAPI_CPCS, /* api */
183 * Handy common code macros
186 #define ATM_INTRO(f) \
189 ATM_DEBUG2("aal5 socket %s (%p)\n", f, so); \
191 * Stack queue should have been drained \
193 if (atm_stackq_head != NULL) \
194 panic("atm_aal5: stack queue not empty"); \
196 #else /* !DIAGNOSTIC */
197 #define ATM_INTRO(f) \
201 #endif /* DIAGNOSTIC */
203 #define ATM_OUTRO() \
205 * Drain any deferred calls \
212 #define ATM_RETERR(errno) { \
219 * Attach protocol to socket
222 * so pointer to socket
223 * proto protocol identifier
224 * p pointer to process
227 * 0 request processed
228 * errno error processing request - reason indicated
232 atm_aal5_attach(so, proto, p)
242 * Do general attach stuff
244 err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace);
249 * Finish up any protocol specific stuff
251 atp = sotoatmpcb(so);
252 atp->atp_type = ATPT_AAL5;
255 * Set default connection attributes
257 atp->atp_attr = atm_aal5_defattr;
258 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
266 * Detach protocol from socket
269 * so pointer to socket
272 * 0 request processed
273 * errno error processing request - reason indicated
282 err = atm_sock_detach(so);
289 * Bind address to socket
292 * so pointer to socket
293 * addr pointer to protocol address
294 * p pointer to process
297 * 0 request processed
298 * errno error processing request - reason indicated
302 atm_aal5_bind(so, addr, p)
304 struct sockaddr *addr;
309 err = atm_sock_bind(so, addr);
316 * Listen for incoming connections
319 * so pointer to socket
320 * p pointer to process
323 * 0 request processed
324 * errno error processing request - reason indicated
328 atm_aal5_listen(so, p)
334 err = atm_sock_listen(so, &atm_aal5_endpt);
341 * Connect socket to peer
344 * so pointer to socket
345 * addr pointer to protocol address
346 * p pointer to process
349 * 0 request processed
350 * errno error processing request - reason indicated
354 atm_aal5_connect(so, addr, p)
356 struct sockaddr *addr;
361 ATM_INTRO("connect");
363 atp = sotoatmpcb(so);
366 * Resize send socket buffer to maximum sdu size
368 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
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)) {
381 * Now get the socket connected
383 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
390 * Accept pending connection
393 * so pointer to socket
394 * addr pointer to pointer to contain protocol address
397 * 0 request processed
398 * errno error processing request - reason indicated
402 atm_aal5_accept(so, addr)
404 struct sockaddr **addr;
409 * Everything is pretty much done already, we just need to
410 * return the caller's address to the user.
412 err = atm_sock_peeraddr(so, addr);
419 * Disconnect connected socket
422 * so pointer to socket
425 * 0 request processed
426 * errno error processing request - reason indicated
430 atm_aal5_disconnect(so)
433 ATM_INTRO("disconnect");
435 err = atm_sock_disconnect(so);
442 * Shut down socket data transmission
445 * so pointer to socket
448 * 0 request processed
449 * errno error processing request - reason indicated
453 atm_aal5_shutdown(so)
456 ATM_INTRO("shutdown");
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
476 * 0 request processed
477 * errno error processing request - reason indicated
481 atm_aal5_send(so, flags, m, addr, control, p)
485 struct sockaddr *addr;
494 * We don't support any control functions
499 clen = KB_LEN(control);
508 * We also don't support any flags or send-level addressing
516 * All we've got left is the data, so push it out
518 atp = sotoatmpcb(so);
519 err = atm_cm_cpcs_data(atp->atp_conn, m);
522 * Output problem, drop packet
524 atm_sock_stat.as_outdrop[atp->atp_type]++;
534 * Abnormally terminate service
537 * so pointer to socket
540 * 0 request processed
541 * errno error processing request - reason indicated
550 so->so_error = ECONNABORTED;
551 err = atm_sock_detach(so);
558 * Do control operation - ioctl system call
561 * so pointer to socket
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
568 * 0 request processed
569 * errno error processing request - reason indicated
573 atm_aal5_control(so, cmd, data, ifp, p)
580 ATM_INTRO("control");
592 * Sense socket status - fstat system call
595 * so pointer to socket
596 * st pointer to file status structure
599 * 0 request processed
600 * errno error processing request - reason indicated
604 atm_aal5_sense(so, st)
611 * Just return the max sdu size for the connection
613 st->st_blksize = so->so_snd.sb_hiwat;
620 * Retrieve local socket address
623 * so pointer to socket
624 * addr pointer to pointer to contain protocol address
627 * 0 request processed
628 * errno error processing request - reason indicated
632 atm_aal5_sockaddr(so, addr)
634 struct sockaddr **addr;
636 ATM_INTRO("sockaddr");
638 err = atm_sock_sockaddr(so, addr);
645 * Retrieve peer socket address
648 * so pointer to socket
649 * addr pointer to pointer to contain protocol address
652 * 0 request processed
653 * errno error processing request - reason indicated
657 atm_aal5_peeraddr(so, addr)
659 struct sockaddr **addr;
661 ATM_INTRO("peeraddr");
663 err = atm_sock_peeraddr(so, addr);
670 * Process Incoming Calls
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
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
690 * errno call rejected - reason indicated
694 atm_aal5_incoming(tok, cop, ap, tokp)
700 Atm_pcb *atp0 = tok, *atp;
705 * Allocate a new socket and pcb for this connection.
707 * Note that our attach function will be called via sonewconn
708 * and it will allocate and setup most of the pcb.
710 atm_sock_stat.as_inconn[atp0->atp_type]++;
711 #if (defined(BSD) && (BSD >= 199103))
712 so = sonewconn(atp0->atp_socket, 0);
714 so = sonewconn(atp0->atp_socket);
719 * Finish pcb setup and pass pcb back to CM
721 atp = sotoatmpcb(so);
723 atp->atp_attr = *atp0->atp_conn->co_lattr;
724 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
728 atm_sock_stat.as_connfail[atp0->atp_type]++;
736 * Process Socket VCC Input Data
739 * tok owner's connection token (atm_pcb)
740 * m pointer to input packet buffer chain
747 atm_aal5_cpcs_data(tok, m)
755 so = atp->atp_socket;
760 * Ensure that the socket is able to receive data and
761 * that there's room in the socket buffer
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]++;
772 * Queue the data and notify the user
774 sbappendrecord(&so->so_rcv, m);
782 * Process getsockopt/setsockopt system calls
785 * so pointer to socket
786 * sopt pointer to socket option info
789 * 0 request processed
790 * errno error processing request - reason indicated
794 atm_aal5_ctloutput(so, sopt)
796 struct sockopt *sopt;
800 ATM_INTRO("ctloutput");
803 * Make sure this is for us
805 if (sopt->sopt_level != T_ATM_SIGNALING) {
808 atp = sotoatmpcb(so);
810 ATM_RETERR(ENOTCONN);
813 switch (sopt->sopt_dir) {
821 * Validate socket state
823 switch (sopt->sopt_name) {
826 case T_ATM_DROP_LEAF:
827 if ((so->so_state & SS_ISCONNECTED) == 0) {
828 ATM_RETERR(ENOTCONN);
837 if (so->so_state & SS_ISCONNECTED) {
844 * Validate and save user-supplied option data
846 err = atm_sock_setopt(so, sopt, atp);
858 err = atm_sock_getopt(so, sopt, atp);
869 * Initialize AAL5 Sockets
882 * Register our endpoint
884 if (atm_endpoint_register(&atm_aal5_endpt))
885 panic("atm_aal5_init: register");
888 * Set default connection attributes
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;
897 * Get Connection's Application/Owner Name
900 * tok owner's connection token (atm_pcb)
903 * addr pointer to string containing our name
907 atm_aal5_getname(tok)
912 return (atp->atp_name);