/*	Author: Traktopel
 *	Title:	Yasp (yet another syn portscanner)
 *	Description:
 *	Copyright:
 * ---------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (by Poul-Henning Kamp, Revision 42):
 * <Traktopel@autistici.org> wrote this file. As long as you retain this notice
 * you can do whatever you want with this stuff. If we meet some day, and you
 * think this stuff is worth it, you can buy me a beer in return.
 * Traktopel
 * ---------------------------------------------------------------------------
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
#include <pcap.h>
#include <pthread.h>

#define DEFAULT_LOG_FILE "/dev/null"

FILE *ld;


int ackhunt(char *dev ) {

	struct pcap *pcap_s;
	struct pcap_pkthdr pcap_h;
	struct libnet_tcp_hdr *tcp;
	struct libnet_ipv4_hdr *ip;
	struct libnet_icmpv4_hdr *icmp;
	struct servent *service;
	char *pkt;
	char errbuf[LIBNET_ERRBUF_SIZE];
	int off;
	bpf_u_int32 netp, maskp;

	if(!dev) dev=pcap_lookupdev(errbuf);

	pcap_s=pcap_open_live(dev,BUFSIZ,0,1,errbuf);


	if(!pcap_s) {

		printf("Error: %s\n",errbuf);
		return EXIT_FAILURE;

	}



	switch (pcap_datalink(pcap_s)) {

		case DLT_EN10MB:
		off = 14;
		break;
      		case DLT_NULL:
		off=0;
      		case DLT_PPP:
		off = 4;
		break;

      		case DLT_LOOP:
        	off=108;
		break;
      		case DLT_SLIP:
		off = 16;
		break;
      		case DLT_RAW:
		off = 0;
		break;
      		case DLT_SLIP_BSDOS:
      		case DLT_PPP_BSDOS:
		off = 24;
		break;
      		case DLT_FDDI:
		off = 21;
		break;
      		case DLT_LINUX_SLL:
        	off = 16;
		break;

      		default:
		printf("Error: unknow Device\n");
		return EXIT_FAILURE;

	}

	printf("Port\t\t\t\tService\n");
	fprintf(ld,"Port\t\t\t\tService\n");



	while(1) {

		if((pkt = (u_char *) pcap_next(pcap_s,&pcap_h))!=NULL) {

	 		ip = (struct libnet_ipv4_hdr *) (pkt + off);
			tcp = (struct libnet_tcp_hdr *) (pkt + off + LIBNET_IPV4_H);

			if (tcp->th_seq != 0 && (tcp->th_flags == (TH_SYN|TH_ACK))) {

				service=getservbyport(htons(ntohs(tcp->th_sport)), "tcp");
				printf("%u\t\t\t\t%s\n",ntohs(tcp->th_sport),(service) ? service->s_name : "unknown");
				fprintf(ld,"%u\t\t\t\t%s\n",ntohs(tcp->th_sport),(service) ? service->s_name : "unknown");
			}

		}
	}

}




int port(libnet_t *l,char *dstip,char *port, char *dev) {

	unsigned short bport, eport, cport, build_ip;
	unsigned long dst_ip, src_ip;
	char errbuf[LIBNET_ERRBUF_SIZE],timed[60];
	struct libnet_tcp_hdr *tcp;
	struct time_t *tm;
   	struct servent *service;
	libnet_plist_t plist, *plist_p;
	pthread_t hunt;

	pthread_create(&hunt, NULL, &ackhunt, dev);


	(int)tm=time(NULL);
	strftime(timed,60,"%b %d %T",localtime((time_t *)&tm));

	fprintf(ld,"Yasp scanning:\nstarted at %s\n",timed);
	printf("Yasp scanning:\nstarted at %s\n",timed);

	if((dst_ip=libnet_name2addr4(l, dstip, LIBNET_RESOLVE))==EOF) {

		printf("Error: %s\n",libnet_geterror(l));
		return EXIT_FAILURE;

	}

	plist_p=&plist;

	if((libnet_plist_chain_new(l, &plist_p, port))==EOF) {

		printf("Error: %s\n", libnet_geterror(l));
		return EXIT_FAILURE;

	}

	if((src_ip = libnet_get_ipaddr4(l))==EOF) {

		printf("Error: %s\n",libnet_geterror(l));
		return EXIT_FAILURE;

	}

	tcp=0;
	build_ip=1;

   while (libnet_plist_chain_next_pair(plist_p, &bport,&eport))
     {
        while (!(bport > eport) && bport != 0) {

	cport = bport++;
	tcp=libnet_build_tcp(
			1050,                                    /* source port */
			cport,                                    /* destination port */
			0x01010101,                                 /* sequence number */
			0,                                          /* acknowledgement num */
			TH_SYN,                                     /* control flags */
			32767,                                      /* window size */
			0,                                          /* checksum */
			0,                                          /* urgent pointer */
			LIBNET_TCP_H,                               /* TCP packet size */
			NULL,                                       /* payload */
			0,                                          /* payload size */
			l,                                          /* libnet handle */
			(int)tcp);
			                                         /* libnet id */


      if (build_ip) {

		build_ip = 0;
		libnet_build_ipv4(
				LIBNET_IPV4_H + LIBNET_TCP_H,               /* length */
				0,                                          /* TOS */
				242,                                        /* IP ID */
				0,                                          /* IP Frag */
				64,                                         /* TTL */
				IPPROTO_TCP,                                /* protocol */
				0,                                          /* checksum */
				src_ip,                                     /* source IP */
				dst_ip,                                     /* destination IP */
				NULL,                                       /* payload */
				0,                                          /* payload size */
				l,                                          /* libnet handle */
				0);

		}
		usleep(8000);
	        libnet_write(l);


	}
}


sleep(6);
pthread_cancel(hunt);






}





int usage(char *arg0) {

	printf("Yasp 1.0\n");
	printf(" Written by Traktopel\n\n");
	printf("Usage:\n\n");
	printf(" -h\t\t\tshow this help\n");
	printf(" -d\t\t\tset manually device\n");
	printf(" -s\t\t\thost to scan\n");
	printf(" -p\t\t\tport range to scan\n");
	printf(" -l\t\t\tset log file\n\n");
	printf("Examples:\n\n");
	printf(" %s -s www.hacklab.altervista.org -p 1-1025 -l trak.log\n",arg0);
	printf(" %s -s 127.0.0.1 -d lo0 -p 1,22,25,139 -l trak.log\n",arg0);

	return EXIT_SUCCESS;

}


int main(int argc, char *argv[]) {

	int opt;
	char *dev, *ip, *portrange, *log, errbuff[LIBNET_ERRBUF_SIZE];

	libnet_t *l;

	dev=ip=portrange=log=0;

	if(argc<2) {

		printf("Yasp: use -h to see the help\n");
		return EXIT_SUCCESS;

	}



	while((opt=getopt(argc,argv,"hd:s:p:l:"))!=EOF) {

		switch(opt)	{

			case 'd':

				dev=optarg;
				break;

			case 's':

				ip=optarg;
				break;

			case 'p':

				portrange=optarg;
				break;

			case 'l':

				log=optarg;
				break;

			case 'h':
			default:

				usage(argv[0]);
				return EXIT_SUCCESS;
				break;

		}

	}

	if(!ip) {

		printf("You must enter host address to scan\n");
		return EXIT_FAILURE;

	}

	if(!portrange) {

		printf("You must enter port range to scan\n");
		return EXIT_FAILURE;

	}

	if(!log) log=DEFAULT_LOG_FILE;

	if(((int)ld=fopen(log,"a+"))==EOF) {

		printf("Can't open logfile: %s\n",log);
		return EXIT_FAILURE;

	}

	if(!dev)
	if(((int)l=libnet_init(LIBNET_RAW4,0,errbuff))==NULL) {

		printf("Error: %s\n",errbuff);
		return EXIT_FAILURE;

	}
	else l=libnet_init(LIBNET_RAW4,dev,errbuff);


	port(l,ip,portrange,dev);

	fclose(ld);
	libnet_destroy(l);

}

