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