⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod-tcpconn.c

📁 linux下traceroute的实现
💻 C
字号:
/*    Copyright (c)  2006, 2007		Dmitry Butskoy					<buc@citadel.stu.neva.ru>    License:  GPL v2 or any later    See COPYING for the status of this software.*/#include <stdlib.h>#include <unistd.h>#include <sys/socket.h>#include <sys/poll.h>#include <netinet/icmp6.h>#include <netinet/ip_icmp.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/ip6.h>#include <netinet/tcp.h>#include <errno.h>#include "traceroute.h"static sockaddr_any dest_addr = {{ 0, }, };static int icmp_sk = -1;static int tcp_init (const sockaddr_any *dest,			    unsigned int port_seq, size_t *packet_len_p) {	int af = dest->sa.sa_family;	dest_addr = *dest;	dest_addr.sin.sin_port = htons (DEF_TCP_PORT);	if (port_seq)	    dest_addr.sin.sin_port = htons (port_seq);	/*  Currently an ICMP socket is the only way	  to obtain the needed info...	*/	icmp_sk = socket (af, SOCK_RAW, (af == AF_INET) ? IPPROTO_ICMP							: IPPROTO_ICMPV6);	if (icmp_sk < 0)		error ("socket");	/*  icmp_sk not need full tune_socket() here, just a receiving one  */	bind_socket (icmp_sk);	use_timestamp (icmp_sk);	use_recv_ttl (icmp_sk);	add_poll (icmp_sk, POLLIN);	return 0;}static void tcp_send_probe (probe *pb, int ttl) {	int sk;	int af = dest_addr.sa.sa_family;	sockaddr_any addr;	socklen_t length = sizeof (addr);	sk = socket (af, SOCK_STREAM, 0);	if (sk < 0)  error ("socket");	tune_socket (sk);	/*  common stuff   */	set_ttl (sk, ttl);	pb->send_time = get_time ();	if (connect (sk, &dest_addr.sa, sizeof (dest_addr)) < 0) {	    if (errno != EINPROGRESS)		    error ("connect");	}	if (getsockname (sk, &addr.sa, &length) < 0)		error ("getsockname");	pb->seq = addr.sin.sin_port;	/*  both ipv4/ipv6  */	pb->sk = sk;	add_poll (sk, POLLERR | POLLHUP | POLLOUT);	return;}static probe *tcp_check_reply (int sk, int err, sockaddr_any *from,						    char *buf, size_t len) {	int af = dest_addr.sa.sa_family;	int type, code, info;	probe *pb;	struct tcphdr *tcp;	if (len < sizeof (struct icmphdr))		return NULL;	if (af == AF_INET) {	    struct icmp *icmp = (struct icmp *) buf;	    struct iphdr *ip;	    int hlen;	    type = icmp->icmp_type;	    code = icmp->icmp_code;	    info = icmp->icmp_void;	    if (type != ICMP_TIME_EXCEEDED && type != ICMP_DEST_UNREACH)		    return NULL;	    if (len < sizeof (struct icmphdr) + sizeof (struct iphdr) + 8)		    /* `8' - rfc1122: 3.2.2  */		    return NULL;	    ip = (struct iphdr *) (((char *)icmp) + sizeof(struct icmphdr));	    hlen = ip->ihl << 2;	    if (len < sizeof (struct icmphdr) + hlen + 8)		    return NULL;	    if (ip->protocol != IPPROTO_TCP)		    return NULL;	    tcp = (struct tcphdr *) (((char *) ip) + hlen);	}	else {	    /*  AF_INET6   */	    struct icmp6_hdr *icmp6 = (struct icmp6_hdr *) buf;	    struct ip6_hdr *ip6;	    type = icmp6->icmp6_type;	    code = icmp6->icmp6_code;	    info = icmp6->icmp6_mtu;	    if (type != ICMP6_TIME_EXCEEDED &&		type != ICMP6_DST_UNREACH &&		type != ICMP6_PACKET_TOO_BIG	    )  return NULL;	    if (len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr) + 8)		    return NULL;	    ip6 = (struct ip6_hdr *) (icmp6 + 1);	    if (ip6->ip6_nxt != IPPROTO_TCP)		    return NULL;	    tcp = (struct tcphdr *) (ip6 + 1);	}	if (tcp->dest != dest_addr.sin.sin_port)		return NULL;	pb = probe_by_seq (tcp->source);	if (!pb)  return NULL;	/*  here only, high level has no data to do this   */	parse_icmp_res (pb, type, code, info);	return pb;}static void tcp_recv_probe (int sk, int revents) {	if (sk != icmp_sk) {	/*  a tcp socket   */	    probe *pb;	    pb = probe_by_sk (sk);	    if (!pb) {		del_poll (sk);		return;	    }	    /*  do connect() again and check errno, regardless of revents  */	    if (connect (sk, &dest_addr.sa, sizeof (dest_addr)) < 0) {		if (errno != EISCONN && errno != ECONNREFUSED)			return;	/*  ICMP say more   */	    }	    /*  we have reached the dest host (either connected or refused)  */	    memcpy (&pb->res, &dest_addr, sizeof (pb->res));	    pb->final = 1;	    pb->recv_time = get_time ();	    probe_done (pb);	    return;	}	/*  ICMP stuff   */	if (!(revents & POLLIN))		return;	recv_reply (icmp_sk, 0, tcp_check_reply);}static void tcp_expire_probe (probe *pb) {	probe_done (pb);}static tr_module tcp_ops = {	.name = "tcpconn",	.init = tcp_init,	.send_probe = tcp_send_probe,	.recv_probe = tcp_recv_probe,	.expire_probe = tcp_expire_probe,	.user = 0,};TR_MODULE (tcp_ops);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -