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