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