Remove usage of NTOHS / NTOHL / HTONS / HTONL.
[dragonfly.git] / sys / netproto / atm / atm_aal5.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
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 $
28  */
29
30 /*
31  * Core ATM Services
32  * -----------------
33  *
34  * ATM AAL5 socket protocol processing
35  *
36  */
37
38 #include "kern_include.h"
39 #include <sys/stat.h>
40
41 /*
42  * Global variables
43  */
44 u_long          atm_aal5_sendspace = 64 * 1024; /* XXX */
45 u_long          atm_aal5_recvspace = 64 * 1024; /* XXX */
46
47
48 /*
49  * Local functions
50  */
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 *, 
55                         struct thread *);
56 static int      atm_aal5_listen (struct socket *, struct thread *);
57 static int      atm_aal5_connect (struct socket *, struct sockaddr *,
58                         struct thread *);
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 *);
74
75
76 #if (defined(__DragonFly__) && (BSD >= 199506))
77 /*
78  * New-style socket request routines
79  */
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 */
101 };
102 #endif
103
104
105 /*
106  * Local variables
107  */
108 static Atm_endpoint     atm_aal5_endpt = {
109         NULL,
110         ENDPT_SOCK_AAL5,
111         NULL,
112         atm_aal5_getname,
113         atm_sock_connected,
114         atm_sock_cleared,
115         atm_aal5_incoming,
116         NULL,
117         NULL,
118         NULL,
119         atm_aal5_cpcs_data,
120         NULL,
121         NULL,
122         NULL,
123         NULL
124 };
125
126 static Atm_attributes   atm_aal5_defattr = {
127         NULL,                   /* nif */
128         CMAPI_CPCS,             /* api */
129         0,                      /* api_init */
130         0,                      /* headin */
131         0,                      /* headout */
132         {                       /* aal */
133                 T_ATM_PRESENT,
134                 ATM_AAL5
135         },
136         {                       /* traffic */
137                 T_ATM_ABSENT,
138         },
139         {                       /* bearer */
140                 T_ATM_ABSENT,
141         },
142         {                       /* bhli */
143                 T_ATM_ABSENT
144         },
145         {                       /* blli */
146                 T_ATM_ABSENT,
147                 T_ATM_ABSENT,
148         },
149         {                       /* llc */
150                 T_ATM_ABSENT,
151         },
152         {                       /* called */
153                 T_ATM_ABSENT,
154                 {
155                         T_ATM_ABSENT,
156                         0
157                 },
158                 {
159                         T_ATM_ABSENT,
160                         0
161                 }
162         },
163         {                       /* calling */
164                 T_ATM_ABSENT
165         },
166         {                       /* qos */
167                 T_ATM_ABSENT,
168         },
169         {                       /* transit */
170                 T_ATM_ABSENT
171         },
172         {                       /* cause */
173                 T_ATM_ABSENT
174         }
175 };
176
177
178 /*
179  * Handy common code macros
180  */
181 #ifdef DIAGNOSTIC
182 #define ATM_INTRO(f)                                            \
183         int             s, err = 0;                             \
184         s = splnet();                                           \
185         ATM_DEBUG2("aal5 socket %s (%p)\n", f, so);             \
186         /*                                                      \
187          * Stack queue should have been drained                 \
188          */                                                     \
189         if (atm_stackq_head != NULL)                            \
190                 panic("atm_aal5: stack queue not empty");       \
191         ;
192 #else /* !DIAGNOSTIC */
193 #define ATM_INTRO(f)                                            \
194         int             s, err = 0;                             \
195         s = splnet();                                           \
196         ;
197 #endif /* DIAGNOSTIC */
198
199 #define ATM_OUTRO()                                             \
200         /*                                                      \
201          * Drain any deferred calls                             \
202          */                                                     \
203         STACK_DRAIN();                                          \
204         (void) splx(s);                                         \
205         return (err);                                           \
206         ;
207
208 #define ATM_RETERR(errno) {                                     \
209         err = errno;                                            \
210         goto out;                                               \
211 }
212
213
214 /*
215  * Attach protocol to socket
216  *
217  * Arguments:
218  *      so      pointer to socket
219  *      proto   protocol identifier
220  *      p       pointer to process
221  *
222  * Returns:
223  *      0       request processed
224  *      errno   error processing request - reason indicated
225  *
226  */
227 static int
228 atm_aal5_attach(so, proto, ai)
229         struct socket   *so;
230         int             proto;
231         struct pru_attach_info *ai;
232 {
233         Atm_pcb         *atp;
234
235         ATM_INTRO("attach");
236
237         /*
238          * Do general attach stuff
239          */
240         err = atm_sock_attach(so, atm_aal5_sendspace, atm_aal5_recvspace,
241                               ai->sb_rlimit);
242         if (err)
243                 ATM_RETERR(err);
244
245         /*
246          * Finish up any protocol specific stuff
247          */
248         atp = sotoatmpcb(so);
249         atp->atp_type = ATPT_AAL5;
250
251         /*
252          * Set default connection attributes
253          */
254         atp->atp_attr = atm_aal5_defattr;
255         strncpy(atp->atp_name, "(AAL5)", T_ATM_APP_NAME_LEN);
256
257 out:
258         ATM_OUTRO();
259 }
260
261
262 /*
263  * Detach protocol from socket
264  *
265  * Arguments:
266  *      so      pointer to socket
267  *
268  * Returns:
269  *      0       request processed
270  *      errno   error processing request - reason indicated
271  *
272  */
273 static int
274 atm_aal5_detach(so)
275         struct socket   *so;
276 {
277         ATM_INTRO("detach");
278
279         err = atm_sock_detach(so);
280
281         ATM_OUTRO();
282 }
283
284
285 /*
286  * Bind address to socket
287  *
288  * Arguments:
289  *      so      pointer to socket
290  *      addr    pointer to protocol address
291  *      p       pointer to process
292  *
293  * Returns:
294  *      0       request processed
295  *      errno   error processing request - reason indicated
296  *
297  */
298 static int
299 atm_aal5_bind(so, addr, td)
300         struct socket   *so;
301         struct sockaddr *addr;
302         struct thread   *td;
303 {
304         ATM_INTRO("bind");
305
306         err = atm_sock_bind(so, addr);
307
308         ATM_OUTRO();
309 }
310
311
312 /*
313  * Listen for incoming connections
314  *
315  * Arguments:
316  *      so      pointer to socket
317  *      p       pointer to process
318  *
319  * Returns:
320  *      0       request processed
321  *      errno   error processing request - reason indicated
322  *
323  */
324 static int
325 atm_aal5_listen(struct socket *so, struct thread *td)
326 {
327         ATM_INTRO("listen");
328
329         err = atm_sock_listen(so, &atm_aal5_endpt);
330
331         ATM_OUTRO();
332 }
333
334
335 /*
336  * Connect socket to peer
337  *
338  * Arguments:
339  *      so      pointer to socket
340  *      addr    pointer to protocol address
341  *      p       pointer to process
342  *
343  * Returns:
344  *      0       request processed
345  *      errno   error processing request - reason indicated
346  *
347  */
348 static int
349 atm_aal5_connect(struct socket *so, struct sockaddr *addr, thread_t td)
350 {
351         Atm_pcb         *atp;
352
353         ATM_INTRO("connect");
354
355         atp = sotoatmpcb(so);
356
357         /*
358          * Resize send socket buffer to maximum sdu size
359          */
360         if (atp->atp_attr.aal.tag == T_ATM_PRESENT) {
361                 long    size;
362
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])) {
367                                 err = ENOBUFS;
368                                 ATM_OUTRO();
369                         }
370                                 
371         }
372
373         /*
374          * Now get the socket connected
375          */
376         err = atm_sock_connect(so, addr, &atm_aal5_endpt);
377
378         ATM_OUTRO();
379 }
380
381
382 /*
383  * Accept pending connection
384  *
385  * Arguments:
386  *      so      pointer to socket
387  *      addr    pointer to pointer to contain protocol address
388  *
389  * Returns:
390  *      0       request processed
391  *      errno   error processing request - reason indicated
392  *
393  */
394 static int
395 atm_aal5_accept(struct socket *so, struct sockaddr **addr)
396 {
397         ATM_INTRO("accept");
398
399         /*
400          * Everything is pretty much done already, we just need to
401          * return the caller's address to the user.
402          */
403         err = atm_sock_peeraddr(so, addr);
404
405         ATM_OUTRO();
406 }
407
408
409 /*
410  * Disconnect connected socket
411  *
412  * Arguments:
413  *      so      pointer to socket
414  *
415  * Returns:
416  *      0       request processed
417  *      errno   error processing request - reason indicated
418  *
419  */
420 static int
421 atm_aal5_disconnect(struct socket *so)
422 {
423         ATM_INTRO("disconnect");
424
425         err = atm_sock_disconnect(so);
426
427         ATM_OUTRO();
428 }
429
430
431 /*
432  * Shut down socket data transmission
433  *
434  * Arguments:
435  *      so      pointer to socket
436  *
437  * Returns:
438  *      0       request processed
439  *      errno   error processing request - reason indicated
440  *
441  */
442 static int
443 atm_aal5_shutdown(struct socket *so)
444 {
445         ATM_INTRO("shutdown");
446
447         socantsendmore(so);
448
449         ATM_OUTRO();
450 }
451
452
453 /*
454  * Send user data
455  *
456  * Arguments:
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
463  *
464  * Returns:
465  *      0       request processed
466  *      errno   error processing request - reason indicated
467  *
468  */
469 static int
470 atm_aal5_send(
471         struct socket   *so,
472         int             flags,
473         KBuffer         *m,
474         struct sockaddr *addr,
475         KBuffer         *control,
476         struct thread   *td
477 ) {
478         Atm_pcb         *atp;
479
480         ATM_INTRO("send");
481
482         /*
483          * We don't support any control functions
484          */
485         if (control) {
486                 int     clen;
487
488                 clen = KB_LEN(control);
489                 KB_FREEALL(control);
490                 if (clen) {
491                         KB_FREEALL(m);
492                         ATM_RETERR(EINVAL);
493                 }
494         }
495
496         /*
497          * We also don't support any flags or send-level addressing
498          */
499         if (flags || addr) {
500                 KB_FREEALL(m);
501                 ATM_RETERR(EINVAL);
502         }
503
504         /*
505          * All we've got left is the data, so push it out
506          */
507         atp = sotoatmpcb(so);
508         err = atm_cm_cpcs_data(atp->atp_conn, m);
509         if (err) {
510                 /*
511                  * Output problem, drop packet
512                  */
513                 atm_sock_stat.as_outdrop[atp->atp_type]++;
514                 KB_FREEALL(m);
515         }
516
517 out:
518         ATM_OUTRO();
519 }
520
521
522 /*
523  * Abnormally terminate service
524  *
525  * Arguments:
526  *      so      pointer to socket
527  *
528  * Returns:
529  *      0       request processed
530  *      errno   error processing request - reason indicated
531  *
532  */
533 static int
534 atm_aal5_abort(struct socket *so)
535 {
536         ATM_INTRO("abort");
537
538         so->so_error = ECONNABORTED;
539         err = atm_sock_detach(so);
540
541         ATM_OUTRO();
542 }
543
544
545 /*
546  * Do control operation - ioctl system call
547  *
548  * Arguments:
549  *      so      pointer to socket
550  *      cmd     ioctl code
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
554  *
555  * Returns:
556  *      0       request processed
557  *      errno   error processing request - reason indicated
558  *
559  */
560 static int
561 atm_aal5_control(
562         struct socket   *so,
563         u_long          cmd,
564         caddr_t         data,
565         struct ifnet    *ifp,
566         struct thread   *td
567 ) {
568         ATM_INTRO("control");
569
570         switch (cmd) {
571
572         default:
573                 err = EOPNOTSUPP;
574         }
575
576         ATM_OUTRO();
577 }
578
579 /*
580  * Sense socket status - fstat system call
581  *
582  * Arguments:
583  *      so      pointer to socket
584  *      st      pointer to file status structure
585  *
586  * Returns:
587  *      0       request processed
588  *      errno   error processing request - reason indicated
589  *
590  */
591 static int
592 atm_aal5_sense(struct socket *so, struct stat *st)
593 {
594         ATM_INTRO("sense");
595
596         /*
597          * Just return the max sdu size for the connection
598          */
599         st->st_blksize = so->so_snd.sb_hiwat;
600
601         ATM_OUTRO();
602 }
603
604
605 /*
606  * Retrieve local socket address
607  *
608  * Arguments:
609  *      so      pointer to socket
610  *      addr    pointer to pointer to contain protocol address
611  *
612  * Returns:
613  *      0       request processed
614  *      errno   error processing request - reason indicated
615  *
616  */
617 static int
618 atm_aal5_sockaddr(struct socket *so, struct sockaddr **addr)
619 {
620         ATM_INTRO("sockaddr");
621
622         err = atm_sock_sockaddr(so, addr);
623
624         ATM_OUTRO();
625 }
626
627
628 /*
629  * Retrieve peer socket address
630  *
631  * Arguments:
632  *      so      pointer to socket
633  *      addr    pointer to pointer to contain protocol address
634  *
635  * Returns:
636  *      0       request processed
637  *      errno   error processing request - reason indicated
638  *
639  */
640 static int
641 atm_aal5_peeraddr(struct socket *so, struct sockaddr **addr)
642 {
643         ATM_INTRO("peeraddr");
644
645         err = atm_sock_peeraddr(so, addr);
646
647         ATM_OUTRO();
648 }
649
650
651 /*
652  * Process Incoming Calls
653  *
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
660  * reject the call.
661  *
662  * Called at splnet.
663  *
664  * Arguments:
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
669  *
670  * Returns:
671  *      0       call is accepted
672  *      errno   call rejected - reason indicated
673  *
674  */
675 static int
676 atm_aal5_incoming(tok, cop, ap, tokp)
677         void            *tok;
678         Atm_connection  *cop;
679         Atm_attributes  *ap;
680         void            **tokp;
681 {
682         Atm_pcb         *atp0 = tok, *atp;
683         struct socket   *so;
684         int             err = 0;
685
686         /*
687          * Allocate a new socket and pcb for this connection.
688          *
689          * Note that our attach function will be called via sonewconn
690          * and it will allocate and setup most of the pcb.
691          */
692         atm_sock_stat.as_inconn[atp0->atp_type]++;
693 #if (defined(BSD) && (BSD >= 199103))
694         so = sonewconn(atp0->atp_socket, 0);
695 #else
696         so = sonewconn(atp0->atp_socket);
697 #endif
698
699         if (so) {
700                 /*
701                  * Finish pcb setup and pass pcb back to CM
702                  */
703                 atp = sotoatmpcb(so);
704                 atp->atp_conn = cop;
705                 atp->atp_attr = *atp0->atp_conn->co_lattr;
706                 strncpy(atp->atp_name, atp0->atp_name, T_ATM_APP_NAME_LEN);
707                 *tokp = atp;
708         } else {
709                 err = ECONNABORTED;
710                 atm_sock_stat.as_connfail[atp0->atp_type]++;
711         }
712
713         return (err);
714 }
715
716
717 /*
718  * Process Socket VCC Input Data
719  *
720  * Arguments:
721  *      tok     owner's connection token (atm_pcb)
722  *      m       pointer to input packet buffer chain
723  *
724  * Returns:
725  *      none
726  *
727  */
728 static void
729 atm_aal5_cpcs_data(tok, m)
730         void            *tok;
731         KBuffer         *m;
732 {
733         Atm_pcb         *atp = tok;
734         struct socket   *so;
735         int             len;
736
737         so = atp->atp_socket;
738
739         KB_PLENGET(m, len);
740
741         /*
742          * Ensure that the socket is able to receive data and
743          * that there's room in the socket buffer
744          */
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]++;
749                 KB_FREEALL(m);
750                 return;
751         }
752
753         /*
754          * Queue the data and notify the user
755          */
756         sbappendrecord(&so->so_rcv, m);
757         sorwakeup(so);
758
759         return;
760 }
761
762
763 /*
764  * Process getsockopt/setsockopt system calls
765  *
766  * Arguments:
767  *      so      pointer to socket
768  *      sopt    pointer to socket option info
769  *
770  * Returns:
771  *      0       request processed
772  *      errno   error processing request - reason indicated
773  *
774  */
775 int
776 atm_aal5_ctloutput(struct socket *so, struct sockopt *sopt)
777 {
778         Atm_pcb         *atp;
779
780         ATM_INTRO("ctloutput");
781
782         /*
783          * Make sure this is for us
784          */
785         if (sopt->sopt_level != T_ATM_SIGNALING) {
786                 ATM_RETERR(EINVAL);
787         }
788         atp = sotoatmpcb(so);
789         if (atp == NULL) {
790                 ATM_RETERR(ENOTCONN);
791         }
792
793         switch (sopt->sopt_dir) {
794
795         case SOPT_SET:
796                 /*
797                  * setsockopt()
798                  */
799
800                 /*
801                  * Validate socket state
802                  */
803                 switch (sopt->sopt_name) {
804
805                 case T_ATM_ADD_LEAF:
806                 case T_ATM_DROP_LEAF:
807                         if ((so->so_state & SS_ISCONNECTED) == 0) {
808                                 ATM_RETERR(ENOTCONN);
809                         }
810                         break;
811
812                 case T_ATM_CAUSE:
813                 case T_ATM_APP_NAME:
814                         break;
815
816                 default:
817                         if (so->so_state & SS_ISCONNECTED) {
818                                 ATM_RETERR(EISCONN);
819                         }
820                         break;
821                 }
822
823                 /*
824                  * Validate and save user-supplied option data
825                  */
826                 err = atm_sock_setopt(so, sopt, atp);
827
828                 break;
829
830         case SOPT_GET:
831                 /*
832                  * getsockopt()
833                  */
834
835                 /*
836                  * Return option data
837                  */
838                 err = atm_sock_getopt(so, sopt, atp);
839
840                 break;
841         }
842
843 out:
844         ATM_OUTRO();
845 }
846
847
848 /*
849  * Initialize AAL5 Sockets
850  *
851  * Arguments:
852  *      none
853  *
854  * Returns:
855  *      none
856  *
857  */
858 void
859 atm_aal5_init()
860 {
861         /*
862          * Register our endpoint
863          */
864         if (atm_endpoint_register(&atm_aal5_endpt))
865                 panic("atm_aal5_init: register");
866
867         /*
868          * Set default connection attributes
869          */
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;
873 }
874
875
876 /*
877  * Get Connection's Application/Owner Name
878  *
879  * Arguments:
880  *      tok     owner's connection token (atm_pcb)
881  *
882  * Returns:
883  *      addr    pointer to string containing our name
884  *
885  */
886 static caddr_t
887 atm_aal5_getname(tok)
888         void            *tok;
889 {
890         Atm_pcb         *atp = tok;
891
892         return (atp->atp_name);
893 }
894