From 83521b52d030d78daee3bf73adb511de267d3f51 Mon Sep 17 00:00:00 2001 From: Pav Lucistnik Date: Wed, 6 Jun 2007 13:46:45 +0000 Subject: [PATCH] - Incorporate Sainsbury's service name resolution patch: http://www.dest-unreach.org/socat/contrib/socat-servicenames.html - Incorporate Lucq's file descriptor patch: http://www.dest-unreach.org/socat/contrib/socat-maxfds.html PR: ports/113283 Submitted by: bf Approved by: Nils Vogels (maintainer) --- net/socat/Makefile | 1 + net/socat/files/patch-socat-maxfds | 442 +++++++++++++++++++++++ net/socat/files/patch-socat-servicenames | 31 ++ 3 files changed, 474 insertions(+) create mode 100644 net/socat/files/patch-socat-maxfds create mode 100644 net/socat/files/patch-socat-servicenames diff --git a/net/socat/Makefile b/net/socat/Makefile index 36b5413ed3d7..5fe7f40889ab 100644 --- a/net/socat/Makefile +++ b/net/socat/Makefile @@ -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 --git a/net/socat/files/patch-socat-maxfds b/net/socat/files/patch-socat-maxfds new file mode 100644 index 000000000000..424a5942ea27 --- /dev/null +++ b/net/socat/files/patch-socat-maxfds @@ -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 --git a/net/socat/files/patch-socat-servicenames b/net/socat/files/patch-socat-servicenames new file mode 100644 index 000000000000..f00d72c743af --- /dev/null +++ b/net/socat/files/patch-socat-servicenames @@ -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 */ + } + }