[PATCH] netcat with ipv6 and udp
Edgar E. Iglesias
edgar.iglesias at axis.com
Wed Dec 28 12:50:31 UTC 2005
Hi all,
This patch adds support for ipv6 and udp sockets for netcat.
Best regards
--
Programmer
Edgar E. Iglesias <edgar.iglesias at axis.com> 46.46.272.1946
-------------- next part --------------
Index: networking/nc.c
===================================================================
--- networking/nc.c (revision 12995)
+++ networking/nc.c (working copy)
@@ -45,9 +45,98 @@
bb_error_msg_and_die("Timed out");
}
+int create_socket(int af, int type, int flags, char *host, char *dport, char *sport) {
+ struct addrinfo hints, *res, *aip;
+ int sockfd = -1;
+ int r;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = flags;
+ hints.ai_family = af;
+ hints.ai_socktype = type;
+
+ if ((r = getaddrinfo(host, dport, &hints, &res)) != 0)
+ bb_error_msg_and_die(gai_strerror(r));
+
+ for (aip = res; aip; aip = aip->ai_next) {
+ int on = 1;
+
+ sockfd = socket(aip->ai_family,
+ aip->ai_socktype,
+ aip->ai_protocol);
+
+ if (sockfd < 0)
+ continue;
+
+ if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) == -1)
+ goto err;
+
+ if (flags & AI_PASSIVE) {
+ int tmpfd;
+#ifdef CONFIG_FEATURE_IPV6
+ if (aip->ai_family == PF_INET6)
+ setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&on, sizeof(on));
+#endif
+ if (bind(sockfd, aip->ai_addr, aip->ai_addrlen) != 0)
+ goto err;
+
+#ifdef CONFIG_NC_UDP
+ if (aip->ai_socktype == SOCK_DGRAM)
+ break;
+#endif
+
+ if (listen(sockfd, SOMAXCONN) != 0)
+ goto err;
+
+ if ((tmpfd = accept(sockfd, NULL, NULL)) < 0)
+ goto err;
+
+ close(sockfd);
+ sockfd = tmpfd;
+ break;
+ } else {
+ if (sport) {
+ int lport;
+ struct sockaddr_storage ss;
+
+ memset(&ss, 0, sizeof ss);
+
+ lport = bb_lookup_port(sport, "tcp", 0);
+ ss.ss_family = aip->ai_family;
+#ifdef CONFIG_FEATURE_IPV6
+ if (aip->ai_family == AF_INET6) {
+ ((struct sockaddr_in6 *)&ss)->sin6_port = lport;
+ }
+ else
+#endif
+ {
+ ((struct sockaddr_in *)&ss)->sin_port = lport;
+ }
+ if (bind(sockfd, (struct sockaddr *)&ss, sizeof ss) != 0)
+ goto err;
+ }
+
+ if (connect(sockfd, aip->ai_addr, aip->ai_addrlen) != 0)
+ goto err;
+ break;
+ }
+ continue;
+ err:
+ close(sockfd);
+ sockfd = -1;
+ }
+
+ if (sockfd == -1)
+ bb_perror_msg_and_die("socket");
+
+ freeaddrinfo(res);
+ return sockfd;
+}
+
int nc_main(int argc, char **argv)
{
- int do_listen = 0, lport = 0, delay = 0, wsecs = 0, tmpfd, opt, sfd, x;
+ int do_listen = 0, delay = 0, wsecs = 0, opt, sfd;
#define buf bb_common_bufsiz1
@@ -55,23 +144,36 @@
char *pr00gie = NULL;
#endif
- struct sockaddr_in address;
- struct hostent *hostinfo;
-
+ char *sport = NULL;
+ int sock_af = PF_UNSPEC;
+ int sock_type = SOCK_STREAM;
fd_set readfds, testfds;
-
- while ((opt = getopt(argc, argv, "lp:i:e:w:")) > 0) {
+
+ while ((opt = getopt(argc, argv, "46lp:ui:e:w:")) > 0) {
switch (opt) {
- case 'l':
+#if CONFIG_FEATURE_IPV6
+ case '4':
+ sock_af = PF_INET;
+ break;
+ case '6':
+ sock_af = PF_INET6;
+ break;
+#endif
+ case 'l':
do_listen++;
break;
case 'p':
- lport = bb_lookup_port(optarg, "tcp", 0);
+ sport = optarg;
break;
+#ifdef CONFIG_NC_UDP
+ case 'u':
+ sock_type = SOCK_DGRAM;
+ break;
+#endif
case 'i':
delay = atoi(optarg);
break;
-#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
+#ifdef GAPING_SECURITY_HOLE
case 'e':
pr00gie = optarg;
break;
@@ -83,56 +185,28 @@
bb_show_usage();
}
}
-
- if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc))
- bb_show_usage();
-
- if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- bb_perror_msg_and_die("socket");
- x = 1;
- if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)) == -1)
- bb_perror_msg_and_die("reuseaddr");
- address.sin_family = AF_INET;
-
- if (wsecs) {
- signal(SIGALRM, timeout);
- alarm(wsecs);
+
+#ifdef GAPING_SECURITY_HOLE
+ if (pr00gie) {
+ /* won't need stdin */
+ close (STDIN_FILENO);
}
-
- if (lport != 0) {
- memset(&address.sin_addr, 0, sizeof(address.sin_addr));
- address.sin_port = lport;
-
- if (bind(sfd, (struct sockaddr *) &address, sizeof(address)) < 0)
- bb_perror_msg_and_die("bind");
- }
-
+#endif /* GAPING_SECURITY_HOLE */
+
+ signal(SIGALRM, timeout);
+ alarm(wsecs);
+
if (do_listen) {
- socklen_t addrlen = sizeof(address);
-
- if (listen(sfd, 1) < 0)
- bb_perror_msg_and_die("listen");
-
- if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0)
- bb_perror_msg_and_die("accept");
-
- close(sfd);
- sfd = tmpfd;
- } else {
- hostinfo = xgethostbyname(argv[optind]);
-
- address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
- address.sin_port = bb_lookup_port(argv[optind+1], "tcp", 0);
-
- if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0)
- bb_perror_msg_and_die("connect");
+ sfd = create_socket(sock_af == PF_UNSPEC ? PF_INET : sock_af,
+ sock_type, AI_PASSIVE, NULL, sport, NULL);
}
-
- if (wsecs) {
- alarm(0);
- signal(SIGALRM, SIG_DFL);
- }
-
+ else
+ sfd = create_socket(sock_af, sock_type, 0,
+ argv[optind], argv[optind + 1], sport);
+
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+
#ifdef CONFIG_NC_GAPING_SECURITY_HOLE
/* -e given? */
if (pr00gie) {
@@ -151,6 +225,11 @@
FD_SET(STDIN_FILENO, &readfds);
while (1) {
+#ifdef CONFIG_NC_UDP
+ struct sockaddr_storage ss;
+ socklen_t slen = sizeof ss;
+ int connected = 0;
+#endif
int fd;
int ofd;
int nread;
@@ -162,10 +241,26 @@
for (fd = 0; fd < FD_SETSIZE; fd++) {
if (FD_ISSET(fd, &testfds)) {
- if ((nread = safe_read(fd, buf, sizeof(buf))) < 0)
- bb_perror_msg_and_die(bb_msg_read_error);
-
+#ifdef CONFIG_NC_UDP
if (fd == sfd) {
+ if ((nread = recvfrom(fd, buf, sizeof(buf), 0,
+ (struct sockaddr *)&ss,
+ &slen)) < 0)
+ bb_perror_msg_and_die("recvfrom");
+
+ if (sock_type == SOCK_DGRAM && !connected) {
+ if (connect(sfd, (struct sockaddr *)&ss,
+ sizeof ss))
+ bb_perror_msg_and_die("connect");
+ connected++;
+ }
+ }
+ else
+#endif
+ if ((nread = safe_read(fd, buf, sizeof(buf))) < 0)
+ bb_perror_msg_and_die("read");
+
+ if (fd == sfd) {
if (nread == 0)
exit(0);
ofd = STDOUT_FILENO;
Index: networking/Config.in
===================================================================
--- networking/Config.in (revision 12995)
+++ networking/Config.in (working copy)
@@ -444,6 +444,13 @@
Add support for executing a program after making or receiving a
successful connection (-e option).
+config CONFIG_NC_UDP
+ bool "UDP support"
+ default n
+ depends on CONFIG_NC
+ help
+ Add support for UDP
+
config CONFIG_NETSTAT
bool "netstat"
default n
Index: include/usage.h
===================================================================
--- include/usage.h (revision 12995)
+++ include/usage.h (working copy)
@@ -2150,13 +2150,30 @@
#else
# define USAGE_NC_EXEC(a)
#endif
+#ifdef CONFIG_FEATURE_IPV6
+# define USAGE_NC_IPV6(a) a
+#else
+# define USAGE_NC_IPV6(a)
+#endif
+#ifdef CONFIG_NC_UDP
+# define USAGE_NC_UDP(a) a
+#else
+# define USAGE_NC_UDP(a)
+#endif
#define nc_trivial_usage \
"[OPTIONS] [IP] [port]"
#define nc_full_usage \
"Netcat opens a pipe to IP:port\n\n" \
"Options:\n" \
+ USAGE_NC_IPV6( \
+ "\t-4\t\tUse IPv4\n" \
+ "\t-6\t\tUse IPv6\n" \
+ )\
"\t-l\t\tlisten mode, for inbound connects\n" \
"\t-p PORT\t\tlocal port number\n" \
+ USAGE_NC_UDP( \
+ "\t-u\t\tUse UDP\n" \
+ ) \
"\t-i SECS\t\tdelay interval for lines sent\n" \
USAGE_NC_EXEC( \
"\t-e PROG\t\tprogram to exec after connect (dangerous!)\n" \
More information about the busybox
mailing list