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