ports/113283: [PATCH] two patches for net/socat

bf bf2006a at yahoo.com
Sun Jun 3 11:00:10 UTC 2007


>Number:         113283
>Category:       ports
>Synopsis:       [PATCH] two patches for net/socat
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jun 03 11:00:09 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     bf
>Release:        6.2-Stable i386
>Organization:
-
>Environment:
>Description:
Incorporate Sainsbury's service name resolution patch:

http://www.dest-unreach.org/socat/contrib/socat-servicenames.html

and Lucq's file descriptor patch:

http://www.dest-unreach.org/socat/contrib/socat-maxfds.html

into the port.


diff -ruN socat.orig/Makefile socat/Makefile
--- socat.orig/Makefile	Sun Apr  8 21:17:59 2007
+++ socat/Makefile	Sat Jun  2 23:17:11 2007
@@ -8,6 +8,7 @@
 
 PORTNAME=	socat
 PORTVERSION=	1.6.0.0
+PORTREVISION=	1
 CATEGORIES=	net
 MASTER_SITES=	http://www.dest-unreach.org/socat/download/
 
diff -ruN socat.orig/files/patch-socat-maxfds socat/files/patch-socat-maxfds
--- socat.orig/files/patch-socat-maxfds	Wed Dec 31 19:00:00 1969
+++ socat/files/patch-socat-maxfds	Sat Jun  2 23:13:01 2007
@@ -0,0 +1,442 @@
+diff -r -N -U 3 socat-1.6.0.0/procan.c socat-1.6.0.0+maxfds/procan.c
+--- procan.c.orig	2006-12-28 08:25:01.000000000 +0100
++++ procan.c	2007-04-05 12:41:26.000000000 +0200
+@@ -161,6 +161,10 @@
+ #endif
+    }
+ 
++   /* C defines */
++   fprintf(outfile, "#define FD_SETSIZE %u\n", FD_SETSIZE);
++   fprintf(outfile, "#define FOPEN_MAX %u\n", FOPEN_MAX);
++
+    /* file descriptors */
+ 
+    /* what was this for?? */
+diff -r -N -U 3 socat-1.6.0.0/socat.c socat-1.6.0.0+maxfds/socat.c
+--- socat.c.orig	2007-03-06 22:03:28.000000000 +0100
++++ socat.c	2007-03-31 22:24:37.000000000 +0200
+@@ -642,8 +642,8 @@
+    returns >0 if child died and left data
+ */
+ int childleftdata(xiofile_t *xfd) {
+-   fd_set in, out, expt;
+-   int retval;
++   fd_set *in = NULL, *out = NULL, *expt = NULL;
++   int max, retval;
+    /* have to check if a child process died before, but left read data */
+    if (XIO_READABLE(xfd) &&
+        (XIO_RDSTREAM(xfd)->howtoend == END_KILL ||
+@@ -652,25 +652,59 @@
+        XIO_RDSTREAM(xfd)->para.exec.pid == 0) {
+       struct timeval time0 = { 0,0 };
+ 
+-      FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
++#ifndef howmany
++#define howmany(x, y) (((x) + ((y) - 1)) / (y))
++#endif
++
++#ifndef NFDBITS
++#     ifndef HAVE_FDS_BITS
++#           define NFDBITS (sizeof(__fd_mask) * 8)
++#     else
++#           define NFDBITS (sizeof(fd_mask) * 8)
++#     endif
++#endif
++
++#ifndef HAVE_FDS_BITS
++#     define FD_MASK_SIZE (sizeof(__fd_mask))
++#else
++#     define FD_MASK_SIZE (sizeof(fd_mask))
++#endif
++
++      max = XIO_GETRDFD(xfd);
++      in = (fd_set *)Calloc(howmany(max+1, NFDBITS), FD_MASK_SIZE);
++      out = (fd_set *)Calloc(howmany(max+1, NFDBITS), FD_MASK_SIZE);
++      expt = (fd_set *)Calloc(howmany(max+1, NFDBITS), FD_MASK_SIZE);
++      if (in == NULL || out == NULL || expt == NULL) {
++         Error2("select(%d): %s", max+1, strerror(errno));
++         if (in != NULL)
++               free(in);
++         if (out != NULL)
++               free(out);
++         if (expt != NULL)
++               free(expt);
++         return -1;
++      }
+       if (XIO_READABLE(xfd) && !(XIO_RDSTREAM(xfd)->eof >= 2 && !XIO_RDSTREAM(xfd)->ignoreeof)) {
+-	 FD_SET(XIO_GETRDFD(xfd), &in);
++	 FD_SET(XIO_GETRDFD(xfd), in);
+ 	 /*0 FD_SET(XIO_GETRDFD(xfd), &expt);*/
+       }
+       do {
+-	 retval = Select(FOPEN_MAX, &in, &out, &expt, &time0);
++	 retval = Select(max+1, in, out, expt, &time0);
+       } while (retval < 0 && errno == EINTR);
+ 
+       if (retval < 0) {
+ #if HAVE_FDS_BITS
+ 	 Error5("select(%d, &0x%lx, &0x%lx, &0x%lx, {0}): %s",
+-		FOPEN_MAX, in.fds_bits[0], out.fds_bits[0],
+-		expt.fds_bits[0], strerror(errno));
++		max+1, in->fds_bits[0], out->fds_bits[0],
++		expt->fds_bits[0], strerror(errno));
+ #else
+ 	 Error5("select(%d, &0x%lx, &0x%lx, &0x%lx, {0}): %s",
+-		FOPEN_MAX, in.__fds_bits[0], out.__fds_bits[0],
+-		expt.__fds_bits[0], strerror(errno));
++		max+1, in->__fds_bits[0], out->__fds_bits[0],
++		expt->__fds_bits[0], strerror(errno));
+ #endif
++         free(in);
++         free(out);
++         free(expt);
+ 	 return -1;
+       } else if (retval == 0) {
+ 	 Info("terminated child did not leave data for us");
+@@ -679,6 +713,9 @@
+ 	 closing = MAX(closing, 1);
+       }
+    }
++   free(in);
++   free(out);
++   free(expt);
+    return 0;
+ }
+ 
+@@ -694,14 +731,34 @@
+    and their options are set/applied
+    returns -1 on error or 0 on success */
+ int _socat(void) {
+-   fd_set in, out, expt;
+-   int retval;
++   fd_set *in, *out, *expt;
++   int max, retval;
+    unsigned char *buff;
+    ssize_t bytes1, bytes2;
+    int polling = 0;	/* handling ignoreeof */
+    int wasaction = 1;	/* last select was active, do NOT sleep before next */
+    struct timeval total_timeout;	/* the actual total timeout timer */
+ 
++#ifndef MAX
++#     define MAX(x, y) (((y) > (x)) ? (y) : (x))
++#endif
++
++   max = MAX(
++      MAX(XIO_GETRDFD(sock1), XIO_GETWRFD(sock1)),
++      MAX(XIO_GETRDFD(sock2), XIO_GETWRFD(sock2)));
++   in = (fd_set *)Calloc(howmany(max+1, NFDBITS), FD_MASK_SIZE);
++   out = (fd_set *)Calloc(howmany(max+1, NFDBITS), FD_MASK_SIZE);
++   expt = (fd_set *)Calloc(howmany(max+1, NFDBITS), FD_MASK_SIZE);
++   if (in == NULL || out == NULL || expt == NULL) {
++       Error2("select(%d): %s", max+1, strerror(errno));
++       if (in != NULL)
++           free(in);
++       if (out != NULL)
++           free(out);
++       if (expt != NULL)
++           free(expt);
++       return -1;
++   }
+ #if WITH_FILAN
+    if (socat_opts.debug) {
+       int fdi, fdo;
+@@ -733,7 +790,7 @@
+ 
+    /* when converting nl to crnl, size might double */
+    buff = Malloc(2*socat_opts.bufsiz+1);
+-   if (buff == NULL)  return -1;
++   if (buff == NULL)  { free(in); free(out); free(expt); return -1; }
+ 
+    if (socat_opts.logopt == 'm' && xioinqopt('l', NULL, 0) == 'm') {
+       Info("switching to syslog");
+@@ -772,6 +829,9 @@
+ 	       if (total_timeout.tv_sec < 0 ||
+ 		   total_timeout.tv_sec == 0 && total_timeout.tv_usec < 0) {
+ 		  Notice("inactivity timeout triggered");
++                  free(in);
++                  free(out);
++                  free(expt);
+ 		  return 0;
+ 	       }
+ 	    }
+@@ -803,7 +863,9 @@
+ 
+       do {
+ 	 int _errno;
+-	 FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
++         memset(in, 0, howmany(max+1, NFDBITS) * FD_MASK_SIZE);
++         memset(out, 0, howmany(max+1, NFDBITS) * FD_MASK_SIZE);
++         memset(expt, 0, howmany(max+1, NFDBITS) * FD_MASK_SIZE);
+ 
+ 	 childleftdata(sock1);
+ 	 childleftdata(sock2);
+@@ -819,23 +881,23 @@
+ 	     !(XIO_RDSTREAM(sock1)->eof > 1 && !XIO_RDSTREAM(sock1)->ignoreeof) &&
+ 	     !socat_opts.righttoleft) {
+ 	    if (!mayrd1) {
+-	       FD_SET(XIO_GETRDFD(sock1), &in);
++	       FD_SET(XIO_GETRDFD(sock1), in);
+ 	    }
+ 	    if (!maywr2) {
+-	       FD_SET(XIO_GETWRFD(sock2), &out);
++	       FD_SET(XIO_GETWRFD(sock2), out);
+ 	    }
+ 	 }
+ 	 if (XIO_READABLE(sock2) &&
+ 	     !(XIO_RDSTREAM(sock2)->eof > 1 && !XIO_RDSTREAM(sock2)->ignoreeof) &&
+ 	     !socat_opts.lefttoright) {
+ 	    if (!mayrd2) {
+-	       FD_SET(XIO_GETRDFD(sock2), &in);
++	       FD_SET(XIO_GETRDFD(sock2), in);
+ 	    }
+ 	    if (!maywr1) {
+-	       FD_SET(XIO_GETWRFD(sock1), &out);
++	       FD_SET(XIO_GETWRFD(sock1), out);
+ 	    }
+ 	 }
+-	 retval = Select(FOPEN_MAX, &in, &out, &expt, to);
++	 retval = Select(max+1, in, out, expt, to);
+ 	 _errno = errno;
+ 	 if (retval < 0 && errno == EINTR) {
+ 	    Info1("select(): %s", strerror(errno));
+@@ -851,15 +913,18 @@
+       if (retval < 0) {
+ #if HAVE_FDS_BITS
+ 	    Error7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu): %s",
+-		   FOPEN_MAX, in.fds_bits[0], out.fds_bits[0],
+-		   expt.fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
++		   max+1, in->fds_bits[0], out->fds_bits[0],
++		   expt->fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
+ 		   strerror(errno));
+ #else
+ 	    Error7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu): %s",
+-		   FOPEN_MAX, in.__fds_bits[0], out.__fds_bits[0],
+-		   expt.__fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
++		   max+1, in->__fds_bits[0], out->__fds_bits[0],
++		   expt->__fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
+ 		   strerror(errno));
+ #endif
++            free(in);
++            free(out);
++            free(expt);
+ 	    return -1;
+       } else if (retval == 0) {
+ 	 Info2("select timed out (no data within %ld.%06ld seconds)",
+@@ -872,6 +937,9 @@
+ 		    socat_opts.total_timeout.tv_usec != 0) {
+ 	    /* there was a total inactivity timeout */
+ 	    Notice("inactivity timeout triggered");
++            free(in);
++            free(out);
++            free(expt);
+ 	    return 0;
+ 	 }
+ 
+@@ -884,17 +952,17 @@
+       }
+ 
+       if (XIO_READABLE(sock1) && XIO_GETRDFD(sock1) >= 0 &&
+-	  FD_ISSET(XIO_GETRDFD(sock1), &in)) {
++	  FD_ISSET(XIO_GETRDFD(sock1), in)) {
+ 	 mayrd1 = true;
+       }
+       if (XIO_READABLE(sock2) && XIO_GETRDFD(sock2) >= 0 &&
+-	  FD_ISSET(XIO_GETRDFD(sock2), &in)) {
++	  FD_ISSET(XIO_GETRDFD(sock2), in)) {
+ 	 mayrd2 = true;
+       }
+-      if (XIO_GETWRFD(sock1) >= 0 && FD_ISSET(XIO_GETWRFD(sock1), &out)) {
++      if (XIO_GETWRFD(sock1) >= 0 && FD_ISSET(XIO_GETWRFD(sock1), out)) {
+ 	 maywr1 = true;
+       }
+-      if (XIO_GETWRFD(sock2) >= 0 && FD_ISSET(XIO_GETWRFD(sock2), &out)) {
++      if (XIO_GETWRFD(sock2) >= 0 && FD_ISSET(XIO_GETWRFD(sock2), out)) {
+ 	 maywr2 = true;
+       }
+ 
+@@ -989,6 +1057,10 @@
+    xioclose(sock1);
+    xioclose(sock2);
+ 
++   free(in);
++   free(out);
++   free(expt);
++
+    return 0;
+ }
+ 
+diff -r -N -U 3 socat-1.6.0.0/test.sh socat-1.6.0.0+maxfds/test.sh
+--- test.sh.orig	2007-03-06 22:06:20.000000000 +0100
++++ test.sh	2007-04-06 10:16:30.000000000 +0200
+@@ -1425,7 +1425,8 @@
+     local arg1="$3";	[ -z "$arg1" ] && arg1="-"
+     local arg2="$4";	[ -z "$arg2" ] && arg2="echo"
+     local opts="$5"
+-    local T="$6";	[ -z "$T" ] && T=0
++    local redir="$6"
++    local T="$7";	[ -z "$T" ] && T=0
+     local tf="$td/test$N.stdout"
+     local te="$td/test$N.stderr"
+     local tdiff="$td/test$N.diff"
+@@ -1435,14 +1436,16 @@
+     $PRINTF "test $F_n %s... " $num "$title"
+     #echo "$da" |$cmd >"$tf" 2>"$te"
+ #set -vx
+-    (echo "$da"; sleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" &
++#    (echo "$da"; sleep $T) |($SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te"; echo $? >"$td/test$N.rc") &
++#    echo eval $SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" $redir
++    (echo "$da"; sleep $T) |(eval $SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" $redir; echo $? >"$td/test$N.rc") &
+     export rc1=$!
+     #sleep 5 && kill $rc1 2>/dev/null &
+ #    rc2=$!
+     wait $rc1
+ #    kill $rc2 2>/dev/null
+-#set +vx
+-    if [ "$?" != 0 ]; then
++set +vx
++    if [ "$(cat "$td/test$N.rc")" != 0 ]; then
+ 	$PRINTF "$FAILED: $SOCAT:\n"
+ 	echo "$SOCAT $opts $arg1 $arg2"
+ 	cat "$te"
+@@ -4129,7 +4132,7 @@
+ case "$TESTS" in
+ *%functions%*|*%$NAME%*)
+ TEST="$NAME: inheritance of stdout to single exec with socketpair"
+-testecho "$N" "$TEST" "-!!exec:cat" "" "$opts" 1
++testecho "$N" "$TEST" "-!!exec:cat" "" "$opts" "" 1
+ esac
+ N=$((N+1))
+ 
+@@ -4137,7 +4140,7 @@
+ case "$TESTS" in
+ *%functions%*|*%$NAME%*)
+ TEST="$NAME: inheritance of stdout to single exec with pipe"
+-testecho "$N" "$TEST" "-!!exec:cat,pipes" "" "$opts" 1
++testecho "$N" "$TEST" "-!!exec:cat,pipes" "" "$opts" "" 1
+ esac
+ N=$((N+1))
+ 
+@@ -4149,7 +4152,7 @@
+     $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N
+     numCANT=$((numCANT+1))
+ else
+-testecho "$N" "$TEST" "-!!exec:cat,pty,raw" "" "$opts" 1
++testecho "$N" "$TEST" "-!!exec:cat,pty,raw" "" "$opts" "" 1
+ fi
+ esac
+ N=$((N+1))
+@@ -4178,7 +4181,7 @@
+     $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N
+     numCANT=$((numCANT+1))
+ else
+-testecho "$N" "$TEST" "exec:cat,pty,raw!!-" "" "$opts" $MISCDELAY
++testecho "$N" "$TEST" "exec:cat,pty,raw!!-" "" "$opts" "" $MISCDELAY
+ fi
+ esac
+ N=$((N+1))
+@@ -5662,7 +5665,7 @@
+ case "$TESTS" in
+ *%parse%*|*%functions%*|*%$NAME%*)
+ TEST="$NAME: does lexical analysis work sensibly (exec)"
+-testecho "$N" "$TEST" "" "exec:'$SOCAT - exec:$CAT,pipes'" "$opts" 1
++testecho "$N" "$TEST" "" "exec:'$SOCAT - exec:$CAT,pipes'" "$opts" "" 1
+ esac
+ N=$((N+1))
+ 
+@@ -5670,7 +5673,7 @@
+ case "$TESTS" in
+ *%parse%*|*%functions%*|*%$NAME%*)
+ TEST="$NAME: does lexical analysis work sensibly (system)"
+-testecho "$N" "$TEST" "" "system:\"$SOCAT - exec:$CAT,pipes\"" "$opts" 1
++testecho "$N" "$TEST" "" "system:\"$SOCAT - exec:$CAT,pipes\"" "$opts" "" 1
+ esac
+ N=$((N+1))
+ 
+@@ -7737,6 +7740,81 @@
+ esac
+ N=$((N+1))
+ 
++
++# test: up to socat 1.6.0.0, the highest file descriptor supported in socats
++# transfer engine was FOPEN_MAX-1; this usually worked fine but would fail when
++# socat was invoked with many file descriptors already opened. socat would 
++# just hang in the select() call. Daniel Lucq found this problem and provided a
++# patch that replaced the FOPEN_MAX limit: this patch not only allows FDs to be
++# up to NFDBITS-1, but should work even when the processes maximum number of
++# open files is increased with ulimit -n.
++# FOPEN_MAX on different OS's:
++#   OS			FOPEN_	ulimit	ulimit	FD_
++#			MAX	-H -n	-S -n	SETSIZE
++#   Linux 2.6:		16	1024	1024	1024
++#   HP-UX 11.11:	60	2048	2048	2048
++#   FreeBSD:		20	11095	11095	1024
++#   Cygwin:		20	unlimit	256	64
++#   AIX:		32767	65534		65534
++NAME=EXCEED_FOPEN_MAX
++case "$TESTS" in
++*%functions%*|*%maxfds%*|*%$NAME%*)
++TEST="$NAME: more than FOPEN_MAX FDs in use"
++# this test opens a number of FDs before socat is invoked. socat will have to
++# allocate higher FD numbers and thus hang if it cannot handle them.
++REDIR=
++FOPEN_MAX=$($PROCAN |grep '^#define FOPEN_MAX' |awk '{print($3);}')
++OPEN_FILES=$FOPEN_MAX	# more than the highest FOPEN_MAX
++i=3; while [ "$i" -lt "$OPEN_FILES" ]; do
++    REDIR="$REDIR $i>&2"
++    i=$((i+1))
++done
++#echo $REDIR
++#testecho "$N" "$TEST" "" "pipe" "$opts -T 3" "" 1 
++#set -vx
++testecho "$N" "$TEST" "" "pipe" "$opts -T 1" "$REDIR" 1
++#set +vx
++esac
++N=$((N+1))
++
++OPEN_FILES="$(ulimit -n)"
++NAME=EXCEED_FD_SETSIZE
++case "$TESTS" in
++*%functions%*|*%maxfds%*|*%root%*|*%$NAME%*)
++TEST="$NAME: more than FD_SETSIZE FDs in use"
++# this test opens a number of FDs before socat is invoked. This number exceeds
++# the size of the fd_set type proposed for use with select(). socat will have
++# to allocate space for a larger record and will hang or crash if it cannot
++# handle this.
++# ulimit -n must be above FD_SETSIZE which might require root
++REDIR=
++FD_SETSIZE=$($PROCAN |grep '^#define FD_SETSIZE' |awk '{print($3);}')
++OPEN_FILES=$(($FD_SETSIZE+2))	# more than the highest FD_SETSIZE
++while true; do	# just go once; so we can break inside
++ if [ $(ulimit -S -n) -lt $OPEN_FILES ]; then
++ # if it increases, -H must be first
++    if [ $(ulimit -H -n) -lt $OPEN_FILES ]; then
++	if ! ulimit -H -n $((OPEN_FILES)); then
++	    $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N
++	    numCANT=$((numCANT+1))
++	    break;
++	fi
++    fi
++    ulimit -S -n $((OPEN_FILES))
++ fi
++ i=3; while [ "$i" -lt "$FD_SETSIZE" ]; do
++    REDIR="$REDIR $i>&2"
++    i=$((i+1))
++ done
++ testecho "$N" "$TEST" "" "pipe" "$opts -T 1" "$REDIR" 1
++ set +vx
++break
++done
++;;
++esac
++N=$((N+1))
++
++
+ echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed"
+ 
+ if [ "$numFAIL" -gt 0 ]; then
+diff -r -N -U 3 socat-1.6.0.0/VERSION socat-1.6.0.0+maxfds/VERSION
+--- VERSION.orig	2007-03-06 21:58:44.000000000 +0100
++++ VERSION	2007-04-06 23:20:11.000000000 +0200
+@@ -1 +1 @@
+-"1.6.0.0"
++"1.6.0.0_1"
diff -ruN socat.orig/files/patch-socat-servicenames socat/files/patch-socat-servicenames
--- socat.orig/files/patch-socat-servicenames	Wed Dec 31 19:00:00 1969
+++ socat/files/patch-socat-servicenames	Sat Jun  2 23:13:59 2007
@@ -0,0 +1,31 @@
+--- xio-ip.c.orig      Wed Mar  7 08:08:02 2007
++++ xio-ip.c    Fri Apr 27 17:10:02 2007
+@@ -144,7 +144,7 @@
+       with NIS), so we handle this specially */
+    if (service && isdigit(service[0]&0xff)) {
+       char *extra;
+-      port = strtoul(service, &extra, 0);
++      port = htons(strtoul(service, &extra, 0));
+       if (*extra != '\0') {
+         Warn2("xiogetaddrinfo(, \"%s\", ...): extra trailing data \"%s\"",
+               service, extra);
+@@ -396,15 +396,16 @@
+
+ #if WITH_TCP || WITH_UDP
+    if (service) {
+-      port = parseport(service, family);
++       port = parseport(service, protocol);
++
+    }
+    if (port >= 0) {
+       switch (family) {
+ #if WITH_IP4
+-      case PF_INET:  sau->ip4.sin_port  = htons(port); break;
++      case PF_INET:  sau->ip4.sin_port  = port; break;
+ #endif /* WITH_IP4 */
+ #if WITH_IP6
+-      case PF_INET6: sau->ip6.sin6_port = htons(port); break;
++      case PF_INET6: sau->ip6.sin6_port = port; break;
+ #endif /* WITH_IP6 */
+       }
+    }

>How-To-Repeat:

>Fix:


>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list