* Copyright (c) 1980, 1986 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)if.c 7.6.1.1 (Berkeley) %G%
int ifqmaxlen
= IFQ_MAXLEN
;
* Network interface utility routines.
* Routines with ifa_ifwith* names take sockaddr *'s as
register struct ifnet
*ifp
;
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
if (ifp
->if_snd
.ifq_maxlen
== 0)
ifp
->if_snd
.ifq_maxlen
= ifqmaxlen
;
* Call each interface on a Unibus reset.
register struct ifnet
*ifp
;
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
(*ifp
->if_reset
)(ifp
->if_unit
, uban
);
* Attach an interface to the
* list of "active" interfaces.
register struct ifnet
**p
= &ifnet
;
* Locate an interface based on a complete address.
register struct sockaddr
*addr
;
register struct ifnet
*ifp
;
register struct ifaddr
*ifa
;
(bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
) {
if (ifa
->ifa_addr
->sa_family
!= addr
->sa_family
)
if (equal(addr
, ifa
->ifa_addr
))
if ((ifp
->if_flags
& IFF_BROADCAST
) &&
equal(&ifa
->ifa_broadaddr
, addr
))
return ((struct ifaddr
*)0);
* Locate the point to point interface with a given destination address.
register struct sockaddr
*addr
;
register struct ifnet
*ifp
;
register struct ifaddr
*ifa
;
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
if (ifp
->if_flags
& IFF_POINTOPOINT
)
for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
) {
if (ifa
->ifa_addr
->sa_family
!= addr
->sa_family
)
if (equal(addr
, ifa
->ifa_dstaddr
))
return ((struct ifaddr
*)0);
* Find an interface on a specific network. If many, choice
register struct ifnet
*ifp
;
register struct ifaddr
*ifa
;
register char *cp
, *cp2
, *cp3
;
u_int af
= addr
->sa_family
;
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
) {
if (ifa
->ifa_addr
->sa_family
!= af
|| ifa
->ifa_netmask
== 0)
cp2
= ifa
->ifa_addr
->sa_data
;
cp3
= ifa
->ifa_netmask
->sa_data
;
cplim
= ifa
->ifa_netmask
->sa_len
+ (char *)ifa
->ifa_netmask
;
for (; cp3
< cplim
; cp3
++)
if ((*cp
++ ^ *cp2
++) & *cp3
)
return ((struct ifaddr
*)0);
* Find an interface using a specific address family
register struct ifnet
*ifp
;
register struct ifaddr
*ifa
;
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
)
for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
if (ifa
->ifa_addr
->sa_family
== af
)
return ((struct ifaddr
*)0);
* Mark an interface down and notify protocols of
* NOTE: must be called at splnet or eqivalent.
register struct ifnet
*ifp
;
register struct ifaddr
*ifa
;
ifp
->if_flags
&= ~IFF_UP
;
for (ifa
= ifp
->if_addrlist
; ifa
; ifa
= ifa
->ifa_next
)
pfctlinput(PRC_IFDOWN
, ifa
->ifa_addr
);
* Flush an interface queue.
register struct ifqueue
*ifq
;
register struct mbuf
*m
, *n
;
* Handle interface watchdog timer routines. Called
* from softclock, we decrement timers (if set) and
* call the appropriate interface routine on expiration.
register struct ifnet
*ifp
;
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
) {
if (ifp
->if_timer
== 0 || --ifp
->if_timer
)
(*ifp
->if_watchdog
)(ifp
->if_unit
);
timeout(if_slowtimo
, (caddr_t
)0, hz
/ IFNET_SLOWHZ
);
* interface structure pointer.
register struct ifnet
*ifp
;
for (cp
= name
; cp
< name
+ IFNAMSIZ
&& *cp
; cp
++)
if (*cp
>= '0' && *cp
<= '9')
if (*cp
== '\0' || cp
== name
+ IFNAMSIZ
)
return ((struct ifnet
*)0);
* Save first char of unit, and pointer to it,
* so we can put a null there to avoid matching
* initial substrings of interface names.
for (unit
= 0; *cp
>= '0' && *cp
<= '9'; )
unit
= unit
* 10 + *cp
++ - '0';
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
) {
if (bcmp(ifp
->if_name
, name
, len
))
if (unit
== ifp
->if_unit
)
register struct ifnet
*ifp
;
register struct ifreq
*ifr
;
return (ifconf(cmd
, data
));
#if defined(INET) && NETHER > 0
return (arpioctl(cmd
, data
));
ifr
= (struct ifreq
*)data
;
ifp
= ifunit(ifr
->ifr_name
);
ifr
->ifr_flags
= ifp
->if_flags
;
ifr
->ifr_metric
= ifp
->if_metric
;
if (ifp
->if_flags
& IFF_UP
&& (ifr
->ifr_flags
& IFF_UP
) == 0) {
ifp
->if_flags
= (ifp
->if_flags
& IFF_CANTCHANGE
) |
(ifr
->ifr_flags
&~ IFF_CANTCHANGE
);
(void) (*ifp
->if_ioctl
)(ifp
, cmd
, data
);
ifp
->if_metric
= ifr
->ifr_metric
;
return ((*so
->so_proto
->pr_usrreq
)(so
, PRU_CONTROL
,
#if BYTE_ORDER != BIG_ENDIAN
if (ifr
->ifr_addr
.sa_family
== 0 &&
ifr
->ifr_addr
.sa_len
< 16) {
ifr
->ifr_addr
.sa_family
= ifr
->ifr_addr
.sa_len
;
ifr
->ifr_addr
.sa_len
= 16;
if (ifr
->ifr_addr
.sa_len
== 0)
ifr
->ifr_addr
.sa_len
= 16;
error
= ((*so
->so_proto
->pr_usrreq
)(so
, PRU_CONTROL
,
*(u_short
*)&ifr
->ifr_addr
= ifr
->ifr_addr
.sa_family
;
* Return interface configuration
* of system. List may be used
* in later ioctl's (above) to get
register struct ifconf
*ifc
= (struct ifconf
*)data
;
register struct ifnet
*ifp
= ifnet
;
register struct ifaddr
*ifa
;
int space
= ifc
->ifc_len
, error
= 0;
ep
= ifr
.ifr_name
+ sizeof (ifr
.ifr_name
) - 2;
for (; space
> sizeof (ifr
) && ifp
; ifp
= ifp
->if_next
) {
bcopy(ifp
->if_name
, ifr
.ifr_name
, sizeof (ifr
.ifr_name
) - 2);
for (cp
= ifr
.ifr_name
; cp
< ep
&& *cp
; cp
++)
*cp
++ = '0' + ifp
->if_unit
; *cp
= '\0';
if ((ifa
= ifp
->if_addrlist
) == 0) {
bzero((caddr_t
)&ifr
.ifr_addr
, sizeof(ifr
.ifr_addr
));
error
= copyout((caddr_t
)&ifr
, (caddr_t
)ifrp
, sizeof (ifr
));
space
-= sizeof (ifr
), ifrp
++;
for ( ; space
> sizeof (ifr
) && ifa
; ifa
= ifa
->ifa_next
) {
register struct sockaddr
*sa
= ifa
->ifa_addr
;
if (cmd
== OSIOCGIFCONF
) {
(struct osockaddr
*)&ifr
.ifr_addr
;
osa
->sa_family
= sa
->sa_family
;
error
= copyout((caddr_t
)&ifr
, (caddr_t
)ifrp
,
if (sa
->sa_len
<= sizeof(*sa
)) {
error
= copyout((caddr_t
)&ifr
, (caddr_t
)ifrp
,
space
-= sa
->sa_len
- sizeof(*sa
);
if (space
< sizeof (ifr
))
error
= copyout((caddr_t
)&ifr
, (caddr_t
)ifrp
,
error
= copyout((caddr_t
)sa
,
(caddr_t
)&ifrp
->ifr_addr
, sa
->sa_len
);
(sa
->sa_len
+ (caddr_t
)&ifrp
->ifr_addr
);