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