summaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c122
1 files changed, 67 insertions, 55 deletions
diff --git a/main.c b/main.c
index 62cb30e..2546712 100644
--- a/main.c
+++ b/main.c
@@ -28,7 +28,7 @@
" -f Exclude sent packets from -e PCAP output They're all the same with different dst IPs.\n" \
" -h Show this help and exit.\n" \
" -k Increment IP addresses in reverse bit endianness (000 100 010 110 001 101 011 111).\n" \
-" -m Scans increasingly larger networks. Input networks are treated as /32. Useful with -n.\n" \
+" -m Scans increasingly larger networks. Input networks are treated as /31. Use with -n.\n" \
" -n Stops scanning after provided number of working servers is found and reported.\n" \
" -p Set the source port number to use instead of a dynamically asigned one.\n" \
" -t Number of microseconds to wait between sent packets. (default & min. 1000 - 64 KB/s)\n" \
@@ -263,6 +263,7 @@ int logudp (int o /* fd */, struct sockaddr_in s, struct sockaddr_in d, char * u
c = (char *) memcpy(c, &v, 2) + 2;
c = (char *) memcpy(c, &n, 2) + 2;
c = (char *) memcpy(c, u, l) + l;
+ c++; c--; /* to make scan-build happy that c is never read */
if (write(o, b, LOGUDP_L) == -1) { /* atomic and thread safe, as per posix */
perror("write(o, b, LOGUDP_L)");
return -3;
@@ -270,7 +271,7 @@ int logudp (int o /* fd */, struct sockaddr_in s, struct sockaddr_in d, char * u
return LOGUDP_L;
}
struct in_addr parse_a (const char * u, int s /* buffer size of u */, const char * d, int l, int n) {
- struct in_addr r = { /* this uses heap and does not fix heap if realloc failed. */
+ struct in_addr r = {
.s_addr = 0 /* returns 0.0.0.0 in case of error or if no more results for n. */
};
int y = normalizedomain_len(d, l);
@@ -283,16 +284,19 @@ struct in_addr parse_a (const char * u, int s /* buffer size of u */, const char
int q = ntohs(h->qdcount);
int a = ntohs(h->ancount+h->nscount+h->arcount);
char * o = NULL;
+ char * fuckc = NULL;
const char * c = u+sizeof(struct header);
while (q--) {
int č = name2domain_len(u, s, c);
if (č < 0)
goto r;
- if (!(o = realloc(o, č)))
+ if (!(fuckc = realloc(o, č)))
goto r;
+ o = fuckc;
if (!(c = name2domain(o, u, s, c)))
goto r;
- struct question * ć = (struct question *) (c+1);
+ struct question * ć = (struct question *) (c+1); /* scan-build ACK: ć is not read */
+ ć++; ć--; /* to make scan-build happy that ć is never read */
if ((c += sizeof(*ć)+1) >= u+512)
goto r;
} /* we skip over any questions */
@@ -300,8 +304,9 @@ struct in_addr parse_a (const char * u, int s /* buffer size of u */, const char
int č = name2domain_len(u, s, c);
if (č < 0)
goto r;
- if (!(o = realloc(o, č)))
+ if (!(fuckc = realloc(o, č)))
goto r;
+ o = fuckc;
if (!(c = name2domain(o, u, s, c)))
goto r;
struct rr * ć = (struct rr *) (c+1);
@@ -334,7 +339,7 @@ void handler () {
exit(1);
}
int main (int argc, char ** argv) {
- int r = 2;
+ int r = 1;
struct in_addr a = {
.s_addr = 0
};
@@ -360,6 +365,7 @@ int main (int argc, char ** argv) {
int w = 1000000;
int e = 0; /* whether to exclude sent packets in PCAP - they're all the same */
struct in_net h; /* host to scan is .addr, h as struct in_net is returned from host() */
+ int notfirst = 0;
signal(SIGINT, handler);
signal(SIGTERM, handler);
while (1) {
@@ -373,7 +379,7 @@ int main (int argc, char ** argv) {
case 'e':
if ((o = open(optarg, O_CREAT | O_TRUNC | O_WRONLY, 00664)) == -1) {
perror("open(optarg, O_CREAT | O_TRUNC | O_WRONLY)");
- r = 1;
+ r = 2;
goto r;
}
struct pcap_global g = {
@@ -387,7 +393,7 @@ int main (int argc, char ** argv) {
};
if (write(o, &g, sizeof g) == -1) {
perror("write(o, &g, sizeof g)");
- r = 2;
+ r = 3;
goto r;
}
break;
@@ -419,19 +425,19 @@ int main (int argc, char ** argv) {
case -1:
if (!(argc-optind)) {
fprintf(stderr, "specify domain name :: " HELP, argv[0]);
- r = 3;
+ r = 4;
goto r;
}
d = argv[optind];
int e = optind+1;
if (!(l = argc-e)) {
fprintf(stderr, "specify targets to scan :: " HELP, argv[0]);
- r = 4;
+ r = 5;
goto r;
}
if (increasinglylarger && l != 1) {
fprintf(stderr, "-m option is set, max one network. :: " HELP, argv[0]);
- r = 5;
+ r = 6;
goto r;
}
n = alloca(l*sizeof *n);
@@ -439,19 +445,19 @@ int main (int argc, char ** argv) {
int w = i-e;
n[w] = str2net(argv[i]);
if (increasinglylarger)
- n[w].mask.s_addr = INADDR_BROADCAST;
+ n[w].mask.s_addr = htonl(ntohl(INADDR_BROADCAST)&~1);
}
goto o;
case '?':
fprintf(stderr, "unknown option :: " HELP, argv[0]);
- r = 6;
+ r = 7;
goto r;
case ':':
fprintf(stderr, "missing option argument :: " HELP, argv[0]);
- r = 7;
+ r = 8;
goto r;
default:
- r = 8;
+ r = 9;
goto r;
}
}
@@ -461,32 +467,32 @@ o:
fprintf(stderr, "resolving %s ... ", d);
if ((e = resolve(d, &a.s_addr))) {
fprintf(stderr, "failed: %s\n", gai_strerror(e));
- r = 9;
+ r = 10;
goto r;
}
fprintf(stderr, " %s\n", inet_ntoa(a));
}
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
perror("socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)");
- r = 10;
+ r = 11;
goto r;
}
int ž = 1;
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &ž, sizeof(ž)) == -1) {
perror("setsockopt(s, SOL_SOCKET, SO_BROADCAST, &ž, sizeof(ž))");
- r = 11;
+ r = 12;
goto r;
} /* setting this so that sending packets to a broadcast address does not fail with noperm */
if (bind(s, (struct sockaddr *) &b, sizeof(struct sockaddr))) {
perror("bind(s, (struct sokaddr *) &b, sizeof(struct sockaddr))");
- r = 12;
+ r = 13;
goto r;
}
struct timespec lp = { /* last packet */
.tv_sec = 0
};
- int notfirst = 0;
- j = localnumber(n[0]);
+ fprintf(stderr, "starting at host number %lld\n", (j = localnumber(n[i])));
+ long int scanuntilhost = -1; /* no limit */
while (!finish) {
if (notfirst) {
if (k) {
@@ -496,32 +502,34 @@ o:
j++;
} else
notfirst++;
- if ((h = host(n[i], j)).mask.s_addr != INADDR_BROADCAST
- || (increasinglylarger && scanuntilhost != -1 && j >= scanuntilhost)) {
+ if (getenv("DF_DEBUG"))
+ fprintf(stderr, "j = %lld, scanuntilhost = %ld\n", j, scanuntilhost);
+ if ((h = host(n[i], j)).mask.s_addr != INADDR_BROADCAST ||
+ (increasinglylarger && scanuntilhost != -1 && j >= scanuntilhost)) {
k:
if (increasinglylarger ? (n[0].mask.s_addr == INADDR_ANY) : (++i >= l)) {
fprintf(stderr, "finished sending, waiting for last replies\n");
if (clock_gettime(CLOCK_MONOTONIC, &lp) == -1) {
perror("clock_gettime(CLOCK_MONOTONIC, &z)");
- r = 13;
+ r = 14;
goto r;
}
goto i;
} else {
- if (increasinglylarger)
- for (int ž = 0; ž < 31; ž++)
- if (n[i].mask.s_addr & 1 << ž) {
- n[i].mask.s_addr &= ~(1 << ž);
- if (n[i].addr.s_addr & 1 << ž) {
- n[i].addr.s_addr &= 1 << ž; /* but here we scan */
- scanuntilhost = localnumber(n[i]); /* UNTIL host */
- n[i].addr.s_addr &= n[i].mask.s_addr; /* from 0 */
- } else {
- n[i].addr.s_addr |= (1 << (ž+1))-1; /* nisem prepr */
- scanuntilhost = -1; /* scan FROM localnum till end */
- }
- break;
+ for (int ž = 0; increasinglylarger && ž < 31; ž++)
+ if (ntohl(n[i].mask.s_addr) & 1 << ž) {
+ n[i].mask.s_addr &= htonl(~(1 << ž));
+ if (ntohl(n[i].addr.s_addr) & 1 << (ž)) {
+ scanuntilhost = 1 << ž;
+ n[i].addr.s_addr &= n[i].mask.s_addr; /* 0 */
+ } else {
+ n[i].addr.s_addr |= htonl((1 << (ž))-1);
+ scanuntilhost = -1; /* until end */
}
+ break;
+ }
+ fprintf(stderr, "increasing scanning net: %s", inet_ntoa(n[i].addr));
+ fprintf(stderr, "/%s t: %ld\n", inet_ntoa(n[i].mask), scanuntilhost);
j = localnumber(n[i]);
h = host(n[i], j);
}
@@ -542,11 +550,11 @@ k:
int v = domain2name_len(d, strlen(d));
#define L (sizeof h + v + 2*2)
if (v < 0) {
- r = 14;
+ r = 15;
goto r;
}
if (L > 65535) { /* pebkac, there'll be no error message here */
- r = 15;
+ r = 16;
goto r;
}
char u[65535]; /* max udp packet, alloca in a loop would be bad (not scope based) */
@@ -557,22 +565,23 @@ k:
c += domain2name(c, d, strlen(d));
c = (char *) memcpy(c, &y, 2) + 2;
c = (char *) memcpy(c, &k, 2) + 2;
+ c++; c--; /* to make scan-build happy that c is never read */
int ž;
if (!e && o != -1 && (ž = logudp(o, b, m, u, L)) < -1) {
fprintf(stderr, "logudp(o, b, m, u, L) == %d\n", ž);
- r = 16;
+ r = 17;
goto r;
}
if (sendto(s, u, L, 0, (struct sockaddr *) &m, sizeof(struct sockaddr)) == -1) {
perror("sendto(s,u, L, 0, (struct sockaddr *) &m, sizeof(struct sockaddr))");
- r = 17;
+ r = 18;
goto r;
}
struct timespec z;
i:
if (clock_gettime(CLOCK_MONOTONIC, &z) == -1) {
perror("clock_gettime(CLOCK_MONOTONIC, &z)");
- r = 18;
+ r = 19;
goto r;
}
if ((z.tv_sec*1000000 + z.tv_nsec/1000) - (lp.tv_sec*1000000 + lp.tv_nsec/1000) > w
@@ -588,7 +597,7 @@ i:
int p;
if ((p = poll(&q, 1, t/1000 == 0 ? 1 : t/1000)) == -1) {
perror("poll(&q, 1, t/1000 == 0 ? 1 : t/1000)");
- r = 19;
+ r = 20;
goto r;
}
if (!p) {
@@ -598,7 +607,7 @@ i:
continue;
}
if (q.revents & POLLERR || q.revents & POLLHUP || q.revents & POLLNVAL) {
- r = 20;
+ r = 21;
goto r;
}
struct sockaddr_in f;
@@ -609,7 +618,7 @@ i:
== -1) {
if (errno != EWOULDBLOCK) {
perror("recvfrom(s, u, 65535, MSG_DONTWAIT, (struct soc...");
- r = 21;
+ r = 22;
goto r;
}
break;
@@ -618,7 +627,7 @@ i:
lp = z; /* this loop ends nearly in an instant */
if (o != -1 && (ž = logudp(o, f, b, u, š)) < -1) {
fprintf(stderr, "logudp(o, f, b, u, š) == %d\n", ž);
- r = 22;
+ r = 23;
goto r;
}
fprintf(stderr, "RESPONSE\t%s", inet_ntoa(f.sin_addr));
@@ -627,15 +636,18 @@ i:
while (parse_a(u, 65535, d, strlen(d), ž++).s_addr);
if (i.s_addr == a.s_addr) { /* if multithread, change printf to write. */
printf("\tWORKING");
- if (--ž == 1)
- if (++workingnum >= targetnum) {
- fprintf(stderr, "discovered %d working servers.\n", workingnum);
- goto r; /* r should be 0 here */
+ if (ž-1 == 1 && i.s_addr)
+ if (++workingnum >= targetnum && targetnum) {
+ printf("\n");
+ fprintf(stderr, "discovered %d working server%s.\n",
+ workingnum, workingnum==1 ? "": "s");
+ r = 0; /* r is 1 by default */
+ goto r;
}
}
if (i.s_addr && i.s_addr != a.s_addr)
printf("\tLYINGWITH\t%s", inet_ntoa(i));
- if (ž > 1)
+ if (--ž > 1)
printf("\tMORETHANONE\t%d", ž);
if (!i.s_addr)
printf("\tNOA");
@@ -646,16 +658,16 @@ i:
goto i;
}
r:
- if (!r && j != -1) { /* TODO: tell EXACT packets that were sent before termination. */
- char * x = alloca(l*31+strlen("SCANNED \n0")); /* currently, if scan was */
- strcpy(x, "SCANNED "); /* terminated, only networks before */
+ if (!r && notfirst) { /* TODO: tell EXACT packets that were sent before termination. */
+ char * x = alloca(l*31+strlen("SCANNED \n0")+strlen("WORKINGNUM aaaaaaaaaaaaaaaa"));
+ strcpy(x, "SCANNED "); /* if scan term, only networks be4 */
for (int m = 0; m < (finish ? i : l); m++) { /* network at which scan was */
strcat(x, inet_ntoa(n[m].addr)); /* terminated are reported to be */
strcat(x, "/"); /* scanned, not mentioning the */
strcat(x, inet_ntoa(n[m].mask)); /* part of the last not mentioned */
strcat(x, " "); /* network that was scanned. */
} /* this may lead to statistical */
- strcat(x, "\n"); /* issues because it would appear */
+ sprintf(x+strlen(x), "\nWORKINGNUM %d\n", workingnum); /* issues cause it'd appear */
write(STDIN_FILENO, x, strlen(x)); /* as if we received packets from */
} /* hosts we haven't queried yet. */
if (s != -1)