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