Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 May 2004 01:49:12 -0400 (EDT)
From:      Paul Chvostek <paul+fbsd@it.ca>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        Paul Chvostek <paul+fbsd@it.ca>
Subject:   ports/67327: New port: net-mgmt/rotorouter - fake traceroute
Message-ID:  <200405290549.i4T5nC1H000778@foo.it.ca>
Resent-Message-ID: <200405290550.i4T5oPBS005994@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         67327
>Category:       ports
>Synopsis:       New port: net-mgmt/rotorouter - fake traceroute
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri May 28 22:50:24 PDT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Paul Chvostek
>Release:        FreeBSD 4.10-PRERELEASE i386
>Organization:
>Environment:
System: FreeBSD foo.it.ca 4.10-PRERELEASE FreeBSD 4.10-PRERELEASE #1: Sat May 1 23:10:02 EDT 2004 paul@foo.it.ca:/usr/obj/usr/src/sys/foo i386


>Description:
	Responds to traceroutes with "fake" path info, written
	by Julian Assange.  No original source seems to exist
	for this, and Julian doesn't seem reachable.

	Firewall rules are required to actually make this thing
	work, but they depend on the targets you specify in your
	config file.  The wish list includes some documentation.

>How-To-Repeat:
	
>Fix:

--- rotorouter.shar begins here ---
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	rotorouter
#	rotorouter/pkg-plist
#	rotorouter/pkg-message
#	rotorouter/pkg-descr
#	rotorouter/Makefile
#	rotorouter/src
#	rotorouter/src/rotorouter.c
#	rotorouter/src/rotorouter.conf-example
#	rotorouter/src/rotorouter.sh
#
echo c - rotorouter
mkdir -p rotorouter > /dev/null 2>&1
echo x - rotorouter/pkg-plist
sed 's/^X//' >rotorouter/pkg-plist << 'END-of-rotorouter/pkg-plist'
Xsbin/rotorouter
Xetc/rc.d/rotorouter.sh
X@unexec if [ -f %D/etc/rotorouter.conf ] && cmp -s %D/etc/rotorouter.conf %D/etc/rotorouter.conf-example; then rm -f %D/etc/rotorouter.conf; fi
Xetc/rotorouter.conf-example
END-of-rotorouter/pkg-plist
echo x - rotorouter/pkg-message
sed 's/^X//' >rotorouter/pkg-message << 'END-of-rotorouter/pkg-message'
X========================================================================
X   NOTICE    NOTICE    NOTICE    NOTICE    NOTICE    NOTICE    NOTICE
X========================================================================
X
XThe rotorouter port has been installed with an example configuration
Xfile, located at %%PREFIX%%/etc/rotorouter.conf-example.
X
XYou need to build your own config file using local network information.
X
X========================================================================
END-of-rotorouter/pkg-message
echo x - rotorouter/pkg-descr
sed 's/^X//' >rotorouter/pkg-descr << 'END-of-rotorouter/pkg-descr'
XA program for faking the standard unix udp-based traceroute.
X
XWWW: http://www.ussrback.com/UNIX/loggers/fakeroute.c
X
X- Paul Chvostek <paul+ports@it.ca>
END-of-rotorouter/pkg-descr
echo x - rotorouter/Makefile
sed 's/^X//' >rotorouter/Makefile << 'END-of-rotorouter/Makefile'
X# New ports collection makefile for:	rotorouter
X# Date created:				Sat May 29 01:30:43 EDT 2004
X# Whom:					Paul Chvostek <paul@it.ca>
X#
X# $FreeBSD$
X#
X# This port is self-contained in the src directory.
X#
X
XPORTNAME=	rotorouter
XPORTVERSION=	1.0
XCATEGORIES=	net-mgmt
XMASTER_SITES=	# nada
XDISTFILES=	# nil
X
XMAINTAINER=	paul+ports@it.ca
XCOMMENT=	Traceroute log and fake
X
XNO_WRKSUBDIR=	yes
X
XSRC=		${.CURDIR}/src
X
XSED_SCRIPT+=	-e 's,%%PREFIX%%,${PREFIX},g' \
X		-e 's,%%RC_SUBR%%,${RC_SUBR},g'
X
X.include <bsd.port.pre.mk>
X
X.if ${OSVERSION} >= 500038
XRC_SUBR?=       /etc/rc.subr
X.else
XUSE_RC_SUBR=    yes
X.endif
X
Xdo-fetch:
X		@${DO_NADA}
X
Xdo-build:
X		${CC} -lpcap -o ${WRKSRC}/rotorouter ${SRC}/rotorouter.c
X		${SED} ${SED_SCRIPT} < ${SRC}/rotorouter.sh > ${WRKSRC}/rotorouter.sh
X
Xdo-install:
X		@${INSTALL_DATA} -m 640 ${SRC}/rotorouter.conf-example ${PREFIX}/etc/
X		@${INSTALL_DATA} -m 640 ${SRC}/rotorouter.conf-example ${PREFIX}/etc/rotorouter.conf
X		@${INSTALL_PROGRAM} ${WRKSRC}/rotorouter ${PREFIX}/sbin/
X		@${INSTALL_SCRIPT} -m 751 ${WRKSRC}/rotorouter.sh ${PREFIX}/etc/rc.d/rotorouter.sh
X
Xpost-install:
X		@${SED} ${SED_SCRIPT} < ${PKGMESSAGE}
X
X.include <bsd.port.post.mk>
END-of-rotorouter/Makefile
echo c - rotorouter/src
mkdir -p rotorouter/src > /dev/null 2>&1
echo x - rotorouter/src/rotorouter.c
sed 's/^X//' >rotorouter/src/rotorouter.c << 'END-of-rotorouter/src/rotorouter.c'
X/* fakeroute (c) 1996 Julian Assange <proff at iq dot org>
X * All Rights Reserved
X *
X * config file ("hops" by default) contains tuples like thus:
X
XDest IP         Hop     Fake router     ms latency
X203.4.184.222    0      204.70.10.250   5
X203.4.184.222    1      204.70.10.250   10
X203.4.184.222    2      198.32.136.88   15
X203.4.184.222    3      137.209.200.202 20
X203.4.184.222    4      137.209.60.1    25
X203.4.184.222    5      198.26.127.26   30
X203.4.184.222   -1      203.4.184.222   35
X203.4.184.217    0      204.70.10.250   5
X203.4.184.217    1      204.70.10.250   10
X203.4.184.217    2      198.32.136.88   15
X203.4.184.217    3      137.209.200.202 20
X203.4.184.217    4      137.209.60.1    25
X203.4.184.217    5      198.26.127.26   30
X203.4.184.217   -1      203.4.184.222   35
X*/
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <unistd.h>
X#include <string.h>
X
X#include <sys/types.h>
X
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/socket.h>
X
X#include <netinet/in_systm.h>
X#include <netinet/in.h>
X#include <netinet/ip.h>
X#include <netinet/udp.h>
X#include <netinet/ip_icmp.h>
X
X#include <arpa/inet.h>
X
X#include <pcap.h>
X
X#define bool int
X#define TRUE 1
X#define FALSE 0
X
X#define ENDIAN_RAW_BUG 1
X
Xtypedef u_short port_t;
X
Xpcap_t *pd;
Xstruct bpf_program fcode;
Xu_char *pcap_userdata;
Xstruct in_addr localnet, netmask;
Xchar ebuf[PCAP_ERRBUF_SIZE];
Xint raw;
Xint a_max_ttl = 1;
Xint a_timeout = 300;
Xint a_verbose = 0;
X
Xvoid ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p);
Xvoid ppp_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p);
Xvoid analyze_udp(struct ip *ip);
X
Xstruct hop
X{
X        struct hop *next;
X        struct in_addr dst, hop;
X        int latency; /* delay */
X        int ttl;
X};
Xstruct hop *hops;
X
Xstruct udp_state
X{
X        struct udp_state *next;
X        struct in_addr src, dst;
X        port_t sport;
X        time_t last_packet;
X};
X
Xstruct udp_state *state;
Xstruct udp_state *queue;
X
Xvoid
Xpexit(char *err)
X{
X        perror(err);
X        exit(1);
X}
X
Xvoid
Xeexit(char *err)
X{
X        fprintf(stderr, "fatal error: %s\n", err);
X        exit(1);
X}
X
Xvoid *
Xxmalloc(int n)
X{
X        void *p=malloc(n);
X        if (!p)
X                pexit("malloc");
X        return p;
X}
X
Xu_short
Xfast_icmp_cksum(struct icmp *icmp)      /* well, for C anyway.. */
X{
X        register u_short *u = (u_short *)icmp;
X        register int sum = 0;
X
X        sum =  *u++;
X                u++;            /* skip checksum */
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u++;
X        sum += *u;
X        sum = (sum >> 16) + (sum & 0xffff);     /* fold accumulated carries */
X        sum += sum>>16;
X        return (u_short) ~sum;
X}
X
Xstruct printer
X{
X        pcap_handler f;
X        int type;
X};
X
X/* XXX needed if using old bpf.h */
X#ifndef DLT_ATM_RFC1483
X#define DLT_ATM_RFC1483 11
X#endif
X
Xstatic struct printer printers[] =
X{
X        { ether_if_print,       DLT_EN10MB },
X        { ether_if_print,       DLT_IEEE802 },
X/*
X        { sl_if_print,          DLT_SLIP },
X*/
X        { ppp_if_print,         DLT_PPP },
X/*
X        { fddi_if_print,        DLT_FDDI },
X        { null_if_print,        DLT_NULL },
X        { atm_if_print,         DLT_ATM_RFC1483 },
X*/
X        { NULL,                 0 },
X};
X
Xstatic pcap_handler
Xlookup_printer(int type)
X{
X        struct printer *p;
X
X        for (p = printers; p->f; ++p)
X                if (type == p->type)
X                        return p->f;
X
X        fprintf(stderr, "unknown data link type 0x%x", type);
X        exit(1);
X        /* NOTREACHED */
X}
X
Xvoid
Xopen_pcap(char *dev, bool f_promisc, char *filt, int usec)
X{
X        if (!dev)
X        {
X                dev = pcap_lookupdev(ebuf);
X                if (!dev)
X                        eexit(ebuf);
X        }
X        pd = pcap_open_live(dev, 96, f_promisc, usec, ebuf);
X        if (!pd)
X                eexit(ebuf);
X        if (pcap_lookupnet(dev, &localnet.s_addr, &netmask.s_addr, ebuf) < 0)
X                eexit(ebuf);
X        if (pcap_compile(pd, &fcode, filt, 1, (u_long)netmask.s_addr) < 0)
X                eexit(pcap_geterr(pd));
X        if (pcap_setfilter(pd, &fcode) < 0)
X                eexit(pcap_geterr(pd));
X}
X
Xvoid
Xether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
X{
X        p += 14;
X        analyze_udp((struct ip *)p);
X}
X
Xvoid
Xppp_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
X{
X        p += 4;
X        analyze_udp((struct ip *)p);
X}
X
X
Xstruct hop *
Xfind_hop(struct in_addr dst, int ttl)
X{
X        struct hop *p, *ret=NULL;
X        for (p = hops; p; p=p->next)
X        {
X                if (p->dst.s_addr == dst.s_addr)
X                {
X                        if (p->ttl == ttl)
X                                return p;
X                        if (p->ttl == -1)
X                                ret = p;
X                }
X        }
X        return ret;
X}
X
Xvoid
Xicmp_reply(struct ip *iip, struct hop *hop)
X{
X        char buf[sizeof(struct ip) + sizeof(struct icmp) + 8];
X        struct ip *ip =(struct ip *)buf;
X        struct icmp *i =(struct icmp *)(buf+sizeof(struct ip));
X        static u_short ip_id;
X        bool f_dest = (hop->ttl == -1);
X        struct sockaddr_in in;
X        int len = sizeof (struct ip) + sizeof (struct icmp) + 8; /* don't bother with the options  */
X        memset(&in, 0, sizeof in);
X        in.sin_family = AF_INET;
X        ip->ip_hl = sizeof (struct ip) / 4;
X        ip->ip_v = 4;
X        ip->ip_tos = 0;
X        ip->ip_len = ENDIAN_RAW_BUG? len: htons(len);
X        ip->ip_id = htons(ip_id++);
X        ip->ip_off = 0;
X        ip->ip_ttl = 255;
X        ip->ip_p = IPPROTO_ICMP;
X        ip->ip_dst = in.sin_addr = iip->ip_src;
X        ip->ip_src = hop->hop;
X        ip->ip_sum = 0; /* let the os calculate it */
X        i->icmp_type = f_dest? ICMP_UNREACH: ICMP_TIMXCEED;
X        i->icmp_code = f_dest? ICMP_UNREACH_PORT: ICMP_TIMXCEED_INTRANS;
X        memcpy(&i->icmp_ip, iip, sizeof (struct ip)+8);
X        i->icmp_cksum = fast_icmp_cksum(i);
X        if (a_verbose>0)
X        {
X                printf("rotorouter: sending %s %s",
X                        f_dest? "ICMP_UNREACH_PORT": "ICMP_TIMXCEED",
X                        inet_ntoa(ip->ip_src));
X                printf(" -> %s for ttl %d\n",
X                        inet_ntoa(ip->ip_dst),
X                        iip->ip_ttl);
X        }
X        usleep(hop->latency);
X        if (sendto (raw, ip, len, 0, (struct sockaddr *)&in, sizeof in)!=len)
X                pexit("sendto");
X}
X
Xvoid
Xanalyze_udp(struct ip *ip)
X{
X        struct udphdr *u;
X        struct hop *hop;
X        struct udp_state *p;
X        static time_t lastclean;
X        time_t t;
X        u = (struct udphdr *)((char *)ip+ip->ip_hl*4);
X        hop = find_hop(ip->ip_dst, ip->ip_ttl);
X        if (!hop)
X                return;
X        for (p = state; p; p = p->next)
X        {
X                if (p->src.s_addr == ip->ip_src.s_addr &&
X                    p->sport == u->uh_sport &&
X                    p->dst.s_addr == ip->ip_dst.s_addr)
X                    goto found;
X        }
X        if (ip->ip_ttl > a_max_ttl)
X                return;
X        p = xmalloc(sizeof *p);
X        p->next = state;
X        p->src = ip->ip_src;
X        p->dst = ip->ip_dst;
X        p->sport = u->uh_sport;
X        state = p;
Xfound:
X        p->last_packet = t = time(NULL);
X        icmp_reply(ip, hop);
X        if (t > lastclean+10)
X        {
X                struct udp_state *prev = NULL;
X                for (p=state; p;)
X                {
X                        if (t > p->last_packet + a_timeout)
X                        {
X                                struct udp_state *p2 = p->next;
X                                if (prev)
X                                        prev->next = p->next;
X                                else
X                                        state = NULL;
X                                free (p);
X                                p = p2;
X                        } else
X                        {
X                                prev = p;
X                                p = p->next;
X                        }
X                }
X        }
X}
X
Xvoid
Xopen_raw()
X{
X        int yes = 1;
X        raw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
X        if (raw<0)
X                pexit("socket");
X        if (setsockopt(raw, IPPROTO_IP, IP_HDRINCL, (char *)&yes, sizeof(yes)) < 0)
X                pexit("IP_HDRINCL");
X}
X
Xvoid
Xpopulate_hops(char *fn)
X{
X        FILE *fh;
X        char host[32];
X        char hop[32];
X        struct hop *p;
X        int latency;
X        int ttl;
X        int rules;
X        fh = fopen(fn, "r");
X        if (!fh)
X                pexit(fn);
X        for (rules = 0; fscanf(fh, "%16s %d %16s %d%*[^\r\n]", host, &ttl, hop, &latency) == 4; rules++)
X        {
X                struct in_addr hostaddr, hopaddr;
X                hostaddr.s_addr = inet_addr(host);
X                if (hostaddr.s_addr == 0xffffffff)
X                {
X                        fprintf(stderr, "bad address: %s\n", host);
X                        exit(1);
X                }
X                hopaddr.s_addr = inet_addr(hop);
X                if (hopaddr.s_addr == 0xffffffff)
X                {
X                        fprintf(stderr, "bad address: %s\n", hop);
X                        exit(1);
X                }
X                p = malloc(sizeof *p);
X                p->dst = hostaddr;
X                p->hop = hopaddr;
X                p->ttl = ttl;
X                p->latency = latency;
X                p->next = hops;
X                hops = p;
X
X        }
X        fprintf(stderr, "%d rotorouter rules loaded\n", rules);
X}
X
Xvoid
Xusage(char *av0)
X{
X        exit(1);
X}
X
Xint
Xmain(int argc, char **argv)
X{
X        int c;
X        pcap_handler printer;
X        char *a_iface = NULL;
X        char *a_filter = "udp";
X        char *a_hops = "hops";
X        int a_usec = 50;
X        bool f_promisc = TRUE;
X        while ((c=getopt(argc, argv, "i:ph:u:n:v"))!=-1)
X        {
X                switch(c)
X                {
X                case 'i':
X                        a_iface = optarg;
X                        break;
X                case 'p':
X                        f_promisc = FALSE;
X                        break;
X                case 'h':
X                        a_hops = optarg;
X                        break;
X                case 'u':
X                        a_usec = atoi(optarg);
X                        break;
X                case 't':
X                        a_max_ttl = atoi(optarg);
X                        break;
X                case 'n':
X                        a_timeout = atoi(optarg);
X                        break;
X                case 'v':
X                        a_verbose++;
X                        break;
X                default:
X                        usage(argv[0]);
X                        /* NOT REACHED */
X                }
X        }
X        populate_hops(a_hops);
X        open_pcap(a_iface, f_promisc, a_filter, a_usec);
X        printer = lookup_printer(pcap_datalink(pd));
X        open_raw();
X        if (pcap_loop(pd, 0, printer, NULL) < 0)
X        {
X                fprintf(stderr, "%s: pcap_loop: %s\n",
X                    argv[0], pcap_geterr(pd));
X                exit(1);
X        }
X        pcap_close(pd);
X        exit(0);
X}
END-of-rotorouter/src/rotorouter.c
echo x - rotorouter/src/rotorouter.conf-example
sed 's/^X//' >rotorouter/src/rotorouter.conf-example << 'END-of-rotorouter/src/rotorouter.conf-example'
X137.39.1.3	0	10.1.0.1	5
X137.39.1.3	1	10.2.0.2	10
X137.39.1.3	2	172.31.1.1	10
X137.39.1.3	-1	172.31.1.2	15
END-of-rotorouter/src/rotorouter.conf-example
echo x - rotorouter/src/rotorouter.sh
sed 's/^X//' >rotorouter/src/rotorouter.sh << 'END-of-rotorouter/src/rotorouter.sh'
X#!/bin/sh
X#
X# $Id$
X#
X
X# PROVIDE: rotorouter
X# REQUIRE: DAEMON
X# BEFORE: LOGIN
X# KEYWORD: FreeBSD shutdown
X#
X# Add the following lines to /etc/rc.conf to enable rotorouter:
X#
X#   rotorouter_enable="YES"
X#
X# See rotorouter(8) for flags.
X#
X
X. %%RC_SUBR%%
X
Xname=rotorouter
Xrcvar=`set_rcvar`
X
Xcommand=%%PREFIX%%/sbin/${name}
X
X# set defaults
X
Xrotorouter_enable=${rotorouter_enable:-"NO"}
Xrotorouter_flags="${rotorouter_flags:--h %%PREFIX%%/etc/rotorouter.conf}"
X
Xrotorouter_flags="${rotorouter_flags} &"
X
Xload_rc_config $name
Xrun_rc_command "$1"
X
END-of-rotorouter/src/rotorouter.sh
exit
--- rotorouter.shar ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200405290549.i4T5nC1H000778>