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