Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Apr 2015 06:55:24 +0000 (UTC)
From:      Emanuel Haupt <ehaupt@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r384479 - in head/net/socat: . files
Message-ID:  <201504220655.t3M6tOni075649@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ehaupt
Date: Wed Apr 22 06:55:23 2015
New Revision: 384479
URL: https://svnweb.freebsd.org/changeset/ports/384479

Log:
  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>

Added:
  head/net/socat/files/patch-xioopts.c   (contents, props changed)
Modified:
  head/net/socat/Makefile

Modified: head/net/socat/Makefile
==============================================================================
--- head/net/socat/Makefile	Wed Apr 22 06:23:07 2015	(r384478)
+++ head/net/socat/Makefile	Wed Apr 22 06:55:23 2015	(r384479)
@@ -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

Added: head/net/socat/files/patch-xioopts.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/net/socat/files/patch-xioopts.c	Wed Apr 22 06:55:23 2015	(r384479)
@@ -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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201504220655.t3M6tOni075649>