mirror of
https://github.com/moparisthebest/socat
synced 2024-11-10 19:15:03 -05:00
added test SETSOCKOPT_INT; some corrections on generic ioctl and setsockopt features
This commit is contained in:
parent
140443794b
commit
8947cc92dc
76
test.sh
76
test.sh
@ -8450,7 +8450,7 @@ N=$((N+1))
|
|||||||
# test the generic ioctl-void option
|
# test the generic ioctl-void option
|
||||||
NAME=IOCTL_VOID
|
NAME=IOCTL_VOID
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
|
*%functions%*|*%pty%*|*%generic%*|*%$NAME%*)
|
||||||
TEST="$NAME: test the ioctl-void option"
|
TEST="$NAME: test the ioctl-void option"
|
||||||
# there are not many ioctls that apply to non global resources and do not
|
# there are not many ioctls that apply to non global resources and do not
|
||||||
# require root. TIOCEXCL seems to fit:
|
# require root. TIOCEXCL seems to fit:
|
||||||
@ -8459,7 +8459,7 @@ TEST="$NAME: test the ioctl-void option"
|
|||||||
# process 2 opens it too and fails with "device or resource busy" only when the
|
# process 2 opens it too and fails with "device or resource busy" only when the
|
||||||
# previous ioctl was successful
|
# previous ioctl was successful
|
||||||
if [ "$UNAME" != Linux ]; then
|
if [ "$UNAME" != Linux ]; then
|
||||||
# we need access to more loopback addresses
|
# we use the numeric value of TIOCEXL which is system dependent
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
else
|
else
|
||||||
@ -8482,7 +8482,7 @@ $CMD2 >/dev/null 2>"${te}2" </dev/null
|
|||||||
rc2=$?
|
rc2=$?
|
||||||
kill $pid0 $pid1 2>/dev/null; wait
|
kill $pid0 $pid1 2>/dev/null; wait
|
||||||
if ! echo "$da" |diff - "$tf"; then
|
if ! echo "$da" |diff - "$tf"; then
|
||||||
$PRINTF "${YELLOW}phase 1 failed{NORMAL}\n"
|
$PRINTF "${YELLOW}phase 1 failed${NORMAL}\n"
|
||||||
echo "$CMD0 &"
|
echo "$CMD0 &"
|
||||||
echo "$CMD1"
|
echo "$CMD1"
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
@ -8501,6 +8501,76 @@ fi
|
|||||||
fi # !Linux
|
fi # !Linux
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# test the generic setsockopt-int option
|
||||||
|
NAME=SETSOCKOPT_INT
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: test the setsockopt-int option"
|
||||||
|
# there are not many socket options that apply to non global resources, do not
|
||||||
|
# require root, do not require a network connection, and can easily be
|
||||||
|
# tested. SO_REUSEADDR seems to fit:
|
||||||
|
# process 0 provides a tcp listening socket with reuseaddr;
|
||||||
|
# process 1 connects to this port; thus the port is connected but no longer
|
||||||
|
# listening
|
||||||
|
# process 2 tries to listen on this port with SO_REUSEADDR, will fail if the
|
||||||
|
# (generically specified) SO_REUSEADDR socket options did not work
|
||||||
|
# process 3 connects to this port; only if it is successful the test is ok
|
||||||
|
if [ "$UNAME" != Linux ]; then
|
||||||
|
# we use the numeric value of SO_REUSEADDR which might be system dependent
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
else
|
||||||
|
tp="$PORT"
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="$(date)"
|
||||||
|
# level=SOL_SOCKET=1, optname=SO_REUSEADDR=2, value=1
|
||||||
|
CMD0="$SOCAT $opts TCP4-L:$tp,setsockopt-int=1:2:1 PIPE"
|
||||||
|
CMD1="$SOCAT $opts - TCP:localhost:$tp"
|
||||||
|
CMD2="$CMD0"
|
||||||
|
CMD3="$CMD1"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
$CMD0 >/dev/null 2>"${te}0" &
|
||||||
|
pid0=$!
|
||||||
|
waittcp4port $tp 1
|
||||||
|
(echo "$da"; sleep 3) |$CMD1 >"$tf" 2>"${te}1" & # this should always work
|
||||||
|
pid1=$!
|
||||||
|
usleep 1000000
|
||||||
|
$CMD2 >/dev/null 2>"${te}2" &
|
||||||
|
pid2=$!
|
||||||
|
waittcp4port $tp 1
|
||||||
|
(echo "$da") |$CMD3 >"${tf}3" 2>"${te}3"
|
||||||
|
rc3=$?
|
||||||
|
kill $pid0 $pid1 $pid2 2>/dev/null; wait
|
||||||
|
if ! echo "$da" |diff - "$tf"; then
|
||||||
|
$PRINTF "${YELLOW}phase 1 failed${NORMAL}\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
echo "$CMD1"
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
elif [ $rc3 -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED: $SOCAT:\n"
|
||||||
|
echo "$CMD2 &"
|
||||||
|
echo "$CMD3"
|
||||||
|
cat "${te}2" "${te}3"
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
elif ! echo "$da" |diff - "${tf}3"; then
|
||||||
|
$PRINTF "$FAILED: $SOCAT:\n"
|
||||||
|
echo "$CMD2 &"
|
||||||
|
echo "$CMD3"
|
||||||
|
echo "$da" |diff - "${tf}3"
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2" "${te}3"; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi
|
||||||
|
fi # !Linux
|
||||||
|
;;
|
||||||
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
10
xio-fd.c
10
xio-fd.c
@ -77,8 +77,8 @@ const struct optdesc opt_cool_write = { "cool-write", "coolwrite", OPT_COOL_WRIT
|
|||||||
const struct optdesc opt_end_close = { "end-close", "close", OPT_END_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoend, END_CLOSE };
|
const struct optdesc opt_end_close = { "end-close", "close", OPT_END_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoend, END_CLOSE };
|
||||||
|
|
||||||
/****** generic ioctl() options ******/
|
/****** generic ioctl() options ******/
|
||||||
const struct optdesc opt_ioctl_void = { "ioctl-void", "ioctl", OPT_IOCTL_VOID, GROUP_FD, PH_FD, TYPE_INT, OFUNC_SPEC, 0, 0, 0 };
|
const struct optdesc opt_ioctl_void = { "ioctl-void", "ioctl", OPT_IOCTL_VOID, GROUP_FD, PH_FD, TYPE_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||||
const struct optdesc opt_ioctl_int = { "ioctl-int", NULL, OPT_IOCTL_INT, GROUP_FD, PH_FD, TYPE_INT_INT, OFUNC_SPEC, 0, 0, 0 };
|
const struct optdesc opt_ioctl_int = { "ioctl-int", NULL, OPT_IOCTL_INT, GROUP_FD, PH_FD, TYPE_INT_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||||
const struct optdesc opt_ioctl_intp = { "ioctl-intp", NULL, OPT_IOCTL_INTP, GROUP_FD, PH_FD, TYPE_INT_INT, OFUNC_SPEC, 0, 0, 0 };
|
const struct optdesc opt_ioctl_intp = { "ioctl-intp", NULL, OPT_IOCTL_INTP, GROUP_FD, PH_FD, TYPE_INT_INTP, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||||
const struct optdesc opt_ioctl_bin = { "ioctl-bin", NULL, OPT_IOCTL_BIN, GROUP_FD, PH_FD, TYPE_INT_BIN, OFUNC_SPEC, 0, 0, 0 };
|
const struct optdesc opt_ioctl_bin = { "ioctl-bin", NULL, OPT_IOCTL_BIN, GROUP_FD, PH_FD, TYPE_INT_BIN, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||||
const struct optdesc opt_ioctl_string = { "ioctl-string",NULL, OPT_IOCTL_STRING,GROUP_FD, PH_FD, TYPE_INT_STRING,OFUNC_SPEC, 0, 0, 0 };
|
const struct optdesc opt_ioctl_string = { "ioctl-string",NULL, OPT_IOCTL_STRING,GROUP_FD, PH_FD, TYPE_INT_STRING,OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||||
|
@ -129,9 +129,9 @@ const struct optdesc opt_connect_timeout = { "connect-timeout", NULL, OPT_CONNEC
|
|||||||
const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_protocol_family = { "protocol-family", "pf", OPT_PROTOCOL_FAMILY, GROUP_SOCKET, PH_PRESOCKET, TYPE_STRING, OFUNC_SPEC };
|
||||||
|
|
||||||
/* generic setsockopt() options */
|
/* generic setsockopt() options */
|
||||||
const struct optdesc opt_setsockopt_int = { "setsockopt-int", "sockopt-int", OPT_SETSOCKOPT_INT, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_INT, OFUNC_SPEC, 0, 0 };
|
const struct optdesc opt_setsockopt_int = { "setsockopt-int", "sockopt-int", OPT_SETSOCKOPT_INT, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_INT, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||||
const struct optdesc opt_setsockopt_bin = { "setsockopt-bin", "sockopt-bin", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_BIN, OFUNC_SPEC, 0, 0 };
|
const struct optdesc opt_setsockopt_bin = { "setsockopt-bin", "sockopt-bin", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||||
const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_STRING, OFUNC_SPEC, 0, 0 };
|
const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_STRING, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||||
|
|
||||||
|
|
||||||
/* a subroutine that is common to all socket addresses that want to connect
|
/* a subroutine that is common to all socket addresses that want to connect
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* source: xio-socket.h */
|
/* source: xio-socket.h */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2008 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_socket_h_included
|
#ifndef __xio_socket_h_included
|
||||||
|
@ -29,7 +29,8 @@ static const char *optiontypenames[] = {
|
|||||||
"STRUCT-IP_MREQ",
|
"STRUCT-IP_MREQ",
|
||||||
#endif
|
#endif
|
||||||
"IP4NAME",
|
"IP4NAME",
|
||||||
"INT:INT", "INT:BIN", "INT:STRING",
|
"INT:INT", "INT:INTP", "INT:BIN", "INT:STRING",
|
||||||
|
"INT:INT:INT", "INT:INT:BIN", "INT:INT:STRING",
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
189
xioopts.c
189
xioopts.c
@ -1313,6 +1313,9 @@ const struct optname optionnames[] = {
|
|||||||
#ifdef SO_USELOOPBACK /* AIX433, Solaris */
|
#ifdef SO_USELOOPBACK /* AIX433, Solaris */
|
||||||
IF_SOCKET ("so-useloopback", &opt_so_useloopback)
|
IF_SOCKET ("so-useloopback", &opt_so_useloopback)
|
||||||
#endif /* SO_USELOOPBACK */
|
#endif /* SO_USELOOPBACK */
|
||||||
|
IF_SOCKET ("sockopt-bin", &opt_setsockopt_bin)
|
||||||
|
IF_SOCKET ("sockopt-int", &opt_setsockopt_int)
|
||||||
|
IF_SOCKET ("sockopt-string", &opt_setsockopt_string)
|
||||||
IF_SOCKS4 ("socksport", &opt_socksport)
|
IF_SOCKS4 ("socksport", &opt_socksport)
|
||||||
IF_SOCKS4 ("socksuser", &opt_socksuser)
|
IF_SOCKS4 ("socksuser", &opt_socksuser)
|
||||||
IF_IPAPP ("sourceport", &opt_sourceport)
|
IF_IPAPP ("sourceport", &opt_sourceport)
|
||||||
@ -2761,6 +2764,48 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
|||||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (opt->desc->func == OFUNC_IOCTL_GENERIC) {
|
||||||
|
switch (opt->desc->type) {
|
||||||
|
case TYPE_INT:
|
||||||
|
if (Ioctl(fd, opt->value.u_int, NULL) < 0) {
|
||||||
|
Error3("ioctl(%d, 0x%x, NULL): %s",
|
||||||
|
fd, opt->value.u_int, strerror(errno));
|
||||||
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_INT_INT:
|
||||||
|
if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) {
|
||||||
|
Error4("ioctl(%d, %d, %p): %s",
|
||||||
|
fd, opt->value.u_int, opt->value2.u_int, strerror(errno));
|
||||||
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_INT_INTP:
|
||||||
|
if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) {
|
||||||
|
Error4("ioctl(%d, 0x%x, %p): %s",
|
||||||
|
fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno));
|
||||||
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_INT_BIN:
|
||||||
|
if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) {
|
||||||
|
Error4("ioctl(%d, 0x%x, %p): %s",
|
||||||
|
fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno));
|
||||||
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_INT_STRING:
|
||||||
|
if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) {
|
||||||
|
Error4("ioctl(%d, 0x%x, %p): %s",
|
||||||
|
fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno));
|
||||||
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error1("ioctl() data type %d not implemented",
|
||||||
|
opt->desc->type);
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_SOCKET
|
#if WITH_SOCKET
|
||||||
} else if (opt->desc->func == OFUNC_SOCKOPT) {
|
} else if (opt->desc->func == OFUNC_SOCKOPT) {
|
||||||
if (0) {
|
if (0) {
|
||||||
@ -2938,6 +2983,38 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
|||||||
opt->desc->defname, opt->desc->type);
|
opt->desc->defname, opt->desc->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) {
|
||||||
|
switch (opt->desc->type) {
|
||||||
|
case TYPE_INT_INT_INT:
|
||||||
|
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
||||||
|
&opt->value3.u_int, sizeof(int)) < 0) {
|
||||||
|
Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
|
||||||
|
fd, opt->value.u_int, opt->value2.u_int,
|
||||||
|
opt->value3.u_int, sizeof(int), strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_INT_INT_BIN:
|
||||||
|
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
||||||
|
opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) {
|
||||||
|
Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s",
|
||||||
|
fd, opt->value.u_int, opt->value2.u_int,
|
||||||
|
opt->value3.u_bin.b_len, strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_INT_INT_STRING:
|
||||||
|
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
||||||
|
opt->value3.u_string,
|
||||||
|
strlen(opt->value3.u_string)+1) < 0) {
|
||||||
|
Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
|
||||||
|
fd, opt->value.u_int, opt->value2.u_int,
|
||||||
|
opt->value3.u_string, strlen(opt->value3.u_string)+1,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error1("setsockopt() data type %d not implemented",
|
||||||
|
opt->desc->type);
|
||||||
|
}
|
||||||
#endif /* WITH_SOCKET */
|
#endif /* WITH_SOCKET */
|
||||||
|
|
||||||
#if HAVE_FLOCK
|
#if HAVE_FLOCK
|
||||||
@ -3156,118 +3233,6 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_IOCTL_VOID:
|
|
||||||
switch (opt->desc->type) {
|
|
||||||
case TYPE_INT:
|
|
||||||
if (Ioctl(fd, opt->value.u_int, NULL) < 0) {
|
|
||||||
Error3("ioctl(%d, 0x%x, NULL): %s",
|
|
||||||
fd, opt->value.u_int, strerror(errno));
|
|
||||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Error1("ioctl() data type %d not implemented", opt->desc->type);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPT_IOCTL_INT:
|
|
||||||
switch (opt->desc->type) {
|
|
||||||
case TYPE_INT_INT:
|
|
||||||
if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) {
|
|
||||||
Error4("ioctl(%d, %d, %p): %s",
|
|
||||||
fd, opt->value.u_int, opt->value2.u_int, strerror(errno));
|
|
||||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Error1("ioctl() data type %d not implemented", opt->desc->type);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPT_IOCTL_INTP:
|
|
||||||
switch (opt->desc->type) {
|
|
||||||
case TYPE_INT_INT:
|
|
||||||
if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) {
|
|
||||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
|
||||||
fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno));
|
|
||||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Error1("ioctl() data type %d not implemented", opt->desc->type);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPT_IOCTL_BIN:
|
|
||||||
switch (opt->desc->type) {
|
|
||||||
case TYPE_INT_BIN:
|
|
||||||
if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) {
|
|
||||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
|
||||||
fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno));
|
|
||||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Error1("ioctl() data type %d not implemented", opt->desc->type);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPT_IOCTL_STRING:
|
|
||||||
switch (opt->desc->type) {
|
|
||||||
case TYPE_INT_STRING:
|
|
||||||
if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) {
|
|
||||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
|
||||||
fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno));
|
|
||||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Error1("ioctl() data type %d not implemented", opt->desc->type);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPT_SETSOCKOPT_INT:
|
|
||||||
switch (opt->desc->type) {
|
|
||||||
case TYPE_INT_INT_INT:
|
|
||||||
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
|
||||||
&opt->value3.u_int, sizeof(int)) < 0) {
|
|
||||||
Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
|
|
||||||
fd, opt->value.u_int, opt->value2.u_int,
|
|
||||||
opt->value3.u_int, sizeof(int), strerror(errno));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Error1("setsockopt() data type %d not implemented",
|
|
||||||
opt->desc->type);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPT_SETSOCKOPT_BIN:
|
|
||||||
switch (opt->desc->type) {
|
|
||||||
case TYPE_INT_INT_BIN:
|
|
||||||
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
|
||||||
opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) {
|
|
||||||
Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s",
|
|
||||||
fd, opt->value.u_int, opt->value2.u_int,
|
|
||||||
opt->value3.u_bin.b_len, strerror(errno));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Error1("setsockopt() data type %d not implemented",
|
|
||||||
opt->desc->type);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OPT_SETSOCKOPT_STRING:
|
|
||||||
switch (opt->desc->type) {
|
|
||||||
case TYPE_INT_INT_STRING:
|
|
||||||
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
|
||||||
opt->value3.u_string,
|
|
||||||
strlen(opt->value3.u_string)+1) < 0) {
|
|
||||||
Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
|
|
||||||
fd, opt->value.u_int, opt->value2.u_int,
|
|
||||||
opt->value3.u_string, strlen(opt->value3.u_string)+1,
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Error1("setsockopt() data type %d not implemented",
|
|
||||||
opt->desc->type);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: Error1("applyopts(): option \"%s\" not implemented",
|
default: Error1("applyopts(): option \"%s\" not implemented",
|
||||||
opt->desc->defname);
|
opt->desc->defname);
|
||||||
|
26
xioopts.h
26
xioopts.h
@ -22,45 +22,53 @@ enum e_types {
|
|||||||
TYPE_BIN, /* raw binary data, length determined by data */
|
TYPE_BIN, /* raw binary data, length determined by data */
|
||||||
TYPE_BOOL, /* value is 0 or 1 (no-value is interpreted as 1) */
|
TYPE_BOOL, /* value is 0 or 1 (no-value is interpreted as 1) */
|
||||||
TYPE_BYTE, /* unsigned char */
|
TYPE_BYTE, /* unsigned char */
|
||||||
|
|
||||||
TYPE_INT, /* int */
|
TYPE_INT, /* int */
|
||||||
TYPE_LONG, /* long */
|
TYPE_LONG, /* long */
|
||||||
TYPE_STRING, /* char * */
|
TYPE_STRING, /* char * */
|
||||||
TYPE_NAME = TYPE_STRING,
|
TYPE_NAME = TYPE_STRING,
|
||||||
TYPE_FILENAME = TYPE_STRING,
|
TYPE_FILENAME = TYPE_STRING,
|
||||||
TYPE_PTRDIFF, /* ptrdiff_t */
|
TYPE_PTRDIFF, /* ptrdiff_t */
|
||||||
|
|
||||||
TYPE_SHORT, /* short */
|
TYPE_SHORT, /* short */
|
||||||
TYPE_SIZE_T, /* size_t */
|
TYPE_SIZE_T, /* size_t */
|
||||||
TYPE_SOCKADDR, /* struct sockaddr * */
|
TYPE_SOCKADDR, /* struct sockaddr * */
|
||||||
TYPE_UINT, /* unsigned int */
|
TYPE_UINT, /* unsigned int */
|
||||||
|
|
||||||
TYPE_ULONG, /* unsigned long */
|
TYPE_ULONG, /* unsigned long */
|
||||||
TYPE_USHORT, /* unsigned short */
|
TYPE_USHORT, /* unsigned short */
|
||||||
|
TYPE_2BYTE = TYPE_USHORT,
|
||||||
TYPE_MODET, /* representation of mode_t */
|
TYPE_MODET, /* representation of mode_t */
|
||||||
TYPE_GIDT, /* representation of gid_t */
|
TYPE_GIDT, /* representation of gid_t */
|
||||||
|
|
||||||
TYPE_UIDT, /* representation of uid_t */
|
TYPE_UIDT, /* representation of uid_t */
|
||||||
/*TYPE_FLAG,*/
|
/*TYPE_FLAG,*/
|
||||||
TYPE_INT3, /* int[3] */
|
TYPE_INT3, /* int[3] */
|
||||||
TYPE_TIMEVAL, /* struct timeval: {long;long;}, seconds and microsec. */
|
TYPE_TIMEVAL, /* struct timeval: {long;long;}, seconds and microsec. */
|
||||||
TYPE_TIMESPEC, /* struct timespec: {time_t;long;}, seconds and nanosec. */
|
TYPE_TIMESPEC, /* struct timespec: {time_t;long;}, seconds and nanosec. */
|
||||||
#if HAVE_STRUCT_LINGER
|
|
||||||
TYPE_LINGER, /* struct linger */
|
|
||||||
#endif /* HAVE_STRUCT_LINGER */
|
|
||||||
TYPE_DOUBLE, /* double */
|
TYPE_DOUBLE, /* double */
|
||||||
TYPE_STRING_NULL, /* char *; string or NULL */
|
TYPE_STRING_NULL, /* char *; string or NULL */
|
||||||
TYPE_LONGLONG, /* long long */
|
TYPE_LONGLONG, /* long long */
|
||||||
TYPE_OFF32, /* off_t */
|
TYPE_OFF32, /* off_t */
|
||||||
|
|
||||||
TYPE_OFF64, /* off64_t */
|
TYPE_OFF64, /* off64_t */
|
||||||
#if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IP_MREQN
|
|
||||||
TYPE_IP_MREQN, /* for struct ip_mreq or struct ip_mreqn */
|
|
||||||
#endif
|
|
||||||
TYPE_IP4NAME, /* IPv4 hostname or address */
|
|
||||||
TYPE_INT_INT, /* 2 parameters: first is int, second is int */
|
TYPE_INT_INT, /* 2 parameters: first is int, second is int */
|
||||||
|
TYPE_INT_INTP, /* 2 parameters: first is int, second is int* */
|
||||||
TYPE_INT_BIN, /* 2 parameters: first is int, second is binary */
|
TYPE_INT_BIN, /* 2 parameters: first is int, second is binary */
|
||||||
|
|
||||||
TYPE_INT_STRING, /* 2 parameters: first is int, second is req string */
|
TYPE_INT_STRING, /* 2 parameters: first is int, second is req string */
|
||||||
TYPE_INT_INT_INT, /* 3 params: first and second are int, 3rd is int */
|
TYPE_INT_INT_INT, /* 3 params: first and second are int, 3rd is int */
|
||||||
TYPE_INT_INT_BIN, /* 3 params: first and second are int, 3rd is binary */
|
TYPE_INT_INT_BIN, /* 3 params: first and second are int, 3rd is binary */
|
||||||
TYPE_INT_INT_STRING, /* 3 params: first and second are int, 3rd is string */
|
TYPE_INT_INT_STRING, /* 3 params: first and second are int, 3rd is string */
|
||||||
|
|
||||||
TYPE_2BYTE = TYPE_USHORT
|
TYPE_IP4NAME, /* IPv4 hostname or address */
|
||||||
|
#if HAVE_STRUCT_LINGER
|
||||||
|
TYPE_LINGER, /* struct linger */
|
||||||
|
#endif /* HAVE_STRUCT_LINGER */
|
||||||
|
#if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IP_MREQN
|
||||||
|
TYPE_IP_MREQN, /* for struct ip_mreq or struct ip_mreqn */
|
||||||
|
#endif
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
enum e_func {
|
enum e_func {
|
||||||
@ -74,8 +82,10 @@ enum e_func {
|
|||||||
is int setrequest */
|
is int setrequest */
|
||||||
OFUNC_IOCTL_MASK_LONG, /* arg1 is getrequest, arg2 is setrequest:
|
OFUNC_IOCTL_MASK_LONG, /* arg1 is getrequest, arg2 is setrequest:
|
||||||
ioctl(arg1, ); |= arg3; ioctl(arg2, ); */
|
ioctl(arg1, ); |= arg3; ioctl(arg2, ); */
|
||||||
|
OFUNC_IOCTL_GENERIC, /* generic ioctl() (request on cmdline) */
|
||||||
OFUNC_SOCKOPT, /* setsockopt() */
|
OFUNC_SOCKOPT, /* setsockopt() */
|
||||||
OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */
|
OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */
|
||||||
|
OFUNC_SOCKOPT_GENERIC,/* generic setsockopt() (level, optname on cmdline) */
|
||||||
OFUNC_FLOCK, /* flock() */
|
OFUNC_FLOCK, /* flock() */
|
||||||
OFUNC_TERMIO, /* termio() ? */
|
OFUNC_TERMIO, /* termio() ? */
|
||||||
OFUNC_SPEC, /* special, i.e. no generalizable function call */
|
OFUNC_SPEC, /* special, i.e. no generalizable function call */
|
||||||
|
Loading…
Reference in New Issue
Block a user