struct tundata {
const char *iff;
ino_t devnetns; /* 0 implies no value given. */
+ ino_t socknetns;
};
static bool cdev_tun_probe(struct cdev *cdev)
if (tundata == NULL || tundata->iff == NULL)
return NULL;
+ xasprintf(&str, "iface=%s", tundata->iff);
if (tundata->devnetns)
- xasprintf(&str, "iface=%s devnetns=%llu",
- tundata->iff, (unsigned long long)tundata->devnetns);
- else
- xasprintf(&str, "iface=%s", tundata->iff);
+ xstrfappend(&str, " devnetns=%llu",
+ (unsigned long long)tundata->devnetns);
+ if (tundata->socknetns)
+ xstrfappend(&str, " socknetns=%llu",
+ (unsigned long long)tundata->socknetns);
return str;
}
return true;
}
break;
+ case COL_SOCK_NETNS:
+ if (tundata && tundata->socknetns) {
+ xasprintf(str, "%llu", (unsigned long long)tundata->socknetns);
+ return true;
+ }
+ break;
}
return false;
}
return 0;
}
-#ifdef TUNGETDEVNETNS
static bool cdev_tun_needs_target_fd(struct cdev *cdev)
{
struct tundata *tundata = cdev->cdev_data;
return (tundata->iff != NULL);
}
-#else
-static bool cdev_tun_needs_target_fd(struct cdev *cdev __attribute__((__unused__)))
-{
- return false;
-}
-#endif /* TUNGETDEVNETNS */
-#ifdef TUNGETDEVNETNS
static void cdev_tun_inspect_target_fd(struct cdev *cdev, int fd)
{
struct tundata *tundata = cdev->cdev_data;
+ tundata->socknetns = get_netns_from_socket(fd);
+
+#ifdef TUNGETDEVNETNS
int nsfd = ioctl(fd, TUNGETDEVNETNS);
struct stat sb;
}
close(nsfd);
-}
-#else
-static void cdev_tun_inspect_target_fd(struct cdev *cdev __attribute__((__unused__)),
- int fd __attribute__((__unused__)))
-{
- /* Do nothing */
-}
#endif /* TUNGETDEVNETNS */
+}
static struct cdev_ops cdev_tun_ops = {
.parent = &cdev_misc_ops,
ts_check_test_command "$TS_CMD_UNSHARE"
ts_check_test_command "$TS_CMD_LSNS"
+ts_check_prog "ip"
+
ts_cd "$TS_OUTDIR"
PID=
ts_skip "the current netns is unknown"
fi
+cdev_tun_test_socknetns()
+{
+ local -r altnetns_name=mkfds-dev-tun-$$
+
+ local -r ifname=$1
+ local -r pid=$2
+ local -r expr=$3
+ local -r localnetns=$4
+ local altnetns
+ local socknetns
+
+ # Move the tun device to another net namespace
+ if ip netns add "$altnetns_name"; then
+ ip link set dev "$ifname" netns "$altnetns_name"
+ altnetns=$(ip netns exec "$altnetns_name" stat -Lc %i /proc/self/ns/net)
+ socknetns=$(${TS_CMD_LSFD} -p "${pid}" -n --raw -o SOCK.NETNS -Q "${expr}")
+ ip netns del "$altnetns_name"
+
+ if [[ "$localnetns" == "$socknetns" ]]; then
+ echo 'SOCK.NETNS': 0
+ else
+ echo 'SOCK.NETNS': 1
+ echo "expected SOCK.NETNS: $localnetns"
+ echo "actual SOCK.NETNS: $socknetns"
+ fi
+ fi
+}
+
cdev_tun_test()
{
local unshare=$1
local tname
local devnetns_available
local netns
+ local output
if [[ -z "$unshare" ]]; then
tname=domestic
fi
ts_finalize_subtest
+ ts_init_subtest "$tname"-socknetns
+ if [[ -n "$IFNAME" ]]; then
+ cdev_tun_test_socknetns \
+ "$IFNAME" "${PID}" "${EXPR}" "$netns" > $TS_OUTPUT 2>&1
+ fi
+ ts_finalize_subtest
if [[ -n "$PID" ]]; then
echo DONE >&"${MKFDS[1]}"