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