Jon Allen Boone on Thu, 27 Feb 2003 11:44:05 -0500


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [tcptra-dev] libnet 1.1.0 / autoconf support (was Fwd: tcptraceroute.c unified diff for use with libnet 1.1.0)


James,

Here's a unified diff with my changes. This is totally *unofficial*, as it doesn't meet mct's requirements for supporting both libnet 1.0 and 1.1, but it would get you started so that you can work on the autoconf stuff.

--jon

Begin forwarded message:

From: Jon Allen Boone <ipmonger@delamancha.org>
Date: Sun Jan 19, 2003  02:56:10 US/Eastern
To: Michael C Toren <mct@toren.net>
Cc: Jon Allen Boone <ipmonger@delamancha.org>
Subject: tcptraceroute.c unified diff for use with libnet 1.1.0

mct,

Here's the revised version. It works under both MacOS X and Debian GNU/Linux (i686) for me. It did turn out that the issue was one of protocol tag (ptag) starvation. It was also responsible for the time-outs that showed up on the overmind/sebastion trace that I pasted to you via IRC. [MacOS X has a higher limit for some reason than Debian...]

In any case, I verified that this code works for me on both systems. It also includes one change to pick up the fact that MacOS X Darwin is composed of FreeBSD + MACH, which means it needs to be treated the same as the other *BSDs.

  Heh.  I suppose this is a bit long-winded.  I must be tired.

--jon

--- tcptraceroute.c.orig	Tue Jul 30 17:51:27 2002
+++ tcptraceroute.c	Sun Jan 19 02:44:45 2003
@@ -30,13 +30,18 @@
  * Updates are available from http://michael.toren.net/code/tcptraceroute/
  */
 
-#define VERSION "tcptraceroute 1.4 (2002-07-30)"
+#define VERSION "tcptraceroute 1.5 (2003-01-18)"
 #define BANNER  "Copyright (c) 2001, 2002 Michael C. Toren <mct@toren.net>\n\
 Updates are available from http://michael.toren.net/code/tcptraceroute/\n";
 
 /*
  * Revision history:
  *
+ *  Version 1.5 (2003-01-18)
+ *
+ *      Converted to use libnet-1.1.x instead of libnet-1.0.x
+ *      by Jon Allen Boone <ipmonger@delamancha.org>
+ *
  *	Version 1.4 (2002-07-30)
  *
  *		Added linklayer support for Linux ISDN Sync-PPP interfaces,
@@ -209,7 +214,7 @@
 #define AF_LINK AF_INET /* BSD defines some AF_INET network interfaces as AF_LINK */
 #endif
 
-#if defined (__OpenBSD__) || defined(__FreeBSD__) || defined(__bsdi__)
+#if defined (__OpenBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__MACH__)
 #define HASSALEN /* Awful, awful hack to make subinterfaces work on BSD. */
 #endif
 
@@ -232,8 +237,8 @@
  * there's a *2 there.  The +32 is just to be safe.
  */
 
-#define SNAPLEN	 (LIBNET_IP_H * 2 + \
-	(LIBNET_TCP_H > LIBNET_ICMP_H ? LIBNET_TCP_H : LIBNET_ICMP_H) + 32)
+#define SNAPLEN	 (LIBNET_IPV4_H * 2 + \
+	(LIBNET_TCP_H > LIBNET_ICMPV4_H ? LIBNET_TCP_H : LIBNET_ICMPV4_H) + 32)
 
 /*
  * To add support for additional link layers, add entries to the following
@@ -314,11 +319,14 @@
 pcap_t *pcap;
 int pcap_fd;
 struct timeval now;
-int	sockfd, datalink, offset;
+int datalink, offset;
 int o_minttl, o_maxttl, o_timeout, o_debug, o_numeric, o_pktlen,
 	o_nqueries, o_dontfrag, o_tos, o_forceport, o_syn, o_ack, o_ecn,
 	o_nofilter, o_nogetinterfaces, o_noselect, o_trackport;
 
+libnet_t *libnet_context;
+char errbuf[LIBNET_ERRBUF_SIZE];
+
 /* interface linked list, built later by getinterfaces() */
 struct interface_entry {
 	char *name;
@@ -593,7 +601,7 @@
 		return iptos(in);
 	}
 
-	return libnet_host_lookup(in, o_numeric > 0 ? 0 : 1);
+	return libnet_addr2name4(in, o_numeric > 0 ? LIBNET_DONT_RESOLVE : LIBNET_RESOLVE);
 }
 
 /*
@@ -820,7 +828,7 @@
 		if (p->addr == dst_ip)
 		{
 			debug("Destination matches local address of interface %s;\n\tattempting to find loopback interface, o_nofilter set\n", p->name);
-			with_src = libnet_name_resolve("127.0.0.1", 0);
+			with_src = libnet_name2addr4(libnet_context, "127.0.0.1", LIBNET_DONT_RESOLVE);
 			o_nofilter = 1;
 		}
 
@@ -882,9 +890,9 @@
 
 		for(i = 0; i < ALLOCATEID_CACHE_SIZE; i++)
 		{
-			for(ids[i] = libnet_get_prand(PRu16), j = i + 1; j < ALLOCATEID_CACHE_SIZE + i; j++)
+			for(ids[i] = libnet_get_prand(LIBNET_PRu16), j = i + 1; j < ALLOCATEID_CACHE_SIZE + i; j++)
 				if (ids[i] == ids[j % ALLOCATEID_CACHE_SIZE])
-					ids[i] = libnet_get_prand(PRu16), j = i + 1;
+					ids[i] = libnet_get_prand(LIBNET_PRu16), j = i + 1;
 		}
 	}
 
@@ -1046,6 +1054,9 @@
 		"o_noselect", o_noselect);
 }
 
+
+
+
 /*
  * Check command line arguments for sanity, and fill in the blanks.
  */
@@ -1057,14 +1068,14 @@
 
 	getinterfaces();
 
-	if ((dst_ip = libnet_name_resolve(dst, 1)) == 0xFFFFFFFF)
+	if ((dst_ip = libnet_name2addr4(libnet_context, dst, 1)) == 0xFFFFFFFF)
 		fatal("Bad destination address: %s\n", dst);
 
 	recommended_src = findsrc(dst_ip);
 
 	if (src)
 	{
-		if ((src_ip = libnet_name_resolve(src, 1)) == 0xFFFFFFFF)
+		if ((src_ip = libnet_name2addr4(libnet_context,src, 1)) == 0xFFFFFFFF)
 			fatal("Bad source address: %s\n", src);
 	}
 	else
@@ -1133,19 +1144,16 @@
 	if (o_timeout <= 0)
 		fatal("Timeout must be at least 1\n");
 
-	if (o_pktlen < LIBNET_TCP_H + LIBNET_IP_H)
+	if (o_pktlen < LIBNET_TCP_H + LIBNET_IPV4_H)
 	{
 		if (o_pktlen != 0)
-			warn("Increasing packet length to %d bytes\n", LIBNET_TCP_H + LIBNET_IP_H);
+			warn("Increasing packet length to %d bytes\n", LIBNET_TCP_H + LIBNET_IPV4_H);
 		o_pktlen = 0;
 	}
 	else
-		o_pktlen -= (LIBNET_TCP_H + LIBNET_IP_H);
+		o_pktlen -= (LIBNET_TCP_H + LIBNET_IPV4_H);
 
-	libnet_seed_prand();
-
-	if ((sockfd = libnet_open_raw_sock(IPPROTO_RAW)) < 0)
-		pfatal("socket allocation");
+	libnet_seed_prand(libnet_context);
 
 	if (strcmp(dst, iptos(dst_ip)) == 0)
 		safe_snprintf(dst_name, TEXTSIZE, "%s", dst);
@@ -1210,6 +1218,22 @@
 }
 
 /*
+ * Initialize the libnet library context.
+ */
+
+void init_libnet()
+{
+	/* Initialize the libnet library context */
+	
+	libnet_context = libnet_init( LIBNET_RAW4, NULL, errbuf);
+	
+	/* verify that we've got a valid context */
+	if (libnet_context == NULL)
+		fatal("libnet_init() failed: %s\n", errbuf);
+}
+
+
+/*
  * Sends out a TCP SYN packet with the specified TTL, and returns a
  * proberecord structure describing the packet sent, so we know what
  * to listen for later.  A new IP ID is generated for each probe, and
@@ -1218,20 +1242,36 @@
 
 void probe(proberecord *record, int ttl, int q)
 {
-	static u_char *payload, *buf;
+	static u_char *payload;
 	int i, size, ret;
 
-	/* Initialize the packet buffer */
-	size = LIBNET_IP_H + LIBNET_TCP_H + o_pktlen;
+	static libnet_ptag_t ip_tag, tcp_tag, data_tag;
+	
+
+
+	/* pre-caclulate the size of the packet */
+	size = LIBNET_IPV4_H + LIBNET_TCP_H + o_pktlen;
+
+	/* set some values of the probe record */
+	record->q = q;
+	record->ttl = ttl;
+	record->addr = INADDR_ANY;
+	record->src_prt = src_prt;
+	record->id = allocateid();
+	record->delta = 0;
 
-	if (!buf)
+	if (o_trackport)
 	{
-		debug("Initializing packet buffer of %d bytes\n", size);
-		buf = xrealloc(buf, size);
+		record->src_prt = allocateport(0);
+		if (record->src_prt == 0)
+			pfatal("Could not allocate local port: bind");
 	}
 
-	memset(buf, 0, size);
+	if (gettimeofday(&(record->timestamp), NULL) < 0)
+		pfatal("gettimeofday");
 
+	/* Build the packet, and send it off into the cold, cruel world ... */
+	
 	/* Initialize the packet payload */
 	if (o_pktlen && !payload)
 	{
@@ -1250,58 +1290,63 @@
 		debug("Payload: %s\n", sprintable(payload));
 	}
 
-	record->q = q;
-	record->ttl = ttl;
-	record->addr = INADDR_ANY;
-	record->src_prt = src_prt;
-	record->id = allocateid();
-	record->delta = 0;
-
-	if (o_trackport)
-	{
-		record->src_prt = allocateport(0);
-		if (record->src_prt == 0)
-			pfatal("Could not allocate local port: bind");
-	}
-
-	if (gettimeofday(&(record->timestamp), NULL) < 0)
-		pfatal("gettimeofday");
-
-	/* Build the packet, and send it off into the cold, cruel world ... */
-	libnet_build_ip(
-		LIBNET_TCP_H+o_pktlen,	/* len			*/
-		o_tos,					/* tos			*/
-		record->id,				/* id			*/
-		o_dontfrag ? IP_DF : 0,	/* frag			*/
-		ttl,					/* ttl			*/
-		IPPROTO_TCP,			/* proto		*/
-		src_ip,					/* saddr		*/
-		dst_ip,					/* daddr		*/
-		NULL,					/* data			*/
-		0,						/* datasize?	*/
-		buf);					/* buffer		*/
-
-	libnet_build_tcp(
-		record->src_prt,		/* source port	*/
-		dst_prt,				/* dest port	*/
-		0,						/* seq number	*/
-		0,						/* ack number	*/
+	data_tag = libnet_build_data(payload, o_pktlen, libnet_context, data_tag);
 
+	/* verify that we were able to add the payload */
+	if (data_tag < 0)
+		fatal("Can't add payload: %s\n", libnet_geterror(libnet_context));
+
+	/* add the TCP Header */
+
+	tcp_tag = libnet_build_tcp(
+		record->src_prt,		     /* source port	        */
+		dst_prt,				     /* dest port	        */
+		0,						     /* seq number	        */
+		0,						     /* ack number	        */
+		
 		(o_syn ? TH_SYN : 0) |
 		(o_ack ? TH_ACK : 0) |
-		(o_ecn ? TH_CWR|TH_ECN : 0), /* control	*/
-
-		0,						/* window		*/
-		0,						/* urgent?		*/
-		payload,				/* data			*/
-		o_pktlen,				/* datasize		*/
-		buf + LIBNET_IP_H);		/* buffer		*/
+		(o_ecn ? TH_CWR|TH_ECN : 0), /* control	            */
 
-	libnet_do_checksum(buf, IPPROTO_TCP, LIBNET_TCP_H + o_pktlen);
-
-	if ((ret = libnet_write_ip(sockfd, buf, size)) < size)
-		fatal("libnet_write_ip failed?  Attempted to write %d bytes, only wrote %d\n",
+		0,						     /* window		        */
+		0,                           /* checksum TBD        */
+		0,						     /* urgent?	            */
+		LIBNET_TCP_H + o_pktlen,     /* TCP PDU size        */
+		NULL,				         /* data		        */
+		0,	          			     /* datasize	        */
+		libnet_context,              /* libnet context      */
+		tcp_tag);                    /* libnet protocol tag */
+
+	/* verify that we were able to build the TCP header */
+	if (tcp_tag < 0)
+		fatal("Can't build TCP header: %s\n", libnet_geterror(libnet_context));
+
+	/* add the IP header */
+	ip_tag = libnet_build_ipv4(
+		size,	                /* total packet len	   */
+		o_tos,					/* tos			       */
+		record->id,				/* id			       */
+		o_dontfrag ? IP_DF : 0,	/* frag			       */
+		ttl,					/* ttl			       */
+		IPPROTO_TCP,			/* proto		       */
+		0,                      /* checksum TBD        */
+		src_ip,					/* saddr		       */
+		dst_ip,					/* daddr		       */
+		NULL,    				/* data			       */
+		0,      				/* datasize?	       */
+		libnet_context,         /* libnet context      */
+		ip_tag);                /* libnet protocol tag */
+
+	/* verify that we were able to add the IP portion */
+	if (ip_tag < 0)
+		fatal("Can't build IP header: %s\n", libnet_geterror(libnet_context));
+	
+	/* attempt to write the packet */
+	if ((ret = libnet_write(libnet_context)) < size)
+		fatal("libnet_write failed?  Attempted to write %d bytes, only wrote %d\n",
 			  size, ret);
+	
+	
 }
 
 /*
@@ -1329,7 +1374,7 @@
 {
 	u_char *packet;
 	struct pcap_pkthdr packet_hdr;
-	struct libnet_ip_hdr *ip_hdr;
+	struct libnet_ipv4_hdr *ip_hdr;
 	struct timeval start, now, timepassed, timeout_tv, timeleft;
 	int firstpass, ret, len;
 	double delta;
@@ -1409,7 +1454,7 @@
 
 		debug("received %d byte IP packet from pcap_next()\n", len);
 
-		if (len < LIBNET_IP_H)
+		if (len < LIBNET_IPV4_H)
 		{
 			debug("Ignoring partial IP packet\n");
 			continue;
@@ -1421,7 +1466,7 @@
 			continue;
 		}
 
-		ALIGN_PACKET(ip_hdr, libnet_ip_hdr, 0);
+		ALIGN_PACKET(ip_hdr, libnet_ipv4_hdr, 0);
 
 		if (ip_hdr->ip_v != 4)
 		{
@@ -1450,17 +1495,17 @@
 
 		if (ip_hdr->ip_p == IPPROTO_ICMP)
 		{
-			struct libnet_icmp_hdr *icmp_hdr;
-			struct libnet_ip_hdr *old_ip_hdr;
+			struct libnet_icmpv4_hdr *icmp_hdr;
+			struct libnet_ipv4_hdr *old_ip_hdr;
 			struct libnet_tcp_hdr *old_tcp_hdr;
 
-			if (len < LIBNET_IP_H + LIBNET_ICMP_H + 4)
+			if (len < LIBNET_IPV4_H + LIBNET_ICMPV4_H + 4)
 			{
 				debug("Ignoring partial icmp packet\n");
 				continue;
 			}
 
-			ALIGN_PACKET(icmp_hdr, libnet_icmp_hdr, 0 + LIBNET_IP_H);
+			ALIGN_PACKET(icmp_hdr, libnet_icmpv4_hdr, 0 + LIBNET_IPV4_H);
 			debug("Received icmp packet\n");
 
 			/*
@@ -1469,14 +1514,14 @@
 			 * padding.
 			 */
 
-			if (len < LIBNET_IP_H + LIBNET_ICMP_H + 4 + LIBNET_IP_H + 8)
+			if (len < LIBNET_IPV4_H + LIBNET_ICMPV4_H + 4 + LIBNET_IPV4_H + 8)
 			{
 				debug("Ignoring icmp packet with incomplete payload\n");
 				continue;
 			}
 
-			ALIGN_PACKET(old_ip_hdr, libnet_ip_hdr,
-				0 + LIBNET_IP_H + LIBNET_ICMP_H + 4);
+			ALIGN_PACKET(old_ip_hdr, libnet_ipv4_hdr,
+				0 + LIBNET_IPV4_H + LIBNET_ICMPV4_H + 4);
 
 			/*
 			 * The entire TCP header isn't here, but the source port,
@@ -1484,7 +1529,7 @@
 			 */
 
 			ALIGN_PACKET(old_tcp_hdr, libnet_tcp_hdr,
-				0 + LIBNET_IP_H + LIBNET_ICMP_H + 4 + LIBNET_IP_H);
+				0 + LIBNET_IPV4_H + LIBNET_ICMPV4_H + 4 + LIBNET_IPV4_H);
 
 			if (old_ip_hdr->ip_v != 4)
 			{
@@ -1619,13 +1664,13 @@
 				continue;
 			}
 
-			if (len < LIBNET_IP_H + LIBNET_TCP_H)
+			if (len < LIBNET_IPV4_H + LIBNET_TCP_H)
 			{
 				debug("Ignoring partial tcp packet\n");
 				continue;
 			}
 
-			ALIGN_PACKET(tcp_hdr, libnet_tcp_hdr, 0 + LIBNET_IP_H);
+			ALIGN_PACKET(tcp_hdr, libnet_tcp_hdr, 0 + LIBNET_IPV4_H);
 
 			debug("Received tcp packet %s:%d -> %s:%d, flags %s%s%s%s%s%s%s%s%s\n",
 				iptos(ip_hdr->ip_src.s_addr), ntohs(tcp_hdr->th_sport),
@@ -1690,7 +1735,7 @@
 	fprintf(stderr, "Tracing the path to %s on TCP port %s, %d hops max",
 		dst_name, dst_prt_name, o_maxttl);
 	if (o_pktlen)
-		fprintf(stderr, ", %d byte packets", o_pktlen + LIBNET_TCP_H + LIBNET_IP_H);
+		fprintf(stderr, ", %d byte packets", o_pktlen + LIBNET_TCP_H + LIBNET_IPV4_H);
 	fprintf(stderr, "\n");
 
 	for (ttl = o_minttl, done = 0; !done && ttl <= o_maxttl; ttl++)
@@ -1716,6 +1761,7 @@
 	if (!done)
 		fprintf(stderr, "Destination not reached\n");
 
+	libnet_destroy(libnet_context);
 	return done ? 0 : 1;
 }
 
@@ -2001,6 +2047,8 @@
 	if (getuid() & geteuid())
 		fatal("Got root?\n");
 
+	
+	init_libnet();
 	defaults();
 	initcapture();
 	seteuid(getuid());