mirror of
https://github.com/rsmarples/dhcpcd.git
synced 2024-11-27 03:54:56 +08:00
sun: Fix carrier detection, MTU detection and plumbing
dhcpcd no longer needs ifconfig to do the initial plumbing.
This commit is contained in:
parent
558c927371
commit
8fd4972237
2
configure
vendored
2
configure
vendored
@ -454,7 +454,7 @@ sunos*)
|
||||
echo "CPPFLAGS+= -D_XPG4_2 -D__EXTENSIONS__ -DBSD_COMP" \
|
||||
>>$CONFIG_MK
|
||||
echo "DHCPCD_SRCS+= if-sun.c" >>$CONFIG_MK
|
||||
echo "LDADD+= -ldlpi" >>$CONFIG_MK
|
||||
echo "LDADD+= -ldlpi -lkstat" >>$CONFIG_MK
|
||||
;;
|
||||
*)
|
||||
echo "DHCPCD_SRCS+= if-bsd.c" >>$CONFIG_MK
|
||||
|
136
src/if-sun.c
136
src/if-sun.c
@ -30,6 +30,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <libdlpi.h>
|
||||
#include <kstat.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stropts.h>
|
||||
@ -45,6 +46,7 @@
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mac.h>
|
||||
#include <sys/pfmod.h>
|
||||
#include <sys/tihdr.h>
|
||||
#include <sys/utsname.h>
|
||||
@ -162,6 +164,63 @@ if_closesockets_os(struct dhcpcd_ctx *ctx)
|
||||
free(ctx->priv);
|
||||
}
|
||||
|
||||
int
|
||||
if_carrier_os(struct interface *ifp)
|
||||
{
|
||||
kstat_ctl_t *kcp;
|
||||
kstat_t *ksp;
|
||||
kstat_named_t *knp;
|
||||
link_state_t linkstate;
|
||||
|
||||
kcp = kstat_open();
|
||||
if (kcp == NULL)
|
||||
goto err;
|
||||
ksp = kstat_lookup(kcp, UNCONST("link"), 0, ifp->name);
|
||||
if (ksp == NULL)
|
||||
goto err;
|
||||
if (kstat_read(kcp, ksp, NULL) == -1)
|
||||
goto err;
|
||||
knp = kstat_data_lookup(ksp, UNCONST("link_state"));
|
||||
if (knp == NULL)
|
||||
goto err;
|
||||
if (knp->data_type != KSTAT_DATA_UINT32)
|
||||
goto err;
|
||||
linkstate = (link_state_t)knp->value.ui32;
|
||||
kstat_close(kcp);
|
||||
|
||||
switch (linkstate) {
|
||||
case LINK_STATE_UP:
|
||||
ifp->flags |= IFF_UP;
|
||||
return LINK_UP;
|
||||
case LINK_STATE_DOWN:
|
||||
return LINK_DOWN;
|
||||
default:
|
||||
return LINK_UNKNOWN;
|
||||
}
|
||||
|
||||
err:
|
||||
if (kcp != NULL)
|
||||
kstat_close(kcp);
|
||||
return LINK_UNKNOWN;
|
||||
}
|
||||
|
||||
int
|
||||
if_mtu_os(const struct interface *ifp)
|
||||
{
|
||||
dlpi_handle_t dh;
|
||||
dlpi_info_t dlinfo;
|
||||
int mtu;
|
||||
|
||||
if (dlpi_open(ifp->name, &dh, 0) != DLPI_SUCCESS)
|
||||
return -1;
|
||||
if (dlpi_info(dh, &dlinfo, 0) == DLPI_SUCCESS)
|
||||
mtu = dlinfo.di_max_sdu;
|
||||
else
|
||||
mtu = -1;
|
||||
dlpi_close(dh);
|
||||
return mtu;
|
||||
}
|
||||
|
||||
int
|
||||
if_getssid(struct interface *ifp)
|
||||
{
|
||||
@ -723,15 +782,18 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm)
|
||||
{
|
||||
struct interface *ifp;
|
||||
int state;
|
||||
unsigned int flags;
|
||||
|
||||
if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
|
||||
return;
|
||||
if (ifm->ifm_flags & IFF_OFFLINE || !(ifm->ifm_flags & IFF_UP))
|
||||
flags = (unsigned int)ifm->ifm_flags;
|
||||
if (ifm->ifm_flags & IFF_OFFLINE)
|
||||
state = LINK_DOWN;
|
||||
else
|
||||
else {
|
||||
state = LINK_UP;
|
||||
dhcpcd_handlecarrier(ctx, state,
|
||||
(unsigned int)ifm->ifm_flags, ifp->name);
|
||||
flags |= IFF_UP;
|
||||
}
|
||||
dhcpcd_handlecarrier(ctx, state, flags, ifp->name);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -819,6 +881,7 @@ if_addaddr(int fd, const char *ifname,
|
||||
if (ioctl(fd, SIOCSLIFFLAGS, &lifr) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -847,15 +910,20 @@ if_plumblif(int cmd, const struct dhcpcd_ctx *ctx, int af, const char *ifname)
|
||||
static int
|
||||
if_plumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname)
|
||||
{
|
||||
dlpi_handle_t dh;
|
||||
int fd, af_fd, mux_fd, retval;
|
||||
dlpi_handle_t dh, dh_arp = NULL;
|
||||
int fd, af_fd, mux_fd, arp_fd = -1, mux_id, retval;
|
||||
uint64_t flags;
|
||||
struct lifreq lifr;
|
||||
const char *udp_dev;
|
||||
struct strioctl ioc;
|
||||
struct if_spec spec;
|
||||
|
||||
if (if_nametospec(ifname, &spec) == -1)
|
||||
return -1;
|
||||
|
||||
memset(&lifr, 0, sizeof(lifr));
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
lifr.lifr_flags = IFF_IPV4;
|
||||
flags = IFF_IPV4;
|
||||
af_fd = ctx->pf_inet_fd;
|
||||
udp_dev = UDP_DEV_NAME;
|
||||
break;
|
||||
@ -864,7 +932,7 @@ if_plumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname)
|
||||
struct priv *priv;
|
||||
|
||||
/* We will take care of setting the link local address. */
|
||||
lifr.lifr_flags = IFF_IPV6 | IFF_NOLINKLOCAL;
|
||||
flags = IFF_IPV6 | IFF_NOLINKLOCAL;
|
||||
priv = (struct priv *)ctx->priv;
|
||||
af_fd = priv->pf_inet6_fd;
|
||||
udp_dev = UDP6_DEV_NAME;
|
||||
@ -885,13 +953,17 @@ if_plumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname)
|
||||
mux_fd = -1;
|
||||
if (ioctl(fd, I_PUSH, IP_MOD_NAME) == -1)
|
||||
goto out;
|
||||
memset(&lifr, 0, sizeof(lifr));
|
||||
strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
|
||||
lifr.lifr_ppa = spec.ppa;
|
||||
lifr.lifr_flags = flags;
|
||||
if (ioctl(fd, SIOCSLIFNAME, &lifr) == -1)
|
||||
goto out;
|
||||
|
||||
/* Get full flags. */
|
||||
if (ioctl(af_fd, SIOCGLIFFLAGS, &lifr) == -1)
|
||||
goto out;
|
||||
flags = lifr.lifr_flags;
|
||||
|
||||
/* Open UDP as a multiplexor to PLINK the interface stream.
|
||||
* UDP is used because STREAMS will not let you PLINK a driver
|
||||
@ -903,20 +975,50 @@ if_plumbif(const struct dhcpcd_ctx *ctx, int af, const char *ifname)
|
||||
;
|
||||
if (errno != EINVAL)
|
||||
goto out;
|
||||
|
||||
if (lifr.lifr_flags & IFF_IPV4 && !(lifr.lifr_flags & IFF_NOARP)) {
|
||||
if (ioctl(mux_fd, I_PUSH, ARP_MOD_NAME) == -1)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* PLINK the interface stream so it persists. */
|
||||
if (ioctl(mux_fd, I_PLINK, fd) == -1)
|
||||
if(ioctl(mux_fd, I_PUSH, ARP_MOD_NAME) == -1)
|
||||
goto out;
|
||||
|
||||
if (flags & (IFF_NOARP | IFF_IPV6)) {
|
||||
/* PLINK the interface stream so it persists. */
|
||||
if (ioctl(mux_fd, I_PLINK, fd) == -1)
|
||||
goto out;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (dlpi_open(ifname, &dh_arp, DLPI_NOATTACH) != DLPI_SUCCESS)
|
||||
goto out;
|
||||
arp_fd = dlpi_fd(dh_arp);
|
||||
if (ioctl(arp_fd, I_PUSH, ARP_MOD_NAME) == -1)
|
||||
goto out;
|
||||
|
||||
memset(&lifr, 0, sizeof(lifr));
|
||||
strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
|
||||
lifr.lifr_ppa = spec.ppa;
|
||||
lifr.lifr_flags = flags;
|
||||
memset(&ioc, 0, sizeof(ioc));
|
||||
ioc.ic_cmd = SIOCSLIFNAME;
|
||||
ioc.ic_dp = (char *)&lifr;
|
||||
ioc.ic_len = sizeof(lifr);
|
||||
if (ioctl(arp_fd, I_STR, &ioc) == -1)
|
||||
goto out;
|
||||
|
||||
/* PLINK the interface stream so it persists. */
|
||||
mux_id = ioctl(mux_fd, I_PLINK, fd);
|
||||
if (mux_id == -1)
|
||||
goto out;
|
||||
if (ioctl(mux_fd, I_PLINK, arp_fd) == -1) {
|
||||
ioctl(mux_fd, I_PUNLINK, mux_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
done:
|
||||
logerrx("plumb %d %d %d", mux_fd, fd, arp_fd);
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
dlpi_close(dh);
|
||||
if (dh_arp != NULL)
|
||||
dlpi_close(dh_arp);
|
||||
if (mux_fd != -1)
|
||||
close(mux_fd);
|
||||
return retval;
|
||||
|
16
src/if.c
16
src/if.c
@ -136,9 +136,15 @@ if_carrier(struct interface *ifp)
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
|
||||
r = ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr);
|
||||
if (r != -1)
|
||||
ifp->flags = (unsigned int)ifr.ifr_flags;
|
||||
|
||||
#ifdef __sun
|
||||
return if_carrier_os(ifp);
|
||||
#else
|
||||
if (r == -1)
|
||||
return LINK_UNKNOWN;
|
||||
ifp->flags = (unsigned int)ifr.ifr_flags;
|
||||
|
||||
#ifdef SIOCGIFMEDIA
|
||||
memset(&ifmr, 0, sizeof(ifmr));
|
||||
@ -155,6 +161,7 @@ if_carrier(struct interface *ifp)
|
||||
#else
|
||||
r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
|
||||
#endif
|
||||
#endif /* __sun */
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -711,6 +718,11 @@ if_domtu(const struct interface *ifp, short int mtu)
|
||||
int r;
|
||||
struct ifreq ifr;
|
||||
|
||||
#ifdef __sun
|
||||
if (mtu == 0)
|
||||
return if_mtu_os(ifp);
|
||||
#endif
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_mtu = mtu;
|
||||
|
3
src/if.h
3
src/if.h
@ -129,6 +129,9 @@ int if_domtu(const struct interface *, short int);
|
||||
#define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu))
|
||||
int if_carrier(struct interface *);
|
||||
|
||||
int if_carrier_os(struct interface *);
|
||||
int if_mtu_os(const struct interface *);
|
||||
|
||||
/*
|
||||
* Helper to decode an interface name of bge0:1 to
|
||||
* devname = bge0, drvname = bge0, ppa = 0, lun = 1.
|
||||
|
Loading…
Reference in New Issue
Block a user