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 $
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 *);
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,
98 .pru_soreceive = soreceive
104 static Atm_endpoint atm_aal5_endpt = {
122 static Atm_attributes atm_aal5_defattr = {
124 CMAPI_CPCS, /* api */
175 * Handy common code macros
178 #define ATM_INTRO(f) \
181 ATM_DEBUG2("aal5 socket %s (%p)\n", f, so); \
183 * Stack queue should have been drained \
185 if (atm_stackq_head != NULL) \
186 panic("atm_aal5: stack queue not empty"); \
188 #else /* !DIAGNOSTIC */
189 #define ATM_INTRO(f) \
193 #endif /* DIAGNOSTIC */
195 #define ATM_OUTRO() \
197 * Drain any deferred calls \
204 #define ATM_RETERR(error) { \
211 * Attach protocol to socket
214 * so pointer to socket
215 * proto protocol identifier
216 * p pointer to process
219 * 0 request processed
220 * error error processing request - reason indicated
224 atm_aal5_attach(struct socket *so, int proto, struct pru_attach_info *ai)
231 * Do general attach stuff
233 err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace,
239 * Finish up any protocol specific stuff
241 atp = sotoatmpcb(so);
242 atp->atp_type = ATPT_AAL5;
245 * Set default connection attributes
247 atp->atp_attr = atm_aal5_defattr;
248 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
256 * Detach protocol from socket
259 * so pointer to socket
262 * 0 request processed
263 * error error processing request - reason indicated
267 atm_aal5_detach(struct socket *so)
271 err = atm_sock_detach(so);
278 * Bind address to socket
281 * so pointer to socket
282 * addr pointer to protocol address
283 * p pointer to process
286 * 0 request processed
287 * error error processing request - reason indicated
291 atm_aal5_bind(struct socket *so, struct sockaddr *addr, struct thread *td)
295 err = atm_sock_bind(so, addr);
302 * Listen for incoming connections
305 * so pointer to socket
306 * p pointer to process
309 * 0 request processed
310 * error error processing request - reason indicated
314 atm_aal5_listen(struct socket *so, struct thread *td)
318 err = atm_sock_listen(so, &atm_aal5_endpt);
325 * Connect socket to peer
328 * so pointer to socket
329 * addr pointer to protocol address
330 * p pointer to process
333 * 0 request processed
334 * error error processing request - reason indicated
338 atm_aal5_connect(struct socket *so, struct sockaddr *addr, thread_t td)
342 ATM_INTRO("connect");
344 atp = sotoatmpcb(so);
347 * Resize send socket buffer to maximum sdu size
349 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
352 size = atp->atp_attr.aal.v.aal5.forward_max_SDU_size;
353 if (size != T_ATM_ABSENT)
354 if (!ssb_reserve(&so->so_snd, size, so,
355 &td->td_proc->p_rlimit[RLIMIT_SBSIZE])) {
363 * Now get the socket connected
365 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
372 * Accept pending connection
375 * so pointer to socket
376 * addr pointer to pointer to contain protocol address
379 * 0 request processed
380 * error error processing request - reason indicated
384 atm_aal5_accept(struct socket *so, struct sockaddr **addr)
389 * Everything is pretty much done already, we just need to
390 * return the caller's address to the user.
392 err = atm_sock_peeraddr(so, addr);
399 * Disconnect connected socket
402 * so pointer to socket
405 * 0 request processed
406 * error error processing request - reason indicated
410 atm_aal5_disconnect(struct socket *so)
412 ATM_INTRO("disconnect");
414 err = atm_sock_disconnect(so);
421 * Shut down socket data transmission
424 * so pointer to socket
427 * 0 request processed
428 * error error processing request - reason indicated
432 atm_aal5_shutdown(struct socket *so)
434 ATM_INTRO("shutdown");
446 * so pointer to socket
447 * flags send data flags
448 * m pointer to buffer containing user data
449 * addr pointer to protocol address
450 * control pointer to buffer containing protocol control data
451 * p pointer to process
454 * 0 request processed
455 * error error processing request - reason indicated
463 struct sockaddr *addr,
472 * We don't support any control functions
477 clen = KB_LEN(control);
486 * We also don't support any flags or send-level addressing
494 * All we've got left is the data, so push it out
496 atp = sotoatmpcb(so);
497 err = atm_cm_cpcs_data(atp->atp_conn, m);
500 * Output problem, drop packet
502 atm_sock_stat.as_outdrop[atp->atp_type]++;
512 * Abnormally terminate service
515 * so pointer to socket
518 * 0 request processed
519 * error error processing request - reason indicated
523 atm_aal5_abort(struct socket *so)
527 so->so_error = ECONNABORTED;
528 err = atm_sock_detach(so);
535 * Do control operation - ioctl system call
538 * so pointer to socket
540 * data pointer to code specific parameter data area
541 * ifp pointer to ifnet structure if it's an interface ioctl
542 * p pointer to process
545 * 0 request processed
546 * error error processing request - reason indicated
557 ATM_INTRO("control");
569 * Sense socket status - fstat system call
572 * so pointer to socket
573 * st pointer to file status structure
576 * 0 request processed
577 * error error processing request - reason indicated
581 atm_aal5_sense(struct socket *so, struct stat *st)
586 * Just return the max sdu size for the connection
588 st->st_blksize = so->so_snd.ssb_hiwat;
595 * Retrieve local socket address
598 * so pointer to socket
599 * addr pointer to pointer to contain protocol address
602 * 0 request processed
603 * error error processing request - reason indicated
607 atm_aal5_sockaddr(struct socket *so, struct sockaddr **addr)
609 ATM_INTRO("sockaddr");
611 err = atm_sock_sockaddr(so, addr);
618 * Retrieve peer socket address
621 * so pointer to socket
622 * addr pointer to pointer to contain protocol address
625 * 0 request processed
626 * error error processing request - reason indicated
630 atm_aal5_peeraddr(struct socket *so, struct sockaddr **addr)
632 ATM_INTRO("peeraddr");
634 err = atm_sock_peeraddr(so, addr);
641 * Process Incoming Calls
643 * This function will receive control when an incoming call has been matched
644 * to one of our registered listen parameter blocks. Assuming the call passes
645 * acceptance criteria and all required resources are available, we will
646 * create a new protocol control block and socket association. We must
647 * then await notification of the final SVC setup results. If any
648 * problems are encountered, we will just tell the connection manager to
651 * Called from a critical section.
654 * tok owner's matched listening token
655 * cop pointer to incoming call's connection block
656 * ap pointer to incoming call's attributes
657 * tokp pointer to location to store our connection token
661 * error call rejected - reason indicated
665 atm_aal5_incoming(void *tok, Atm_connection *cop, Atm_attributes *ap,
668 Atm_pcb *atp0 = tok, *atp;
673 * Allocate a new socket and pcb for this connection.
675 * Note that our attach function will be called via sonewconn
676 * and it will allocate and setup most of the pcb.
678 atm_sock_stat.as_inconn[atp0->atp_type]++;
679 so = sonewconn(atp0->atp_socket, 0);
683 * Finish pcb setup and pass pcb back to CM
685 atp = sotoatmpcb(so);
687 atp->atp_attr = *atp0->atp_conn->co_lattr;
688 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
692 atm_sock_stat.as_connfail[atp0->atp_type]++;
700 * Process Socket VCC Input Data
703 * tok owner's connection token (atm_pcb)
704 * m pointer to input packet buffer chain
711 atm_aal5_cpcs_data(void *tok, KBuffer *m)
717 so = atp->atp_socket;
722 * Ensure that the socket is able to receive data and
723 * that there's room in the socket buffer
725 if (((so->so_state & SS_ISCONNECTED) == 0) ||
726 (so->so_state & SS_CANTRCVMORE) ||
727 (len > ssb_space(&so->so_rcv))) {
728 atm_sock_stat.as_indrop[atp->atp_type]++;
734 * Queue the data and notify the user
736 ssb_appendrecord(&so->so_rcv, m);
744 * Process getsockopt/setsockopt system calls
747 * so pointer to socket
748 * sopt pointer to socket option info
751 * 0 request processed
752 * error error processing request - reason indicated
756 atm_aal5_ctloutput(struct socket *so, struct sockopt *sopt)
760 ATM_INTRO("ctloutput");
763 * Make sure this is for us
765 if (sopt->sopt_level != T_ATM_SIGNALING) {
768 atp = sotoatmpcb(so);
770 ATM_RETERR(ENOTCONN);
773 switch (sopt->sopt_dir) {
781 * Validate socket state
783 switch (sopt->sopt_name) {
786 case T_ATM_DROP_LEAF:
787 if ((so->so_state & SS_ISCONNECTED) == 0) {
788 ATM_RETERR(ENOTCONN);
797 if (so->so_state & SS_ISCONNECTED) {
804 * Validate and save user-supplied option data
806 err = atm_sock_setopt(so, sopt, atp);
818 err = atm_sock_getopt(so, sopt, atp);
829 * Initialize AAL5 Sockets
842 * Register our endpoint
844 if (atm_endpoint_register(&atm_aal5_endpt))
845 panic("atm_aal5_init: register");
848 * Set default connection attributes
850 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
851 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
852 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
857 * Get Connection's Application/Owner Name
860 * tok owner's connection token (atm_pcb)
863 * addr pointer to string containing our name
867 atm_aal5_getname(void *tok)
871 return (atp->atp_name);