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