/* * an experimental dsnattest server * Waits for 27900:UDP, 27901:UDP and returns something * Usage: $0 */ #include #include /*atoi*/ #include #include #include #include /*inet_aton*/ #include /*memcpy*/ #include #include /* isprint */ void xdump(FILE *o, const unsigned char *buf, size_t len) { size_t i; for (i=0; isin_port), inet_ntoa(from_addr.sin_addr),ntohs(from_addr.sin_port), (int)recvlen); xdump(stdout, rbuf,(recvlen<32)?recvlen:32); if (rsock == rsock27900) { sendlen = 7; memcpy(rbuf, "\xfe\xfd\x09\x00\x00\x00\x00", 7); } else { sendlen = (recvlen<21)?recvlen:21; /* genuine natneg server doesn't reply * if first 6 bytes wasn't the magic * FD FC 1E 66 6A B2, but we do for now */ printf(" proto_ver=%d command=0x%02X msgid=0x%04X server_select=%d\n", rbuf[0x06], rbuf[0x07], rbuf[0x0a]*256+rbuf[0x0b], rbuf[0x0c]); /* genuine natneg server only responds if * server_select matches itself, * (natneg1:3, natneg2:2, natneg3:!2&!3) * but we respond anyway for now */ /*rbuf[0x06] == 3; protocol ver? */ switch (rbuf[0x07]) /*command*/ { case 0x00: /* return fixed magic in payload */ rbuf[0x07] = 0x01; rbuf[0x0d] = 0; /* reply flag */ memcpy(&rbuf[14], "\xFF\xFF\x6D\x16\xB5\x7D\xEA", 7); break; case 0x08: /* plain return */ rbuf[0x07] = 0x09; break; case 0x0a: /* return global addr/port seen */ rbuf[0x07] = 0x0b; rbuf[0x0d] = 0; /* reply flag */ memcpy(&rbuf[15], &from_addr.sin_addr, 4); memcpy(&rbuf[19], &from_addr.sin_port, 2); /*rbuf[15]^=0x55; /*changing the addr will result in 41212/61212 (5th digit 4 or 6)*/ /*rbuf[20]^=0x55; /*changing the port will result in 21312/31312 (3rd digit 3)*/ break; case 0x0c: /* plain return */ rbuf[0x07] = 0x02; rbuf[0x0d] = 0; /* reply flag */ break; default: /* genuine natneg server doesn't reply * anything otherwise, but we will just * echo back for now */ break; } } /*endif*/ printf("sending back %d bytes\n", sendlen); xdump(stdout, rbuf, sendlen); sendto(rsock, rbuf, sendlen, 0/*flags*/, &from_addr,from_addr_len); } }