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