aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorehaupt <ehaupt@FreeBSD.org>2015-04-22 14:55:23 +0800
committerehaupt <ehaupt@FreeBSD.org>2015-04-22 14:55:23 +0800
commit01ccaecd85aee624cb3ce7c5f9009423e7331c5d (patch)
tree8c42c184a088b18122720082ecfb5f17fabf6489 /net
parentcb6c4aed0a8e0b80c09990541143fc2447ff34f6 (diff)
downloadfreebsd-ports-gnome-01ccaecd85aee624cb3ce7c5f9009423e7331c5d.tar.gz
freebsd-ports-gnome-01ccaecd85aee624cb3ce7c5f9009423e7331c5d.tar.zst
freebsd-ports-gnome-01ccaecd85aee624cb3ce7c5f9009423e7331c5d.zip
With SOCAT on systems where b0 to b4000000 options are not available, like
FreeBSD, setting the speed of a TERMIOS terminal is done using the ispeed and ospeed options. But when using simultaneously ispeed and ospeed parameters with SOCAT, the speed values are set within two distinct ioctl requests, so changing the speed of terminals or devices that need matching input and output returns an Invalid argument error (the TIOCSETA/TIOCSETAW/TIOCSETAF ioctl returns -1 and sets errno to EINVAL). This is especially the case On FreeBSD, where many tty device drivers need matching input and output speeds: - those that depend on ucom(4): uark(4), ubsa(4), ubser(4), uftdi(4), umcs(4), uplcom(4), uslcom(4), uvscom(4) - some others, even not depending on ucom(4): sio(4), digi(4), rp(4) But some don't: tty(4) With those drivers, the input and output speeds must match and be set inside a single ioctl request (TIOCSETA, TIOCSETAW or TIOCSETAF). The only exception to this rule is when the input baud rate is zero because, according to POSIX, in that case, the input baud rate is set equal to the output baud rate. For instance, this call to SOCAT on FreeBSD 10.1 terminates immediately with an EINVAL error: # socat -d /dev/cuaU2,ispeed=57600,ospeed=57600,echo=0,raw TCP-LISTEN:9000,reuseaddr 2015/03/09 00:43:33 socat[20723] E tcsetattr(3, TCSADRAIN, 0x7fffffffe148): Invalid argument Provide a patch that avoids this type of error: when setting both input and output speeds, only one ioctl syscall is performed. PR: 198441 Submitted by: Alexandre Fenyo <fbsd.bugzilla@fenyo.net>
Diffstat (limited to 'net')
-rw-r--r--net/socat/Makefile2
-rw-r--r--net/socat/files/patch-xioopts.c73
2 files changed, 74 insertions, 1 deletions
diff --git a/net/socat/Makefile b/net/socat/Makefile
index 9d556a1faa32..fc34cc913a00 100644
--- a/net/socat/Makefile
+++ b/net/socat/Makefile
@@ -3,7 +3,7 @@
PORTNAME= socat
PORTVERSION= 1.7.3.0
-PORTREVISION= 1
+PORTREVISION= 2
CATEGORIES= net ipv6
MASTER_SITES= http://www.dest-unreach.org/socat/download/ \
LOCAL/ehaupt
diff --git a/net/socat/files/patch-xioopts.c b/net/socat/files/patch-xioopts.c
new file mode 100644
index 000000000000..1a257fc36a31
--- /dev/null
+++ b/net/socat/files/patch-xioopts.c
@@ -0,0 +1,73 @@
+--- xioopts.c.orig 2015-01-24 10:15:22 UTC
++++ xioopts.c
+@@ -2971,6 +2971,25 @@ int retropt_bind(struct opt *opts,
+ OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
+ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
+ struct opt *opt;
++#ifdef HAVE_TERMIOS_ISPEED
++ int ispeed_major = -1, ospeed_major = -1;
++ unsigned int ispeed_value, ospeed_value;
++ bool speed_done = false;
++
++ opt = opts; while (opt && opt->desc != ODESC_END) {
++ if (opt->desc == ODESC_DONE ||
++ (phase != PH_ALL && opt->desc->phase != phase)) {
++ ++opt; continue; }
++ if (opt->desc->optcode == OPT_ISPEED) {
++ ispeed_major = opt->desc->major;
++ ispeed_value = opt->value.u_uint; }
++ if (opt->desc->optcode == OPT_OSPEED) {
++ ospeed_major = opt->desc->major;
++ ospeed_value = opt->value.u_uint; }
++ ++opt;
++ continue;
++ }
++#endif /* HAVE_TERMIOS_ISPEED */
+
+ opt = opts; while (opt && opt->desc != ODESC_END) {
+ if (opt->desc == ODESC_DONE ||
+@@ -3605,21 +3624,29 @@ int applyopts(int fd, struct opt *opts,
+
+ #ifdef HAVE_TERMIOS_ISPEED
+ } else if (opt->desc->func == OFUNC_TERMIOS_SPEED) {
+- union {
+- struct termios termarg;
+- speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
+- } tdata;
+- if (Tcgetattr(fd, &tdata.termarg) < 0) {
+- Error3("tcgetattr(%d, %p): %s",
+- fd, &tdata.termarg, strerror(errno));
+- opt->desc = ODESC_ERROR; ++opt; continue;
+- }
+- tdata.speeds[opt->desc->major] = opt->value.u_uint;
+- if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
+- Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
+- fd, &tdata.termarg, strerror(errno));
+- opt->desc = ODESC_ERROR; ++opt; continue;
+- }
++ if (speed_done == false) {
++ union {
++ struct termios termarg;
++ speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
++ } tdata;
++ if (Tcgetattr(fd, &tdata.termarg) < 0) {
++ Error3("tcgetattr(%d, %p): %s",
++ fd, &tdata.termarg, strerror(errno));
++ opt->desc = ODESC_ERROR; ++opt; continue;
++ }
++ if (ispeed_major < 0 || ospeed_major < 0)
++ tdata.speeds[opt->desc->major] = opt->value.u_uint;
++ else{
++ tdata.speeds[ispeed_major] = ispeed_value;
++ tdata.speeds[ospeed_major] = ospeed_value;
++ speed_done = true;
++ }
++ if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
++ Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
++ fd, &tdata.termarg, strerror(errno));
++ opt->desc = ODESC_ERROR; ++opt; continue;
++ }
++ }
+ #endif /* HAVE_TERMIOS_ISPEED */
+
+ } else if (opt->desc->func == OFUNC_TERMIOS_SPEC) {