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.1/sys/netatm/atm_usrreq.c 108172 2002-12-22 05:35:03Z hsu $
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.1/sys/netatm/atm_usrreq.c 108172 2002-12-22 05:35:03Z hsu $");
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 IFNET_RLOCK();
398 TAILQ_FOREACH(ifp2, &ifnet, if_link) {
399 if (!strcmp(ifp2->if_name, asp->asr_nif_pref)) {
400 /*
401 * If this is for the interface we're
402 * (re-)defining, let it through
403 */
404 for (nip = pip->pif_nif; nip;
405 nip = nip->nif_pnext) {
406 if (&nip->nif_if == ifp2)
407 break;
408 }
409 if (nip)
410 continue;
411 IFNET_RUNLOCK();
412 ATM_RETERR(EEXIST);
413 }
414 }
415 IFNET_RUNLOCK();
416
417 /*
418 * Let interface handle it from here
419 */
420 err = (*pip->pif_ioctl)(AIOCS_SET_NIF, data,
421 (caddr_t)pip);
422 break;
423
424 case AIOCS_SET_PRF:
425 /*
426 * Set interface NSAP Prefix
427 */
428
429 /*
430 * Locate appropriate sigmgr
431 */
432 if ((pip = atm_pifname(asp->asr_prf_intf)) == NULL)
433 ATM_RETERR(ENXIO);
434 if ((smp = pip->pif_sigmgr) == NULL)
435 ATM_RETERR(ENOENT);
436
437 /*
438 * Let sigmgr handle it from here
439 */
440 err = (*smp->sm_ioctl)(AIOCS_SET_PRF, data,
441 (caddr_t)pip->pif_siginst);
442 break;
443
444 default:
445 err = EOPNOTSUPP;
446 }
447 break;
448 }
449
450 case AIOCINFO:
451 err = atm_dgram_info(data);
452 break;
453
454 default:
455 err = EOPNOTSUPP;
456 }
457
458 out:
459 ATM_OUTRO();
460 }
461
462
463 /*
464 * Process AIOCINFO ioctl system calls
465 *
466 * Called at splnet.
467 *
468 * Arguments:
469 * data pointer to AIOCINFO parameter structure
470 *
471 * Returns:
472 * 0 request processed
473 * errno error processing request - reason indicated
474 *
475 */
476 static int
477 atm_dgram_info(data)
478 caddr_t data;
479 {
480 struct atminfreq *aip = (struct atminfreq *)data;
481 struct atm_pif *pip;
482 struct atm_nif *nip;
483 struct sigmgr *smp;
484 Atm_endpoint *epp;
485 int len = aip->air_buf_len;
486 int err = 0;
487
488 switch (aip->air_opcode) {
489
490 case AIOCS_INF_VST:
491 case AIOCS_INF_CFG:
492 /*
493 * Get vendor interface information
494 */
495 if (aip->air_vinfo_intf[0] != '\0') {
496 /*
497 * Interface specified
498 */
499 if ((pip = atm_pifname(aip->air_vinfo_intf))) {
500 err = (*pip->pif_ioctl)(aip->air_opcode, data,
501 (caddr_t)pip);
502 } else {
503 err = ENXIO;
504 }
505 } else {
506 /*
507 * Want info for every interface
508 */
509 for (pip = atm_interface_head; pip;
510 pip = pip->pif_next) {
511 err = (*pip->pif_ioctl)(aip->air_opcode, data,
512 (caddr_t)pip);
513 if (err)
514 break;
515 }
516 }
517 break;
518
519 case AIOCS_INF_IPM:
520 /*
521 * Get IP Map information
522 */
523 epp = atm_endpoints[ENDPT_IP];
524 if (epp) {
525 err = (*epp->ep_ioctl) (AIOCS_INF_IPM, data, NULL);
526 } else {
527 err = ENOPROTOOPT;
528 }
529 break;
530
531 case AIOCS_INF_ARP:
532 /*
533 * Get ARP table information
534 */
535 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
536 if ((smp = pip->pif_sigmgr) != NULL) {
537 err = (*smp->sm_ioctl)(AIOCS_INF_ARP,
538 data, (caddr_t)pip->pif_siginst);
539 }
540 if (err)
541 break;
542 }
543 break;
544
545 case AIOCS_INF_ASV:
546 /*
547 * Get ARP server information
548 */
549 if (aip->air_asrv_intf[0] != '\0') {
550 /*
551 * Interface specified
552 */
553 if ((nip = atm_nifname(aip->air_asrv_intf))) {
554 if ((smp = nip->nif_pif->pif_sigmgr) != NULL) {
555 err = (*smp->sm_ioctl)(AIOCS_INF_ASV,
556 data, (caddr_t)nip);
557 }
558 } else {
559 err = ENXIO;
560 }
561 } else {
562 /*
563 * Want info for all arp servers
564 */
565 for (pip = atm_interface_head; pip;
566 pip = pip->pif_next) {
567 if ((smp = pip->pif_sigmgr) != NULL) {
568 for (nip = pip->pif_nif; nip;
569 nip = nip->nif_pnext) {
570 err = (*smp->sm_ioctl)
571 (AIOCS_INF_ASV, data,
572 (caddr_t)nip);
573 if (err)
574 break;
575 }
576 if (err)
577 break;
578 }
579 }
580 }
581 break;
582
583 case AIOCS_INF_INT:
584 /*
585 * Get physical interface info
586 */
587 if (aip->air_int_intf[0] != '\0') {
588 /*
589 * Interface specified
590 */
591 if ((pip = atm_pifname(aip->air_int_intf))) {
592 err = (*pip->pif_ioctl)(AIOCS_INF_INT,
593 data, (caddr_t)pip);
594 } else {
595 err = ENXIO;
596 }
597 } else {
598 /*
599 * Want info for every physical interface
600 */
601 for (pip = atm_interface_head; pip;
602 pip = pip->pif_next) {
603 err = (*pip->pif_ioctl)(AIOCS_INF_INT,
604 data, (caddr_t)pip);
605 if (err)
606 break;
607 }
608 }
609 break;
610
611 case AIOCS_INF_VCC:
612 /*
613 * Get VCC information
614 */
615 if (aip->air_vcc_intf[0] != '\0') {
616 /*
617 * Interface specified
618 */
619 if ((pip = atm_pifname(aip->air_vcc_intf))) {
620 if ((smp = pip->pif_sigmgr) != NULL) {
621 err = (*smp->sm_ioctl)(AIOCS_INF_VCC,
622 data,
623 (caddr_t)pip->pif_siginst);
624 }
625 } else {
626 err = ENXIO;
627 }
628 } else {
629 /*
630 * Want info for every interface
631 */
632 for (pip = atm_interface_head; pip;
633 pip = pip->pif_next) {
634 if ((smp = pip->pif_sigmgr) != NULL) {
635 err = (*smp->sm_ioctl)(AIOCS_INF_VCC,
636 data,
637 (caddr_t)pip->pif_siginst);
638 }
639 if (err)
640 break;
641 }
642 }
643 break;
644
645 case AIOCS_INF_NIF:
646 /*
647 * Get network interface info
648 */
649 if (aip->air_int_intf[0] != '\0') {
650 /*
651 * Interface specified
652 */
653 if ((nip = atm_nifname(aip->air_int_intf))) {
654 pip = nip->nif_pif;
655 err = (*pip->pif_ioctl)(AIOCS_INF_NIF,
656 data, (caddr_t)nip);
657 } else {
658 err = ENXIO;
659 }
660 } else {
661 /*
662 * Want info for every network interface
663 */
664 for (pip = atm_interface_head; pip;
665 pip = pip->pif_next) {
666 for (nip = pip->pif_nif; nip;
667 nip = nip->nif_pnext) {
668 err = (*pip->pif_ioctl)(AIOCS_INF_NIF,
669 data, (caddr_t)nip);
670 if (err)
671 break;
672 }
673 if (err)
674 break;
675 }
676 }
677 break;
678
679 case AIOCS_INF_PIS:
680 /*
681 * Get physical interface statistics
682 */
683 if (aip->air_physt_intf[0] != '\0') {
684 /*
685 * Interface specified
686 */
687 if ((pip = atm_pifname(aip->air_physt_intf))) {
688 err = (*pip->pif_ioctl)(AIOCS_INF_PIS,
689 data, (caddr_t)pip);
690 } else {
691 err = ENXIO;
692 }
693 } else {
694 /*
695 * Want statistics for every physical interface
696 */
697 for (pip = atm_interface_head; pip;
698 pip = pip->pif_next) {
699 err = (*pip->pif_ioctl)(AIOCS_INF_PIS,
700 data, (caddr_t)pip);
701 if (err)
702 break;
703 }
704 }
705 break;
706
707 case AIOCS_INF_VER:
708 /*
709 * Get ATM software version
710 */
711 if (len < sizeof(atm_version)) {
712 err = ENOSPC;
713 break;
714 }
715 if ((err = copyout((caddr_t)&atm_version,
716 aip->air_buf_addr,
717 sizeof(atm_version))) != 0) {
718 break;
719 }
720 aip->air_buf_addr += sizeof(atm_version);
721 aip->air_buf_len -= sizeof(atm_version);
722 break;
723
724 default:
725 err = EOPNOTSUPP;
726 }
727
728 /*
729 * Calculate returned buffer length
730 */
731 aip->air_buf_len = len - aip->air_buf_len;
732
733 return (err);
734 }
735
Cache object: adf2a0a8a8b6a71d24544a53f9a70d5a
|