FreeBSD/Linux Kernel Cross Reference
sys/netatm/atm_if.c
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 interface management
35 *
36 */
37
38 #include <netatm/kern_include.h>
39
40 #ifndef lint
41 __RCSID("@(#) $FreeBSD$");
42 #endif
43
44
45 #if (defined(BSD) && (BSD < 199506))
46 extern int ifqmaxlen;
47 #endif
48
49 /*
50 * Local functions
51 */
52 static int atm_physif_ioctl __P((int, caddr_t, caddr_t));
53 #if (defined(BSD) && (BSD >= 199306))
54 static int atm_netif_rtdel __P((struct radix_node *, void *));
55 #endif
56 static int atm_if_ioctl __P((struct ifnet *, u_long, caddr_t));
57 static int atm_ifparse __P((char *, char *, int, int *));
58
59 /*
60 * Local variables
61 */
62 static int (*atm_ifouttbl[AF_MAX+1])
63 __P((struct ifnet *, KBuffer *, struct sockaddr *))
64 = {NULL};
65
66
67 /*
68 * Register an ATM physical interface
69 *
70 * Each ATM device interface must register itself here upon completing
71 * its internal initialization. This applies to both linked and loaded
72 * device drivers. The interface must be registered before a signalling
73 * manager can be attached.
74 *
75 * Arguments:
76 * cup pointer to interface's common unit structure
77 * name pointer to device name string
78 * sdp pointer to interface's stack services
79 *
80 * Returns:
81 * 0 registration successful
82 * errno registration failed - reason indicated
83 *
84 */
85 int
86 atm_physif_register(cup, name, sdp)
87 Cmn_unit *cup;
88 char *name;
89 struct stack_defn *sdp;
90 {
91 struct atm_pif *pip;
92 int s;
93
94 /*
95 * See if we need to be initialized
96 */
97 if (!atm_init)
98 atm_initialize();
99
100 /*
101 * Make sure we're not already registered
102 */
103 if (cup->cu_flags & CUF_REGISTER) {
104 return (EALREADY);
105 }
106
107 s = splnet();
108
109 /*
110 * Make sure an interface is only registered once
111 */
112 for (pip = atm_interface_head; pip != NULL; pip = pip->pif_next) {
113 if ((cup->cu_unit == pip->pif_unit) &&
114 (strcmp(name, pip->pif_name) == 0)) {
115 (void) splx(s);
116 return (EEXIST);
117 }
118 }
119
120 /*
121 * Fill in physical interface parameters
122 */
123 pip = &cup->cu_pif;
124 pip->pif_name = name;
125 pip->pif_unit = cup->cu_unit;
126 pip->pif_flags = PIF_UP;
127 pip->pif_services = sdp;
128 pip->pif_ioctl = atm_physif_ioctl;
129
130 /*
131 * Link in the interface and mark us registered
132 */
133 LINK2TAIL(pip, struct atm_pif, atm_interface_head, pif_next);
134 cup->cu_flags |= CUF_REGISTER;
135
136 (void) splx(s);
137 return (0);
138 }
139
140
141 /*
142 * De-register an ATM physical interface
143 *
144 * Each ATM interface must de-register itself before downing the interface.
145 * The interface's signalling manager will be detached and any network
146 * interface and VCC control blocks will be freed.
147 *
148 * Arguments:
149 * cup pointer to interface's common unit structure
150 *
151 * Returns:
152 * 0 de-registration successful
153 * errno de-registration failed - reason indicated
154 *
155 */
156 int
157 atm_physif_deregister(cup)
158 Cmn_unit *cup;
159 {
160 struct atm_pif *pip = (struct atm_pif *)&cup->cu_pif;
161 Cmn_vcc *cvp;
162 int err;
163 int s = splnet();
164
165 /*
166 * Detach and deregister, if needed
167 */
168 if ((cup->cu_flags & CUF_REGISTER)) {
169
170 /*
171 * Detach from signalling manager
172 */
173 if (pip->pif_sigmgr != NULL) {
174 err = atm_sigmgr_detach(pip);
175 if (err && (err != ENOENT)) {
176 (void) splx(s);
177 return (err);
178 }
179 }
180
181 /*
182 * Make sure signalling manager is detached
183 */
184 if (pip->pif_sigmgr != NULL) {
185 (void) splx(s);
186 return (EBUSY);
187 }
188
189 /*
190 * Unlink interface
191 */
192 UNLINK(pip, struct atm_pif, atm_interface_head, pif_next);
193
194 cup->cu_flags &= ~CUF_REGISTER;
195 }
196
197 /*
198 * Free all of our network interfaces
199 */
200 atm_physif_freenifs(pip);
201
202 /*
203 * Free unit's vcc information
204 */
205 cvp = cup->cu_vcc;
206 while (cvp) {
207 atm_free(cvp);
208 cvp = cvp->cv_next;
209 }
210 cup->cu_vcc = (Cmn_vcc *)NULL;
211
212 (void) splx(s);
213
214 return (0);
215 }
216
217
218 /*
219 * Free all network interfaces on a physical interface
220 *
221 * Arguments
222 * pip pointer to physical interface structure
223 *
224 * Returns
225 * none
226 *
227 */
228 void
229 atm_physif_freenifs(pip)
230 struct atm_pif *pip;
231 {
232 struct atm_nif *nip = pip->pif_nif;
233 int s = splnet();
234
235 while ( nip )
236 {
237 /*
238 * atm_nif_detach zeros pointers - save so we can
239 * walk the chain.
240 */
241 struct atm_nif *nipp = nip->nif_pnext;
242
243 /*
244 * Clean up network i/f trails
245 */
246 atm_nif_detach ( nip );
247 atm_free ((caddr_t)nip);
248 nip = nipp;
249 }
250 pip->pif_nif = (struct atm_nif *)NULL;
251
252 (void) splx(s);
253
254 return;
255 }
256
257
258 /*
259 * Handle physical interface ioctl's
260 *
261 * See <netatm/atm_ioctl.h> for definitions.
262 *
263 * Called at splnet.
264 *
265 * Arguments:
266 * code Ioctl function (sub)code
267 * data Data block. On input contains command,
268 * on output, contains results
269 * arg Optional code specific arguments
270 *
271 * Returns:
272 * 0 Request processed successfully
273 * errno Request failed - reason code
274 *
275 */
276 static int
277 atm_physif_ioctl(code, data, arg)
278 int code;
279 caddr_t data;
280 caddr_t arg;
281 {
282 struct atminfreq *aip = (struct atminfreq *)data;
283 struct atmsetreq *asr = (struct atmsetreq *)data;
284 struct atm_pif *pip;
285 struct atm_nif *nip;
286 struct sigmgr *smp;
287 struct siginst *sip;
288 struct ifnet *ifp;
289 Cmn_unit *cup;
290 Atm_config *acp;
291 caddr_t buf = aip->air_buf_addr;
292 struct air_phy_stat_rsp *apsp;
293 struct air_int_rsp apr;
294 struct air_netif_rsp anr;
295 struct air_cfg_rsp acr;
296 int count, len, buf_len = aip->air_buf_len;
297 int err = 0;
298 char ifname[2*IFNAMSIZ];
299 #if (defined(BSD) && (BSD >= 199103))
300 struct ifaddr *ifa;
301 struct in_ifaddr *ia;
302 struct sockaddr_dl *sdl;
303 #endif
304
305
306 switch ( aip->air_opcode ) {
307
308 case AIOCS_INF_INT:
309 /*
310 * Get physical interface information
311 */
312 aip = (struct atminfreq *)data;
313 pip = (struct atm_pif *)arg;
314
315 /*
316 * Make sure there's room in user buffer
317 */
318 if (aip->air_buf_len < sizeof(apr)) {
319 err = ENOSPC;
320 break;
321 }
322
323 /*
324 * Fill in info to be returned
325 */
326 KM_ZERO((caddr_t)&apr, sizeof(apr));
327 smp = pip->pif_sigmgr;
328 sip = pip->pif_siginst;
329 (void) snprintf(apr.anp_intf, sizeof(apr.anp_intf),
330 "%s%d", pip->pif_name, pip->pif_unit );
331 if ( pip->pif_nif )
332 {
333 strcpy(apr.anp_nif_pref, pip->pif_nif->nif_if.if_name);
334
335 nip = pip->pif_nif;
336 while ( nip ) {
337 apr.anp_nif_cnt++;
338 nip = nip->nif_pnext;
339 }
340 }
341 if (sip) {
342 ATM_ADDR_COPY(&sip->si_addr, &apr.anp_addr);
343 ATM_ADDR_COPY(&sip->si_subaddr, &apr.anp_subaddr);
344 apr.anp_sig_proto = smp->sm_proto;
345 apr.anp_sig_state = sip->si_state;
346 }
347
348 /*
349 * Copy data to user buffer
350 */
351 err = copyout((caddr_t)&apr, aip->air_buf_addr, sizeof(apr));
352 if (err)
353 break;
354
355 /*
356 * Update buffer pointer/count
357 */
358 aip->air_buf_addr += sizeof(apr);
359 aip->air_buf_len -= sizeof(apr);
360 break;
361
362 case AIOCS_INF_NIF:
363 /*
364 * Get network interface information
365 */
366 aip = (struct atminfreq *)data;
367 nip = (struct atm_nif *)arg;
368 ifp = &nip->nif_if;
369 pip = nip->nif_pif;
370
371 /*
372 * Make sure there's room in user buffer
373 */
374 if (aip->air_buf_len < sizeof(anr)) {
375 err = ENOSPC;
376 break;
377 }
378
379 /*
380 * Fill in info to be returned
381 */
382 KM_ZERO((caddr_t)&anr, sizeof(anr));
383 (void) snprintf(anr.anp_intf, sizeof(anr.anp_intf),
384 "%s%d", ifp->if_name, ifp->if_unit);
385 IFP_TO_IA(ifp, ia);
386 if (ia) {
387 anr.anp_proto_addr = *ia->ia_ifa.ifa_addr;
388 }
389 (void) snprintf(anr.anp_phy_intf, sizeof(anr.anp_phy_intf),
390 "%s%d", pip->pif_name, pip->pif_unit);
391
392 /*
393 * Copy data to user buffer
394 */
395 err = copyout((caddr_t)&anr, aip->air_buf_addr, sizeof(anr));
396 if (err)
397 break;
398
399 /*
400 * Update buffer pointer/count
401 */
402 aip->air_buf_addr += sizeof(anr);
403 aip->air_buf_len -= sizeof(anr);
404 break;
405
406 case AIOCS_INF_PIS:
407 /*
408 * Get per interface statistics
409 */
410 pip = (struct atm_pif *)arg;
411 if ( pip == NULL )
412 return ( ENXIO );
413 snprintf ( ifname, sizeof(ifname),
414 "%s%d", pip->pif_name, pip->pif_unit );
415
416 /*
417 * Cast response into users buffer
418 */
419 apsp = (struct air_phy_stat_rsp *)buf;
420
421 /*
422 * Sanity check
423 */
424 len = sizeof ( struct air_phy_stat_rsp );
425 if ( buf_len < len )
426 return ( ENOSPC );
427
428 /*
429 * Copy interface name into response
430 */
431 if ( err = copyout ( ifname, apsp->app_intf, IFNAMSIZ ) )
432 break;
433
434 /*
435 * Copy counters
436 */
437 if ( err = copyout ( &pip->pif_ipdus, &apsp->app_ipdus,
438 len - sizeof ( apsp->app_intf ) ) )
439 break;
440
441 /*
442 * Adjust buffer elements
443 */
444 buf += len;
445 buf_len -= len;
446
447 aip->air_buf_addr = buf;
448 aip->air_buf_len = buf_len;
449 break;
450
451 case AIOCS_SET_NIF:
452 /*
453 * Set NIF - allow user to configure 1 or more logical
454 * interfaces per physical interface.
455 */
456
457 /*
458 * Get pointer to physical interface structure from
459 * ioctl argument.
460 */
461 pip = (struct atm_pif *)arg;
462 cup = (Cmn_unit *)pip;
463
464 /*
465 * Sanity check - are we already connected to something?
466 */
467 if ( pip->pif_sigmgr )
468 {
469 err = EBUSY;
470 break;
471 }
472
473 /*
474 * Free any previously allocated NIFs
475 */
476 atm_physif_freenifs(pip);
477
478 /*
479 * Add list of interfaces
480 */
481 for ( count = 0; count < asr->asr_nif_cnt; count++ )
482 {
483 nip = (struct atm_nif *)atm_allocate(cup->cu_nif_pool);
484 if ( nip == NULL )
485 {
486 /*
487 * Destroy any successful nifs
488 */
489 atm_physif_freenifs(pip);
490 err = ENOMEM;
491 break;
492 }
493
494 nip->nif_pif = pip;
495 ifp = &nip->nif_if;
496
497 strcpy ( nip->nif_name, asr->asr_nif_pref );
498 nip->nif_sel = count;
499
500 ifp->if_name = nip->nif_name;
501 ifp->if_unit = count;
502 ifp->if_mtu = ATM_NIF_MTU;
503 ifp->if_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
504 ifp->if_output = atm_ifoutput;
505 ifp->if_ioctl = atm_if_ioctl;
506 ifp->if_snd.ifq_maxlen = ifqmaxlen;
507 #if (defined(BSD) && (BSD >= 199103))
508 /*
509 * Set if_type and if_baudrate
510 */
511 ifp->if_type = IFT_ATM;
512 switch ( cup->cu_config.ac_media ) {
513 case MEDIA_TAXI_100:
514 ifp->if_baudrate = 100000000;
515 break;
516 case MEDIA_TAXI_140:
517 ifp->if_baudrate = 140000000;
518 break;
519 case MEDIA_OC3C:
520 case MEDIA_OC12C:
521 case MEDIA_UTP155:
522 ifp->if_baudrate = 155000000;
523 break;
524 }
525 #endif
526
527 if ( err = atm_nif_attach ( nip ) )
528 {
529 atm_free ( (caddr_t)nip );
530
531 /*
532 * Destroy any successful nifs
533 */
534 atm_physif_freenifs(pip);
535 break;
536 }
537 #if (defined(BSD) && (BSD >= 199103))
538 /*
539 * Set macaddr in <Link> address
540 */
541 ifp->if_addrlen = 6;
542 ifa = ifnet_addrs[ifp->if_index - 1];
543 if ( ifa ) {
544 sdl = (struct sockaddr_dl *)
545 ifa->ifa_addr;
546 sdl->sdl_type = IFT_ETHER;
547 sdl->sdl_alen = ifp->if_addrlen;
548 bcopy ( (caddr_t)&cup->cu_config.ac_macaddr,
549 LLADDR(sdl), ifp->if_addrlen );
550 }
551 #endif
552 }
553 break;
554
555 case AIOCS_INF_CFG:
556 /*
557 * Get adapter configuration information
558 */
559 aip = (struct atminfreq *)data;
560 pip = (struct atm_pif *)arg;
561 cup = (Cmn_unit *)pip;
562 acp = &cup->cu_config;
563
564 /*
565 * Make sure there's room in user buffer
566 */
567 if (aip->air_buf_len < sizeof(acr)) {
568 err = ENOSPC;
569 break;
570 }
571
572 /*
573 * Fill in info to be returned
574 */
575 KM_ZERO((caddr_t)&acr, sizeof(acr));
576 (void) snprintf(acr.acp_intf, sizeof(acr.acp_intf),
577 "%s%d", pip->pif_name, pip->pif_unit);
578 KM_COPY((caddr_t)acp, (caddr_t)&acr.acp_cfg,
579 sizeof(Atm_config));
580
581 /*
582 * Copy data to user buffer
583 */
584 err = copyout((caddr_t)&acr, aip->air_buf_addr,
585 sizeof(acr));
586 if (err)
587 break;
588
589 /*
590 * Update buffer pointer/count
591 */
592 aip->air_buf_addr += sizeof(acr);
593 aip->air_buf_len -= sizeof(acr);
594 break;
595
596 case AIOCS_INF_VST:
597 /*
598 * Pass off to device-specific handler
599 */
600 cup = (Cmn_unit *)arg;
601 if (cup == NULL)
602 err = ENXIO;
603 else
604 err = (*cup->cu_ioctl)(code, data, arg);
605 break;
606
607 default:
608 err = ENOSYS;
609 }
610
611 return ( err );
612 }
613
614
615 /*
616 * Register a Network Convergence Module
617 *
618 * Each ATM network convergence module must register itself here before
619 * it will receive network interface status notifications.
620 *
621 * Arguments:
622 * ncp pointer to network convergence definition structure
623 *
624 * Returns:
625 * 0 registration successful
626 * errno registration failed - reason indicated
627 *
628 */
629 int
630 atm_netconv_register(ncp)
631 struct atm_ncm *ncp;
632 {
633 struct atm_ncm *tdp;
634 int s = splnet();
635
636 /*
637 * See if we need to be initialized
638 */
639 if (!atm_init)
640 atm_initialize();
641
642 /*
643 * Validate protocol family
644 */
645 if (ncp->ncm_family > AF_MAX) {
646 (void) splx(s);
647 return (EINVAL);
648 }
649
650 /*
651 * Ensure no duplicates
652 */
653 for (tdp = atm_netconv_head; tdp != NULL; tdp = tdp->ncm_next) {
654 if (tdp->ncm_family == ncp->ncm_family) {
655 (void) splx(s);
656 return (EEXIST);
657 }
658 }
659
660 /*
661 * Add module to list
662 */
663 LINK2TAIL(ncp, struct atm_ncm, atm_netconv_head, ncm_next);
664
665 /*
666 * Add new interface output function
667 */
668 atm_ifouttbl[ncp->ncm_family] = ncp->ncm_ifoutput;
669
670 (void) splx(s);
671 return (0);
672 }
673
674
675 /*
676 * De-register an ATM Network Convergence Module
677 *
678 * Each ATM network convergence provider must de-register its registered
679 * service(s) before terminating. Specifically, loaded kernel modules
680 * must de-register their services before unloading themselves.
681 *
682 * Arguments:
683 * ncp pointer to network convergence definition structure
684 *
685 * Returns:
686 * 0 de-registration successful
687 * errno de-registration failed - reason indicated
688 *
689 */
690 int
691 atm_netconv_deregister(ncp)
692 struct atm_ncm *ncp;
693 {
694 int found, s = splnet();
695
696 /*
697 * Remove module from list
698 */
699 UNLINKF(ncp, struct atm_ncm, atm_netconv_head, ncm_next, found);
700
701 if (!found) {
702 (void) splx(s);
703 return (ENOENT);
704 }
705
706 /*
707 * Remove module's interface output function
708 */
709 atm_ifouttbl[ncp->ncm_family] = NULL;
710
711 (void) splx(s);
712 return (0);
713 }
714
715
716 /*
717 * Attach an ATM Network Interface
718 *
719 * Before an ATM network interface can be used by the system, the owning
720 * device interface must attach the network interface using this function.
721 * The physical interface for this network interface must have been previously
722 * registered (using atm_interface_register). The network interface will be
723 * added to the kernel's interface list and to the physical interface's list.
724 * The caller is responsible for initializing the control block fields.
725 *
726 * Arguments:
727 * nip pointer to atm network interface control block
728 *
729 * Returns:
730 * 0 attach successful
731 * errno attach failed - reason indicated
732 *
733 */
734 int
735 atm_nif_attach(nip)
736 struct atm_nif *nip;
737 {
738 struct atm_pif *pip, *pip2;
739 struct ifnet *ifp;
740 struct atm_ncm *ncp;
741 int s;
742
743 ifp = &nip->nif_if;
744 pip = nip->nif_pif;
745
746 s = splimp();
747
748 /*
749 * Verify physical interface is registered
750 */
751 for (pip2 = atm_interface_head; pip2 != NULL; pip2 = pip2->pif_next) {
752 if (pip == pip2)
753 break;
754 }
755 if ((pip == NULL) || (pip2 == NULL)) {
756 (void) splx(s);
757 return (EFAULT);
758 }
759
760 /*
761 * Add to system interface list
762 */
763 if_attach(ifp);
764
765 /*
766 * Add to physical interface list
767 */
768 LINK2TAIL(nip, struct atm_nif, pip->pif_nif, nif_pnext);
769
770 /*
771 * Notify network convergence modules of new network i/f
772 */
773 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
774 int err;
775
776 err = (*ncp->ncm_stat)(NCM_ATTACH, nip, 0);
777 if (err) {
778 atm_nif_detach(nip);
779 (void) splx(s);
780 return (err);
781 }
782 }
783
784 (void) splx(s);
785 return (0);
786 }
787
788
789 /*
790 * Detach an ATM Network Interface
791 *
792 * Before an ATM network interface control block can be freed, all kernel
793 * references to/from this block must be released. This function will delete
794 * all routing references to the interface and free all interface addresses
795 * for the interface. The network interface will then be removed from the
796 * kernel's interface list and from the owning physical interface's list.
797 * The caller is responsible for free'ing the control block.
798 *
799 * Arguments:
800 * nip pointer to atm network interface control block
801 *
802 * Returns:
803 * none
804 *
805 */
806 void
807 atm_nif_detach(nip)
808 struct atm_nif *nip;
809 {
810 struct atm_ncm *ncp;
811 int s, i;
812 struct ifnet *ifp = &nip->nif_if;
813 struct ifaddr *ifa;
814 struct in_ifaddr *ia;
815 struct radix_node_head *rnh;
816
817
818 s = splimp();
819
820 /*
821 * Notify convergence modules of network i/f demise
822 */
823 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
824 (void) (*ncp->ncm_stat)(NCM_DETACH, nip, 0);
825 }
826
827 /*
828 * Mark interface down
829 */
830 if_down(ifp);
831
832 /*
833 * Free all interface routes and addresses
834 */
835 while (1) {
836 IFP_TO_IA(ifp, ia);
837 if (ia == NULL)
838 break;
839
840 /* Delete interface route */
841 in_ifscrub(ifp, ia);
842
843 /* Remove interface address from queues */
844 ifa = &ia->ia_ifa;
845 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
846 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
847
848 /* Free interface address */
849 IFAFREE(ifa);
850 }
851
852 /*
853 * Delete all remaining routes using this interface
854 * Unfortuneatly the only way to do this is to slog through
855 * the entire routing table looking for routes which point
856 * to this interface...oh well...
857 */
858 for (i = 1; i <= AF_MAX; i++) {
859 if ((rnh = rt_tables[i]) == NULL)
860 continue;
861 (void) rnh->rnh_walktree(rnh, atm_netif_rtdel, ifp);
862 }
863
864 /*
865 * Remove from system interface list (ie. if_detach())
866 */
867 TAILQ_REMOVE(&ifnet, ifp, if_link);
868
869 /*
870 * Remove from physical interface list
871 */
872 UNLINK(nip, struct atm_nif, nip->nif_pif->pif_nif, nif_pnext);
873
874 (void) splx(s);
875 }
876
877
878 /*
879 * Delete Routes for a Network Interface
880 *
881 * Called for each routing entry via the rnh->rnh_walktree() call above
882 * to delete all route entries referencing a detaching network interface.
883 *
884 * Arguments:
885 * rn pointer to node in the routing table
886 * arg argument passed to rnh->rnh_walktree() - detaching interface
887 *
888 * Returns:
889 * 0 successful
890 * errno failed - reason indicated
891 *
892 */
893 static int
894 atm_netif_rtdel(rn, arg)
895 struct radix_node *rn;
896 void *arg;
897 {
898 struct rtentry *rt = (struct rtentry *)rn;
899 struct ifnet *ifp = arg;
900 int err;
901
902 if (rt->rt_ifp == ifp) {
903
904 /*
905 * Protect (sorta) against walktree recursion problems
906 * with cloned routes
907 */
908 if ((rt->rt_flags & RTF_UP) == 0)
909 return (0);
910
911 err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
912 rt_mask(rt), rt->rt_flags,
913 (struct rtentry **) NULL);
914 if (err) {
915 log(LOG_WARNING, "atm_netif_rtdel: error %d\n", err);
916 }
917 }
918
919 return (0);
920 }
921
922
923 /*
924 * Set an ATM Network Interface address
925 *
926 * This is called from a device interface when processing an SIOCSIFADDR
927 * ioctl request. We just notify all convergence modules of the new address
928 * and hope everyone has non-overlapping interests, since if someone reports
929 * an error we don't go back and tell everyone to undo the change.
930 *
931 * Arguments:
932 * nip pointer to atm network interface control block
933 * ifa pointer to new interface address
934 *
935 * Returns:
936 * 0 set successful
937 * errno set failed - reason indicated
938 *
939 */
940 int
941 atm_nif_setaddr(nip, ifa)
942 struct atm_nif *nip;
943 struct ifaddr *ifa;
944 {
945 struct atm_ncm *ncp;
946 int err = 0, s = splnet();
947
948 /*
949 * Notify convergence modules of network i/f change
950 */
951 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
952 err = (*ncp->ncm_stat)(NCM_SETADDR, nip, (int)ifa);
953 if (err)
954 break;
955 }
956 (void) splx(s);
957
958 return (err);
959 }
960
961
962 /*
963 * ATM Interface Packet Output
964 *
965 * All ATM network interfaces must have their ifnet if_output address set to
966 * this function. Since no existing network layer code is to be modified
967 * for ATM support, this function serves as the hook to allow network output
968 * packets to be assigned to their proper outbound VCC. Each network address
969 * family which is to be supported over ATM must be assigned an output
970 * packet processing function via atm_netconv_register().
971 *
972 * Arguments:
973 * ifp pointer to ifnet structure
974 * m pointer to packet buffer chain to be output
975 * dst pointer to packet's network destination address
976 *
977 * Returns:
978 * 0 packet queued to interface
979 * errno output failed - reason indicated
980 *
981 */
982 int
983 #if (defined(BSD) && (BSD >= 199103))
984 atm_ifoutput(ifp, m, dst, rt)
985 #else
986 atm_ifoutput(ifp, m, dst)
987 #endif
988 struct ifnet *ifp;
989 KBuffer *m;
990 struct sockaddr *dst;
991 #if (defined(BSD) && (BSD >= 199103))
992 struct rtentry *rt;
993 #endif
994 {
995 u_short fam = dst->sa_family;
996 int (*func)__P((struct ifnet *, KBuffer *,
997 struct sockaddr *));
998
999 /*
1000 * Validate address family
1001 */
1002 if (fam > AF_MAX) {
1003 KB_FREEALL(m);
1004 return (EAFNOSUPPORT);
1005 }
1006
1007 /*
1008 * Hand packet off for dst-to-VCC mapping
1009 */
1010 func = atm_ifouttbl[fam];
1011 if (func == NULL) {
1012 KB_FREEALL(m);
1013 return (EAFNOSUPPORT);
1014 }
1015 return ((*func)(ifp, m, dst));
1016 }
1017
1018
1019 /*
1020 * Handle interface ioctl requests.
1021 *
1022 * Arguments:
1023 * ifp pointer to network interface structure
1024 * cmd IOCTL cmd
1025 * data arguments to/from ioctl
1026 *
1027 * Returns:
1028 * error errno value
1029 */
1030 static int
1031 atm_if_ioctl(ifp, cmd, data)
1032 struct ifnet *ifp;
1033 u_long cmd;
1034 caddr_t data;
1035 {
1036 register struct ifreq *ifr = (struct ifreq *)data;
1037 struct atm_nif *nip = (struct atm_nif *)ifp;
1038 int error = 0;
1039 int s = splnet();
1040
1041 switch ( cmd )
1042 {
1043 case SIOCGIFADDR:
1044 KM_COPY ( (caddr_t)&(nip->nif_pif->pif_macaddr),
1045 (caddr_t)ifr->ifr_addr.sa_data,
1046 sizeof(struct mac_addr) );
1047 break;
1048
1049 case SIOCSIFADDR:
1050 error = atm_nif_setaddr ( nip, (struct ifaddr *)data);
1051 ifp->if_flags |= IFF_UP | IFF_RUNNING | IFF_BROADCAST;
1052 break;
1053
1054 case SIOCGIFFLAGS:
1055 *(short *)data = ifp->if_flags;
1056 break;
1057
1058 case SIOCSIFFLAGS:
1059 break;
1060
1061 default:
1062 error = EINVAL;
1063 break;
1064 }
1065
1066 (void) splx(s);
1067 return ( error );
1068 }
1069
1070
1071 /*
1072 * Parse interface name
1073 *
1074 * Parses an interface name string into a name and a unit component.
1075 *
1076 * Arguments:
1077 * name pointer to interface name string
1078 * namep address to store interface name
1079 * size size available at namep
1080 * unitp address to store interface unit number
1081 *
1082 * Returns:
1083 * 0 name parsed
1084 * else parse error
1085 *
1086 */
1087 static int
1088 atm_ifparse(name, namep, size, unitp)
1089 char *name;
1090 char *namep;
1091 int size;
1092 int *unitp;
1093 {
1094 char *cp, *np;
1095 int len = 0, unit = 0;
1096
1097 /*
1098 * Separate supplied string into name and unit parts.
1099 */
1100 cp = name;
1101 np = namep;
1102 while (*cp) {
1103 if (*cp >= '' && *cp <= '9')
1104 break;
1105 if (++len >= size)
1106 return (-1);
1107 *np++ = *cp++;
1108 }
1109 *np = '\0';
1110 while (*cp && *cp >= '' && *cp <= '9')
1111 unit = 10 * unit + *cp++ - '';
1112
1113 *unitp = unit;
1114
1115 return (0);
1116 }
1117
1118
1119 /*
1120 * Locate ATM physical interface via name
1121 *
1122 * Uses the supplied interface name string to locate a registered
1123 * ATM physical interface.
1124 *
1125 * Arguments:
1126 * name pointer to interface name string
1127 *
1128 * Returns:
1129 * 0 interface not found
1130 * else pointer to atm physical interface structure
1131 *
1132 */
1133 struct atm_pif *
1134 atm_pifname(name)
1135 char *name;
1136 {
1137 struct atm_pif *pip;
1138 char n[IFNAMSIZ];
1139 int unit;
1140
1141 /*
1142 * Break down name
1143 */
1144 if (atm_ifparse(name, n, sizeof(n), &unit))
1145 return ((struct atm_pif *)0);
1146
1147 /*
1148 * Look for the physical interface
1149 */
1150 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
1151 if ((pip->pif_unit == unit) && (strcmp(pip->pif_name, n) == 0))
1152 break;
1153 }
1154
1155 return (pip);
1156 }
1157
1158
1159 /*
1160 * Locate ATM network interface via name
1161 *
1162 * Uses the supplied interface name string to locate an ATM network interface.
1163 *
1164 * Arguments:
1165 * name pointer to interface name string
1166 *
1167 * Returns:
1168 * 0 interface not found
1169 * else pointer to atm network interface structure
1170 *
1171 */
1172 struct atm_nif *
1173 atm_nifname(name)
1174 char *name;
1175 {
1176 struct atm_pif *pip;
1177 struct atm_nif *nip;
1178 char n[IFNAMSIZ];
1179 int unit;
1180
1181 /*
1182 * Break down name
1183 */
1184 if (atm_ifparse(name, n, sizeof(n), &unit))
1185 return ((struct atm_nif *)0);
1186
1187 /*
1188 * Search thru each physical interface
1189 */
1190 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
1191 /*
1192 * Looking for network interface
1193 */
1194 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
1195 struct ifnet *ifp = (struct ifnet *)nip;
1196 if ((ifp->if_unit == unit) &&
1197 (strcmp(ifp->if_name, n) == 0))
1198 return (nip);
1199 }
1200 }
1201 return (NULL);
1202 }
1203
Cache object: 95b5c2ca4be4ad404ca63974a81354c1
|