fetch.9: Minor fixes.
[dragonfly.git] / sys / netproto / atm / atm_usrreq.c
blob8a928fcb18133a827b396515569ee64ce2512e3c
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
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.13 2007/04/21 02:26:48 dillon Exp $
31 * Core ATM Services
32 * -----------------
34 * ATM DGRAM socket protocol processing
38 #include "kern_include.h"
41 * Local functions
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);
50 * New-style socket request routines
52 struct pr_usrreqs atm_dgram_usrreqs = {
53 .pru_abort = atm_proto_notsupp1,
54 .pru_accept = pru_accept_notsupp,
55 .pru_attach = atm_dgram_attach,
56 .pru_bind = atm_proto_notsupp2,
57 .pru_connect = pru_connect_notsupp,
58 .pru_connect2 = pru_connect2_notsupp,
59 .pru_control = atm_dgram_control,
60 .pru_detach = atm_proto_notsupp1,
61 .pru_disconnect = atm_proto_notsupp1,
62 .pru_listen = pru_listen_notsupp,
63 .pru_peeraddr = atm_proto_notsupp3,
64 .pru_rcvd = pru_rcvd_notsupp,
65 .pru_rcvoob = pru_rcvoob_notsupp,
66 .pru_send = atm_proto_notsupp4,
67 .pru_sense = pru_sense_null,
68 .pru_shutdown = atm_proto_notsupp1,
69 .pru_sockaddr = atm_proto_notsupp3,
70 .pru_sosend = sosend,
71 .pru_soreceive = soreceive,
72 .pru_sopoll = sopoll
76 * Handy common code macros
78 #ifdef DIAGNOSTIC
79 #define ATM_INTRO() \
80 int err = 0; \
81 crit_enter(); \
82 /* \
83 * Stack queue should have been drained \
84 */ \
85 if (atm_stackq_head != NULL) \
86 panic("atm_usrreq: stack queue not empty"); \
88 #else
89 #define ATM_INTRO() \
90 int err = 0; \
91 crit_enter(); \
93 #endif
95 #define ATM_OUTRO() \
96 /* \
97 * Drain any deferred calls \
98 */ \
99 STACK_DRAIN(); \
100 crit_exit(); \
101 return (err); \
104 #define ATM_RETERR(errno) { \
105 err = errno; \
106 goto out; \
111 * Attach protocol to socket
113 * Arguments:
114 * so pointer to socket
115 * proto protocol identifier
116 * p pointer to process
118 * Returns:
119 * 0 request processed
120 * errno error processing request - reason indicated
123 static int
124 atm_dgram_attach(struct socket *so, int proto, struct pru_attach_info *ai)
126 ATM_INTRO();
129 * Nothing to do here for ioctl()-only sockets
131 ATM_OUTRO();
136 * Process ioctl system calls
138 * Arguments:
139 * so pointer to socket
140 * cmd ioctl code
141 * data pointer to code specific parameter data area
142 * ifp pointer to ifnet structure if it's an interface ioctl
143 * p pointer to process
145 * Returns:
146 * 0 request processed
147 * errno error processing request - reason indicated
150 static int
151 atm_dgram_control(struct socket *so, u_long cmd, caddr_t data,
152 struct ifnet *ifp, struct thread *td)
154 ATM_INTRO();
157 * First, figure out which ioctl we're dealing with and
158 * then process it based on the sub-op code
160 switch (cmd) {
162 case AIOCCFG: {
163 struct atmcfgreq *acp = (struct atmcfgreq *)data;
164 struct atm_pif *pip;
166 if (priv_check(td, PRIV_ROOT))
167 ATM_RETERR(EPERM);
169 switch (acp->acr_opcode) {
171 case AIOCS_CFG_ATT:
173 * Attach signalling manager
175 if ((pip = atm_pifname(acp->acr_att_intf)) == NULL)
176 ATM_RETERR(ENXIO);
177 err = atm_sigmgr_attach(pip, acp->acr_att_proto);
178 break;
180 case AIOCS_CFG_DET:
182 * Detach signalling manager
184 if ((pip = atm_pifname(acp->acr_det_intf)) == NULL)
185 ATM_RETERR(ENXIO);
186 err = atm_sigmgr_detach(pip);
187 break;
189 default:
190 err = EOPNOTSUPP;
192 break;
195 case AIOCADD: {
196 struct atmaddreq *aap = (struct atmaddreq *)data;
197 Atm_endpoint *epp;
199 if (priv_check(td, PRIV_ROOT))
200 ATM_RETERR(EPERM);
202 switch (aap->aar_opcode) {
204 case AIOCS_ADD_PVC:
206 * Add a PVC definition
210 * Locate requested endpoint service
212 epp = aap->aar_pvc_sap > ENDPT_MAX ? NULL :
213 atm_endpoints[aap->aar_pvc_sap];
214 if (epp == NULL)
215 ATM_RETERR(ENOPROTOOPT);
218 * Let endpoint service handle it from here
220 err = (*epp->ep_ioctl)(AIOCS_ADD_PVC, data, NULL);
221 break;
223 case AIOCS_ADD_ARP:
225 * Add an ARP mapping
227 epp = atm_endpoints[ENDPT_IP];
228 if (epp == NULL)
229 ATM_RETERR(ENOPROTOOPT);
232 * Let IP/ATM endpoint handle this
234 err = (*epp->ep_ioctl) (AIOCS_ADD_ARP, data, NULL);
235 break;
237 default:
238 err = EOPNOTSUPP;
240 break;
243 case AIOCDEL: {
244 struct atmdelreq *adp = (struct atmdelreq *)data;
245 struct atm_pif *pip;
246 struct sigmgr *smp;
247 Atm_endpoint *epp;
249 if (priv_check(td, PRIV_ROOT))
250 ATM_RETERR(EPERM);
252 switch (adp->adr_opcode) {
254 case AIOCS_DEL_PVC:
255 case AIOCS_DEL_SVC:
257 * Delete a PVC or SVC
261 * Locate appropriate sigmgr
263 if ((pip = atm_pifname(adp->adr_pvc_intf)) == NULL)
264 ATM_RETERR(ENXIO);
265 if ((smp = pip->pif_sigmgr) == NULL)
266 ATM_RETERR(ENOENT);
269 * Let sigmgr handle it from here
271 err = (*smp->sm_ioctl)(adp->adr_opcode, data,
272 (caddr_t)pip->pif_siginst);
273 break;
275 case AIOCS_DEL_ARP:
277 * Delete an ARP mapping
279 epp = atm_endpoints[ENDPT_IP];
280 if (epp == NULL)
281 ATM_RETERR(ENOPROTOOPT);
284 * Let IP/ATM endpoint handle this
286 err = (*epp->ep_ioctl) (AIOCS_DEL_ARP, data, NULL);
287 break;
289 default:
290 err = EOPNOTSUPP;
292 break;
295 case AIOCSET: {
296 struct atmsetreq *asp = (struct atmsetreq *)data;
297 struct atm_pif *pip;
298 struct atm_nif *nip;
299 struct sigmgr *smp;
300 struct ifnet *ifp2;
302 if (priv_check(td, PRIV_ROOT))
303 ATM_RETERR(EPERM);
305 switch (asp->asr_opcode) {
307 case AIOCS_SET_ASV:
309 * Set an ARP server address
313 * Locate appropriate sigmgr
315 if ((nip = atm_nifname(asp->asr_arp_intf)) == NULL)
316 ATM_RETERR(ENXIO);
317 pip = nip->nif_pif;
318 if ((smp = pip->pif_sigmgr) == NULL)
319 ATM_RETERR(ENOENT);
322 * Let sigmgr handle it from here
324 err = (*smp->sm_ioctl)(AIOCS_SET_ASV, data,
325 (caddr_t)nip);
326 break;
328 case AIOCS_SET_MAC:
330 * Set physical interface MAC/ESI address
334 * Locate physical interface
336 if ((pip = atm_pifname(asp->asr_mac_intf)) == NULL)
337 ATM_RETERR(ENXIO);
340 * Interface must be detached
342 if (pip->pif_sigmgr != NULL)
343 ATM_RETERR(EADDRINUSE);
346 * Just plunk the address into the pif
348 KM_COPY((caddr_t)&asp->asr_mac_addr,
349 (caddr_t)&pip->pif_macaddr,
350 sizeof(struct mac_addr));
351 break;
353 case AIOCS_SET_NIF:
355 * Define network interfaces
357 if ((pip = atm_pifname(asp->asr_nif_intf)) == NULL)
358 ATM_RETERR(ENXIO);
361 * Validate interface count - logical interfaces
362 * are differentiated by the atm address selector.
364 if ((asp->asr_nif_cnt <= 0) || (asp->asr_nif_cnt > 256))
365 ATM_RETERR(EINVAL);
368 * Make sure prefix name is unique
370 TAILQ_FOREACH(ifp2, &ifnet, if_link) {
371 if (!strcmp(ifp2->if_dname, asp->asr_nif_pref)) {
373 * If this is for the interface we're
374 * (re-)defining, let it through
376 for (nip = pip->pif_nif; nip;
377 nip = nip->nif_pnext) {
378 if (&nip->nif_if == ifp2)
379 break;
381 if (nip)
382 continue;
383 ATM_RETERR(EEXIST);
388 * Let interface handle it from here
390 err = (*pip->pif_ioctl)(AIOCS_SET_NIF, data,
391 (caddr_t)pip);
392 break;
394 case AIOCS_SET_PRF:
396 * Set interface NSAP Prefix
400 * Locate appropriate sigmgr
402 if ((pip = atm_pifname(asp->asr_prf_intf)) == NULL)
403 ATM_RETERR(ENXIO);
404 if ((smp = pip->pif_sigmgr) == NULL)
405 ATM_RETERR(ENOENT);
408 * Let sigmgr handle it from here
410 err = (*smp->sm_ioctl)(AIOCS_SET_PRF, data,
411 (caddr_t)pip->pif_siginst);
412 break;
414 default:
415 err = EOPNOTSUPP;
417 break;
420 case AIOCINFO:
421 err = atm_dgram_info(data);
422 break;
424 default:
425 err = EOPNOTSUPP;
428 out:
429 ATM_OUTRO();
434 * Process AIOCINFO ioctl system calls
436 * Called from a critical section.
438 * Arguments:
439 * data pointer to AIOCINFO parameter structure
441 * Returns:
442 * 0 request processed
443 * errno error processing request - reason indicated
446 static int
447 atm_dgram_info(caddr_t data)
449 struct atminfreq *aip = (struct atminfreq *)data;
450 struct atm_pif *pip;
451 struct atm_nif *nip;
452 struct sigmgr *smp;
453 Atm_endpoint *epp;
454 int len = aip->air_buf_len;
455 int err = 0;
457 switch (aip->air_opcode) {
459 case AIOCS_INF_VST:
460 case AIOCS_INF_CFG:
462 * Get vendor interface information
464 if (aip->air_vinfo_intf[0] != '\0') {
466 * Interface specified
468 if ((pip = atm_pifname(aip->air_vinfo_intf))) {
469 err = (*pip->pif_ioctl)(aip->air_opcode, data,
470 (caddr_t)pip);
471 } else {
472 err = ENXIO;
474 } else {
476 * Want info for every interface
478 for (pip = atm_interface_head; pip;
479 pip = pip->pif_next) {
480 err = (*pip->pif_ioctl)(aip->air_opcode, data,
481 (caddr_t)pip);
482 if (err)
483 break;
486 break;
488 case AIOCS_INF_IPM:
490 * Get IP Map information
492 epp = atm_endpoints[ENDPT_IP];
493 if (epp) {
494 err = (*epp->ep_ioctl) (AIOCS_INF_IPM, data, NULL);
495 } else {
496 err = ENOPROTOOPT;
498 break;
500 case AIOCS_INF_ARP:
502 * Get ARP table information
504 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
505 if ((smp = pip->pif_sigmgr) != NULL) {
506 err = (*smp->sm_ioctl)(AIOCS_INF_ARP,
507 data, (caddr_t)pip->pif_siginst);
509 if (err)
510 break;
512 break;
514 case AIOCS_INF_ASV:
516 * Get ARP server information
518 if (aip->air_asrv_intf[0] != '\0') {
520 * Interface specified
522 if ((nip = atm_nifname(aip->air_asrv_intf))) {
523 if ((smp = nip->nif_pif->pif_sigmgr) != NULL) {
524 err = (*smp->sm_ioctl)(AIOCS_INF_ASV,
525 data, (caddr_t)nip);
527 } else {
528 err = ENXIO;
530 } else {
532 * Want info for all arp servers
534 for (pip = atm_interface_head; pip;
535 pip = pip->pif_next) {
536 if ((smp = pip->pif_sigmgr) != NULL) {
537 for (nip = pip->pif_nif; nip;
538 nip = nip->nif_pnext) {
539 err = (*smp->sm_ioctl)
540 (AIOCS_INF_ASV, data,
541 (caddr_t)nip);
542 if (err)
543 break;
545 if (err)
546 break;
550 break;
552 case AIOCS_INF_INT:
554 * Get physical interface info
556 if (aip->air_int_intf[0] != '\0') {
558 * Interface specified
560 if ((pip = atm_pifname(aip->air_int_intf))) {
561 err = (*pip->pif_ioctl)(AIOCS_INF_INT,
562 data, (caddr_t)pip);
563 } else {
564 err = ENXIO;
566 } else {
568 * Want info for every physical interface
570 for (pip = atm_interface_head; pip;
571 pip = pip->pif_next) {
572 err = (*pip->pif_ioctl)(AIOCS_INF_INT,
573 data, (caddr_t)pip);
574 if (err)
575 break;
578 break;
580 case AIOCS_INF_VCC:
582 * Get VCC information
584 if (aip->air_vcc_intf[0] != '\0') {
586 * Interface specified
588 if ((pip = atm_pifname(aip->air_vcc_intf))) {
589 if ((smp = pip->pif_sigmgr) != NULL) {
590 err = (*smp->sm_ioctl)(AIOCS_INF_VCC,
591 data,
592 (caddr_t)pip->pif_siginst);
594 } else {
595 err = ENXIO;
597 } else {
599 * Want info for every interface
601 for (pip = atm_interface_head; pip;
602 pip = pip->pif_next) {
603 if ((smp = pip->pif_sigmgr) != NULL) {
604 err = (*smp->sm_ioctl)(AIOCS_INF_VCC,
605 data,
606 (caddr_t)pip->pif_siginst);
608 if (err)
609 break;
612 break;
614 case AIOCS_INF_NIF:
616 * Get network interface info
618 if (aip->air_int_intf[0] != '\0') {
620 * Interface specified
622 if ((nip = atm_nifname(aip->air_int_intf))) {
623 pip = nip->nif_pif;
624 err = (*pip->pif_ioctl)(AIOCS_INF_NIF,
625 data, (caddr_t)nip);
626 } else {
627 err = ENXIO;
629 } else {
631 * Want info for every network interface
633 for (pip = atm_interface_head; pip;
634 pip = pip->pif_next) {
635 for (nip = pip->pif_nif; nip;
636 nip = nip->nif_pnext) {
637 err = (*pip->pif_ioctl)(AIOCS_INF_NIF,
638 data, (caddr_t)nip);
639 if (err)
640 break;
642 if (err)
643 break;
646 break;
648 case AIOCS_INF_PIS:
650 * Get physical interface statistics
652 if (aip->air_physt_intf[0] != '\0') {
654 * Interface specified
656 if ((pip = atm_pifname(aip->air_physt_intf))) {
657 err = (*pip->pif_ioctl)(AIOCS_INF_PIS,
658 data, (caddr_t)pip);
659 } else {
660 err = ENXIO;
662 } else {
664 * Want statistics for every physical interface
666 for (pip = atm_interface_head; pip;
667 pip = pip->pif_next) {
668 err = (*pip->pif_ioctl)(AIOCS_INF_PIS,
669 data, (caddr_t)pip);
670 if (err)
671 break;
674 break;
676 case AIOCS_INF_VER:
678 * Get ATM software version
680 if (len < sizeof(atm_version)) {
681 err = ENOSPC;
682 break;
684 if ((err = copyout((caddr_t)&atm_version,
685 aip->air_buf_addr,
686 sizeof(atm_version))) != 0) {
687 break;
689 aip->air_buf_addr += sizeof(atm_version);
690 aip->air_buf_len -= sizeof(atm_version);
691 break;
693 default:
694 err = EOPNOTSUPP;
698 * Calculate returned buffer length
700 aip->air_buf_len = len - aip->air_buf_len;
702 return (err);