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