add IPv6 patch
This commit is contained in:
parent
9274c7d458
commit
3807536449
|
@ -286,6 +286,7 @@ There's a BIG swamp lurking where network code of any sort lives.
|
|||
#undef HAVE_TTYENT_H
|
||||
#define HAVE_SIGSETJMP
|
||||
#define HAVE_SOCKLEN_T
|
||||
#define INET6
|
||||
#endif /* linux */
|
||||
|
||||
/* irix 5.x; may not be correct for earlier ones */
|
||||
|
|
550
netcat.c
550
netcat.c
|
@ -86,6 +86,12 @@
|
|||
#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.. */
|
||||
#ifdef INET6
|
||||
#define SS struct sockaddr
|
||||
#define SAI6 struct sockaddr_in6
|
||||
#define IA6 struct in6_addr
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
|
@ -117,6 +123,15 @@ struct host_poop {
|
|||
};
|
||||
#define HINF struct host_poop
|
||||
|
||||
#ifdef INET6
|
||||
struct host6_poop {
|
||||
char name[MAXHOSTNAMELEN]; /* dns name */
|
||||
char addrs[8][64]; /* ascii-format IP addresses */
|
||||
struct in6_addr iaddrs[8]; /* real addresses: in_addr.s_addr: ulong */
|
||||
};
|
||||
#define HINF6 struct host6_poop
|
||||
#endif
|
||||
|
||||
struct port_poop {
|
||||
char name [64]; /* name in /etc/services */
|
||||
USHORT num; /* real host-order number */
|
||||
|
@ -156,6 +171,10 @@ static char hexnibs[20] = "0123456789abcdef ";
|
|||
/* will malloc up the following globals: */
|
||||
struct timeval * timer1 = NULL;
|
||||
struct timeval * timer2 = NULL;
|
||||
#ifdef INET6
|
||||
SAI6 * lclend6 = NULL; /* sockaddr_in6 structs */
|
||||
SAI6 * remend6 = NULL;
|
||||
#endif
|
||||
SAI * lclend = NULL; /* sockaddr_in structs */
|
||||
SAI * remend = NULL;
|
||||
HINF ** gates = NULL; /* LSRR hop hostpoop */
|
||||
|
@ -349,6 +368,40 @@ int comparehosts (poop, hp)
|
|||
/* ... do we need to do anything over and above that?? */
|
||||
} /* comparehosts */
|
||||
|
||||
#ifdef INET6
|
||||
char *inet_ntoa6 (struct in6_addr *s)
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
if (IN6_IS_ADDR_V4MAPPED(s))
|
||||
inet_ntop (AF_INET, s+12, buf, sizeof (buf));
|
||||
else
|
||||
inet_ntop (AF_INET6, s, buf, sizeof (buf));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int comparehosts6 (poop, hp)
|
||||
HINF6 * poop;
|
||||
struct hostent * hp;
|
||||
{
|
||||
errno = 0;
|
||||
h_errno = 0;
|
||||
/* The DNS spec is officially case-insensitive, but for those times when you
|
||||
*really* wanna see any and all discrepancies, by all means define this. */
|
||||
#ifdef ANAL
|
||||
if (strcmp (poop->name, hp->h_name) != 0) { /* case-sensitive */
|
||||
#else
|
||||
if (strcasecmp (poop->name, hp->h_name) != 0) { /* normal */
|
||||
#endif
|
||||
holler ("DNS fwd/rev mismatch: %s != %s", poop->name, hp->h_name);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
/* ... do we need to do anything over and above that?? */
|
||||
} /* comparehosts */
|
||||
#endif
|
||||
|
||||
/* gethostpoop :
|
||||
resolve a host 8 ways from sunday; return a new host_poop struct with its
|
||||
info. The argument can be a name or [ascii] IP address; it will try its
|
||||
|
@ -447,6 +500,82 @@ HINF * gethostpoop (name, numeric)
|
|||
return (poop);
|
||||
} /* gethostpoop */
|
||||
|
||||
#ifdef INET6
|
||||
HINF6 * gethost6poop (name, numeric)
|
||||
char *name;
|
||||
USHORT numeric;
|
||||
{
|
||||
struct hostent *hostent;
|
||||
struct in6_addr iaddr;
|
||||
register HINF6 *poop = NULL;
|
||||
register int x;
|
||||
|
||||
/* If we want to see all the DNS stuff, do the following hair --
|
||||
if inet_addr, do reverse and forward with any warnings; otherwise try
|
||||
to do forward and reverse with any warnings. In other words, as long
|
||||
as we're here, do a complete DNS check on these clowns. Yes, it slows
|
||||
things down a bit for a first run, but once it's cached, who cares? */
|
||||
|
||||
errno = 0;
|
||||
h_errno = 0;
|
||||
if (name)
|
||||
poop = (HINF6 *) Hmalloc (sizeof (HINF6));
|
||||
if (!poop)
|
||||
bail ("gethost6poop fuxored");
|
||||
strcpy (poop->name, unknown); /* preload it */
|
||||
|
||||
if (! inet_pton (AF_INET6, name, &iaddr)) { /* here's the great split: names... */
|
||||
if (numeric)
|
||||
bail ("Can't parse %s as an IP address", name);
|
||||
hostent = gethostbyname2 (name, AF_INET6);
|
||||
if (!hostent)
|
||||
/* failure to look up a name is fatal, since we can't do anything with it */
|
||||
bail ("%s: forward host lookup failed: ", name);
|
||||
strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
|
||||
for (x = 0; hostent->h_addr_list[x] && (x < 8); x++) {
|
||||
memcpy (&poop->iaddrs[x], hostent->h_addr_list[x], sizeof (IA6));
|
||||
strncpy (poop->addrs[x], inet_ntoa6 (&poop->iaddrs[x]), sizeof (poop->addrs[0]));
|
||||
} /* for x -> addrs, part A */
|
||||
if (!o_verbose) /* if we didn't want to see the */
|
||||
return (poop); /* inverse stuff, we're done. */
|
||||
/* do inverse lookups in separate loop based on our collected forward addrs,
|
||||
since gethostby* tends to crap into the same buffer over and over */
|
||||
for (x = 0; !IN6_IS_ADDR_UNSPECIFIED(&poop->iaddrs[x]) && (x < 8); x++) {
|
||||
hostent = gethostbyaddr ((char *) &poop->iaddrs[x], sizeof (IA6), AF_INET6);
|
||||
if (!hostent || !hostent->h_name)
|
||||
holler ("Warning: inverse host lookup failed for %s: ", poop->addrs[x]);
|
||||
else
|
||||
(void) comparehosts6 (poop, hostent);
|
||||
} /* for x -> addrs, part B */
|
||||
|
||||
} else { /* not INADDR_NONE: numeric addresses... */
|
||||
inet_ntop (AF_INET6, &iaddr, poop->addrs[0], sizeof (poop->addrs[0]));
|
||||
memcpy (poop->iaddrs, &iaddr, sizeof (IA6));
|
||||
if (numeric) /* if numeric-only, we're done */
|
||||
return (poop);
|
||||
if (!o_verbose) /* likewise if we don't want */
|
||||
return (poop); /* the full DNS hair */
|
||||
hostent = gethostbyaddr ((char *) &iaddr, sizeof (IA6), AF_INET6);
|
||||
/* numeric or not, failure to look up a PTR is *not* considered fatal */
|
||||
if (!hostent)
|
||||
holler ("%s: inverse host lookup failed: ", name);
|
||||
else {
|
||||
strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
|
||||
hostent = gethostbyname2 (poop->name, AF_INET6);
|
||||
if (!hostent || !hostent->h_addr_list[0])
|
||||
holler ("Warning: forward host lookup failed for %s: ", poop->name);
|
||||
else
|
||||
(void) comparehosts6 (poop, hostent);
|
||||
} /* if hostent */
|
||||
} /* INADDR_NONE Great Split */
|
||||
|
||||
/* whatever-all went down previously, we should now have a host_poop struct
|
||||
with at least one IP address in it. */
|
||||
h_errno = 0;
|
||||
return (poop);
|
||||
} /* gethost6poop */
|
||||
#endif
|
||||
|
||||
/* getportpoop :
|
||||
Same general idea as gethostpoop -- look up a port in /etc/services, fill
|
||||
in global port_poop, but return the actual port *number*. Pass ONE of:
|
||||
|
@ -982,9 +1111,9 @@ dol_noop:
|
|||
x = 1;
|
||||
if (x) /* guilty! */
|
||||
bail ("invalid connection to [%s] from %s [%s] %d",
|
||||
cp, whozis->name, whozis->addrs[0], z);
|
||||
cp, whozis->name, whozis->addrs[0], z);
|
||||
holler ("connect to [%s] from %s [%s] %d", /* oh, you're okay.. */
|
||||
cp, whozis->name, whozis->addrs[0], z);
|
||||
cp, whozis->name, whozis->addrs[0], z);
|
||||
return (nnetfd); /* open! */
|
||||
|
||||
dol_tmo:
|
||||
|
@ -1038,6 +1167,305 @@ udptest (fd, where)
|
|||
return (-1);
|
||||
} /* udptest */
|
||||
|
||||
#ifdef INET6
|
||||
/* doconnect6 :
|
||||
do all the socket stuff, and return an fd for one of
|
||||
an open outbound TCP connection
|
||||
a UDP stub-socket thingie
|
||||
with appropriate socket options set up if we wanted source-routing, or
|
||||
an unconnected TCP or UDP socket to listen on.
|
||||
Examines various global o_blah flags to figure out what-all to do. */
|
||||
int doconnect6 (rad, rp, lad, lp)
|
||||
IA6 *rad;
|
||||
USHORT rp;
|
||||
IA6 *lad;
|
||||
USHORT lp;
|
||||
{
|
||||
register int nnetfd;
|
||||
register int rr;
|
||||
int x, y;
|
||||
errno = 0;
|
||||
|
||||
/* grab a socket; set opts */
|
||||
newskt:
|
||||
if (o_udpmode)
|
||||
nnetfd = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
else
|
||||
nnetfd = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (nnetfd < 0)
|
||||
bail ("Can't get socket");
|
||||
if (nnetfd == 0) /* if stdin was closed this might *be* 0, */
|
||||
goto newskt; /* so grab another. See text for why... */
|
||||
x = 1;
|
||||
rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
|
||||
if (rr == -1)
|
||||
holler ("nnetfd reuseaddr failed"); /* ??? */
|
||||
#ifdef SO_REUSEPORT /* doesnt exist everywhere... */
|
||||
rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
|
||||
if (rr == -1)
|
||||
holler ("nnetfd reuseport failed"); /* ??? */
|
||||
#endif
|
||||
#if 0
|
||||
/* If you want to screw with RCVBUF/SNDBUF, do it here. Liudvikas Bukys at
|
||||
Rochester sent this example, which would involve YET MORE options and is
|
||||
just archived here in case you want to mess with it. o_xxxbuf are global
|
||||
integers set in main() getopt loop, and check for rr == 0 afterward. */
|
||||
rr = setsockopt (nnetfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
|
||||
rr = setsockopt (nnetfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);
|
||||
#endif
|
||||
|
||||
/* fill in all the right sockaddr crud */
|
||||
lclend6->sin6_family = AF_INET6;
|
||||
remend6->sin6_family = AF_INET6;
|
||||
|
||||
/* if lad/lp, do appropriate binding */
|
||||
if (lad)
|
||||
memcpy (&lclend6->sin6_addr, lad, sizeof (IA6));
|
||||
else
|
||||
memcpy (&lclend6->sin6_addr, &in6addr_any, sizeof (IA6));
|
||||
if (lp)
|
||||
lclend6->sin6_port = htons (lp);
|
||||
rr = 0;
|
||||
if (lad || lp) {
|
||||
x = (int) lp;
|
||||
/* try a few times for the local bind, a la ftp-data-port... */
|
||||
for (y = 4; y > 0; y--) {
|
||||
rr = bind (nnetfd, (SA *) lclend6, sizeof (SAI6));
|
||||
if (rr == 0)
|
||||
break;
|
||||
if (errno != EADDRINUSE)
|
||||
break;
|
||||
else {
|
||||
holler ("retrying local %s:%d", inet_ntoa6 (&lclend6->sin6_addr), lp);
|
||||
sleep (2);
|
||||
errno = 0; /* clear from sleep */
|
||||
} /* if EADDRINUSE */
|
||||
} /* for y counter */
|
||||
} /* if lad or lp */
|
||||
if (rr)
|
||||
bail ("Can't grab %s:%d with bind", inet_ntoa6 (&lclend6->sin6_addr), lp);
|
||||
|
||||
if (o_listen)
|
||||
return (nnetfd); /* thanks, that's all for today */
|
||||
|
||||
memcpy (&remend6->sin6_addr, rad, sizeof (IA6));
|
||||
remend6->sin6_port = htons (rp);
|
||||
|
||||
if (gatesidx) { /* if we wanted any srcrt hops ... */
|
||||
holler ("Warning: source routing unavailable on this machine, ignoring");
|
||||
}
|
||||
|
||||
/* if gatesidx */
|
||||
/* wrap connect inside a timer, and hit it */
|
||||
arm_timer (1, o_wait);
|
||||
if (setjmp (jbuf) == 0) {
|
||||
rr = connect (nnetfd, (SA *) remend6, sizeof (SAI6));
|
||||
} else { /* setjmp: connect failed... */
|
||||
rr = -1;
|
||||
errno = ETIMEDOUT; /* fake it */
|
||||
}
|
||||
arm_timer (0, 0);
|
||||
if (rr == 0)
|
||||
return (nnetfd);
|
||||
close (nnetfd); /* clean up junked socket FD!! */
|
||||
return (-1);
|
||||
} /* doconnect6 */
|
||||
|
||||
/* dolisten6 :
|
||||
just like doconnect6, and in fact calls a hunk of doconnect6, but listens for
|
||||
incoming and returns an open connection *from* someplace. If we were
|
||||
given host/port args, any connections from elsewhere are rejected. This
|
||||
in conjunction with local-address binding should limit things nicely... */
|
||||
int dolisten6 (rad, rp, lad, lp)
|
||||
IA6 *rad;
|
||||
USHORT rp;
|
||||
IA6 *lad;
|
||||
USHORT lp;
|
||||
{
|
||||
register int nnetfd;
|
||||
register int rr;
|
||||
HINF6 *whozis = NULL;
|
||||
socklen_t x;
|
||||
char *cp;
|
||||
USHORT z;
|
||||
errno = 0;
|
||||
|
||||
/* Pass everything off to doconnect6, who in o_listen mode just gets a socket */
|
||||
nnetfd = doconnect6 (rad, rp, lad, lp);
|
||||
if (nnetfd <= 0)
|
||||
return (-1);
|
||||
if (o_udpmode) { /* apparently UDP can listen ON */
|
||||
if (!lp) /* "port 0", but that's not useful */
|
||||
bail ("UDP listen needs -p arg");
|
||||
} else {
|
||||
rr = listen (nnetfd, 1); /* gotta listen() before we can get */
|
||||
if (rr < 0) /* our local random port. sheesh. */
|
||||
bail ("local listen fuxored");
|
||||
}
|
||||
|
||||
/* Various things that follow temporarily trash bigbuf_net, which might contain
|
||||
a copy of any recvfrom()ed packet, but we'll read() another copy later. */
|
||||
|
||||
/* I can't believe I have to do all this to get my own goddamn bound address
|
||||
and port number. It should just get filled in during bind() or something.
|
||||
All this is only useful if we didn't say -p for listening, since if we
|
||||
said -p we *know* what port we're listening on. At any rate we won't bother
|
||||
with it all unless we wanted to see it, although listening quietly on a
|
||||
random unknown port is probably not very useful without "netstat". */
|
||||
if (o_verbose) {
|
||||
x = sizeof (SAI6); /* how 'bout getsockNUM instead, pinheads?! */
|
||||
rr = getsockname (nnetfd, (SA *) lclend6, &x);
|
||||
if (rr < 0)
|
||||
holler ("local getsockname failed");
|
||||
strcpy (bigbuf_net, "listening on ["); /* buffer reuse... */
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&lclend6->sin6_addr))
|
||||
strcat (bigbuf_net, inet_ntoa6 (&lclend6->sin6_addr));
|
||||
else
|
||||
strcat (bigbuf_net, "any");
|
||||
strcat (bigbuf_net, "] %d ...");
|
||||
z = ntohs (lclend6->sin6_port);
|
||||
holler (bigbuf_net, z);
|
||||
}
|
||||
|
||||
/* verbose -- whew!! */
|
||||
/* UDP is a speeeeecial case -- we have to do I/O *and* get the calling
|
||||
party's particulars all at once, listen() and accept() don't apply.
|
||||
At least in the BSD universe, however, recvfrom/PEEK is enough to tell
|
||||
us something came in, and we can set things up so straight read/write
|
||||
actually does work after all. Yow. YMMV on strange platforms! */
|
||||
if (o_udpmode) {
|
||||
x = sizeof (SAI6); /* retval for recvfrom */
|
||||
arm_timer (2, o_wait); /* might as well timeout this, too */
|
||||
if (setjmp (jbuf) == 0) { /* do timeout for initial connect */
|
||||
/* and here we block... */
|
||||
rr = recvfrom (nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend6, &x);
|
||||
Debug (("dolisten/recvfrom ding, rr = %d, netbuf %s ",
|
||||
rr, bigbuf_net))
|
||||
} else
|
||||
goto dol_tmo; /* timeout */
|
||||
arm_timer (0, 0);
|
||||
/* I'm not completely clear on how this works -- BSD seems to make UDP
|
||||
just magically work in a connect()ed context, but we'll undoubtedly run
|
||||
into systems this deal doesn't work on. For now, we apparently have to
|
||||
issue a connect() on our just-tickled socket so we can write() back.
|
||||
Again, why the fuck doesn't it just get filled in and taken care of?!
|
||||
This hack is anything but optimal. Basically, if you want your listener
|
||||
to also be able to send data back, you need this connect() line, which
|
||||
also has the side effect that now anything from a different source or even a
|
||||
different port on the other end won't show up and will cause ICMP errors.
|
||||
I guess that's what they meant by "connect".
|
||||
Let's try to remember what the "U" is *really* for, eh? */
|
||||
rr = connect (nnetfd, (SA *) remend6, sizeof (SAI6));
|
||||
goto whoisit;
|
||||
}
|
||||
|
||||
/* o_udpmode */
|
||||
/* fall here for TCP */
|
||||
x = sizeof (SAI6); /* retval for accept */
|
||||
arm_timer (2, o_wait); /* wrap this in a timer, too; 0 = forever */
|
||||
if (setjmp (jbuf) == 0) {
|
||||
rr = accept (nnetfd, (SA *) remend6, &x);
|
||||
} else
|
||||
goto dol_tmo; /* timeout */
|
||||
arm_timer (0, 0);
|
||||
close (nnetfd); /* dump the old socket */
|
||||
nnetfd = rr; /* here's our new one */
|
||||
|
||||
whoisit:
|
||||
if (rr < 0)
|
||||
goto dol_err; /* bail out if any errors so far */
|
||||
|
||||
/* find out what address the connection was *to* on our end, in case we're
|
||||
doing a listen-on-any on a multihomed machine. This allows one to
|
||||
offer different services via different alias addresses, such as the
|
||||
"virtual web site" hack. */
|
||||
memset (bigbuf_net, 0, 64);
|
||||
cp = &bigbuf_net[32];
|
||||
x = sizeof (SAI6);
|
||||
rr = getsockname (nnetfd, (SA *) lclend6, &x);
|
||||
if (rr < 0)
|
||||
holler ("post-rcv getsockname failed");
|
||||
strcpy (cp, inet_ntoa6 (&lclend6->sin6_addr));
|
||||
|
||||
/* now check out who it is. We don't care about mismatched DNS names here,
|
||||
but any ADDR and PORT we specified had better fucking well match the caller.
|
||||
Converting from addr to inet_ntoa and back again is a bit of a kludge, but
|
||||
gethostpoop wants a string and there's much gnarlier code out there already,
|
||||
so I don't feel bad.
|
||||
The *real* question is why BFD sockets wasn't designed to allow listens for
|
||||
connections *from* specific hosts/ports, instead of requiring the caller to
|
||||
accept the connection and then reject undesireable ones by closing. In
|
||||
other words, we need a TCP MSG_PEEK. */
|
||||
z = ntohs (remend6->sin6_port);
|
||||
strcpy (bigbuf_net, inet_ntoa6 (&remend6->sin6_addr));
|
||||
whozis = gethost6poop (bigbuf_net, o_nflag);
|
||||
errno = 0;
|
||||
x = 0; /* use as a flag... */
|
||||
if (rad) /* xxx: fix to go down the *list* if we have one? */
|
||||
if (memcmp (rad, whozis->iaddrs, sizeof (SAI6)))
|
||||
x = 1;
|
||||
if (rp)
|
||||
if (z != rp)
|
||||
x = 1;
|
||||
if (x) /* guilty! */
|
||||
bail ("invalid connection to [%s] from %s [%s] %d",
|
||||
cp, whozis->name, whozis->addrs[0], z);
|
||||
holler ("connect to [%s] from %s [%s] %d", /* oh, you're okay.. */
|
||||
cp, whozis->name, whozis->addrs[0], z);
|
||||
return (nnetfd); /* open! */
|
||||
|
||||
dol_tmo:
|
||||
errno = ETIMEDOUT; /* fake it */
|
||||
dol_err:
|
||||
close (nnetfd);
|
||||
return (-1);
|
||||
} /* dolisten */
|
||||
|
||||
/* udptest :
|
||||
fire a couple of packets at a UDP target port, just to see if it's really
|
||||
there. On BSD kernels, ICMP host/port-unreachable errors get delivered to
|
||||
our socket as ECONNREFUSED write errors. On SV kernels, we lose; we'll have
|
||||
to collect and analyze raw ICMP ourselves a la satan's probe_udp_ports
|
||||
backend. Guess where one could swipe the appropriate code from...
|
||||
|
||||
Use the time delay between writes if given, otherwise use the "tcp ping"
|
||||
trick for getting the RTT. [I got that idea from pluvius, and warped it.]
|
||||
Return either the original fd, or clean up and return -1. */
|
||||
int
|
||||
udptest6 (fd, where)
|
||||
int fd;
|
||||
IA6 *where;
|
||||
{
|
||||
register int rr;
|
||||
|
||||
rr = write (fd, bigbuf_in, 1);
|
||||
if (rr != 1)
|
||||
holler ("udptest first write failed?! errno %d", errno);
|
||||
if (o_wait)
|
||||
sleep (o_wait);
|
||||
else {
|
||||
/* use the tcp-ping trick: try connecting to a normally refused port, which
|
||||
causes us to block for the time that SYN gets there and RST gets back.
|
||||
Not completely reliable, but it *does* mostly work. */
|
||||
o_udpmode = 0; /* so doconnect6 does TCP this time */
|
||||
/* Set a temporary connect timeout, so packet filtration doesnt cause
|
||||
us to hang forever, and hit it */
|
||||
o_wait = 5; /* enough that we'll notice?? */
|
||||
rr = doconnect6 (where, SLEAZE_PORT, 0, 0);
|
||||
if (rr > 0)
|
||||
close (rr); /* in case it *did* open */
|
||||
o_wait = 0; /* reset it */
|
||||
o_udpmode++; /* we *are* still doing UDP, right? */
|
||||
} /* if o_wait */
|
||||
errno = 0; /* clear from sleep */
|
||||
rr = write (fd, bigbuf_in, 1);
|
||||
if (rr == 1) /* if write error, no UDP listener */
|
||||
return (fd);
|
||||
close (fd); /* use it or lose it! */
|
||||
return (-1);
|
||||
} /* udptest */
|
||||
#endif
|
||||
|
||||
/* oprint :
|
||||
Hexdump bytes shoveled either way to a running logfile, in the format:
|
||||
D offset - - - - --- 16 bytes --- - - - - # .... ascii .....
|
||||
|
@ -1385,6 +1813,8 @@ options:");
|
|||
-e filename program to exec after connect [dangerous!!]");
|
||||
#endif
|
||||
holler ("\
|
||||
-4 Use IPv4 (default)\n\
|
||||
-6 Use IPv6\n\
|
||||
-b allow broadcasts\n\
|
||||
-g gateway source-routing hop point[s], up to 8\n\
|
||||
-G num source-routing pointer: 4, 8, 12, ...\n\
|
||||
|
@ -1428,6 +1858,13 @@ main (argc, argv)
|
|||
HINF * wherefrom = NULL;
|
||||
IA * ouraddr = NULL;
|
||||
IA * themaddr = NULL;
|
||||
#ifdef INET6
|
||||
HINF6 * whereto6 = NULL;
|
||||
HINF6 * wherefrom6 = NULL;
|
||||
IA6 * ouraddr6 = NULL;
|
||||
IA6 * themaddr6 = NULL;
|
||||
int want6 = 0;
|
||||
#endif
|
||||
USHORT o_lport = 0;
|
||||
USHORT ourport = 0;
|
||||
USHORT loport = 0; /* for scanning stuff */
|
||||
|
@ -1443,6 +1880,10 @@ main (argc, argv)
|
|||
/* round up the usual suspects, i.e. malloc up all the stuff we need */
|
||||
lclend = (SAI *) Hmalloc (sizeof (SA));
|
||||
remend = (SAI *) Hmalloc (sizeof (SA));
|
||||
#ifdef INET6
|
||||
lclend6 = (SAI6 *) Hmalloc (sizeof (SS));
|
||||
remend6 = (SAI6 *) Hmalloc (sizeof (SS));
|
||||
#endif
|
||||
bigbuf_in = Hmalloc (BIGSIZ);
|
||||
bigbuf_net = Hmalloc (BIGSIZ);
|
||||
ding1 = (fd_set *) Hmalloc (sizeof (fd_set));
|
||||
|
@ -1511,9 +1952,17 @@ main (argc, argv)
|
|||
|
||||
/* If your shitbox doesn't have getopt, step into the nineties already. */
|
||||
/* optarg, optind = next-argv-component [i.e. flag arg]; optopt = last-char */
|
||||
while ((x = getopt (argc, argv, "abc:e:g:G:hi:lno:p:q:rs:tuvw:z")) != EOF) {
|
||||
while ((x = getopt (argc, argv, "46abc:e:g:G:hi:lno:p:q:rs:tuvw:z")) != EOF) {
|
||||
/* Debug (("in go: x now %c, optarg %x optind %d", x, optarg, optind)) */
|
||||
switch (x) {
|
||||
#ifdef INET6
|
||||
case '4':
|
||||
want6 = 0;
|
||||
break;
|
||||
case '6':
|
||||
want6 = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'a':
|
||||
bail ("all-A-records NIY");
|
||||
o_alla++; break;
|
||||
|
@ -1578,8 +2027,16 @@ main (argc, argv)
|
|||
/* do a full lookup [since everything else goes through the same mill],
|
||||
unless -n was previously specified. In fact, careful placement of -n can
|
||||
be useful, so we'll still pass o_nflag here instead of forcing numeric. */
|
||||
wherefrom = gethostpoop (optarg, o_nflag);
|
||||
ouraddr = &wherefrom->iaddrs[0];
|
||||
#ifdef INET6
|
||||
if (want6) {
|
||||
wherefrom6 = gethost6poop (optarg, o_nflag);
|
||||
ouraddr6 = &wherefrom6->iaddrs[0];
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
wherefrom = gethostpoop (optarg, o_nflag);
|
||||
ouraddr = &wherefrom->iaddrs[0];
|
||||
}
|
||||
break;
|
||||
#ifdef TELNET
|
||||
case 't': /* do telnet fakeout */
|
||||
|
@ -1633,12 +2090,24 @@ Debug (("after go: x now %c, optarg %x optind %d", x, optarg, optind))
|
|||
/* gonna only use first addr of host-list, like our IQ was normal; if you wanna
|
||||
get fancy with addresses, look up the list yourself and plug 'em in for now.
|
||||
unless we finally implement -a, that is. */
|
||||
if (argv[optind])
|
||||
whereto = gethostpoop (argv[optind], o_nflag);
|
||||
if (whereto && whereto->iaddrs)
|
||||
themaddr = &whereto->iaddrs[0];
|
||||
if (themaddr)
|
||||
optind++; /* skip past valid host lookup */
|
||||
if (argv[optind]) {
|
||||
#ifdef INET6
|
||||
if (want6) {
|
||||
whereto6 = gethost6poop (argv[optind], o_nflag);
|
||||
if (whereto6 && whereto6->iaddrs)
|
||||
themaddr6 = &whereto6->iaddrs[0];
|
||||
if (themaddr6)
|
||||
optind++; /* skip past valid host lookup */
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
whereto = gethostpoop (argv[optind], o_nflag);
|
||||
if (whereto && whereto->iaddrs)
|
||||
themaddr = &whereto->iaddrs[0];
|
||||
if (themaddr)
|
||||
optind++; /* skip past valid host lookup */
|
||||
}
|
||||
}
|
||||
errno = 0;
|
||||
h_errno = 0;
|
||||
|
||||
|
@ -1653,7 +2122,12 @@ Debug (("after go: x now %c, optarg %x optind %d", x, optarg, optind))
|
|||
if (curport == 0) /* if given, demand correctness */
|
||||
bail ("invalid port %s", argv[optind]);
|
||||
} /* if port-arg */
|
||||
netfd = dolisten (themaddr, curport, ouraddr, o_lport);
|
||||
#ifdef INET6
|
||||
if (want6)
|
||||
netfd = dolisten6 (themaddr6, curport, ouraddr6, o_lport);
|
||||
else
|
||||
#endif
|
||||
netfd = dolisten (themaddr, curport, ouraddr, o_lport);
|
||||
/* dolisten does its own connect reporting, so we don't holler anything here */
|
||||
if (netfd > 0) {
|
||||
#ifdef GAPING_SECURITY_HOLE
|
||||
|
@ -1672,8 +2146,16 @@ Debug (("after go: x now %c, optarg %x optind %d", x, optarg, optind))
|
|||
} /* o_listen */
|
||||
|
||||
/* fall thru to outbound connects. Now we're more picky about args... */
|
||||
if (! themaddr)
|
||||
bail ("no destination");
|
||||
#ifdef INET6
|
||||
if (want6) {
|
||||
if (! themaddr6)
|
||||
bail ("no destination");
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (! themaddr)
|
||||
bail ("no destination");
|
||||
}
|
||||
if (argv[optind] == NULL)
|
||||
bail ("no port[s] to connect to");
|
||||
if (argv[optind + 1]) /* look ahead: any more port args given? */
|
||||
|
@ -1716,15 +2198,32 @@ Debug (("Single %d, curport %d", Single, curport))
|
|||
ourport += 8192; /* if it *still* conflicts, use -s. */
|
||||
}
|
||||
curport = getportpoop (NULL, curport);
|
||||
netfd = doconnect (themaddr, curport, ouraddr, ourport);
|
||||
#ifdef INET6
|
||||
if (want6)
|
||||
netfd = doconnect6 (themaddr6, curport, ouraddr6, ourport);
|
||||
else
|
||||
#endif
|
||||
netfd = doconnect (themaddr, curport, ouraddr, ourport);
|
||||
Debug (("netfd %d from port %d to port %d", netfd, ourport, curport))
|
||||
if (netfd > 0)
|
||||
if (o_zero && o_udpmode) /* if UDP scanning... */
|
||||
netfd = udptest (netfd, themaddr);
|
||||
if (o_zero && o_udpmode) { /* if UDP scanning... */
|
||||
#ifdef INET6
|
||||
if (want6)
|
||||
netfd = udptest6 (netfd, themaddr6);
|
||||
else
|
||||
#endif
|
||||
netfd = udptest (netfd, themaddr);
|
||||
}
|
||||
if (netfd > 0) { /* Yow, are we OPEN YET?! */
|
||||
x = 0; /* pre-exit status */
|
||||
holler ("%s [%s] %d (%s) open",
|
||||
whereto->name, whereto->addrs[0], curport, portpoop->name);
|
||||
#ifdef INET6
|
||||
if (want6)
|
||||
holler ("%s [%s] %d (%s) open",
|
||||
whereto6->name, whereto6->addrs[0], curport, portpoop->name);
|
||||
else
|
||||
#endif
|
||||
holler ("%s [%s] %d (%s) open",
|
||||
whereto->name, whereto->addrs[0], curport, portpoop->name);
|
||||
#ifdef GAPING_SECURITY_HOLE
|
||||
if (pr00gie) /* exec is valid for outbound, too */
|
||||
doexec (netfd);
|
||||
|
@ -1735,9 +2234,16 @@ Debug (("netfd %d from port %d to port %d", netfd, ourport, curport))
|
|||
x = 1; /* preload exit status for later */
|
||||
/* if we're scanning at a "one -v" verbosity level, don't print refusals.
|
||||
Give it another -v if you want to see everything. */
|
||||
if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED))
|
||||
holler ("%s [%s] %d (%s)",
|
||||
whereto->name, whereto->addrs[0], curport, portpoop->name);
|
||||
if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED)) {
|
||||
#ifdef INET6
|
||||
if (want6)
|
||||
holler ("%s [%s] %d (%s)",
|
||||
whereto6->name, whereto6->addrs[0], curport, portpoop->name);
|
||||
else
|
||||
#endif
|
||||
holler ("%s [%s] %d (%s)",
|
||||
whereto->name, whereto->addrs[0], curport, portpoop->name);
|
||||
}
|
||||
} /* if netfd */
|
||||
close (netfd); /* just in case we didn't already */
|
||||
if (o_interval)
|
||||
|
|
Loading…
Reference in New Issue