示例#1
0
static int
test_ping(void)
{
	struct pkt *pkt;
	struct timeval tv;
	
	printf("ping: "); fflush(stdout);

	ping->pkt_icmp_msg->echo.icmp_id = rand_uint16(ctx.rnd);
	pkt = pkt_dup(ping);
	pkt->pkt_ip->ip_id = rand_uint16(ctx.rnd);
	ip_checksum(pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data);
	
	pcap_filter(ctx.pcap, "icmp[0] = 0 and src %s and dst %s",
	    addr_ntoa(&ctx.dst), addr_ntoa(&ctx.src));

	send_pkt(pkt);

	for (tv = read_tv; (pkt = recv_pkt(&tv)) != NULL; tv = read_tv) {
		if (memcmp(&pkt->pkt_icmp_msg->echo,
		    &ping->pkt_icmp_msg->echo, 8) == 0)
			break;
	}
	printf("%s\n", pkt ? timeval_ntoa(&tv) : "no reply");

	return (0);
}
示例#2
0
static int
pcap_read_haiku(pcap_t* handle, int maxPackets, pcap_handler callback,
	u_char* userdata)
{
	// Receive a single packet

	struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
	u_char* buffer = (u_char*)handle->buffer + handle->offset;
	struct sockaddr_dl from;
	ssize_t bytesReceived;
	do {
		if (handle->break_loop) {
			// Clear the break loop flag, and return -2 to indicate our
			// reasoning
			handle->break_loop = 0;
			return -2;
		}

		socklen_t fromLength = sizeof(from);
		bytesReceived = recvfrom(handle->fd, buffer, handle->bufsize, MSG_TRUNC,
			(struct sockaddr*)&from, &fromLength);
	} while (bytesReceived < 0 && errno == B_INTERRUPTED);

	if (bytesReceived < 0) {
		if (errno == B_WOULD_BLOCK) {
			// there is no packet for us
			return 0;
		}

		snprintf(handle->errbuf, sizeof(handle->errbuf),
			"recvfrom: %s", strerror(errno));
		return -1;
	}

	int32 captureLength = bytesReceived;
	if (captureLength > handle->snapshot)
		captureLength = handle->snapshot;

	// run the packet filter
	if (handle->fcode.bf_insns) {
		if (pcap_filter(handle->fcode.bf_insns, buffer, bytesReceived,
				captureLength) == 0) {
			// packet got rejected
			return 0;
		}
	}

	// fill in pcap_header
	pcap_pkthdr header;
	header.caplen = captureLength;
	header.len = bytesReceived;
	header.ts.tv_usec = system_time() % 1000000;
	header.ts.tv_sec = system_time() / 1000000;
	// TODO: get timing from packet!!!

	/* Call the user supplied callback function */
	callback(userdata, &header, buffer);
	return 1;
}
示例#3
0
static int
test_frag(char *overlap, int drop)
{
	struct timeval tv, save_tv = read_tv;
	struct pkt *pkt;
	struct icmp_msg_echo *echo;
	char *frag_argv[4];

	if (overlap != NULL)
		printf("frag-%s: ", overlap);
	else if (drop)
		printf("frag-timeout (please wait): ");
	else
		printf("frag: ");
	fflush(stdout);

	ping->pkt_ip->ip_id = rand_uint16(ctx.rnd);
	ping->pkt_icmp_msg->echo.icmp_id = rand_uint16(ctx.rnd);
	pkt = pkt_dup(ping);
	ip_checksum(pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data);
	TAILQ_INSERT_TAIL(&ctx.pktq, pkt, pkt_next);
	
	frag_argv[0] = "ip_frag";
	frag_argv[1] = "8";
	frag_argv[2] = overlap;
	frag_argv[3] = NULL;
	
	mod_ip_frag.open(overlap ? 3 : 2, frag_argv, NULL);
	mod_ip_frag.apply(NULL, &ctx.pktq, NULL);

	if (drop) {
		pkt = TAILQ_LAST(&ctx.pktq, pktq);
		TAILQ_REMOVE(&ctx.pktq, pkt, pkt_next);
		pkt_free(pkt);
		save_tv.tv_sec = FRAG_TIMEOUT;
	}
	pcap_filter(ctx.pcap, "icmp[0] = %d and src %s and dst %s",
	    drop ? 11 : 0, addr_ntoa(&ctx.dst), addr_ntoa(&ctx.src));

	send_pktq(&ctx.pktq);

	for (tv = save_tv; (pkt = recv_pkt(&tv)) != NULL; tv = save_tv) {
		if (drop) {
			echo = (struct icmp_msg_echo *)
			    (pkt->pkt_icmp_msg->timexceed.icmp_ip +
				IP_HDR_LEN + ICMP_HDR_LEN);
		} else {
			echo = &pkt->pkt_icmp_msg->echo;
		}
		if (echo->icmp_id == ping->pkt_icmp_msg->echo.icmp_id)
			break;
	}
	printf("%s\n", pkt ? timeval_ntoa(&tv) : "no reply");
	
	return (0);
}
示例#4
0
static int
test_ip_tracert(void)
{
	struct timeval tv;
	struct hop hops[IP_TTL_DEFAULT];
	struct pkt *pkt;
	struct icmp_msg_echo *echo;
	int i, hopcnt, max_ttl;

	printf("ip-tracert: "); fflush(stdout);

	pcap_filter(ctx.pcap, "icmp[0] = 0 and src %s and dst %s",
	    addr_ntoa(&ctx.dst), addr_ntoa(&ctx.src));
	
	ping->pkt_icmp_msg->echo.icmp_id = rand_uint16(ctx.rnd);
	pkt = pkt_dup(ping);
	pkt->pkt_ip->ip_id = rand_uint16(ctx.rnd);
	ip_checksum(pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data);
	
	send_pkt(pkt);
	tv = read_tv;
	
	if ((pkt = recv_pkt(&tv)) == NULL) {
		printf("no reply\n");
		return (0);
	}
	/* XXX - guess remote stack's starting TTL */
	for (i = 2; pkt->pkt_ip->ip_ttl > i; i <<= 1)
		;
	
	if ((max_ttl = i - pkt->pkt_ip->ip_ttl + 1) > IP_TTL_DEFAULT)
		max_ttl = IP_TTL_DEFAULT;

	printf("%s, %d hops max\n", ip_ntoa(&ping->pkt_ip->ip_dst), max_ttl);
	pcap_filter(ctx.pcap, "icmp and dst %s", addr_ntoa(&ctx.src));

	for (i = 1; i < max_ttl + 1; i++) {
		pkt = pkt_dup(ping);
		pkt->pkt_ip->ip_id = rand_uint16(ctx.rnd);
		pkt->pkt_ip->ip_ttl = i;
		pkt->pkt_icmp_msg->echo.icmp_seq = htons(i);
		ip_checksum(pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data);
		send_pkt(pkt);
		usleep(42);	/* XXX */
	}
	memset(&hops, 0, sizeof(hops));
	hopcnt = 0;
	
	for (tv = read_tv; (pkt = recv_pkt(&tv)) != NULL; tv = read_tv) {
		if ((pkt->pkt_icmp->icmp_type == ICMP_TIMEXCEED ||
		    pkt->pkt_icmp->icmp_type == ICMP_UNREACH) &&
		    pkt->pkt_end - pkt->pkt_eth_data >=
		    (IP_HDR_LEN + ICMP_LEN_MIN) * 2) {
			echo = (struct icmp_msg_echo *)
			    (pkt->pkt_icmp_msg->timexceed.icmp_ip +
				IP_HDR_LEN + ICMP_HDR_LEN);
		} else if (pkt->pkt_icmp->icmp_type == ICMP_ECHOREPLY) {
			echo = &pkt->pkt_icmp_msg->echo;
		} else
			continue;

		if (echo->icmp_id != ping->pkt_icmp_msg->echo.icmp_id)
			continue;
		
		i = ntohs(echo->icmp_seq);
		addr_pack(&hops[i].addr, ADDR_TYPE_IP, IP_ADDR_BITS,
		    &pkt->pkt_ip->ip_src, IP_ADDR_LEN);
		memcpy(&hops[i].icmp, pkt->pkt_icmp, ICMP_HDR_LEN);
		hops[i].ttl = pkt->pkt_ip->ip_ttl;
		hopcnt++;
		
		if (pkt->pkt_ip->ip_src == ping->pkt_ip->ip_dst)
			break;
	}
	for (i = 1; i < hopcnt + 1; i++) {
		if (hops[i].addr.addr_type == ADDR_TYPE_IP) {
			printf("%2d  %s (%d)\n",
			    i, addr_ntoa(&hops[i].addr), hops[i].ttl);
		} else
			printf("%2d  *\n", i);
	}
	return (0);
}
示例#5
0
static int
test_ip_opt(void)
{
	struct pkt *pkt;
	struct timeval tv;
	struct ip_opt opts[IP_OPT_MAX];
	int i, len, max;
	
	printf("ip-opt: "); fflush(stdout);
	
	memset(&opts, 0, sizeof(opts));
	max = 0;
	opts[max].opt_type = IP_OPT_SEC;
	opts[max].opt_len = IP_OPT_LEN + 9;
	max++;
	opts[max].opt_type = IP_OPT_LSRR;
	opts[max].opt_len = IP_OPT_LEN + 1 + 4;
	opts[max].opt_data.rr.ptr = 8;
	opts[max].opt_data.rr.iplist[0] = ping->pkt_ip->ip_src;
	max++;
	opts[max].opt_type = IP_OPT_TS;
	opts[max].opt_len = IP_OPT_LEN + 1 + 1 + 4;
	opts[max].opt_data.ts.ptr = 5;
	opts[max].opt_data.ts.flg = IP_OPT_TS_TSONLY;
	max++;
	opts[max].opt_type = IP_OPT_ESEC;
	opts[max].opt_len = IP_OPT_LEN;
	max++;
	opts[max].opt_type = IP_OPT_CIPSO;
	opts[max].opt_len = IP_OPT_LEN;
	max++;
	opts[max].opt_type = IP_OPT_RR;
	opts[max].opt_len = IP_OPT_LEN + 1 + 4;
	opts[max].opt_data.rr.ptr = 4;
	max++;
	opts[max].opt_type = IP_OPT_SATID;
	opts[max].opt_len = IP_OPT_LEN + 2;
	max++;
	opts[max].opt_type = IP_OPT_SSRR;
	opts[max].opt_len = IP_OPT_LEN + 1 + 4;
	opts[max].opt_data.rr.ptr = 8;
	opts[max].opt_data.rr.iplist[0] = ping->pkt_ip->ip_src;
	max++;
	
	pcap_filter(ctx.pcap, "icmp and src %s and dst %s",
	    addr_ntoa(&ctx.dst), addr_ntoa(&ctx.src));

	ping->pkt_icmp_msg->echo.icmp_id = rand_uint16(ctx.rnd);
	
	for (i = 0; i < max; i++) {
		pkt = pkt_dup(ping);
		pkt->pkt_ip->ip_id = rand_uint16(ctx.rnd);
		pkt->pkt_icmp_msg->echo.icmp_seq = opts[i].opt_type;
		len = ip_add_option(pkt->pkt_ip, PKT_BUF_LEN - ETH_HDR_LEN +
		    IP_HDR_LEN, IP_PROTO_IP, &opts[i], opts[i].opt_len);
		pkt->pkt_end += len;
		
		ip_checksum(pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data);
		
		send_pkt(pkt);
	}
	i = 0;
	for (tv = read_tv; (pkt = recv_pkt(&tv)) != NULL; tv = read_tv) {
		if (pkt->pkt_icmp->icmp_type == ICMP_ECHOREPLY &&
		    pkt->pkt_icmp_msg->echo.icmp_id ==
		    ping->pkt_icmp_msg->echo.icmp_id) {
			i = IP_OPT_NUMBER(pkt->pkt_icmp_msg->echo.icmp_seq);
			printf("%s ", optnames[i]);
		}
	}
	printf("%s\n", i ? "" : "none");
	
	return (0);
}
static int
netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
	struct pcap_netfilter *handlep = handle->priv;
	register u_char *bp, *ep;
	int count = 0;
	ssize_t len;

	/*
	 * Has "pcap_breakloop()" been called?
	 */
	if (handle->break_loop) {
		/*
		 * Yes - clear the flag that indicates that it
		 * has, and return PCAP_ERROR_BREAK to indicate
		 * that we were told to break out of the loop.
		 */
		handle->break_loop = 0;
		return PCAP_ERROR_BREAK;
	}
	len = handle->cc;
	if (len == 0) {
		/*
		 * The buffer is empty; refill it.
		 *
		 * We ignore EINTR, as that might just be due to a signal
		 * being delivered - if the signal should interrupt the
		 * loop, the signal handler should call pcap_breakloop()
		 * to set handle->break_loop (we ignore it on other
		 * platforms as well).
		 */
		do {
			len = recv(handle->fd, handle->buffer, handle->bufsize, 0);
			if (handle->break_loop) {
				handle->break_loop = 0;
				return PCAP_ERROR_BREAK;
			}
			if (errno == ENOBUFS)
				handlep->packets_nobufs++;
		} while ((len == -1) && (errno == EINTR || errno == ENOBUFS));

		if (len < 0) {
			pcap_fmt_errmsg_for_errno(handle->errbuf,
			    PCAP_ERRBUF_SIZE, errno, "Can't receive packet");
			return PCAP_ERROR;
		}

		bp = (unsigned char *)handle->buffer;
	} else
		bp = handle->bp;
	ep = bp + len;
	while (bp < ep) {
		const struct nlmsghdr *nlh = (const struct nlmsghdr *) bp;
		uint32_t msg_len;
		nftype_t type = OTHER;
		/*
		 * Has "pcap_breakloop()" been called?
		 * If so, return immediately - if we haven't read any
		 * packets, clear the flag and return PCAP_ERROR_BREAK
		 * to indicate that we were told to break out of the loop,
		 * otherwise leave the flag set, so that the *next* call
		 * will break out of the loop without having read any
		 * packets, and return the number of packets we've
		 * processed so far.
		 */
		if (handle->break_loop) {
			handle->bp = bp;
			handle->cc = (int)(ep - bp);
			if (count == 0) {
				handle->break_loop = 0;
				return PCAP_ERROR_BREAK;
			} else
				return count;
		}
		if (ep - bp < NLMSG_SPACE(0)) {
			/*
			 * There's less than one netlink message left
			 * in the buffer.  Give up.
			 */
			break;
		}

		if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || (u_int)len < nlh->nlmsg_len) {
			pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %zd) (nlmsg_len: %u)", len, nlh->nlmsg_len);
			return -1;
		}

		if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG &&
		    NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET)
			type = NFLOG;
		else if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE &&
		         NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET)
			type = NFQUEUE;

		if (type != OTHER) {
			const unsigned char *payload = NULL;
			struct pcap_pkthdr pkth;

			const struct nfgenmsg *nfg = NULL;
			int id = 0;

			if (handle->linktype != DLT_NFLOG) {
				const struct nfattr *payload_attr = NULL;

				if (nlh->nlmsg_len < HDR_LENGTH) {
					pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
					return -1;
				}

				nfg = NLMSG_DATA(nlh);
				if (nlh->nlmsg_len > HDR_LENGTH) {
					struct nfattr *attr = NFM_NFA(nfg);
					int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH);

					while (NFA_OK(attr, attr_len)) {
						if (type == NFQUEUE) {
							switch (NFA_TYPE(attr)) {
								case NFQA_PACKET_HDR:
									{
										const struct nfqnl_msg_packet_hdr *pkt_hdr = (const struct nfqnl_msg_packet_hdr *) NFA_DATA(attr);

										id = ntohl(pkt_hdr->packet_id);
										break;
									}
								case NFQA_PAYLOAD:
									payload_attr = attr;
									break;
							}

						} else if (type == NFLOG) {
							switch (NFA_TYPE(attr)) {
								case NFULA_PAYLOAD:
									payload_attr = attr;
									break;
							}
						}
						attr = NFA_NEXT(attr, attr_len);
					}
				}

				if (payload_attr) {
					payload = NFA_DATA(payload_attr);
					pkth.len = pkth.caplen = NFA_PAYLOAD(payload_attr);
				}

			} else {
				payload = NLMSG_DATA(nlh);
				pkth.caplen = pkth.len = nlh->nlmsg_len-NLMSG_ALIGN(sizeof(struct nlmsghdr));
			}

			if (payload) {
				/* pkth.caplen = min (payload_len, handle->snapshot); */

				gettimeofday(&pkth.ts, NULL);
				if (handle->fcode.bf_insns == NULL ||
						pcap_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
				{
					handlep->packets_read++;
					callback(user, &pkth, payload);
					count++;
				}
			}

			if (type == NFQUEUE) {
				/* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */
				/* if type == NFQUEUE, handle->linktype is always != DLT_NFLOG,
				   so nfg is always initialized to NLMSG_DATA(nlh). */
				if (nfg != NULL)
					nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT);
			}
		}

		msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
		/*
		 * If the message length would run past the end of the
		 * buffer, truncate it to the remaining space in the
		 * buffer.
		 */
		if (msg_len > ep - bp)
			msg_len = (uint32_t)(ep - bp);

		bp += msg_len;
		if (count >= max_packets && !PACKET_COUNT_IS_UNLIMITED(max_packets)) {
			handle->bp = bp;
			handle->cc = (int)(ep - bp);
			if (handle->cc < 0)
				handle->cc = 0;
			return count;
		}
	}

	handle->cc = 0;
	return count;
}
示例#7
0
static int
rdmasniff_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
{
	struct pcap_rdmasniff *priv = handle->priv;
	struct ibv_cq *ev_cq;
	void *ev_ctx;
	struct ibv_wc wc;
	struct pcap_pkthdr pkth;
	u_char *pktd;
	int count = 0;

	if (!priv->cq_event) {
		while (ibv_get_cq_event(priv->channel, &ev_cq, &ev_ctx) < 0) {
			if (errno != EINTR) {
				return PCAP_ERROR;
			}
			if (handle->break_loop) {
				handle->break_loop = 0;
				return PCAP_ERROR_BREAK;
			}
		}
		ibv_ack_cq_events(priv->cq, 1);
		ibv_req_notify_cq(priv->cq, 0);
		priv->cq_event = 1;
	}

	while (count < max_packets || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
		if (ibv_poll_cq(priv->cq, 1, &wc) != 1) {
			priv->cq_event = 0;
			break;
		}

		if (wc.status != IBV_WC_SUCCESS) {
			fprintf(stderr, "failed WC wr_id %lld status %d/%s\n",
				(unsigned long long) wc.wr_id,
				wc.status, ibv_wc_status_str(wc.status));
			continue;
		}

		pkth.len = wc.byte_len;
		pkth.caplen = min(pkth.len, (u_int)handle->snapshot);
		gettimeofday(&pkth.ts, NULL);

		pktd = (u_char *) handle->buffer + wc.wr_id * RDMASNIFF_RECEIVE_SIZE;

		if (handle->fcode.bf_insns == NULL ||
		    pcap_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
			callback(user, &pkth, pktd);
			++priv->packets_recv;
			++count;
		}

		rdmasniff_post_recv(handle, wc.wr_id);

		if (handle->break_loop) {
			handle->break_loop = 0;
			return PCAP_ERROR_BREAK;
		}
	}

	return count;
}