kernel/atm: Fix wrong rt_tables[] access.
[dragonfly.git] / sys / netproto / atm / atm_if.c
blob9a4f7676b011e36c38fa4a741db42ec2b543cdea
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/atm_if.c,v 1.5 1999/08/28 00:48:35 peter Exp $
30 * Core ATM Services
31 * -----------------
33 * ATM interface management
37 #include "kern_include.h"
40 * Local functions
42 static int atm_physif_ioctl (int, caddr_t, caddr_t);
43 static int atm_netif_rtdel (struct radix_node *, void *);
44 static int atm_if_ioctl (struct ifnet *, u_long, caddr_t, struct ucred *);
45 static int atm_ifparse (char *, char *, int, int *);
48 * Local variables
50 static int (*atm_ifouttbl[AF_MAX+1])
51 (struct ifnet *, KBuffer *, struct sockaddr *)
52 = {NULL};
56 * Register an ATM physical interface
58 * Each ATM device interface must register itself here upon completing
59 * its internal initialization. This applies to both linked and loaded
60 * device drivers. The interface must be registered before a signalling
61 * manager can be attached.
63 * Arguments:
64 * cup pointer to interface's common unit structure
65 * name pointer to device name string
66 * sdp pointer to interface's stack services
68 * Returns:
69 * 0 registration successful
70 * errno registration failed - reason indicated
73 int
74 atm_physif_register(Cmn_unit *cup, char *name, struct stack_defn *sdp)
76 struct atm_pif *pip;
79 * See if we need to be initialized
81 if (!atm_init)
82 atm_initialize();
85 * Make sure we're not already registered
87 if (cup->cu_flags & CUF_REGISTER) {
88 return (EALREADY);
91 crit_enter();
94 * Make sure an interface is only registered once
96 for (pip = atm_interface_head; pip != NULL; pip = pip->pif_next) {
97 if ((cup->cu_unit == pip->pif_unit) &&
98 (strcmp(name, pip->pif_name) == 0)) {
99 crit_exit();
100 return (EEXIST);
105 * Fill in physical interface parameters
107 pip = &cup->cu_pif;
108 pip->pif_name = name;
109 pip->pif_unit = cup->cu_unit;
110 pip->pif_flags = PIF_UP;
111 pip->pif_services = sdp;
112 pip->pif_ioctl = atm_physif_ioctl;
115 * Link in the interface and mark us registered
117 LINK2TAIL(pip, struct atm_pif, atm_interface_head, pif_next);
118 cup->cu_flags |= CUF_REGISTER;
120 crit_exit();
121 return (0);
126 * De-register an ATM physical interface
128 * Each ATM interface must de-register itself before downing the interface.
129 * The interface's signalling manager will be detached and any network
130 * interface and VCC control blocks will be freed.
132 * Arguments:
133 * cup pointer to interface's common unit structure
135 * Returns:
136 * 0 de-registration successful
137 * errno de-registration failed - reason indicated
141 atm_physif_deregister(Cmn_unit *cup)
143 struct atm_pif *pip = (struct atm_pif *)&cup->cu_pif;
144 Cmn_vcc *cvp;
145 int err;
147 crit_enter();
150 * Detach and deregister, if needed
152 if ((cup->cu_flags & CUF_REGISTER)) {
155 * Detach from signalling manager
157 if (pip->pif_sigmgr != NULL) {
158 err = atm_sigmgr_detach(pip);
159 if (err && (err != ENOENT)) {
160 crit_exit();
161 return (err);
166 * Make sure signalling manager is detached
168 if (pip->pif_sigmgr != NULL) {
169 crit_exit();
170 return (EBUSY);
174 * Unlink interface
176 UNLINK(pip, struct atm_pif, atm_interface_head, pif_next);
178 cup->cu_flags &= ~CUF_REGISTER;
182 * Free all of our network interfaces
184 atm_physif_freenifs(pip);
187 * Free unit's vcc information
189 cvp = cup->cu_vcc;
190 while (cvp) {
191 atm_free(cvp);
192 cvp = cvp->cv_next;
194 cup->cu_vcc = NULL;
196 crit_exit();
198 return (0);
203 * Free all network interfaces on a physical interface
205 * Arguments
206 * pip pointer to physical interface structure
208 * Returns
209 * none
212 void
213 atm_physif_freenifs(struct atm_pif *pip)
215 struct atm_nif *nip = pip->pif_nif;
217 crit_enter();
218 while ( nip )
221 * atm_nif_detach zeros pointers - save so we can
222 * walk the chain.
224 struct atm_nif *nipp = nip->nif_pnext;
227 * Clean up network i/f trails
229 atm_nif_detach ( nip );
230 atm_free ((caddr_t)nip);
231 nip = nipp;
233 pip->pif_nif = NULL;
235 crit_exit();
237 return;
242 * Handle physical interface ioctl's
244 * See <netatm/atm_ioctl.h> for definitions.
246 * Called from a critical section.
248 * Arguments:
249 * code Ioctl function (sub)code
250 * data Data block. On input contains command,
251 * on output, contains results
252 * arg Optional code specific arguments
254 * Returns:
255 * 0 Request processed successfully
256 * errno Request failed - reason code
259 static int
260 atm_physif_ioctl(int code, caddr_t data, caddr_t arg)
262 struct atminfreq *aip = (struct atminfreq *)data;
263 struct atmsetreq *asr = (struct atmsetreq *)data;
264 struct atm_pif *pip;
265 struct atm_nif *nip;
266 struct sigmgr *smp;
267 struct siginst *sip;
268 struct ifnet *ifp;
269 Cmn_unit *cup;
270 Atm_config *acp;
271 caddr_t buf = aip->air_buf_addr;
272 struct air_phy_stat_rsp *apsp;
273 struct air_int_rsp apr;
274 struct air_netif_rsp anr;
275 struct air_cfg_rsp acr;
276 int count, len, buf_len = aip->air_buf_len;
277 int err = 0;
278 char ifname[2*IFNAMSIZ];
279 struct in_ifaddr *ia;
280 struct sockaddr_dl *sdl;
282 switch ( aip->air_opcode ) {
284 case AIOCS_INF_INT:
286 * Get physical interface information
288 aip = (struct atminfreq *)data;
289 pip = (struct atm_pif *)arg;
292 * Make sure there's room in user buffer
294 if (aip->air_buf_len < sizeof(apr)) {
295 err = ENOSPC;
296 break;
300 * Fill in info to be returned
302 KM_ZERO((caddr_t)&apr, sizeof(apr));
303 smp = pip->pif_sigmgr;
304 sip = pip->pif_siginst;
305 ksnprintf(apr.anp_intf, sizeof(apr.anp_intf),
306 "%s%d", pip->pif_name, pip->pif_unit );
307 if ( pip->pif_nif )
309 strcpy(apr.anp_nif_pref, /* XXX: strings */
310 pip->pif_nif->nif_if.if_dname);
312 nip = pip->pif_nif;
313 while ( nip ) {
314 apr.anp_nif_cnt++;
315 nip = nip->nif_pnext;
318 if (sip) {
319 ATM_ADDR_COPY(&sip->si_addr, &apr.anp_addr);
320 ATM_ADDR_COPY(&sip->si_subaddr, &apr.anp_subaddr);
321 apr.anp_sig_proto = smp->sm_proto;
322 apr.anp_sig_state = sip->si_state;
326 * Copy data to user buffer
328 err = copyout((caddr_t)&apr, aip->air_buf_addr, sizeof(apr));
329 if (err)
330 break;
333 * Update buffer pointer/count
335 aip->air_buf_addr += sizeof(apr);
336 aip->air_buf_len -= sizeof(apr);
337 break;
339 case AIOCS_INF_NIF:
341 * Get network interface information
343 aip = (struct atminfreq *)data;
344 nip = (struct atm_nif *)arg;
345 ifp = &nip->nif_if;
346 pip = nip->nif_pif;
349 * Make sure there's room in user buffer
351 if (aip->air_buf_len < sizeof(anr)) {
352 err = ENOSPC;
353 break;
357 * Fill in info to be returned
359 KM_ZERO((caddr_t)&anr, sizeof(anr));
360 ksnprintf(anr.anp_intf, sizeof(anr.anp_intf),
361 "%s", ifp->if_xname);
362 ia = IFP_TO_IA(ifp);
363 if (ia) {
364 anr.anp_proto_addr = *ia->ia_ifa.ifa_addr;
366 ksnprintf(anr.anp_phy_intf, sizeof(anr.anp_phy_intf),
367 "%s%d", pip->pif_name, pip->pif_unit);
370 * Copy data to user buffer
372 err = copyout((caddr_t)&anr, aip->air_buf_addr, sizeof(anr));
373 if (err)
374 break;
377 * Update buffer pointer/count
379 aip->air_buf_addr += sizeof(anr);
380 aip->air_buf_len -= sizeof(anr);
381 break;
383 case AIOCS_INF_PIS:
385 * Get per interface statistics
387 pip = (struct atm_pif *)arg;
388 if ( pip == NULL )
389 return ( ENXIO );
390 ksnprintf ( ifname, sizeof(ifname),
391 "%s%d", pip->pif_name, pip->pif_unit );
394 * Cast response into users buffer
396 apsp = (struct air_phy_stat_rsp *)buf;
399 * Sanity check
401 len = sizeof ( struct air_phy_stat_rsp );
402 if ( buf_len < len )
403 return ( ENOSPC );
406 * Copy interface name into response
408 if ((err = copyout ( ifname, apsp->app_intf, IFNAMSIZ)) != 0)
409 break;
412 * Copy counters
414 if ((err = copyout(&pip->pif_ipdus, &apsp->app_ipdus,
415 len - sizeof(apsp->app_intf))) != 0)
416 break;
419 * Adjust buffer elements
421 buf += len;
422 buf_len -= len;
424 aip->air_buf_addr = buf;
425 aip->air_buf_len = buf_len;
426 break;
428 case AIOCS_SET_NIF:
430 * Set NIF - allow user to configure 1 or more logical
431 * interfaces per physical interface.
435 * Get pointer to physical interface structure from
436 * ioctl argument.
438 pip = (struct atm_pif *)arg;
439 cup = (Cmn_unit *)pip;
442 * Sanity check - are we already connected to something?
444 if ( pip->pif_sigmgr )
446 err = EBUSY;
447 break;
451 * Free any previously allocated NIFs
453 atm_physif_freenifs(pip);
456 * Add list of interfaces
458 for ( count = 0; count < asr->asr_nif_cnt; count++ )
460 nip = (struct atm_nif *)atm_allocate(cup->cu_nif_pool);
461 if ( nip == NULL )
464 * Destroy any successful nifs
466 atm_physif_freenifs(pip);
467 err = ENOMEM;
468 break;
471 nip->nif_pif = pip;
472 ifp = &nip->nif_if;
474 strcpy ( nip->nif_name, asr->asr_nif_pref );
475 nip->nif_sel = count;
477 if_initname(ifp, nip->nif_name, count);
478 ifp->if_mtu = ATM_NIF_MTU;
479 ifp->if_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
480 ifp->if_output = atm_ifoutput;
481 ifp->if_ioctl = atm_if_ioctl;
482 ifp->if_snd.ifq_maxlen = ifqmaxlen;
484 * Set if_type and if_baudrate
486 ifp->if_type = IFT_ATM;
487 switch ( cup->cu_config.ac_media ) {
488 case MEDIA_TAXI_100:
489 ifp->if_baudrate = 100000000;
490 break;
491 case MEDIA_TAXI_140:
492 ifp->if_baudrate = 140000000;
493 break;
494 case MEDIA_OC3C:
495 case MEDIA_OC12C:
496 case MEDIA_UTP155:
497 ifp->if_baudrate = 155000000;
498 break;
499 default:
500 panic("AIOCF_SETNIF: unknown media");
503 if ((err = atm_nif_attach(nip, NULL)) != 0) {
504 atm_free ( (caddr_t)nip );
507 * Destroy any successful nifs
509 atm_physif_freenifs(pip);
510 break;
513 * Set macaddr in <Link> address
515 ifp->if_addrlen = 6;
516 sdl = IF_LLSOCKADDR(ifp);
517 sdl->sdl_type = IFT_ETHER;
518 sdl->sdl_alen = ifp->if_addrlen;
519 bcopy ( (caddr_t)&cup->cu_config.ac_macaddr,
520 LLADDR(sdl), ifp->if_addrlen );
522 break;
524 case AIOCS_INF_CFG:
526 * Get adapter configuration information
528 aip = (struct atminfreq *)data;
529 pip = (struct atm_pif *)arg;
530 cup = (Cmn_unit *)pip;
531 acp = &cup->cu_config;
534 * Make sure there's room in user buffer
536 if (aip->air_buf_len < sizeof(acr)) {
537 err = ENOSPC;
538 break;
542 * Fill in info to be returned
544 KM_ZERO((caddr_t)&acr, sizeof(acr));
545 ksnprintf(acr.acp_intf, sizeof(acr.acp_intf),
546 "%s%d", pip->pif_name, pip->pif_unit);
547 KM_COPY((caddr_t)acp, (caddr_t)&acr.acp_cfg,
548 sizeof(Atm_config));
551 * Copy data to user buffer
553 err = copyout((caddr_t)&acr, aip->air_buf_addr,
554 sizeof(acr));
555 if (err)
556 break;
559 * Update buffer pointer/count
561 aip->air_buf_addr += sizeof(acr);
562 aip->air_buf_len -= sizeof(acr);
563 break;
565 case AIOCS_INF_VST:
567 * Pass off to device-specific handler
569 cup = (Cmn_unit *)arg;
570 if (cup == NULL)
571 err = ENXIO;
572 else
573 err = (*cup->cu_ioctl)(code, data, arg);
574 break;
576 default:
577 err = ENOSYS;
580 return ( err );
585 * Register a Network Convergence Module
587 * Each ATM network convergence module must register itself here before
588 * it will receive network interface status notifications.
590 * Arguments:
591 * ncp pointer to network convergence definition structure
593 * Returns:
594 * 0 registration successful
595 * errno registration failed - reason indicated
599 atm_netconv_register(struct atm_ncm *ncp)
601 struct atm_ncm *tdp;
603 crit_enter();
605 * See if we need to be initialized
607 if (!atm_init)
608 atm_initialize();
611 * Validate protocol family
613 if (ncp->ncm_family > AF_MAX) {
614 crit_exit();
615 return (EINVAL);
619 * Ensure no duplicates
621 for (tdp = atm_netconv_head; tdp != NULL; tdp = tdp->ncm_next) {
622 if (tdp->ncm_family == ncp->ncm_family) {
623 crit_exit();
624 return (EEXIST);
629 * Add module to list
631 LINK2TAIL(ncp, struct atm_ncm, atm_netconv_head, ncm_next);
634 * Add new interface output function
636 atm_ifouttbl[ncp->ncm_family] = ncp->ncm_ifoutput;
638 crit_exit();
639 return (0);
644 * De-register an ATM Network Convergence Module
646 * Each ATM network convergence provider must de-register its registered
647 * service(s) before terminating. Specifically, loaded kernel modules
648 * must de-register their services before unloading themselves.
650 * Arguments:
651 * ncp pointer to network convergence definition structure
653 * Returns:
654 * 0 de-registration successful
655 * errno de-registration failed - reason indicated
659 atm_netconv_deregister(struct atm_ncm *ncp)
661 int found;
663 crit_enter();
666 * Remove module from list
668 UNLINKF(ncp, struct atm_ncm, atm_netconv_head, ncm_next, found);
670 if (!found) {
671 crit_exit();
672 return (ENOENT);
676 * Remove module's interface output function
678 atm_ifouttbl[ncp->ncm_family] = NULL;
680 crit_exit();
681 return (0);
686 * Attach an ATM Network Interface
688 * Before an ATM network interface can be used by the system, the owning
689 * device interface must attach the network interface using this function.
690 * The physical interface for this network interface must have been previously
691 * registered (using atm_interface_register). The network interface will be
692 * added to the kernel's interface list and to the physical interface's list.
693 * The caller is responsible for initializing the control block fields.
695 * Arguments:
696 * nip pointer to atm network interface control block
698 * Returns:
699 * 0 attach successful
700 * errno attach failed - reason indicated
704 atm_nif_attach(struct atm_nif *nip, lwkt_serialize_t serializer)
706 struct atm_pif *pip, *pip2;
707 struct ifnet *ifp;
708 struct atm_ncm *ncp;
710 ifp = &nip->nif_if;
711 pip = nip->nif_pif;
713 crit_enter();
716 * Verify physical interface is registered
718 for (pip2 = atm_interface_head; pip2 != NULL; pip2 = pip2->pif_next) {
719 if (pip == pip2)
720 break;
722 if ((pip == NULL) || (pip2 == NULL)) {
723 crit_exit();
724 return (EFAULT);
728 * Add to system interface list
730 if_attach(ifp, serializer);
733 * Add to physical interface list
735 LINK2TAIL(nip, struct atm_nif, pip->pif_nif, nif_pnext);
738 * Notify network convergence modules of new network i/f
740 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
741 int err;
743 err = (*ncp->ncm_stat)(NCM_ATTACH, nip, 0);
744 if (err) {
745 atm_nif_detach(nip);
746 crit_exit();
747 return (err);
751 crit_exit();
752 return (0);
757 * Detach an ATM Network Interface
759 * Before an ATM network interface control block can be freed, all kernel
760 * references to/from this block must be released. This function will delete
761 * all routing references to the interface and free all interface addresses
762 * for the interface. The network interface will then be removed from the
763 * kernel's interface list and from the owning physical interface's list.
764 * The caller is responsible for free'ing the control block.
766 * Arguments:
767 * nip pointer to atm network interface control block
769 * Returns:
770 * none
773 void
774 atm_nif_detach(struct atm_nif *nip)
776 struct atm_ncm *ncp;
777 int i;
778 struct ifnet *ifp = &nip->nif_if;
779 struct ifaddr *ifa;
780 struct in_ifaddr *ia;
781 struct radix_node_head *rnh;
783 crit_enter();
786 * Notify convergence modules of network i/f demise
788 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
789 (*ncp->ncm_stat)(NCM_DETACH, nip, 0);
793 * Mark interface down
795 if_down(ifp);
798 * Free all interface routes and addresses
800 while (1) {
801 ia = IFP_TO_IA(ifp);
802 if (ia == NULL)
803 break;
805 /* Delete interface route */
806 in_ifscrub(ifp, ia);
808 /* Remove interface address from queues */
809 ifa = &ia->ia_ifa;
810 ifa_ifunlink(ifa, ifp);
811 in_iaunlink(ia);
813 /* Free interface address */
814 ifa_destroy(ifa);
818 * Delete all remaining routes using this interface
819 * Unfortuneatly the only way to do this is to slog through
820 * the entire routing table looking for routes which point
821 * to this interface...oh well...
823 for (i = 1; i <= AF_MAX; i++) {
824 if ((rnh = rt_tables[mycpuid][i]) == NULL)
825 continue;
826 rnh->rnh_walktree(rnh, atm_netif_rtdel, ifp);
830 * Remove from system interface list (ie. if_detach())
832 TAILQ_REMOVE(&ifnet, ifp, if_link);
835 * Remove from physical interface list
837 UNLINK(nip, struct atm_nif, nip->nif_pif->pif_nif, nif_pnext);
839 crit_exit();
844 * Delete Routes for a Network Interface
846 * Called for each routing entry via the rnh->rnh_walktree() call above
847 * to delete all route entries referencing a detaching network interface.
849 * Arguments:
850 * rn pointer to node in the routing table
851 * arg argument passed to rnh->rnh_walktree() - detaching interface
853 * Returns:
854 * 0 successful
855 * errno failed - reason indicated
858 static int
859 atm_netif_rtdel(struct radix_node *rn, void *arg)
861 struct rtentry *rt = (struct rtentry *)rn;
862 struct ifnet *ifp = arg;
863 int err;
865 if (rt->rt_ifp == ifp) {
868 * Protect (sorta) against walktree recursion problems
869 * with cloned routes
871 if ((rt->rt_flags & RTF_UP) == 0)
872 return (0);
874 err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
875 rt_mask(rt), rt->rt_flags,
876 NULL);
877 if (err) {
878 log(LOG_WARNING, "atm_netif_rtdel: error %d\n", err);
882 return (0);
887 * Set an ATM Network Interface address
889 * This is called from a device interface when processing an SIOCSIFADDR
890 * ioctl request. We just notify all convergence modules of the new address
891 * and hope everyone has non-overlapping interests, since if someone reports
892 * an error we don't go back and tell everyone to undo the change.
894 * Arguments:
895 * nip pointer to atm network interface control block
896 * ifa pointer to new interface address
898 * Returns:
899 * 0 set successful
900 * errno set failed - reason indicated
904 atm_nif_setaddr(struct atm_nif *nip, struct ifaddr *ifa)
906 struct atm_ncm *ncp;
907 int err = 0;
909 crit_enter();
911 * Notify convergence modules of network i/f change
913 for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
914 err = (*ncp->ncm_stat)(NCM_SETADDR, nip, (int)ifa);
915 if (err)
916 break;
918 crit_exit();
920 return (err);
925 * ATM Interface Packet Output
927 * All ATM network interfaces must have their ifnet if_output address set to
928 * this function. Since no existing network layer code is to be modified
929 * for ATM support, this function serves as the hook to allow network output
930 * packets to be assigned to their proper outbound VCC. Each network address
931 * family which is to be supported over ATM must be assigned an output
932 * packet processing function via atm_netconv_register().
934 * Arguments:
935 * ifp pointer to ifnet structure
936 * m pointer to packet buffer chain to be output
937 * dst pointer to packet's network destination address
939 * Returns:
940 * 0 packet queued to interface
941 * errno output failed - reason indicated
944 static int
945 atm_ifoutput_serialized(struct ifnet *ifp, KBuffer *m, struct sockaddr *dst,
946 struct rtentry *rt)
948 u_short fam = dst->sa_family;
949 int (*func)(struct ifnet *, KBuffer *,
950 struct sockaddr *);
953 * Validate address family
955 if (fam > AF_MAX) {
956 KB_FREEALL(m);
957 return (EAFNOSUPPORT);
961 * Hand packet off for dst-to-VCC mapping
963 func = atm_ifouttbl[fam];
964 if (func == NULL) {
965 KB_FREEALL(m);
966 return (EAFNOSUPPORT);
968 return ((*func)(ifp, m, dst));
972 atm_ifoutput(struct ifnet *ifp, KBuffer *m, struct sockaddr *dst,
973 struct rtentry *rt)
975 int error;
977 ifnet_serialize_tx(ifp);
978 error = atm_ifoutput_serialized(ifp, m, dst, rt);
979 ifnet_deserialize_tx(ifp);
981 return error;
985 * Handle interface ioctl requests.
987 * Arguments:
988 * ifp pointer to network interface structure
989 * cmd IOCTL cmd
990 * data arguments to/from ioctl
992 * Returns:
993 * error errno value
995 static int
996 atm_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
998 struct ifreq *ifr = (struct ifreq *)data;
999 struct atm_nif *nip = (struct atm_nif *)ifp;
1000 int error = 0;
1002 crit_enter();
1003 switch ( cmd )
1005 case SIOCGIFADDR:
1006 KM_COPY ( (caddr_t)&(nip->nif_pif->pif_macaddr),
1007 (caddr_t)ifr->ifr_addr.sa_data,
1008 sizeof(struct mac_addr) );
1009 break;
1011 case SIOCSIFADDR:
1012 error = atm_nif_setaddr ( nip, (struct ifaddr *)data);
1013 ifp->if_flags |= IFF_UP | IFF_RUNNING | IFF_BROADCAST;
1014 break;
1016 case SIOCGIFFLAGS:
1017 *(short *)data = ifp->if_flags;
1018 break;
1020 case SIOCSIFFLAGS:
1021 break;
1023 default:
1024 error = EINVAL;
1025 break;
1028 crit_exit();
1029 return ( error );
1034 * Parse interface name
1036 * Parses an interface name string into a name and a unit component.
1038 * Arguments:
1039 * name pointer to interface name string
1040 * namep address to store interface name
1041 * size size available at namep
1042 * unitp address to store interface unit number
1044 * Returns:
1045 * 0 name parsed
1046 * else parse error
1049 static int
1050 atm_ifparse(char *name, char *namep, int size, int *unitp)
1052 char *cp, *np;
1053 int len = 0, unit = 0;
1056 * Separate supplied string into name and unit parts.
1058 cp = name;
1059 np = namep;
1060 while (*cp) {
1061 if (*cp >= '0' && *cp <= '9')
1062 break;
1063 if (++len >= size)
1064 return (-1);
1065 *np++ = *cp++;
1067 *np = '\0';
1068 while (*cp && *cp >= '0' && *cp <= '9')
1069 unit = 10 * unit + *cp++ - '0';
1071 *unitp = unit;
1073 return (0);
1078 * Locate ATM physical interface via name
1080 * Uses the supplied interface name string to locate a registered
1081 * ATM physical interface.
1083 * Arguments:
1084 * name pointer to interface name string
1086 * Returns:
1087 * 0 interface not found
1088 * else pointer to atm physical interface structure
1091 struct atm_pif *
1092 atm_pifname(char *name)
1094 struct atm_pif *pip;
1095 char n[IFNAMSIZ];
1096 int unit;
1099 * Break down name
1101 if (atm_ifparse(name, n, sizeof(n), &unit))
1102 return (NULL);
1105 * Look for the physical interface
1107 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
1108 if ((pip->pif_unit == unit) && (strcmp(pip->pif_name, n) == 0))
1109 break;
1112 return (pip);
1117 * Locate ATM network interface via name
1119 * Uses the supplied interface name string to locate an ATM network interface.
1121 * Arguments:
1122 * name pointer to interface name string
1124 * Returns:
1125 * 0 interface not found
1126 * else pointer to atm network interface structure
1129 struct atm_nif *
1130 atm_nifname(char *name)
1132 struct atm_pif *pip;
1133 struct atm_nif *nip;
1134 char n[IFNAMSIZ];
1135 int unit;
1138 * Break down name
1140 if (atm_ifparse(name, n, sizeof(n), &unit))
1141 return (NULL);
1144 * Search thru each physical interface
1146 for (pip = atm_interface_head; pip; pip = pip->pif_next) {
1148 * Looking for network interface
1150 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
1151 struct ifnet *ifp = (struct ifnet *)nip;
1152 if ((ifp->if_dunit == unit) &&
1153 (strcmp(ifp->if_dname, n) == 0))
1154 return (nip);
1157 return (NULL);