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 *);
94 * New-style socket request routines
96 struct pr_usrreqs atm_aal5_usrreqs = {
97 .pru_abort = atm_aal5_abort,
98 .pru_accept = atm_aal5_accept,
99 .pru_attach = atm_aal5_attach,
100 .pru_bind = atm_aal5_bind,
101 .pru_connect = atm_aal5_connect,
102 .pru_control = atm_aal5_control,
103 .pru_detach = atm_aal5_detach,
104 .pru_disconnect = atm_aal5_disconnect,
105 .pru_listen = atm_aal5_listen,
106 .pru_peeraddr = atm_aal5_peeraddr,
107 .pru_send = atm_aal5_send,
108 .pru_sense = atm_aal5_sense,
109 .pru_shutdown = atm_aal5_shutdown,
110 .pru_sockaddr = atm_aal5_sockaddr,
116 static Atm_endpoint atm_aal5_endpt = {
134 static Atm_attributes atm_aal5_defattr = {
136 CMAPI_CPCS, /* api */
187 * Handy common code macros
190 #define ATM_INTRO(f) \
193 ATM_DEBUG2("aal5 socket %s (%p)\n", f, so); \
195 * Stack queue should have been drained \
197 if (atm_stackq_head != NULL) \
198 panic("atm_aal5: stack queue not empty"); \
200 #else /* !DIAGNOSTIC */
201 #define ATM_INTRO(f) \
205 #endif /* DIAGNOSTIC */
207 #define ATM_INTRO_NOERR(f) \
212 #define ATM_OUTRO() \
214 * Drain any deferred calls \
221 #define ATM_OUTRO_NOERR() \
223 * Drain any deferred calls \
229 #define ATM_RETERR(errno) { \
236 * Attach protocol to socket
239 * so pointer to socket
240 * proto protocol identifier
241 * p pointer to process
244 * 0 request processed
245 * errno error processing request - reason indicated
249 atm_aal5_attach(so, proto, td)
259 * Do general attach stuff
261 err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace);
266 * Finish up any protocol specific stuff
268 atp = sotoatmpcb(so);
269 atp->atp_type = ATPT_AAL5;
272 * Set default connection attributes
274 atp->atp_attr = atm_aal5_defattr;
275 strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
283 * Detach protocol from socket
286 * so pointer to socket
289 * 0 request processed
290 * errno error processing request - reason indicated
297 ATM_INTRO_NOERR("detach");
306 * Bind address to socket
309 * so pointer to socket
310 * addr pointer to protocol address
311 * p pointer to process
314 * 0 request processed
315 * errno error processing request - reason indicated
319 atm_aal5_bind(so, addr, td)
321 struct sockaddr *addr;
326 err = atm_sock_bind(so, addr);
333 * Listen for incoming connections
336 * so pointer to socket
337 * p pointer to process
340 * 0 request processed
341 * errno error processing request - reason indicated
345 atm_aal5_listen(so, backlog, td)
352 err = atm_sock_listen(so, &atm_aal5_endpt, backlog);
359 * Connect socket to peer
362 * so pointer to socket
363 * addr pointer to protocol address
364 * p pointer to process
367 * 0 request processed
368 * errno error processing request - reason indicated
372 atm_aal5_connect(so, addr, td)
374 struct sockaddr *addr;
379 ATM_INTRO("connect");
381 atp = sotoatmpcb(so);
384 * Resize send socket buffer to maximum sdu size
386 if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
389 size = atp->atp_attr.aal.v.aal5.forward_max_SDU_size;
390 if (size != T_ATM_ABSENT)
391 if (!sbreserve(&so->so_snd, size, so, td)) {
399 * Now get the socket connected
401 err = atm_sock_connect(so, addr, &atm_aal5_endpt);
408 * Accept pending connection
411 * so pointer to socket
412 * addr pointer to pointer to contain protocol address
415 * 0 request processed
416 * errno error processing request - reason indicated
420 atm_aal5_accept(so, addr)
422 struct sockaddr **addr;
427 * Everything is pretty much done already, we just need to
428 * return the caller's address to the user.
430 err = atm_sock_peeraddr(so, addr);
437 * Disconnect connected socket
440 * so pointer to socket
443 * 0 request processed
444 * errno error processing request - reason indicated
448 atm_aal5_disconnect(so)
451 ATM_INTRO("disconnect");
453 err = atm_sock_disconnect(so);
460 * Shut down socket data transmission
463 * so pointer to socket
466 * 0 request processed
467 * errno error processing request - reason indicated
471 atm_aal5_shutdown(so)
474 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 * errno error processing request - reason indicated
499 atm_aal5_send(so, flags, m, addr, control, td)
503 struct sockaddr *addr;
512 * We don't support any control functions
517 clen = KB_LEN(control);
526 * We also don't support any flags or send-level addressing
534 * All we've got left is the data, so push it out
536 atp = sotoatmpcb(so);
537 err = atm_cm_cpcs_data(atp->atp_conn, m);
540 * Output problem, drop packet
542 atm_sock_stat.as_outdrop[atp->atp_type]++;
552 * Abnormally terminate service
555 * so pointer to socket
558 * 0 request processed
559 * errno error processing request - reason indicated
566 ATM_INTRO_NOERR("abort");
568 so->so_error = ECONNABORTED;
576 * Do control operation - ioctl system call
579 * so pointer to socket
581 * data pointer to code specific parameter data area
582 * ifp pointer to ifnet structure if it's an interface ioctl
583 * p pointer to process
586 * 0 request processed
587 * errno error processing request - reason indicated
591 atm_aal5_control(so, cmd, data, ifp, td)
598 ATM_INTRO("control");
610 * Sense socket status - fstat system call
613 * so pointer to socket
614 * st pointer to file status structure
617 * 0 request processed
618 * errno error processing request - reason indicated
622 atm_aal5_sense(so, st)
629 * Just return the max sdu size for the connection
631 st->st_blksize = so->so_snd.sb_hiwat;
638 * Retrieve local socket address
641 * so pointer to socket
642 * addr pointer to pointer to contain protocol address
645 * 0 request processed
646 * errno error processing request - reason indicated
650 atm_aal5_sockaddr(so, addr)
652 struct sockaddr **addr;
654 ATM_INTRO("sockaddr");
656 err = atm_sock_sockaddr(so, addr);
663 * Retrieve peer socket address
666 * so pointer to socket
667 * addr pointer to pointer to contain protocol address
670 * 0 request processed
671 * errno error processing request - reason indicated
675 atm_aal5_peeraddr(so, addr)
677 struct sockaddr **addr;
679 ATM_INTRO("peeraddr");
681 err = atm_sock_peeraddr(so, addr);
688 * Process Incoming Calls
690 * This function will receive control when an incoming call has been matched
691 * to one of our registered listen parameter blocks. Assuming the call passes
692 * acceptance criteria and all required resources are available, we will
693 * create a new protocol control block and socket association. We must
694 * then await notification of the final SVC setup results. If any
695 * problems are encountered, we will just tell the connection manager to
701 * tok owner's matched listening token
702 * cop pointer to incoming call's connection block
703 * ap pointer to incoming call's attributes
704 * tokp pointer to location to store our connection token
708 * errno call rejected - reason indicated
712 atm_aal5_incoming(tok, cop, ap, tokp)
718 Atm_pcb *atp0 = tok, *atp;
723 * Allocate a new socket and pcb for this connection.
725 * Note that our attach function will be called via sonewconn
726 * and it will allocate and setup most of the pcb.
728 atm_sock_stat.as_inconn[atp0->atp_type]++;
729 so = sonewconn(atp0->atp_socket, 0);
733 * Finish pcb setup and pass pcb back to CM
735 atp = sotoatmpcb(so);
737 atp->atp_attr = *atp0->atp_conn->co_lattr;
738 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
742 atm_sock_stat.as_connfail[atp0->atp_type]++;
750 * Process Socket VCC Input Data
753 * tok owner's connection token (atm_pcb)
754 * m pointer to input packet buffer chain
761 atm_aal5_cpcs_data(tok, m)
769 so = atp->atp_socket;
774 * Ensure that the socket is able to receive data and
775 * that there's room in the socket buffer
777 if (((so->so_state & SS_ISCONNECTED) == 0) ||
778 (so->so_rcv.sb_state & SBS_CANTRCVMORE) ||
779 (len > sbspace(&so->so_rcv))) {
780 atm_sock_stat.as_indrop[atp->atp_type]++;
786 * Queue the data and notify the user
788 sbappendrecord(&so->so_rcv, m);
796 * Process getsockopt/setsockopt system calls
799 * so pointer to socket
800 * sopt pointer to socket option info
803 * 0 request processed
804 * errno error processing request - reason indicated
808 atm_aal5_ctloutput(so, sopt)
810 struct sockopt *sopt;
814 ATM_INTRO("ctloutput");
817 * Make sure this is for us
819 if (sopt->sopt_level != T_ATM_SIGNALING) {
822 atp = sotoatmpcb(so);
824 ATM_RETERR(ENOTCONN);
827 switch (sopt->sopt_dir) {
835 * Validate socket state
837 switch (sopt->sopt_name) {
840 case T_ATM_DROP_LEAF:
841 if ((so->so_state & SS_ISCONNECTED) == 0) {
842 ATM_RETERR(ENOTCONN);
851 if (so->so_state & SS_ISCONNECTED) {
858 * Validate and save user-supplied option data
860 err = atm_sock_setopt(so, sopt, atp);
872 err = atm_sock_getopt(so, sopt, atp);
883 * Initialize AAL5 Sockets
896 * Register our endpoint
898 if (atm_endpoint_register(&atm_aal5_endpt))
899 panic("atm_aal5_init: register");
902 * Set default connection attributes
904 atm_aal5_defattr.aal.v.aal5.forward_max_SDU_size = T_ATM_ABSENT;
905 atm_aal5_defattr.aal.v.aal5.backward_max_SDU_size = T_ATM_ABSENT;
906 atm_aal5_defattr.aal.v.aal5.SSCS_type = T_ATM_NULL;
911 * Get Connection's Application/Owner Name
914 * tok owner's connection token (atm_pcb)
917 * addr pointer to string containing our name
921 atm_aal5_getname(tok)
926 return (atp->atp_name);