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