/* icmp netmask request: useful but sadly appears to be widely blocked */
#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <ip.h>
#include <bio.h>
#include <ndb.h>
#include "/sys/src/cmd/ip/icmp.h"
enum {
IPV4MASK_LEN = 4
};
static int Timeout = 0;
static uchar loopbacknet[IPaddrlen] = {
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0xff, 0xff,
127, 0, 0, 0
};
static uchar loopbackmask[IPaddrlen] = {
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0, 0, 0
};
/*
* find first ip addr suitable for proto and
* that isn't the friggin loopback address.
* deprecate link-local and multicast addresses.
*/
static int
myipvnaddr(uchar *ip, char *net)
{
Ipifc *nifc;
Iplifc *lifc;
uchar mynet[IPaddrlen], linklocal[IPaddrlen];
static Ipifc *ifc;
ipmove(linklocal, IPnoaddr);
ifc = readipifc(net, ifc, -1);
for(nifc = ifc; nifc; nifc = nifc->next)
for(lifc = nifc->lifc; lifc; lifc = lifc->next){
maskip(lifc->ip, loopbackmask, mynet);
if(ipcmp(mynet, loopbacknet) == 0)
continue;
if(ISIPV6MCAST(lifc->ip) || ISIPV6LINKLOCAL(lifc->ip)) {
ipmove(linklocal, lifc->ip);
continue;
}
if(ipcmp(lifc->ip, IPnoaddr) != 0){
ipmove(ip, lifc->ip);
return 0;
}
}
/* no global unicast addrs found, fall back to link-local, if any */
ipmove(ip, linklocal);
return ipcmp(ip, IPnoaddr) == 0? -1: 0;
}
Icmphdr *
geticmp(void *v)
{
char *p = v;
return (Icmphdr *)(p + IPV4HDR_LEN);
}
static void
ding(void *a, char *msg)
{
USED(a);
if(strstr(msg, "alarm")){
Timeout = 1;
noted(NCONT);
}
else if(strstr(msg, "die"))
exits("errors");
else
noted(NDFLT);
}
void
main(int argc, char *argv[])
{
char *ds;
int n, msglen, fd;
Icmphdr *icmp;
char buf[64*1024+512];
uchar me[IPaddrlen], mev4[IPv4addrlen];
ARGBEGIN{
}ARGEND
if(argc != 1){
fprint(2, "usage: %s host\n", argv0);
exits("usage");
}
ds = netmkaddr(argv[0], "icmp", "1");
if((fd = dial(ds, 0, 0, 0)) == -1)
sysfatal("dial(%s) failed - %r\n", argv[0]);
icmp = geticmp(buf);
msglen = IPV4HDR_LEN + ICMP_HDRSIZE + IPV4MASK_LEN;
memset(buf, 0, msglen);
icmp->type = AddrMaskRequest;
icmp->code = 0;
myipvnaddr(me, "/net");
v6tov4(mev4, me);
memmove(((Ip4hdr *)buf)->src, mev4, IPv4addrlen);
memset(icmp->data, 0x5a, IPv4addrlen);
notify(ding);
alarm(2000);
if(write(fd, buf, msglen) < msglen)
sysfatal("write failed: %r\n");
n = read(fd, buf, sizeof buf);
if(Timeout)
sysfatal("timeout\n");
if(n < 0)
sysfatal("read failed: %r\n");
if(n < msglen)
sysfatal("receive - bad length (%d != %d)\n", n, msglen);
if(icmp->type != AddrMaskReply)
sysfatal("%d!=%d bad reply message type\n", icmp->type, AddrMaskReply);
print("%-48s %02x%02x%02x%02x\n",
argv[0], icmp->data[0], icmp->data[1],
icmp->data[2], icmp->data[3]);
}
|