[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Suggestion and patch for tcp-server-sockets
From: |
Ralf Goertz |
Subject: |
Suggestion and patch for tcp-server-sockets |
Date: |
Fri, 8 Jun 2007 12:52:47 +0200 |
User-agent: |
KMail/1.9.7 |
Hi,
the other day I asked for a reason why there are no server sockets for
bash. Since I got no answer, I decided to do it myself. I included a
patch against the unpatched 3.2 file lib/sh/netopen.c (I think that file
has not been patched by any of the 17 official patches). I think it is
not reasonable to have udp-server-sockets so I omitted them (it would
have been much more complicated to include them anyway).
Now, if you want to open a server socket just do
exec 5<>/dev/tcp//port
Here is the patch
--- bash-3.2/lib/sh/netopen.c 2006-08-02 23:20:30.000000000 +0200
+++ bash-3.2-serversocketpatch/lib/sh/netopen.c 2007-06-08
12:14:46.000000000 +0200
@@ -70,8 +70,10 @@
static int _getaddr __P((char *, struct in_addr *));
static int _getserv __P((char *, int, unsigned short *));
static int _netopen4 __P((char *, char *, int));
+static int _netopenserver4 __P((char *));
#else /* HAVE_GETADDRINFO */
static int _netopen6 __P((char *, char *, int));
+static int _netopenserver6 __P((char *));
#endif
static int _netopen __P((char *, char *, int));
@@ -200,6 +202,65 @@
return(s);
}
+
+static int
+_netopenserver4(serv)
+ char *serv;
+{
+ struct sockaddr_in sin;
+ unsigned short p;
+ int s, e, ls, sockopt; /*ls is the listening socket */
+ struct linger fix_ling; /* as suggested by netcat */
+ char *errstring, *errstrings[]={"bind","listen","accept"};
+
+ if (_getserv(serv, 't', &p) == 0)
+ {
+ internal_error(_("%s: invalid service"), serv);
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset ((char *)&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = p;
+
+ ls = socket(AF_INET, SOCK_STREAM, 0);
+ if (ls < 0)
+ {
+ sys_error ("socket");
+ return (-1);
+ }
+ if (setsockopt(ls, SOL_SOCKET, SO_LINGER, &fix_ling, sizeof(fix_ling)
< 0)); /* FIXME what to do if this fails */
+ if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)
< 0)); /* FIXME what to do if this fails */
+
+ if (bind(ls, (struct sockaddr *) &sin, sizeof(sin)) < 0)
+ {
+ errstring=errstrings[0];
+ goto err;
+ }
+
+ if (listen(ls,1) < 0)
+ {
+ errstring=errstrings[1];
+ goto err;
+ }
+
+ s = accept(ls,NULL,NULL);
+ if (s<0)
+ {
+ errstring=errstrings[2];
+ goto err;
+ }
+ close(ls);
+ return(s);
+err:
+ e = errno;
+ sys_error(errstring);
+ close(ls);
+ errno = e;
+ return (-1);
+}
+
#endif /* ! HAVE_GETADDRINFO */
#ifdef HAVE_GETADDRINFO
@@ -266,6 +327,95 @@
}
return s;
}
+/*
+ * Open a TCP server socket on port SERV. Uses getaddrinfo(3) which
+ * provides support for IPv6. Returns the connected socket or -1 on
+ * error.
+ */
+static int
+_netopenserver6 (serv)
+ char *serv;
+{
+ int s, e, ls, sockopt; /* ls is the listening socket */
+ struct linger fix_ling; /* as suggested by netcat */
+ struct addrinfo hints, *res, *res0;
+ int gerr,retval;
+ char *errstring, *errstrings[]={"bind","listen","accept"};
+
+ memset ((char *)&hints, 0, sizeof (hints));
+ /* XXX -- if problems with IPv6, set to PF_INET for IPv4 only */
+#ifdef DEBUG /* PF_INET is the one that works for me */
+ hints.ai_family = PF_INET;
+#else
+ hints.ai_family = PF_UNSPEC;
+#endif
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+ fix_ling.l_onoff = 1;
+ fix_ling.l_linger = 0;
+
+
+ gerr = getaddrinfo (NULL, serv, &hints, &res0);
+ if (gerr)
+ {
+ if (gerr == EAI_SERVICE)
+ internal_error ("%s: %s", serv, gai_strerror (gerr));
+ else
+ internal_error ("%s: %s", "localhost", gai_strerror (gerr));
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (res = res0; res; res = res->ai_next)
+ {
+ if ((ls = socket (res->ai_family, res->ai_socktype,
res->ai_protocol)) < 0)
+ {
+ if (res->ai_next)
+ continue;
+ sys_error ("socket");
+ freeaddrinfo (res0);
+ return -1;
+ }
+ retval = setsockopt(ls, SOL_SOCKET, SO_LINGER, &fix_ling,
sizeof(fix_ling)); /* FIXME what to do if this fails */
+ retval = setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &sockopt,
sizeof(sockopt)); /* FIXME what to do if this fails */
+ retval = bind(ls, res->ai_addr, res->ai_addrlen);
+ if (retval<0)
+ {
+ errstring=errstrings[0];
+ goto err;
+ }
+ retval = listen(ls,1);
+ if (retval<0)
+ {
+ errstring=errstrings[1];
+ goto err;
+ }
+ s = accept(ls,NULL,NULL);
+ if (s<0)
+ {
+ errstring=errstrings[2];
+ goto err;
+ }
+ close(ls);
+ freeaddrinfo (res0);
+ break;
+
+err:
+ if (res->ai_next)
+ {
+ close (ls);
+ continue;
+ }
+ e = errno;
+ sys_error (errstring);
+ close (ls);
+ freeaddrinfo (res0);
+ errno = e;
+ return -1;
+ }
+ return s;
+}
+
#endif /* HAVE_GETADDRINFO */
/*
@@ -279,9 +429,15 @@
int typ;
{
#ifdef HAVE_GETADDRINFO
- return (_netopen6 (host, serv, typ));
+ if ((strlen(host) == 0) && (typ == 't')) /* /dev/tcp//serv */
+ return (_netopenserver6 (serv));
+ else
+ return (_netopen6 (host, serv, typ));
#else
- return (_netopen4 (host, serv, typ));
+ if ((strlen(host) == 0) && (typ == 't')) /* /dev/tcp//serv */
+ return (_netopenserver4 (serv));
+ else
+ return (_netopen4 (host, serv, typ));
#endif
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Suggestion and patch for tcp-server-sockets,
Ralf Goertz <=