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