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