]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netatm/atm_usrreq.c
This commit was generated by cvs2svn to compensate for changes in r165182,
[FreeBSD/FreeBSD.git] / sys / netatm / atm_usrreq.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 DGRAM socket protocol processing
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/sockio.h>
39 #include <sys/priv.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.h>
42 #include <net/if.h>
43 #include <netatm/port.h>
44 #include <netatm/queue.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_sys.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_cm.h>
49 #include <netatm/atm_if.h>
50 #include <netatm/atm_ioctl.h>
51 #include <netatm/atm_sigmgr.h>
52 #include <netatm/atm_stack.h>
53 #include <netatm/atm_pcb.h>
54 #include <netatm/atm_var.h>
55
56
57 /*
58  * Local functions
59  */
60 static int      atm_dgram_attach(struct socket *, int, struct thread *);
61 static int      atm_dgram_control(struct socket *, u_long, caddr_t, 
62                         struct ifnet *, struct thread *);
63 static int      atm_dgram_info(caddr_t);
64
65
66 /*
67  * New-style socket request routines
68  */
69 struct pr_usrreqs       atm_dgram_usrreqs = {
70         .pru_abort =            atm_proto_notsupp5,
71         .pru_attach =           atm_dgram_attach,
72         .pru_bind =             atm_proto_notsupp2,
73         .pru_control =          atm_dgram_control,
74         .pru_detach =           atm_proto_notsupp5,
75         .pru_disconnect =       atm_proto_notsupp1,
76         .pru_peeraddr =         atm_proto_notsupp3,
77         .pru_send =             atm_proto_notsupp4,
78         .pru_shutdown =         atm_proto_notsupp1,
79         .pru_sockaddr =         atm_proto_notsupp3,
80         .pru_sosend =           NULL,
81         .pru_soreceive =        NULL,
82         .pru_sopoll =           NULL,
83         .pru_close =            atm_proto_notsupp5,
84 };
85
86
87 /*
88  * Handy common code macros
89  */
90 #ifdef DIAGNOSTIC
91 #define ATM_INTRO()                                             \
92         int             s, err = 0;                             \
93         s = splnet();                                           \
94         /*                                                      \
95          * Stack queue should have been drained                 \
96          */                                                     \
97         if (atm_stackq_head != NULL)                            \
98                 panic("atm_usrreq: stack queue not empty");     \
99         ;
100 #else
101 #define ATM_INTRO()                                             \
102         int             s, err = 0;                             \
103         s = splnet();                                           \
104         ;
105 #endif
106
107 #define ATM_OUTRO()                                             \
108         /*                                                      \
109          * Drain any deferred calls                             \
110          */                                                     \
111         STACK_DRAIN();                                          \
112         (void) splx(s);                                         \
113         return (err);                                           \
114         ;
115
116 #define ATM_RETERR(errno) {                                     \
117         err = errno;                                            \
118         goto out;                                               \
119 }
120
121
122 /*
123  * Attach protocol to socket
124  *
125  * Arguments:
126  *      so      pointer to socket
127  *      proto   protocol identifier
128  *      p       pointer to process
129  *
130  * Returns:
131  *      0       request processed
132  *      errno   error processing request - reason indicated
133  *
134  */
135 static int
136 atm_dgram_attach(so, proto, td)
137         struct socket   *so;
138         int             proto;
139         struct thread   *td;
140 {
141         ATM_INTRO();
142
143         /*
144          * Nothing to do here for ioctl()-only sockets
145          */
146         ATM_OUTRO();
147 }
148
149
150 /*
151  * Process ioctl system calls
152  *
153  * Arguments:
154  *      so      pointer to socket
155  *      cmd     ioctl code
156  *      data    pointer to code specific parameter data area
157  *      ifp     pointer to ifnet structure if it's an interface ioctl
158  *      p       pointer to process
159  *
160  * Returns:
161  *      0       request processed
162  *      errno   error processing request - reason indicated
163  *
164  */
165 static int
166 atm_dgram_control(so, cmd, data, ifp, td)
167         struct socket   *so;
168         u_long          cmd;
169         caddr_t         data;
170         struct ifnet    *ifp;
171         struct thread   *td;
172 {
173         ATM_INTRO();
174
175         /*
176          * First, figure out which ioctl we're dealing with and
177          * then process it based on the sub-op code
178          */
179         switch (cmd) {
180
181         case AIOCCFG: {
182                 struct atmcfgreq        *acp = (struct atmcfgreq *)data;
183                 struct atm_pif          *pip;
184
185                 if (td != NULL) {
186                         err = priv_check(td, PRIV_NETATM_CFG);
187                         if (err)
188                                 ATM_RETERR(err);
189                 }
190
191                 switch (acp->acr_opcode) {
192
193                 case AIOCS_CFG_ATT:
194                         /*
195                          * Attach signalling manager
196                          */
197                         if ((pip = atm_pifname(acp->acr_att_intf)) == NULL)
198                                 ATM_RETERR(ENXIO);
199                         err = atm_sigmgr_attach(pip, acp->acr_att_proto);
200                         break;
201
202                 case AIOCS_CFG_DET:
203                         /*
204                          * Detach signalling manager
205                          */
206                         if ((pip = atm_pifname(acp->acr_det_intf)) == NULL)
207                                 ATM_RETERR(ENXIO);
208                         err = atm_sigmgr_detach(pip);
209                         break;
210
211                 default:
212                         err = EOPNOTSUPP;
213                 }
214                 break;
215         }
216
217         case AIOCADD: {
218                 struct atmaddreq        *aap = (struct atmaddreq *)data;
219                 Atm_endpoint            *epp;
220
221                 if (td != NULL) {
222                         err = priv_check(td, PRIV_NETATM_ADD);
223                         if (err)
224                                 ATM_RETERR(err);
225                 }
226
227                 switch (aap->aar_opcode) {
228
229                 case AIOCS_ADD_PVC:
230                         /*
231                          * Add a PVC definition
232                          */
233
234                         /*
235                          * Locate requested endpoint service
236                          */
237                         epp = aap->aar_pvc_sap > ENDPT_MAX ? NULL : 
238                                         atm_endpoints[aap->aar_pvc_sap];
239                         if (epp == NULL)
240                                 ATM_RETERR(ENOPROTOOPT);
241
242                         /*
243                          * Let endpoint service handle it from here
244                          */
245                         err = (*epp->ep_ioctl)(AIOCS_ADD_PVC, data, NULL);
246                         break;
247
248                 case AIOCS_ADD_ARP:
249                         /*
250                          * Add an ARP mapping
251                          */
252                         epp = atm_endpoints[ENDPT_IP];
253                         if (epp == NULL)
254                                 ATM_RETERR(ENOPROTOOPT);
255
256                         /*
257                          * Let IP/ATM endpoint handle this
258                          */
259                         err = (*epp->ep_ioctl) (AIOCS_ADD_ARP, data, NULL);
260                         break;
261
262                 default:
263                         err = EOPNOTSUPP;
264                 }
265                 break;
266         }
267
268         case AIOCDEL: {
269                 struct atmdelreq        *adp = (struct atmdelreq *)data;
270                 struct atm_pif          *pip;
271                 struct sigmgr           *smp;
272                 Atm_endpoint            *epp;
273
274                 if (td != NULL) {
275                         err = priv_check(td, PRIV_NETATM_DEL);
276                         if (err)
277                                 ATM_RETERR(err);
278                 }
279
280                 switch (adp->adr_opcode) {
281
282                 case AIOCS_DEL_PVC:
283                 case AIOCS_DEL_SVC:
284                         /*
285                          * Delete a PVC or SVC
286                          */
287
288                         /*
289                          * Locate appropriate sigmgr
290                          */
291                         if ((pip = atm_pifname(adp->adr_pvc_intf)) == NULL)
292                                 ATM_RETERR(ENXIO);
293                         if ((smp = pip->pif_sigmgr) == NULL)
294                                 ATM_RETERR(ENOENT);
295
296                         /*
297                          * Let sigmgr handle it from here
298                          */
299                         err = (*smp->sm_ioctl)(adp->adr_opcode, data, 
300                                         (caddr_t)pip->pif_siginst);
301                         break;
302
303                 case AIOCS_DEL_ARP:
304                         /*
305                          * Delete an ARP mapping
306                          */
307                         epp = atm_endpoints[ENDPT_IP];
308                         if (epp == NULL)
309                                 ATM_RETERR(ENOPROTOOPT);
310
311                         /*
312                          * Let IP/ATM endpoint handle this
313                          */
314                         err = (*epp->ep_ioctl) (AIOCS_DEL_ARP, data, NULL);
315                         break;
316
317                 default:
318                         err = EOPNOTSUPP;
319                 }
320                 break;
321         }
322
323         case AIOCSET: {
324                 struct atmsetreq        *asp = (struct atmsetreq *)data;
325                 struct atm_pif          *pip;
326                 struct atm_nif          *nip;
327                 struct sigmgr           *smp;
328                 struct ifnet            *ifp2;
329
330                 if (td != NULL) {
331                         err = priv_check(td, PRIV_NETATM_SET);
332                         if (err)
333                                 ATM_RETERR(err);
334                 }
335
336                 switch (asp->asr_opcode) {
337
338                 case AIOCS_SET_ASV:
339                         /*
340                          * Set an ARP server address
341                          */
342
343                         /*
344                          * Locate appropriate sigmgr
345                          */
346                         if ((nip = atm_nifname(asp->asr_arp_intf)) == NULL)
347                                 ATM_RETERR(ENXIO);
348                         pip = nip->nif_pif;
349                         if ((smp = pip->pif_sigmgr) == NULL)
350                                 ATM_RETERR(ENOENT);
351
352                         /*
353                          * Let sigmgr handle it from here
354                          */
355                         err = (*smp->sm_ioctl)(AIOCS_SET_ASV, data, 
356                                         (caddr_t)nip);
357                         break;
358
359                 case AIOCS_SET_MAC:
360                         /*
361                          * Set physical interface MAC/ESI address
362                          */
363
364                         /*
365                          * Locate physical interface
366                          */
367                         if ((pip = atm_pifname(asp->asr_mac_intf)) == NULL)
368                                 ATM_RETERR(ENXIO);
369
370                         /*
371                          * Interface must be detached
372                          */
373                         if (pip->pif_sigmgr != NULL)
374                                 ATM_RETERR(EADDRINUSE);
375
376                         /*
377                          * Just plunk the address into the pif
378                          */
379                         bcopy((caddr_t)&asp->asr_mac_addr,
380                                 (caddr_t)&pip->pif_macaddr,
381                                 sizeof(struct mac_addr));
382                         break;
383
384                 case AIOCS_SET_NIF:
385                         /*
386                          * Define network interfaces
387                          */
388                         if ((pip = atm_pifname(asp->asr_nif_intf)) == NULL)
389                                 ATM_RETERR(ENXIO);
390
391                         /*
392                          * Validate interface count - logical interfaces
393                          * are differentiated by the atm address selector.
394                          */
395                         if (asp->asr_nif_cnt == 0 || asp->asr_nif_cnt > 256)
396                                 ATM_RETERR(EINVAL);
397
398                         /*
399                          * Make sure prefix name is unique
400                          */
401                         IFNET_RLOCK();
402                         TAILQ_FOREACH(ifp2, &ifnet, if_link) {
403                                 if (!strcmp(ifp2->if_dname, asp->asr_nif_pref)) {
404                                         /*
405                                          * If this is for the interface we're
406                                          * (re-)defining, let it through
407                                          */
408                                         for (nip = pip->pif_nif; nip;
409                                                         nip = nip->nif_pnext) {
410                                                 if (ANIF2IFP(nip) == ifp2)
411                                                         break;
412                                         }
413                                         if (nip)
414                                                 continue;
415                                         IFNET_RUNLOCK();
416                                         ATM_RETERR(EEXIST);
417                                 }
418                         }
419                         IFNET_RUNLOCK();
420
421                         /*
422                          * Let interface handle it from here
423                          */
424                         err = (*pip->pif_ioctl)(AIOCS_SET_NIF, data,
425                                         (caddr_t)pip);
426                         break;
427
428                 case AIOCS_SET_PRF:
429                         /*
430                          * Set interface NSAP Prefix 
431                          */
432
433                         /*
434                          * Locate appropriate sigmgr
435                          */
436                         if ((pip = atm_pifname(asp->asr_prf_intf)) == NULL)
437                                 ATM_RETERR(ENXIO);
438                         if ((smp = pip->pif_sigmgr) == NULL)
439                                 ATM_RETERR(ENOENT);
440
441                         /*
442                          * Let sigmgr handle it from here
443                          */
444                         err = (*smp->sm_ioctl)(AIOCS_SET_PRF, data, 
445                                         (caddr_t)pip->pif_siginst);
446                         break;
447
448                 default:
449                         err = EOPNOTSUPP;
450                 }
451                 break;
452         }
453
454         case AIOCINFO:
455                 err = atm_dgram_info(data);
456                 break;
457
458         default:
459                 err = EOPNOTSUPP;
460         }
461
462 out:
463         ATM_OUTRO();
464 }
465
466
467 /*
468  * Process AIOCINFO ioctl system calls
469  *
470  * Called at splnet.
471  *
472  * Arguments:
473  *      data    pointer to AIOCINFO parameter structure
474  *
475  * Returns:
476  *      0       request processed
477  *      errno   error processing request - reason indicated
478  *
479  */
480 static int
481 atm_dgram_info(data)
482         caddr_t                 data;
483 {
484         struct atminfreq        *aip = (struct atminfreq *)data;
485         struct atm_pif          *pip;
486         struct atm_nif          *nip;
487         struct sigmgr           *smp;
488         Atm_endpoint            *epp;
489         int             len = aip->air_buf_len;
490         int             err = 0;
491
492         switch (aip->air_opcode) {
493
494         case AIOCS_INF_VST:
495         case AIOCS_INF_CFG:
496                 /*
497                  * Get vendor interface information
498                  */
499                 if (aip->air_vinfo_intf[0] != '\0') {
500                         /*
501                          * Interface specified
502                          */
503                         if ((pip = atm_pifname(aip->air_vinfo_intf))) {
504                                 err = (*pip->pif_ioctl)(aip->air_opcode, data,
505                                                 (caddr_t)pip);
506                         } else {
507                                 err = ENXIO;
508                         }
509                 } else {
510                         /*
511                          * Want info for every interface
512                          */
513                         for (pip = atm_interface_head; pip; 
514                                         pip = pip->pif_next) {
515                                 err = (*pip->pif_ioctl)(aip->air_opcode, data,
516                                                 (caddr_t)pip);
517                                 if (err)
518                                         break;
519                         }
520                 }
521                 break;
522
523         case AIOCS_INF_IPM:
524                 /*
525                  * Get IP Map information
526                  */
527                 epp = atm_endpoints[ENDPT_IP];
528                 if (epp) {
529                         err = (*epp->ep_ioctl) (AIOCS_INF_IPM, data, NULL);
530                 } else {
531                         err = ENOPROTOOPT;
532                 }
533                 break;
534
535         case AIOCS_INF_ARP:
536                 /*
537                  * Get ARP table information
538                  */
539                 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
540                         if ((smp = pip->pif_sigmgr) != NULL) {
541                                 err = (*smp->sm_ioctl)(AIOCS_INF_ARP,
542                                         data, (caddr_t)pip->pif_siginst);
543                         }
544                         if (err)
545                                 break;
546                 }
547                 break;
548
549         case AIOCS_INF_ASV:
550                 /*
551                  * Get ARP server information
552                  */
553                 if (aip->air_asrv_intf[0] != '\0') {
554                         /*
555                          * Interface specified
556                          */
557                         if ((nip = atm_nifname(aip->air_asrv_intf))) {
558                                 if ((smp = nip->nif_pif->pif_sigmgr) != NULL) {
559                                         err = (*smp->sm_ioctl)(AIOCS_INF_ASV,
560                                                 data, (caddr_t)nip);
561                                 }
562                         } else {
563                                 err = ENXIO;
564                         }
565                 } else {
566                         /*
567                          * Want info for all arp servers
568                          */
569                         for (pip = atm_interface_head; pip;
570                                         pip = pip->pif_next) {
571                                 if ((smp = pip->pif_sigmgr) != NULL) {
572                                         for (nip = pip->pif_nif; nip; 
573                                                         nip = nip->nif_pnext) {
574                                                 err = (*smp->sm_ioctl)
575                                                         (AIOCS_INF_ASV, data,
576                                                         (caddr_t)nip);
577                                                 if (err)
578                                                         break;
579                                         }
580                                         if (err)
581                                                 break;
582                                 }
583                         }
584                 }
585                 break;
586
587         case AIOCS_INF_INT:
588                 /*
589                  * Get physical interface info
590                  */
591                 if (aip->air_int_intf[0] != '\0') {
592                         /*
593                          * Interface specified
594                          */
595                         if ((pip = atm_pifname(aip->air_int_intf))) {
596                                 err = (*pip->pif_ioctl)(AIOCS_INF_INT,
597                                         data, (caddr_t)pip);
598                         } else {
599                                 err = ENXIO;
600                         }
601                 } else {
602                         /*
603                          * Want info for every physical interface
604                          */
605                         for (pip = atm_interface_head; pip; 
606                                         pip = pip->pif_next) {
607                                 err = (*pip->pif_ioctl)(AIOCS_INF_INT,
608                                                 data, (caddr_t)pip);
609                                 if (err)
610                                         break;
611                         }
612                 }
613                 break;
614
615         case AIOCS_INF_VCC:
616                 /*
617                  * Get VCC information
618                  */
619                 if (aip->air_vcc_intf[0] != '\0') {
620                         /*
621                          * Interface specified
622                          */
623                         if ((pip = atm_pifname(aip->air_vcc_intf))) {
624                                 if ((smp = pip->pif_sigmgr) != NULL) {
625                                         err = (*smp->sm_ioctl)(AIOCS_INF_VCC,
626                                                 data,
627                                                 (caddr_t)pip->pif_siginst);
628                                 } 
629                         } else {
630                                 err = ENXIO;
631                         }
632                 } else {
633                         /*
634                          * Want info for every interface
635                          */
636                         for (pip = atm_interface_head; pip; 
637                                         pip = pip->pif_next) {
638                                 if ((smp = pip->pif_sigmgr) != NULL) {
639                                         err = (*smp->sm_ioctl)(AIOCS_INF_VCC,
640                                                 data,
641                                                 (caddr_t)pip->pif_siginst);
642                                 }
643                                 if (err)
644                                         break;
645                         }
646                 }
647                 break;
648
649         case AIOCS_INF_NIF:
650                 /*
651                  * Get network interface info
652                  */
653                 if (aip->air_int_intf[0] != '\0') {
654                         /*
655                          * Interface specified
656                          */
657                         if ((nip = atm_nifname(aip->air_int_intf))) {
658                                 pip = nip->nif_pif;
659                                 err = (*pip->pif_ioctl)(AIOCS_INF_NIF,
660                                         data, (caddr_t)nip);
661                         } else {
662                                 err = ENXIO;
663                         }
664                 } else {
665                         /*
666                          * Want info for every network interface
667                          */
668                         for (pip = atm_interface_head; pip; 
669                                         pip = pip->pif_next) {
670                                 for (nip = pip->pif_nif; nip; 
671                                                 nip = nip->nif_pnext) {
672                                         err = (*pip->pif_ioctl)(AIOCS_INF_NIF,
673                                                         data, (caddr_t)nip);
674                                         if (err)
675                                                 break;
676                                 }
677                                 if (err)
678                                         break;
679                         }
680                 }
681                 break;
682
683         case AIOCS_INF_PIS:
684                 /*
685                  * Get physical interface statistics
686                  */
687                 if (aip->air_physt_intf[0] != '\0') {
688                         /*
689                          * Interface specified
690                          */
691                         if ((pip = atm_pifname(aip->air_physt_intf))) {
692                                 err = (*pip->pif_ioctl)(AIOCS_INF_PIS,
693                                         data, (caddr_t)pip);
694                         } else {
695                                 err = ENXIO;
696                         }
697                 } else {
698                         /*
699                          * Want statistics for every physical interface
700                          */
701                         for (pip = atm_interface_head; pip; 
702                                         pip = pip->pif_next) {
703                                 err = (*pip->pif_ioctl)(AIOCS_INF_PIS,
704                                                 data, (caddr_t)pip);
705                                 if (err)
706                                         break;
707                         }
708                 }
709                 break;
710
711         case AIOCS_INF_VER:
712                 /*
713                  * Get ATM software version
714                  */
715                 if (len < sizeof(atm_version)) {
716                         err = ENOSPC;
717                         break;
718                 }
719                 if ((err = copyout((caddr_t)&atm_version,
720                                 aip->air_buf_addr,
721                                 sizeof(atm_version))) != 0) {
722                         break;
723                 }
724                 aip->air_buf_addr += sizeof(atm_version);
725                 aip->air_buf_len -= sizeof(atm_version);
726                 break;
727
728         default:
729                 err = EOPNOTSUPP;
730         }
731
732         /*
733          * Calculate returned buffer length
734          */
735         aip->air_buf_len = len - aip->air_buf_len;
736
737         return (err);
738 }
739