예제 #1
0
static void
fragroute_process(const struct pcap_pkthdr *hdr, void *buf, size_t len, void *arg)
{
    struct pktq pktq;
    struct pkt *pkt, *next;
    
    if ((pkt = pkt_new()) == NULL) {
        warn("pkt_new");
        return;
    }
    if (ETH_HDR_LEN + len > PKT_BUF_LEN) {
        warn("dropping oversized packet");
        return;
    }
    memcpy(pkt->pkt_data + ETH_HDR_LEN, buf, len);
    pkt->pkt_end = pkt->pkt_data + ETH_HDR_LEN + len;

    pkt_decorate(pkt);
    
    if (pkt->pkt_ip == NULL) {
        warn("dropping non-IP packet");
        return;
    }
    eth_pack_hdr(pkt->pkt_eth, ctx.dmac.addr_eth,
        ctx.smac.addr_eth, ETH_TYPE_IP);
    
    pkt->pkt_ip->ip_src = ctx.src.addr_ip;
    ip_checksum(pkt->pkt_ip, len);

    /* Forward this packet along as is. */
    if(ctx.dfile && 
       eth_send(ctx.eth, pkt->pkt_data, pkt->pkt_end - pkt->pkt_data) < 0)
        warn("eth_send");

    TAILQ_INIT(&pktq);
    TAILQ_INSERT_TAIL(&pktq, pkt, pkt_next);
    
    mod_apply(&pktq);

    for (pkt = TAILQ_FIRST(&pktq); pkt != TAILQ_END(&pktq); pkt = next) {
        next = TAILQ_NEXT(pkt, pkt_next);
        _resend_outgoing(pkt);
    }

}
예제 #2
0
int
ip_opt_apply(void *d, struct pktq *pktq)
{
	struct ip_opt *opt = (struct ip_opt *)d;
	struct pkt *pkt;
	size_t len;

	TAILQ_FOREACH(pkt, pktq, pkt_next) {
		len = ip_add_option(pkt->pkt_ip, PKT_BUF_LEN - ETH_HDR_LEN,
		    IP_PROTO_IP, opt, opt->opt_len);

		if (len > 0) {
			pkt->pkt_end += len;
			pkt_decorate(pkt);
			ip_checksum(pkt->pkt_ip,
			    pkt->pkt_end - pkt->pkt_eth_data);
		}
	}
예제 #3
0
int
tcp_opt_apply(void *d, struct pktq *pktq, struct rule **next_rule)
{
	struct tcp_opt *opt = (struct tcp_opt *)d;
	struct pkt *pkt;
	size_t len;

	TAILQ_FOREACH(pkt, pktq, pkt_next) {
		uint16_t eth_type = htons(pkt->pkt_eth->eth_type);

		len = inet_add_option(eth_type, pkt->pkt_ip,
				sizeof(pkt->pkt_data) - ETH_HDR_LEN,
				IP_PROTO_TCP, opt, opt->opt_len);

		if (len > 0) {
			pkt->pkt_end += len;
			pkt_decorate(pkt);
			inet_checksum(eth_type, pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data);
		}
	}
예제 #4
0
static struct pkt *
recv_pkt(struct timeval *tv)
{
	struct pcap_pkthdr phdr;
	struct timeval now, start;
	struct pkt *pkt;
	u_char *p;
	long timeout_usec;
	int i;
	
	timeout_usec = tv->tv_sec * 1000000 + tv->tv_usec;
	gettimeofday(&start, NULL);
	
	/*
	 * XXX - can't select() on pcap_fileno on Solaris,
	 * seems to be unreliable on Linux as well. *sigh*
	 */
	for (;;) {
		gettimeofday(&now, NULL);
		
		if ((p = (u_char *)pcap_next(ctx.pcap, &phdr)) != NULL ||
		    (now.tv_sec - start.tv_sec) * 1000000 +
		    now.tv_usec - start.tv_usec > timeout_usec)
			break;
	}
	if (p == NULL)
		return (NULL);
	
	p += ctx.dloff;
	i = phdr.caplen - ctx.dloff;
	
	pkt = pkt_new();
	memcpy(pkt->pkt_eth_data, p, i);
	pkt->pkt_end = pkt->pkt_eth_data + i;
	pkt_decorate(pkt);
	
	tv->tv_sec = phdr.ts.tv_sec - start.tv_sec;
	tv->tv_usec = phdr.ts.tv_usec - start.tv_usec;
	
	return (pkt);
}
예제 #5
0
int
ip6_opt_apply(void *d, struct pktq *pktq)
{
	struct ip6_opt_data *opt = (struct ip6_opt_data *)d;
	struct __ip6_ext_data_routing* route;
	struct ip6_ext_hdr* ext;
	int offset, len;
	struct pkt *pkt;
	uint8_t nxt, iph_nxt;
	uint8_t* p;
	int i;

	TAILQ_FOREACH(pkt, pktq, pkt_next) {
		uint16_t eth_type = htons(pkt->pkt_eth->eth_type);

		if (eth_type != ETH_TYPE_IPV6) {
			continue;
		}

		nxt = pkt->pkt_ip6->ip6_nxt;
		ext = (struct ip6_ext_hdr*)(((u_char*)pkt->pkt_ip6) + IP6_HDR_LEN);

		if (opt->type == OPT6_TYPE_ROUTE) {
			offset = 8 + IP6_ADDR_LEN * opt->u.route.segments;
			memmove(((u_char*)ext) + offset, ext, pkt->pkt_end - (u_char*)ext);

			pkt->pkt_end += offset;
			pkt->pkt_ip_data += offset;

			len = (IP6_ADDR_LEN / 8) * opt->u.route.segments;

			route = (struct __ip6_ext_data_routing*)ext;

			ext->ext_data.routing.type = 0;
			ext->ext_data.routing.segleft = opt->u.route.segments;
			((uint32_t*)ext)[1] = 0; /* reserved */

			iph_nxt = IP_PROTO_ROUTING;

			p = (uint8_t*)(ext) + 8;

			for (i = 0; i < opt->u.route.segments; ++i, p += IP6_ADDR_LEN) {
				memcpy(p, opt->u.route.addr[i].addr_data8, IP6_ADDR_LEN);
			}

		} else if (opt->type == OPT6_TYPE_RAW) {
			offset = opt->u.raw.len;
			memmove(((u_char*)ext) + offset, ext, pkt->pkt_end - (u_char*)ext);

			pkt->pkt_end += offset;
			pkt->pkt_ip_data += offset;

			iph_nxt = opt->u.raw.proto;

			p = (uint8_t*)ext;
			memcpy(p, opt->u.raw.data8, opt->u.raw.len);

#if 0
			printf("len: %d, data %02x %02x %02x %02x %02x %02x %02x %02x\n",
					opt->u.raw.len, opt->u.raw.data8[0], opt->u.raw.data8[1],
					opt->u.raw.data8[2], opt->u.raw.data8[3],
					opt->u.raw.data8[4], opt->u.raw.data8[5],
					opt->u.raw.data8[6], opt->u.raw.data8[7]);
#endif

			len = (opt->u.raw.len - 8) / 8;

		} else {
			continue;
		}

		ext->ext_nxt = nxt;
		ext->ext_len = len;

		pkt->pkt_ip6->ip6_nxt = iph_nxt;
		pkt->pkt_ip6->ip6_plen = htons(htons(pkt->pkt_ip6->ip6_plen) + offset);

		/* XXX: do we need it? */
		pkt_decorate(pkt);
		/* ip6_checksum(pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data); */
	}
예제 #6
0
int
main(int argc, char *argv[])
{
	struct intf_entry ifent;
	intf_t *intf;
	int i, tests;
	char *cmd;
	
	if (argc < 3)
		usage();

	for (tests = 0, i = 1; i < argc - 1; i++) {
		cmd = argv[i];
		
		if (strcmp(cmd, "all") == 0)
			tests = ~0;
		else if (strcmp(cmd, "ping") == 0)
			tests |= TEST_PING;
		else if (strcmp(cmd, "ip-opt") == 0)
			tests |= TEST_IP_OPT;
		else if (strcmp(cmd, "ip-tracert") == 0)
			tests |= TEST_IP_TRACERT;
		else if (strcmp(cmd, "frag") == 0)
			tests |= TEST_FRAG;
		else if (strcmp(cmd, "frag-new") == 0)
			tests |= TEST_FRAG_NEW;
		else if (strcmp(cmd, "frag-old") == 0)
			tests |= TEST_FRAG_OLD;
		else if (strcmp(cmd, "frag-timeout") == 0)
			tests |= TEST_FRAG_TIMEOUT;
		else
			usage();
	}
	if (addr_aton(argv[i], &ctx.dst) < 0)
		err(1, "invalid host %s", argv[i]);

	if ((intf = intf_open()) == NULL)
		err(1, "couldn't open interface handle");

	ifent.intf_len = sizeof(ifent);
	
	if (intf_get_dst(intf, &ifent, &ctx.dst) < 0)
		err(1, "couldn't find interface for %s", addr_ntoa(&ctx.dst));
	
	memcpy(&ctx.src, &ifent.intf_addr, sizeof(ctx.src));
	ctx.src.addr_bits = IP_ADDR_BITS;
	
	intf_close(intf);
	
	if ((ctx.ip = ip_open()) == NULL)
		err(1, "couldn't open raw IP interface");

	if ((ctx.pcap = pcap_open(ifent.intf_name)) == NULL)
		err(1, "couldn't open %s for sniffing", ifent.intf_name);
	
	if ((ctx.dloff = pcap_dloff(ctx.pcap)) < 0)
		err(1, "couldn't determine link layer offset");
	
	ctx.rnd = rand_open();
	pkt_init(16);
	TAILQ_INIT(&ctx.pktq);

	ping = pkt_new();
	ip_pack_hdr(ping->pkt_ip, 0, IP_HDR_LEN + 8 + 24, 666, 0,
	    IP_TTL_DEFAULT, IP_PROTO_ICMP, ctx.src.addr_ip, ctx.dst.addr_ip);
	icmp_pack_hdr_echo(ping->pkt_icmp, ICMP_ECHO, ICMP_CODE_NONE,
	    666, 1, "AAAAAAAABBBBBBBBCCCCCCCC", 24);
	ping->pkt_end = ping->pkt_eth_data + IP_HDR_LEN + 8 + 24;
	pkt_decorate(ping);
	
	if ((tests & TEST_PING) != 0)
		test_ping();
	if ((tests & TEST_IP_OPT) != 0)
		test_ip_opt();
	if ((tests & TEST_IP_TRACERT) != 0)
		test_ip_tracert();
	if ((tests & TEST_FRAG) != 0)
		test_frag(NULL, 0);
	if ((tests & TEST_FRAG_NEW) != 0)
		test_frag("new", 0);
	if ((tests & TEST_FRAG_OLD) != 0)
		test_frag("old", 0);
	if ((tests & TEST_FRAG_TIMEOUT) != 0)
		test_frag(NULL, 1);

	rand_close(ctx.rnd);
	pcap_close(ctx.pcap);
	ip_close(ctx.ip);
	
	exit(0);
}