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.7 2004/03/05 19:17:25 hsu Exp $
34 * ATM AAL5 socket protocol processing
38 #include "kern_include.h"
44 u_long atm_aal5_sendspace = 64 * 1024; /* XXX */
45 u_long atm_aal5_recvspace = 64 * 1024; /* XXX */
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 *,
56 static int atm_aal5_listen (struct socket *, struct thread *);
57 static int atm_aal5_connect (struct socket *, struct sockaddr *,
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 *);
76 #if (defined(__DragonFly__) && (BSD >= 199506))
78 * New-style socket request routines
80 struct pr_usrreqs atm_aal5_usrreqs = {
81 atm_aal5_abort, /* pru_abort */
82 atm_aal5_accept, /* pru_accept */
83 atm_aal5_attach, /* pru_attach */
84 atm_aal5_bind, /* pru_bind */
85 atm_aal5_connect, /* pru_connect */
86 pru_connect2_notsupp, /* pru_connect2 */
87 atm_aal5_control, /* pru_control */
88 atm_aal5_detach, /* pru_detach */
89 atm_aal5_disconnect, /* pru_disconnect */
90 atm_aal5_listen, /* pru_listen */
91 atm_aal5_peeraddr, /* pru_peeraddr */
92 pru_rcvd_notsupp, /* pru_rcvd */
93 pru_rcvoob_notsupp, /* pru_rcvoob */
94 atm_aal5_send, /* pru_send */
95 atm_aal5_sense, /* pru_sense */
96 atm_aal5_shutdown, /* pru_shutdown */
97 atm_aal5_sockaddr, /* pru_sockaddr */
98 sosend, /* pru_sosend */
99 soreceive, /* pru_soreceive */
100 sopoll /* pru_sopoll */
108 static Atm_endpoint atm_aal5_endpt = {
126 static Atm_attributes atm_aal5_defattr = {
128 CMAPI_CPCS, /* api */
179 * Handy common code macros
182 #define ATM_INTRO(f) \
185 ATM_DEBUG2("aal5 socket %s (%p)\n", f, so); \
187 * Stack queue should have been drained \
189 if (atm_stackq_head != NULL) \
190 panic("atm_aal5: stack queue not empty"); \
192 #else /* !DIAGNOSTIC */
193 #define ATM_INTRO(f) \
197 #endif /* DIAGNOSTIC */
199 #define ATM_OUTRO() \
201 * Drain any deferred calls \
208 #define ATM_RETERR(errno) { \
215 * Attach protocol to socket
218 * so pointer to socket
219 * proto protocol identifier
220 * p pointer to process
223 * 0 request processed
224 * errno error processing request - reason indicated
228 atm_aal5_attach(so, proto, ai)
231 struct pru_attach_info *ai;
238 * Do general attach stuff
240 err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace,
246 * Finish up any protocol specific stuff
248 atp = sotoatmpcb(so);
249 atp->atp_type = ATPT_AAL5;
252 * Set default connection attributes
254 atp->atp_attr = atm_aal5_defattr;
255 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
263 * Detach protocol from socket
266 * so pointer to socket
269 * 0 request processed
270 * errno error processing request - reason indicated
279 err = atm_sock_detach(so);
286 * Bind address to socket
289 * so pointer to socket
290 * addr pointer to protocol address
291 * p pointer to process
294 * 0 request processed
295 * errno error processing request - reason indicated
299 atm_aal5_bind(so, addr, td)
301 struct sockaddr *addr;
306 err = atm_sock_bind(so, addr);
313 * Listen for incoming connections
316 * so pointer to socket
317 * p pointer to process
320 * 0 request processed
321 * errno error processing request - reason indicated
325 atm_aal5_listen(struct socket *so, struct thread *td)
329 err = atm_sock_listen(so, &atm_aal5_endpt);
336 * Connect socket to peer
339 * so pointer to socket
340 * addr pointer to protocol address
341 * p pointer to process
344 * 0 request processed
345 * errno error processing request - reason indicated
349 atm_aal5_connect(struct socket *so, struct sockaddr *addr, thread_t td)
353 ATM_INTRO("connect");
355 atp = sotoatmpcb(so);
358 * Resize send socket buffer to maximum sdu size
360 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
363 size = atp->atp_attr.aal.v.aal5.forward_max_SDU_size;
364 if (size != T_ATM_ABSENT)
365 if (!sbreserve(&so->so_snd, size, so,
366 &td->td_proc->p_rlimit[RLIMIT_SBSIZE])) {
374 * Now get the socket connected
376 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
383 * Accept pending connection
386 * so pointer to socket
387 * addr pointer to pointer to contain protocol address
390 * 0 request processed
391 * errno error processing request - reason indicated
395 atm_aal5_accept(struct socket *so, struct sockaddr **addr)
400 * Everything is pretty much done already, we just need to
401 * return the caller's address to the user.
403 err = atm_sock_peeraddr(so, addr);
410 * Disconnect connected socket
413 * so pointer to socket
416 * 0 request processed
417 * errno error processing request - reason indicated
421 atm_aal5_disconnect(struct socket *so)
423 ATM_INTRO("disconnect");
425 err = atm_sock_disconnect(so);
432 * Shut down socket data transmission
435 * so pointer to socket
438 * 0 request processed
439 * errno error processing request - reason indicated
443 atm_aal5_shutdown(struct socket *so)
445 ATM_INTRO("shutdown");
457 * so pointer to socket
458 * flags send data flags
459 * m pointer to buffer containing user data
460 * addr pointer to protocol address
461 * control pointer to buffer containing protocol control data
462 * p pointer to process
465 * 0 request processed
466 * errno error processing request - reason indicated
474 struct sockaddr *addr,
483 * We don't support any control functions
488 clen = KB_LEN(control);
497 * We also don't support any flags or send-level addressing
505 * All we've got left is the data, so push it out
507 atp = sotoatmpcb(so);
508 err = atm_cm_cpcs_data(atp->atp_conn, m);
511 * Output problem, drop packet
513 atm_sock_stat.as_outdrop[atp->atp_type]++;
523 * Abnormally terminate service
526 * so pointer to socket
529 * 0 request processed
530 * errno error processing request - reason indicated
534 atm_aal5_abort(struct socket *so)
538 so->so_error = ECONNABORTED;
539 err = atm_sock_detach(so);
546 * Do control operation - ioctl system call
549 * so pointer to socket
551 * data pointer to code specific parameter data area
552 * ifp pointer to ifnet structure if it's an interface ioctl
553 * p pointer to process
556 * 0 request processed
557 * errno error processing request - reason indicated
568 ATM_INTRO("control");
580 * Sense socket status - fstat system call
583 * so pointer to socket
584 * st pointer to file status structure
587 * 0 request processed
588 * errno error processing request - reason indicated
592 atm_aal5_sense(struct socket *so, struct stat *st)
597 * Just return the max sdu size for the connection
599 st->st_blksize = so->so_snd.sb_hiwat;
606 * Retrieve local socket address
609 * so pointer to socket
610 * addr pointer to pointer to contain protocol address
613 * 0 request processed
614 * errno error processing request - reason indicated
618 atm_aal5_sockaddr(struct socket *so, struct sockaddr **addr)
620 ATM_INTRO("sockaddr");
622 err = atm_sock_sockaddr(so, addr);
629 * Retrieve peer socket address
632 * so pointer to socket
633 * addr pointer to pointer to contain protocol address
636 * 0 request processed
637 * errno error processing request - reason indicated
641 atm_aal5_peeraddr(struct socket *so, struct sockaddr **addr)
643 ATM_INTRO("peeraddr");
645 err = atm_sock_peeraddr(so, addr);
652 * Process Incoming Calls
654 * This function will receive control when an incoming call has been matched
655 * to one of our registered listen parameter blocks. Assuming the call passes
656 * acceptance criteria and all required resources are available, we will
657 * create a new protocol control block and socket association. We must
658 * then await notification of the final SVC setup results. If any
659 * problems are encountered, we will just tell the connection manager to
665 * tok owner's matched listening token
666 * cop pointer to incoming call's connection block
667 * ap pointer to incoming call's attributes
668 * tokp pointer to location to store our connection token
672 * errno call rejected - reason indicated
676 atm_aal5_incoming(tok, cop, ap, tokp)
682 Atm_pcb *atp0 = tok, *atp;
687 * Allocate a new socket and pcb for this connection.
689 * Note that our attach function will be called via sonewconn
690 * and it will allocate and setup most of the pcb.
692 atm_sock_stat.as_inconn[atp0->atp_type]++;
693 #if (defined(BSD) && (BSD >= 199103))
694 so = sonewconn(atp0->atp_socket, 0);
696 so = sonewconn(atp0->atp_socket);
701 * Finish pcb setup and pass pcb back to CM
703 atp = sotoatmpcb(so);
705 atp->atp_attr = *atp0->atp_conn->co_lattr;
706 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
710 atm_sock_stat.as_connfail[atp0->atp_type]++;
718 * Process Socket VCC Input Data
721 * tok owner's connection token (atm_pcb)
722 * m pointer to input packet buffer chain
729 atm_aal5_cpcs_data(tok, m)
737 so = atp->atp_socket;
742 * Ensure that the socket is able to receive data and
743 * that there's room in the socket buffer
745 if (((so->so_state & SS_ISCONNECTED) == 0) ||
746 (so->so_state & SS_CANTRCVMORE) ||
747 (len > sbspace(&so->so_rcv))) {
748 atm_sock_stat.as_indrop[atp->atp_type]++;
754 * Queue the data and notify the user
756 sbappendrecord(&so->so_rcv, m);
764 * Process getsockopt/setsockopt system calls
767 * so pointer to socket
768 * sopt pointer to socket option info
771 * 0 request processed
772 * errno error processing request - reason indicated
776 atm_aal5_ctloutput(struct socket *so, struct sockopt *sopt)
780 ATM_INTRO("ctloutput");
783 * Make sure this is for us
785 if (sopt->sopt_level != T_ATM_SIGNALING) {
788 atp = sotoatmpcb(so);
790 ATM_RETERR(ENOTCONN);
793 switch (sopt->sopt_dir) {
801 * Validate socket state
803 switch (sopt->sopt_name) {
806 case T_ATM_DROP_LEAF:
807 if ((so->so_state & SS_ISCONNECTED) == 0) {
808 ATM_RETERR(ENOTCONN);
817 if (so->so_state & SS_ISCONNECTED) {
824 * Validate and save user-supplied option data
826 err = atm_sock_setopt(so, sopt, atp);
838 err = atm_sock_getopt(so, sopt, atp);
849 * Initialize AAL5 Sockets
862 * Register our endpoint
864 if (atm_endpoint_register(&atm_aal5_endpt))
865 panic("atm_aal5_init: register");
868 * Set default connection attributes
870 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
871 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
872 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
877 * Get Connection's Application/Owner Name
880 * tok owner's connection token (atm_pcb)
883 * addr pointer to string containing our name
887 atm_aal5_getname(tok)
892 return (atp->atp_name);