📄 netcat.c
字号:
/* Netcat 1.00 951010
A damn useful little "backend" utility begun 950915 or thereabouts,
as *Hobbit*'s first real stab at some sockets programming. Something that
should have and indeed may have existed ten years ago, but never became a
standard Unix utility. IMHO, "nc" could take its place right next to cat,
cp, rm, mv, dd, ls, and all those other cryptic and Unix-like things.
Read the README for the whole story, doc, applications, etc.
Layout:
conditional includes:
includes:
handy defines:
globals:
malloced globals:
cmd-flag globals:
support routines:
main:
todo:
more of the portability swamp, and an updated generic.h
frontend progs to generate various packets, raw or otherwise...
char-mode [cbreak, fcntl-unbuffered, etc...]
connect-to-all-A-records hack
bluesky:
RAW mode!
backend progs to grab a pty and look like a real telnetd?!
Modified by jojo@farm9.com, 19-Sept-2000 -- added twofish encrypted pipe,
uses hardcoded key generated by "metallica"
Bill Weiss -- added "-k" option (actually added -P, but I changed it because
Linux version already had the option as "-k")
*/
#include "generic.h" /* same as with L5, skey, etc */
#include "farm9crypt.h"
/* conditional includes -- a very messy section: */
/* #undef _POSIX_SOURCE /* might need this for something? */
#define HAVE_BIND /* XXX -- for now, see below... */
#define HAVE_HELP /* undefine if you dont want the help text */
/* #define ANAL /* if you want case-sensitive DNS matching */
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
#include <malloc.h> /* xxx: or does it live in sys/ ?? */
#endif
/* have to do this *before* including types.h. xxx: Linux still has it wrong */
#ifdef FD_SETSIZE /* should be in types.h, butcha never know. */
#undef FD_SETSIZE /* if we ever need more than 16 active */
#endif /* fd's, something is horribly wrong! */
#ifdef WIN32
#define FD_SETSIZE 64 /* WIN32 does this as an array not a bitfield and it likes 64 */
#else
#define FD_SETSIZE 16 /* <-- this'll give us a long anyways, wtf */
#endif
#include <sys/types.h> /* *now* do it. Sigh, this is broken */
#ifdef WIN32
#undef HAVE_RANDOM
#undef IP_OPTIONS
#undef SO_REUSEPORT
#include <windows.h>
#endif
#ifdef HAVE_RANDOM
#define SRAND srandom
#define RAND random
#else
#define SRAND srand
#define RAND rand
#endif /* HAVE_RANDOM */
/* xxx: these are rsh leftovers, move to new generic.h */
/* will we even need any nonblocking shit? Doubt it. */
/* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
/* #include <sys/filio.h> */
/*
#include <sys/ioctl.h>
#include <sys/file.h>
*/
/* includes: */
#ifdef WIN32
#include "getopt.h"
#define sleep _sleep
#define strcasecmp strcmpi
#define EADDRINUSE WSAEADDRINUSE
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNREFUSED WSAECONNREFUSED
#endif
#ifndef WIN32
#include <sys/time.h> /* timeval, time_t */
#else
#include <time.h>
#endif
#include <setjmp.h> /* jmp_buf et al */
#ifndef WIN32
#include <sys/socket.h> /* basics, SO_ and AF_ defs, sockaddr, ... */
#include <netinet/in.h> /* sockaddr_in, htons, in_addr */
#include <netinet/in_systm.h> /* misc crud that netinet/ip.h references */
#include <netinet/ip.h> /* IPOPT_LSRR, header stuff */
#include <netdb.h> /* hostent, gethostby*, getservby* */
#include <arpa/inet.h> /* inet_ntoa */
#else
#include <fcntl.h>
#include <io.h>
#include <conio.h>
#include <winsock.h>
#endif
#include <stdio.h>
#include <string.h> /* strcpy, strchr, yadda yadda */
#include <errno.h>
#include <signal.h>
/* handy stuff: */
#define SA struct sockaddr /* socket overgeneralization braindeath */
#define SAI struct sockaddr_in /* ... whoever came up with this model */
#define IA struct in_addr /* ... should be taken out and shot, */
/* ... not that TLI is any better. sigh.. */
#define SLEAZE_PORT 31337 /* for UDP-scan RTT trick, change if ya want */
#define USHORT unsigned short /* use these for options an' stuff */
#define BIGSIZ 8192 /* big buffers */
#define SMALLSIZ 256 /* small buffers, hostnames, etc */
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
#ifdef MAXHOSTNAMELEN
#undef MAXHOSTNAMELEN /* might be too small on aix, so fix it */
#endif
#define MAXHOSTNAMELEN 256
struct host_poop {
char name[MAXHOSTNAMELEN]; /* dns name */
char addrs[8][24]; /* ascii-format IP addresses */
struct in_addr iaddrs[8]; /* real addresses: in_addr.s_addr: ulong */
};
#define HINF struct host_poop
struct port_poop {
char name [64]; /* name in /etc/services */
char anum [8]; /* ascii-format number */
USHORT num; /* real host-order number */
};
#define PINF struct port_poop
/* globals: */
jmp_buf jbuf; /* timer crud */
int jval = 0; /* timer crud */
int netfd = -1;
int ofd = 0; /* hexdump output fd */
static char unknown[] = "(UNKNOWN)";
static char p_tcp[] = "tcp"; /* for getservby* */
static char p_udp[] = "udp";
#ifndef WIN32
#ifdef HAVE_BIND
extern int h_errno;
#endif
#endif
int gatesidx = 0; /* LSRR hop count */
int gatesptr = 4; /* initial LSRR pointer, settable */
USHORT Single = 1; /* zero if scanning */
unsigned int insaved = 0; /* stdin-buffer size for multi-mode */
unsigned int wrote_out = 0; /* total stdout bytes */
unsigned int wrote_net = 0; /* total net bytes */
static char wrote_txt[] = " sent %d, rcvd %d";
static char hexnibs[20] = "0123456789abcdef ";
/* will malloc up the following globals: */
struct timeval * timer1 = NULL;
struct timeval * timer2 = NULL;
SAI * lclend = NULL; /* sockaddr_in structs */
SAI * remend = NULL;
HINF ** gates = NULL; /* LSRR hop hostpoop */
char * optbuf = NULL; /* LSRR or sockopts */
char * bigbuf_in; /* data buffers */
char * bigbuf_net;
fd_set * ding1; /* for select loop */
fd_set * ding2;
PINF * portpoop = NULL; /* for getportpoop / getservby* */
unsigned char * stage = NULL; /* hexdump line buffer */
#ifdef WIN32
char * setsockopt_c;
int nnetfd;
#endif
/* global cmd flags: */
USHORT o_alla = 0;
unsigned int o_interval = 0;
USHORT o_listen = 0;
USHORT o_nflag = 0;
USHORT o_wfile = 0;
USHORT o_random = 0;
USHORT o_udpmode = 0;
USHORT o_verbose = 0;
unsigned int o_wait = 0;
USHORT o_zero = 0;
/* Debug macro: squirt whatever to stderr and sleep a bit so we can see it go
by. need to call like Debug ((stuff)) [with no ; ] so macro args match!
Beware: writes to stdOUT... */
#ifdef DEBUG
#define Debug(x) printf x; printf ("\n"); fflush (stdout); sleep (1);
#else
#define Debug(x) /* nil... */
#endif
/* support routines -- the bulk of this thing. Placed in such an order that
we don't have to forward-declare anything: */
int helpme(); /* oop */
#ifdef WIN32
/* res_init
winsock needs to be initialized. Might as well do it as the res_init
call for Win32 */
void res_init()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
return;
/* Confirm that the Windows Sockets DLL supports 1.1.*/
/* Note that if the DLL supports versions greater */
/* than 1.1 in addition to 1.1, it will still return */
/* 1.1 in wVersion since that is the version we */
/* requested. */
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
WSACleanup();
return;
}
}
/* winsockstr
Windows Sockets cannot report errors through perror() so we need to define
our own error strings to print. Someday all the string should be prettied up.
Prettied the errors I usually get */
char * winsockstr(error)
int error;
{
switch (error)
{
case WSAEINTR : return("INTR ");
case WSAEBADF : return("BADF ");
case WSAEACCES : return("ACCES ");
case WSAEFAULT : return("FAULT ");
case WSAEINVAL : return("INVAL ");
case WSAEMFILE : return("MFILE ");
case WSAEWOULDBLOCK : return("WOULDBLOCK ");
case WSAEINPROGRESS : return("INPROGRESS ");
case WSAEALREADY : return("ALREADY ");
case WSAENOTSOCK : return("NOTSOCK ");
case WSAEDESTADDRREQ : return("DESTADDRREQ ");
case WSAEMSGSIZE : return("MSGSIZE ");
case WSAEPROTOTYPE : return("PROTOTYPE ");
case WSAENOPROTOOPT : return("NOPROTOOPT ");
case WSAEPROTONOSUPPORT: return("PROTONOSUPPORT");
case WSAESOCKTNOSUPPORT: return("SOCKTNOSUPPORT");
case WSAEOPNOTSUPP : return("OPNOTSUPP ");
case WSAEPFNOSUPPORT : return("PFNOSUPPORT ");
case WSAEAFNOSUPPORT : return("AFNOSUPPORT ");
case WSAEADDRINUSE : return("ADDRINUSE ");
case WSAEADDRNOTAVAIL : return("ADDRNOTAVAIL ");
case WSAENETDOWN : return("NETDOWN ");
case WSAENETUNREACH : return("NETUNREACH ");
case WSAENETRESET : return("NETRESET ");
case WSAECONNABORTED : return("CONNABORTED ");
case WSAECONNRESET : return("CONNRESET ");
case WSAENOBUFS : return("NOBUFS ");
case WSAEISCONN : return("ISCONN ");
case WSAENOTCONN : return("NOTCONN ");
case WSAESHUTDOWN : return("SHUTDOWN ");
case WSAETOOMANYREFS : return("TOOMANYREFS ");
case WSAETIMEDOUT : return("TIMEDOUT ");
case WSAECONNREFUSED : return("connection refused");
case WSAELOOP : return("LOOP ");
case WSAENAMETOOLONG : return("NAMETOOLONG ");
case WSAEHOSTDOWN : return("HOSTDOWN ");
case WSAEHOSTUNREACH : return("HOSTUNREACH ");
case WSAENOTEMPTY : return("NOTEMPTY ");
case WSAEPROCLIM : return("PROCLIM ");
case WSAEUSERS : return("USERS ");
case WSAEDQUOT : return("DQUOT ");
case WSAESTALE : return("STALE ");
case WSAEREMOTE : return("REMOTE ");
case WSAEDISCON : return("DISCON ");
case WSASYSNOTREADY : return("SYSNOTREADY ");
case WSAVERNOTSUPPORTED: return("VERNOTSUPPORTED");
case WSANOTINITIALISED : return("NOTINITIALISED ");
case WSAHOST_NOT_FOUND : return("HOST_NOT_FOUND ");
case WSATRY_AGAIN : return("TRY_AGAIN ");
case WSANO_RECOVERY : return("NO_RECOVERY ");
case WSANO_DATA : return("NO_DATA ");
default : return("unknown socket error");
}
}
#endif
/* holler :
fake varargs -- need to do this way because we wind up calling through
more levels of indirection than vanilla varargs can handle, and not all
machines have vfprintf/vsyslog/whatever! 6 params oughta be enough. */
void holler (str, p1, p2, p3, p4, p5, p6)
char * str;
char * p1, * p2, * p3, * p4, * p5, * p6;
{
if (o_verbose) {
fprintf (stderr, str, p1, p2, p3, p4, p5, p6);
#ifdef WIN32
if (h_errno)
fprintf (stderr, ": %s\n",winsockstr(h_errno));
#else
if (errno) { /* this gives funny-looking messages, but */
perror (" "); /* it's more portable than sys_errlist[]... */
} /* xxx: do something better. */
#endif
else
fprintf (stderr, "\n");
fflush (stderr);
}
} /* holler */
/* bail :
error-exit handler, callable from anywhere */
void bail (str, p1, p2, p3, p4, p5, p6)
char * str;
char * p1, * p2, * p3, * p4, * p5, * p6;
{
o_verbose = 1;
holler (str, p1, p2, p3, p4, p5, p6);
#ifdef WIN32
closesocket (netfd);
#else
close (netfd);
#endif
sleep (1);
exit (1);
} /* bail */
/* catch :
no-brainer interrupt handler */
void catch ()
{
errno = 0;
if (o_verbose > 1) /* normally we don't care */
bail (wrote_txt, wrote_net, wrote_out);
bail (" punt!");
}
/* timeout and other signal handling cruft */
void tmtravel ()
{
#ifdef NTFIXTHIS
signal (SIGALRM, SIG_IGN);
alarm (0);
#endif
if (jval == 0)
bail ("spurious timer interrupt!");
longjmp (jbuf, jval);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -