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 void atm_aal5_abort(netmsg_t);
52 static void atm_aal5_accept(netmsg_t);
53 static void atm_aal5_attach(netmsg_t);
54 static void atm_aal5_bind(netmsg_t);
55 static void atm_aal5_connect(netmsg_t);
56 static void atm_aal5_control(netmsg_t);
57 static void atm_aal5_detach(netmsg_t);
58 static void atm_aal5_listen(netmsg_t);
59 static void atm_aal5_peeraddr(netmsg_t);
60 static void atm_aal5_send(netmsg_t);
61 static void atm_aal5_sense(netmsg_t);
62 static void atm_aal5_disconnect(netmsg_t);
63 static void atm_aal5_shutdown(netmsg_t);
64 static void atm_aal5_sockaddr(netmsg_t);
66 static int atm_aal5_incoming (void *, Atm_connection *,
67 Atm_attributes *, void **);
68 static void atm_aal5_cpcs_data (void *, KBuffer *);
69 static caddr_t atm_aal5_getname (void *);
73 * New-style socket request routines
75 struct pr_usrreqs atm_aal5_usrreqs = {
76 .pru_abort = atm_aal5_abort,
77 .pru_accept = atm_aal5_accept,
78 .pru_attach = atm_aal5_attach,
79 .pru_bind = atm_aal5_bind,
80 .pru_connect = atm_aal5_connect,
81 .pru_connect2 = pr_generic_notsupp,
82 .pru_control = atm_aal5_control,
83 .pru_detach = atm_aal5_detach,
84 .pru_disconnect = atm_aal5_disconnect,
85 .pru_listen = atm_aal5_listen,
86 .pru_peeraddr = atm_aal5_peeraddr,
87 .pru_rcvd = pr_generic_notsupp,
88 .pru_rcvoob = pr_generic_notsupp,
89 .pru_send = atm_aal5_send,
90 .pru_sense = atm_aal5_sense,
91 .pru_shutdown = atm_aal5_shutdown,
92 .pru_sockaddr = atm_aal5_sockaddr,
94 .pru_soreceive = soreceive
100 static Atm_endpoint atm_aal5_endpt = {
118 static Atm_attributes atm_aal5_defattr = {
120 CMAPI_CPCS, /* api */
171 * Handy common code macros
175 #define ATM_INTRO(f) \
178 ATM_DEBUG2("aal5 socket %s (%p)\n", f, so); \
180 * Stack queue should have been drained \
182 if (atm_stackq_head != NULL) \
183 panic("atm_aal5: stack queue not empty"); \
186 #else /* !DIAGNOSTIC */
188 #define ATM_INTRO(f) \
193 #endif /* DIAGNOSTIC */
195 #define ATM_OUTRO() \
198 * Drain any deferred calls \
202 lwkt_replymsg(&msg->lmsg, error); \
208 * Abnormally terminate service
211 * so pointer to socket
214 * 0 request processed
215 * error error processing request - reason indicated
217 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
218 * will sofree() it when we return.
221 atm_aal5_abort(netmsg_t msg)
223 struct socket *so = msg->abort.base.nm_so;
227 so->so_error = ECONNABORTED;
228 error = atm_sock_detach(so);
233 * Accept pending connection
236 * so pointer to socket
237 * addr pointer to pointer to contain protocol address
240 * 0 request processed
241 * error error processing request - reason indicated
245 atm_aal5_accept(netmsg_t msg)
247 struct socket *so = msg->accept.base.nm_so;
253 * Everything is pretty much done already, we just need to
254 * return the caller's address to the user.
256 error = atm_sock_peeraddr(so, msg->accept.nm_nam);
261 * Attach protocol to socket
264 * so pointer to socket
265 * proto protocol identifier
266 * p pointer to process
269 * 0 request processed
270 * error error processing request - reason indicated
274 atm_aal5_attach(netmsg_t msg)
276 struct socket *so = msg->attach.base.nm_so;
277 struct pru_attach_info *ai = msg->attach.nm_ai;
284 * Do general attach stuff
286 error = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace,
292 * Finish up any protocol specific stuff
294 atp = sotoatmpcb(so);
295 atp->atp_type = ATPT_AAL5;
298 * Set default connection attributes
300 atp->atp_attr = atm_aal5_defattr;
301 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
307 * Detach protocol from socket
310 * so pointer to socket
313 * 0 request processed
314 * error error processing request - reason indicated
318 atm_aal5_detach(netmsg_t msg)
320 struct socket *so = msg->detach.base.nm_so;
325 error = atm_sock_detach(so);
331 * Bind address to socket
334 * so pointer to socket
335 * addr pointer to protocol address
336 * p pointer to process
339 * 0 request processed
340 * error error processing request - reason indicated
344 atm_aal5_bind(netmsg_t msg)
346 struct socket *so = msg->bind.base.nm_so;
351 error = atm_sock_bind(so, msg->bind.nm_nam);
357 * Listen for incoming connections
360 * so pointer to socket
361 * p pointer to process
364 * 0 request processed
365 * error error processing request - reason indicated
369 atm_aal5_listen(netmsg_t msg)
371 struct socket *so = msg->listen.base.nm_so;
376 error = atm_sock_listen(so, &atm_aal5_endpt);
383 * Connect socket to peer
386 * so pointer to socket
387 * addr pointer to protocol address
388 * p pointer to process
391 * 0 request processed
392 * error error processing request - reason indicated
396 atm_aal5_connect(netmsg_t msg)
398 struct socket *so = msg->connect.base.nm_so;
399 struct thread *td = msg->connect.nm_td;
403 ATM_INTRO("connect");
405 atp = sotoatmpcb(so);
408 * Resize send socket buffer to maximum sdu size
410 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
413 size = atp->atp_attr.aal.v.aal5.forward_max_SDU_size;
414 if (size != T_ATM_ABSENT) {
415 if (!ssb_reserve(&so->so_snd, size, so,
416 &td->td_proc->p_rlimit[RLIMIT_SBSIZE])) {
424 * Now get the socket connected
426 error = atm_sock_connect(so, msg->connect.nm_nam, &atm_aal5_endpt);
432 * Disconnect connected socket
435 * so pointer to socket
438 * 0 request processed
439 * error error processing request - reason indicated
443 atm_aal5_disconnect(netmsg_t msg)
445 struct socket *so = msg->disconnect.base.nm_so;
448 ATM_INTRO("disconnect");
450 error = atm_sock_disconnect(so);
457 * Shut down socket data transmission
460 * so pointer to socket
463 * 0 request processed
464 * error error processing request - reason indicated
468 atm_aal5_shutdown(netmsg_t msg)
470 struct socket *so = msg->shutdown.base.nm_so;
473 ATM_INTRO("shutdown");
486 * so pointer to socket
487 * flags send data flags
488 * m pointer to buffer containing user data
489 * addr pointer to protocol address
490 * control pointer to buffer containing protocol control data
491 * p pointer to process
494 * 0 request processed
495 * error error processing request - reason indicated
499 atm_aal5_send(netmsg_t msg)
501 struct socket *so = msg->send.base.nm_so;
502 KBuffer *m = msg->send.nm_m;
503 KBuffer *control = msg->send.nm_control;
510 * We don't support any control functions
515 clen = KB_LEN(control);
525 * We also don't support any flags or send-level addressing
527 if (msg->send.nm_flags || msg->send.nm_addr) {
534 * All we've got left is the data, so push it out
536 atp = sotoatmpcb(so);
537 error = atm_cm_cpcs_data(atp->atp_conn, m);
540 * Output problem, drop packet
542 atm_sock_stat.as_outdrop[atp->atp_type]++;
551 * Do control operation - ioctl system call
554 * so pointer to socket
556 * data pointer to code specific parameter data area
557 * ifp pointer to ifnet structure if it's an interface ioctl
558 * p pointer to process
561 * 0 request processed
562 * error error processing request - reason indicated
566 atm_aal5_control(netmsg_t msg)
568 struct socket *so = msg->control.base.nm_so;
571 ATM_INTRO("control");
573 switch (msg->control.nm_cmd) {
583 * Sense socket status - fstat system call
586 * so pointer to socket
587 * st pointer to file status structure
590 * 0 request processed
591 * error error processing request - reason indicated
595 atm_aal5_sense(netmsg_t msg)
597 struct socket *so = msg->sense.base.nm_so;
598 struct stat *st = msg->sense.nm_stat;
604 * Just return the max sdu size for the connection
606 st->st_blksize = so->so_snd.ssb_hiwat;
614 * Retrieve local socket address
617 * so pointer to socket
618 * addr pointer to pointer to contain protocol address
621 * 0 request processed
622 * error error processing request - reason indicated
626 atm_aal5_sockaddr(netmsg_t msg)
628 struct socket *so = msg->sockaddr.base.nm_so;
631 ATM_INTRO("sockaddr");
633 error = atm_sock_sockaddr(so, msg->sockaddr.nm_nam);
640 * Retrieve peer socket address
643 * so pointer to socket
644 * addr pointer to pointer to contain protocol address
647 * 0 request processed
648 * error error processing request - reason indicated
652 atm_aal5_peeraddr(netmsg_t msg)
654 struct socket *so = msg->peeraddr.base.nm_so;
657 ATM_INTRO("peeraddr");
659 error = atm_sock_peeraddr(so, msg->peeraddr.nm_nam);
665 * Process getsockopt/setsockopt system calls
668 * so pointer to socket
669 * sopt pointer to socket option info
672 * 0 request processed
673 * error error processing request - reason indicated
677 atm_aal5_ctloutput(netmsg_t msg)
679 struct socket *so = msg->ctloutput.base.nm_so;
680 struct sockopt *sopt = msg->ctloutput.nm_sopt;
684 ATM_INTRO("ctloutput");
687 * Make sure this is for us
689 if (sopt->sopt_level != T_ATM_SIGNALING) {
693 atp = sotoatmpcb(so);
699 switch (sopt->sopt_dir) {
706 * Validate socket state
708 switch (sopt->sopt_name) {
710 case T_ATM_DROP_LEAF:
711 if ((so->so_state & SS_ISCONNECTED) == 0) {
720 if (so->so_state & SS_ISCONNECTED) {
728 * Validate and save user-supplied option data
730 error = atm_sock_setopt(so, sopt, atp);
740 error = atm_sock_getopt(so, sopt, atp);
751 * Process Incoming Calls
753 * This function will receive control when an incoming call has been matched
754 * to one of our registered listen parameter blocks. Assuming the call passes
755 * acceptance criteria and all required resources are available, we will
756 * create a new protocol control block and socket association. We must
757 * then await notification of the final SVC setup results. If any
758 * problems are encountered, we will just tell the connection manager to
761 * Called from a critical section.
764 * tok owner's matched listening token
765 * cop pointer to incoming call's connection block
766 * ap pointer to incoming call's attributes
767 * tokp pointer to location to store our connection token
771 * error call rejected - reason indicated
775 atm_aal5_incoming(void *tok, Atm_connection *cop, Atm_attributes *ap,
778 Atm_pcb *atp0 = tok, *atp;
783 * Allocate a new socket and pcb for this connection.
785 * Note that our attach function will be called via sonewconn
786 * and it will allocate and setup most of the pcb.
788 atm_sock_stat.as_inconn[atp0->atp_type]++;
789 so = sonewconn(atp0->atp_socket, 0);
793 * Finish pcb setup and pass pcb back to CM
795 atp = sotoatmpcb(so);
797 atp->atp_attr = *atp0->atp_conn->co_lattr;
798 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
802 atm_sock_stat.as_connfail[atp0->atp_type]++;
810 * Process Socket VCC Input Data
813 * tok owner's connection token (atm_pcb)
814 * m pointer to input packet buffer chain
821 atm_aal5_cpcs_data(void *tok, KBuffer *m)
827 so = atp->atp_socket;
832 * Ensure that the socket is able to receive data and
833 * that there's room in the socket buffer
835 if (((so->so_state & SS_ISCONNECTED) == 0) ||
836 (so->so_state & SS_CANTRCVMORE) ||
837 (len > ssb_space(&so->so_rcv))) {
838 atm_sock_stat.as_indrop[atp->atp_type]++;
844 * Queue the data and notify the user
846 ssb_appendrecord(&so->so_rcv, m);
853 * Initialize AAL5 Sockets
866 * Register our endpoint
868 if (atm_endpoint_register(&atm_aal5_endpt))
869 panic("atm_aal5_init: register");
872 * Set default connection attributes
874 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
875 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
876 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
881 * Get Connection's Application/Owner Name
884 * tok owner's connection token (atm_pcb)
887 * addr pointer to string containing our name
891 atm_aal5_getname(void *tok)
895 return (atp->atp_name);