/* vi: set sw=4 ts=4: * * nc: mini-netcat - Forward stdin/stdout to a file or network connection. * * Copyright 2007 Rob Landley * * Not in SUSv3. USE_NETCAT(OLDTOY(nc, netcat, "i#w#l@p#s:q#f:e", TOYFLAG_BIN)) USE_NETCAT(NEWTOY(netcat, "i#w#l@p#s:q#f:e", TOYFLAG_BIN)) config NETCAT bool "netcat" default n help usage: netcat [-iwlp] {IPADDR PORTNUM|-f FILENAME} [-e COMMAND] -e exec the rest of the command line -i SECONDS delay after each line sent -w SECONDS timeout for connection -f filename use file (ala /dev/ttyS0) instead of network -l listen for incoming connection (twice for persistent connection) -p local port number -s local source address -q SECONDS quit this many seconds after EOF on stdin. Use -l twice with -e for a quick-and-dirty server. Use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with netcat -f to connect to a serial port. */ #include "toys.h" #include "toynet.h" DEFINE_GLOBALS( char *filename; // -f read from filename instead of network long quit_delay; // -q Exit after EOF from stdin after # seconds. char *source_address; // -s Bind to a specific source address. long port; // -p Bind to a specific source port. long listen; // -l Listen for connection instead of dialing out. long wait; // -w Wait # seconds for a connection. long delay; // -i delay between lines sent ) #define TT this.netcat static void timeout(int signum) { error_exit("Timeout"); } // Translate x.x.x.x numeric IPv4 address, or else DNS lookup an IPv4 name. void lookup_name(char *name, uint32_t *result) { struct hostent *hostbyname; hostbyname = gethostbyname(*toys.optargs); if (!hostbyname) error_exit("name lookup failed"); *result = *(uint32_t *)*hostbyname->h_addr_list; } // Worry about a fancy lookup later. void lookup_port(char *str, uint16_t *port) { *port = SWAP_BE16(atoi(str)); } void netcat_main(void) { int sockfd, pollcount; struct pollfd pollfds[2]; if (TT.wait) { signal(SIGALRM, timeout); alarm(TT.wait); } if (TT.filename) pollfds[0].fd = xopen(TT.filename, O_RDWR); else { int temp; struct sockaddr_in address; // The argument parsing logic can't make "<2" conditional on "-f", so... if (!*toys.optargs || !toys.optargs[1]) { toys.exithelp++; error_exit("Need address and port"); } // Setup socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if (-1 == sockfd) perror_exit("socket"); fcntl(sockfd, F_SETFD, FD_CLOEXEC); temp = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(temp)); memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; if (TT.port) { address.sin_port = TT.port; if (-1 == bind(sockfd, &address, sizeof(address))) perror_exit("bind"); } // Figure out where to dial out to. lookup_name(*toys.optargs, (uint32_t *)&address.sin_addr); lookup_port(toys.optargs[1], &address.sin_port); temp = connect(sockfd, (struct sockaddr *)&address, sizeof(address)); if (temp<0) perror_exit("connect"); pollfds[0].fd = sockfd; } // We have a connection. Disarm timeout. if (TT.wait) { alarm(0); signal(SIGALRM, SIG_DFL); } pollcount = 2; pollfds[1].fd = 0; pollfds[0].events = pollfds[1].events = POLLIN; // Poll loop copying stdin->socket and socket->stdout. for (;;) { int i; if (0>poll(pollfds, pollcount, -1)) perror_exit("poll"); for (i=0; i