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