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