/* icmp netmask request: useful but sadly appears to be widely blocked */ #include #include #include #include #include #include #include "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, 0xff, 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); print("%-48s %02x%02x%02x%02x\n", argv[0], icmp->data[0], icmp->data[1], icmp->data[2], icmp->data[3]); }