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