Hello, Patch 8
# HG changeset patch # User MJP # Date 1452862954 -3600 # Fri Jan 15 14:02:34 2016 +0100 # Node ID 55eeedfb0cb54ed0d91c7de080b507fc79f64c30 # Parent 8d76f9f8cc873602c8593b896133648cdedb6afd Add: Introduce priv_get_if_rdomain() to get the rdomain of a device. diff -r 8d76f9f8cc87 -r 55eeedfb0cb5 usr.sbin/npppd/npppd/privsep.c --- usr.sbin/npppd/npppd/privsep.c Fri Jan 15 14:02:34 2016 +0100 +++ usr.sbin/npppd/npppd/privsep.c Fri Jan 15 14:02:34 2016 +0100 @@ -54,7 +54,8 @@ PRIVSEP_SET_IF_ADDR, PRIVSEP_DEL_IF_ADDR, PRIVSEP_GET_IF_FLAGS, - PRIVSEP_SET_IF_FLAGS + PRIVSEP_SET_IF_FLAGS, + PRIVSEP_GET_IF_RDOMAIN }; struct PRIVSEP_OPEN_ARG { @@ -126,6 +127,17 @@ int flags; }; +struct PRIVSEP_GET_IF_RDOMAIN_ARG { + char ifname[IFNAMSIZ]; + u_int rdomain; +}; + +struct PRIVSEP_GET_IF_RDOMAIN_RESP { + int retval; + int rerrno; + u_int rdomain; +}; + struct PRIVSEP_COMMON_RESP { int retval; int rerrno; @@ -164,6 +176,8 @@ struct PRIVSEP_GET_IF_FLAGS_ARG *); static int privsep_npppd_check_set_if_flags ( struct PRIVSEP_SET_IF_FLAGS_ARG *); +static int privsep_npppd_check_get_if_rdomain ( + struct PRIVSEP_GET_IF_RDOMAIN_ARG *); static int privsep_sock = -1; static struct imsgbuf privsep_ibuf; @@ -512,6 +526,37 @@ return (privsep_common_resp()); } +int +priv_get_if_rdomain(const char *ifname, int *prdomain) +{ + struct PRIVSEP_GET_IF_RDOMAIN_ARG a; + struct PRIVSEP_GET_IF_RDOMAIN_RESP *r; + struct imsg imsg; + int retval = -1; + + strlcpy(a.ifname, ifname, sizeof(a.ifname)); + a.rdomain = 0; + + (void)imsg_compose(&privsep_ibuf, PRIVSEP_GET_IF_RDOMAIN, 0, 0, -1, + &a, sizeof(a)); + imsg_flush(&privsep_ibuf); + + if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1) + return (-1); + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r)) + errno = EACCES; + else { + r = imsg.data; + *prdomain = r->rdomain; + if (r->retval != 0) + errno = r->rerrno; + retval = r->retval; + } + imsg_free(&imsg); + + return (retval); +} + static int privsep_recvfd(void) { @@ -946,6 +991,41 @@ imsg_flush(ibuf); } break; + case PRIVSEP_GET_IF_RDOMAIN: { + int s; + struct ifreq ifr; + struct PRIVSEP_GET_IF_RDOMAIN_ARG *a = imsg.data; + struct PRIVSEP_GET_IF_RDOMAIN_RESP r; + + memset(&r, 0, sizeof(r)); + r.retval = -1; + + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a)) + r.rerrno = EINVAL; + else if (privsep_npppd_check_get_if_rdomain(a)) { + r.rerrno = EACCES; + } else { + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, a->ifname, + sizeof(ifr.ifr_name)); + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + r.retval = -1; + r.rerrno = errno; + } else { + r.retval = 0; + if (ioctl(s, SIOCGIFRDOMAIN, &ifr) == -1) + r.rdomain = 0; + else + r.rdomain = ifr.ifr_rdomainid; + } + if (s >= 0) + close(s); + } + (void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1, + &r, sizeof(r)); + imsg_flush(ibuf); + } + break; } imsg_free(&imsg); } @@ -1114,3 +1194,12 @@ return (1); } + +static int +privsep_npppd_check_get_if_rdomain(struct PRIVSEP_GET_IF_RDOMAIN_ARG *arg) +{ + if (startswith(arg->ifname, "tun") || startswith(arg->ifname, "pppx") || startswith(arg->ifname, "lo")) + return (0); + + return (1); +} diff -r 8d76f9f8cc87 -r 55eeedfb0cb5 usr.sbin/npppd/npppd/privsep.h --- usr.sbin/npppd/npppd/privsep.h Fri Jan 15 14:02:34 2016 +0100 +++ usr.sbin/npppd/npppd/privsep.h Fri Jan 15 14:02:34 2016 +0100 @@ -45,6 +45,7 @@ int priv_delete_if_addr(const char *); int priv_set_if_flags(const char *, int); int priv_get_if_flags(const char *, int *); +int priv_get_if_rdomain(const char *, int *); #ifdef __cplusplus }