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

📄 drcom.c

📁 校园网拨号端软件
💻 C
📖 第 1 页 / 共 2 页
字号:
		todo = TODO_NONE;		goto out;	}	*/	/* Handshake ACK with data*/	if (oldtcpstate == TCP_STATE_SYN_RECV && skb->len > hdrlen && dir == CONN_DIR_ORIG		    && tcph->ack && !tcph->syn 		    && (ntohl(tcph->ack_seq) == conn->seq[!dir].syn_seq+1)		    && (ntohl(tcph->seq) == conn->seq[dir].syn_seq+1)		    && !(conn->flags & CONN_F_AUTHSENT))	{		todo = TODO_SEND_ACK | TODO_SEND_AUTH | TODO_ADJUST_SEQ;		conn->flags |= CONN_F_AUTHSENT;		goto out;	}	/* The first data packet */	if (oldtcpstate == TCP_STATE_ESTABLISHED && skb->len > hdrlen && dir == CONN_DIR_ORIG		    && tcph->ack && !tcph->syn 		/*    && (ntohl(tcph->ack_seq) == conn->seq[!dir].syn_seq+1) *//* ftp server will send first */		    && (ntohl(tcph->seq) == conn->seq[dir].syn_seq+1)		    && !(conn->flags & CONN_F_AUTHSENT))	{		todo = TODO_SEND_AUTH | TODO_ADJUST_SEQ;		conn->flags |= CONN_F_AUTHSENT;		goto out;	}	/*	 * CONN_F_AUTHSENT not set, 	 * and not the case to set CONN_F_AUTHSENT, 	 * just bypass	 */	todo = TODO_NONE;out:	__conn_refresh_timer(conn, tcp_timeouts[newstate]);	write_unlock_bh(&state_lock);	return todo;}static struct sk_buff *build_ack_skb(struct sk_buff *oskb){	struct iphdr *iph;	struct tcphdr *tcph;	struct sk_buff *skb;	/* FIXME: Can we avoid the copy here? */	skb = skb_copy(oskb, GFP_ATOMIC);	if (skb == NULL)		return NULL;	iph = ip_hdr(skb);	tcph = (void *)skb->data + ip_hdrlen(skb);	skb_trim(skb, (iph->ihl + tcph->doff) * 4);	skb_shinfo(skb)->gso_segs = 1;	skb_shinfo(skb)->gso_size = 0;	skb_shinfo(skb)->gso_type = 0;	skb->ip_summed = CHECKSUM_NONE;	skb->csum = 0;	tcph->check = 0;	tcph->check = tcp_v4_check(tcph->doff << 2, iph->saddr, iph->daddr, 					csum_partial((char *)tcph, tcph->doff << 2, skb->csum));	iph->tot_len = htons(skb->len);	__ip_select_ident(iph, skb->dst, 0);	ip_send_check(iph);	return skb;}static struct sk_buff *build_auth_skb(struct sk_buff *oskb){	struct iphdr *iph;	struct tcphdr *tcph;	unsigned int hdrlen;	struct sk_buff *skb;	/* FIXME: Can we avoid the copy here? */	skb = skb_copy_expand(oskb, skb_headroom(oskb), CONN_AUTH_DATA_LEN, GFP_ATOMIC);	if (skb == NULL)		return NULL;	iph = ip_hdr(skb);	tcph = (void *)skb->data + ip_hdrlen(skb);	hdrlen = (iph->ihl + tcph->doff) * 4;	skb_trim(skb, hdrlen);	skb_put(skb, CONN_AUTH_DATA_LEN);	memcpy(skb->data + hdrlen, conn_auth_data, CONN_AUTH_DATA_LEN);	skb_shinfo(skb)->gso_segs = 1;	skb_shinfo(skb)->gso_size = 0;	skb_shinfo(skb)->gso_type = 0;	skb->ip_summed = CHECKSUM_NONE;	skb->csum = 0;	tcph->check = 0;	tcph->check = tcp_v4_check(skb->len-ip_hdrlen(skb), iph->saddr, iph->daddr, 					csum_partial((char *)tcph, skb->len-ip_hdrlen(skb), skb->csum));	iph->tot_len = htons(skb->len);	__ip_select_ident(iph, skb->dst, 0);	ip_send_check(iph);	return skb;}static inline int is_our_packet(struct sk_buff *skb){	struct iphdr *iph = ip_hdr(skb);	return (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP);}static inline int is_udp_packet(struct sk_buff *skb){	struct iphdr *iph = ip_hdr(skb);	return (iph->protocol == IPPROTO_UDP);}static void conn_do_udp(struct sk_buff *oskb, int (*okfn)(struct sk_buff *)){	struct sk_buff *skb;	struct iphdr *iph;	struct udphdr *udph;	unsigned short len;	/* FIXME: Can we avoid the copy here? */	skb = skb_copy_expand(oskb, skb_headroom(oskb) + CONN_AUTH_DATA_LEN, 0, GFP_ATOMIC);	if (skb == NULL)		return;	kfree_skb(oskb);	iph = ip_hdr(skb);	udph = (void *)iph + ip_hdrlen(skb);	memcpy((void *)iph-CONN_AUTH_DATA_LEN, (void*)iph, ip_hdrlen(skb)+8);	memcpy((void*)udph+8-CONN_AUTH_DATA_LEN, conn_auth_data, CONN_AUTH_DATA_LEN);	skb_push(skb, CONN_AUTH_DATA_LEN);	skb_reset_network_header(skb);	iph = ip_hdr(skb);	udph = (void *)iph + ip_hdrlen(skb);	skb_shinfo(skb)->gso_segs = 1;	skb_shinfo(skb)->gso_size = 0;	skb_shinfo(skb)->gso_type = 0;	skb->ip_summed = CHECKSUM_NONE;	skb->csum = 0;	len = ntohs(udph->len) + CONN_AUTH_DATA_LEN;	udph->len = htons(len);	udph->check = 0;	udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, len, IPPROTO_UDP, 					csum_partial((unsigned char *)udph, len, 0));	/* ip stuff */	iph->tot_len = htons(skb->len);	ip_send_check(iph);	okfn(skb);}static int need_auth_input(struct sk_buff *skb){	u_int32_t saddr = ip_hdr(skb)->saddr;	int i;	for (i=0; i<conn_e_count; i++) 		if ((conn_e_addr[i].mask & saddr) == conn_e_addr[i].addr)			return 0;	return 1;}static int need_auth_output(struct sk_buff *skb){	u_int32_t daddr = ip_hdr(skb)->daddr;	int i;	for (i=0; i<conn_e_count; i++) 		if ((conn_e_addr[i].mask & daddr) == conn_e_addr[i].addr)			return 0;	return 1;}#define CONN_KEEPALIVE_TIMEOUT	(2*60*HZ)#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)#define kill_proc(pid, sig, priv)	kill_pid(find_vpid(pid), sig, priv)#endifstatic void keepalive_func(unsigned long ul){	read_lock_bh(&mode_lock);	if (track_mode != CONN_MODE_NONE && conn_autologout && conn_pid)		kill_proc(conn_pid, SIGUSR1, 1);	read_unlock_bh(&mode_lock);}static void init_keepalive_timer(void){	read_lock_bh(&mode_lock);	if (track_mode != CONN_MODE_NONE && conn_autologout) {		setup_timer(&conn_keepalive_timer, keepalive_func, 0);		conn_keepalive_timer.expires = jiffies+CONN_KEEPALIVE_TIMEOUT;		add_timer(&conn_keepalive_timer);	}	read_unlock_bh(&mode_lock);}/* under mode_lock */static void __refresh_keepalive_timer(void){	if (conn_autologout)		mod_timer(&conn_keepalive_timer, jiffies+CONN_KEEPALIVE_TIMEOUT);}static void del_keepalive_timer(void){	read_lock_bh(&mode_lock);	del_timer(&conn_keepalive_timer);	read_unlock_bh(&mode_lock);}static unsigned int preroute_hook(unsigned int hooknum,				struct sk_buff *skb,				const struct net_device *in,				const struct net_device *out,				int (*okfn)(struct sk_buff *)){	struct tcp_tuplehash *hash;	unsigned int todo;	read_lock_bh(&mode_lock);	if (track_mode == CONN_MODE_NONE)		goto out_unlock;	if (in != track_dev || !is_our_packet(skb))		goto out_unlock;	if (!need_auth_input(skb))		goto out_unlock;	__refresh_keepalive_timer();	if (is_udp_packet(skb)) {		/* 		 * we need do nothing here		 */		read_unlock_bh(&mode_lock);		return NF_ACCEPT;	}	hash = resolve_tcp_conn(skb);	if (hash == NULL)		goto out_unlock;	todo = check_tcp_packet(skb, hash);	if (todo & TODO_ADJUST_SEQ)		(void)tcp_adjust_seq(skb, hash);	conn_put(tuplehash_to_conn(hash));out_unlock:	read_unlock_bh(&mode_lock);	return NF_ACCEPT;}static unsigned int postroute_hook(unsigned int hooknum,				struct sk_buff *skb,				const struct net_device *in,				const struct net_device *out,				int (*okfn)(struct sk_buff *)){	struct tcp_tuplehash *hash;	unsigned int todo;	struct sk_buff *skb2;	read_lock_bh(&mode_lock);	if (track_mode == CONN_MODE_NONE)		goto out_unlock;	if (out != track_dev || !is_our_packet(skb))		goto out_unlock;	if (!need_auth_output(skb))		goto out_unlock;	__refresh_keepalive_timer();	if (is_udp_packet(skb)) {		conn_do_udp(skb, okfn);		read_unlock_bh(&mode_lock);		return NF_STOLEN;	}	hash = resolve_tcp_conn(skb);	if (hash == NULL)		goto out_unlock;	todo = check_tcp_packet(skb, hash);	if (todo & TODO_SEND_ACK) {		skb2 = build_ack_skb(skb);		if (skb2 != NULL)			okfn(skb2);	}	if (todo & TODO_SEND_AUTH) {		skb2 = build_auth_skb(skb);		if (skb2 != NULL)			okfn(skb2);	}	if (todo & TODO_ADJUST_SEQ)		(void)tcp_adjust_seq(skb, hash);	conn_put(tuplehash_to_conn(hash));out_unlock:	read_unlock_bh(&mode_lock);	return NF_ACCEPT;}static struct nf_hook_ops preroute_hook_ops = {	.hook = preroute_hook,	.owner = THIS_MODULE,	.pf = PF_INET,	.hooknum = NF_IP_PRE_ROUTING,	.priority = NF_IP_PRI_CONNTRACK_DEFRAG+1,};static struct nf_hook_ops postroute_hook_ops = {	.hook = postroute_hook,	.owner = THIS_MODULE,	.pf = PF_INET,	.hooknum = NF_IP_POST_ROUTING,	.priority = NF_IP_PRI_LAST,};static void conn_hash_cleanup(void){	struct tcp_conn *conn;	struct tcp_tuplehash *h;	int i;	/* free tcp_conn hash memory */i_see_dead_people:	while (1) {		conn = NULL;		write_lock_bh(&hash_lock);		for (i=0; i<TCP_CONN_HASH_SIZE; i++) {			struct list_head *head = &tcp_conn_hash[i];			if (!list_empty(head)){				h = list_entry(head->next, struct tcp_tuplehash, list);				conn = tuplehash_to_conn(h);				conn_get(conn);				break;			}		}		write_unlock_bh(&hash_lock);		if (conn == NULL)			break;		if (del_timer(&conn->timeout)) {			death_by_timeout((unsigned long)conn);			conn_put(conn);		}	}	while (atomic_read(&tcp_conn_count) != 0) {		schedule();		goto i_see_dead_people;	}}static int conn_hooks_init(void){	int ret;	ret = nf_register_hook(&preroute_hook_ops);	if(ret < 0){		printk(KERN_ERR "PRE-ROUTE hook register failed\n");		goto out_err;	}	ret = nf_register_hook(&postroute_hook_ops);	if(ret < 0){		printk(KERN_ERR "POST-ROUTE hook register failed\n");		goto out_unregister_1;	}	return 0;out_unregister_1:	nf_unregister_hook(&preroute_hook_ops);out_err:	return ret;}static void conn_hooks_cleanup(void){	nf_unregister_hook(&postroute_hook_ops);	nf_unregister_hook(&preroute_hook_ops);	synchronize_net();}static int conn_set_params(struct sock *sk, int optname, void *optval, unsigned int optlen){	struct conn_param cp;	struct net_device *dev, *tmp_dev = NULL;	struct e_address *e_addr=NULL, *tmp_addr;	unsigned int e_len;	int i;	if (optlen < sizeof(struct conn_param))		return -EINVAL;	if (copy_from_user(&cp, optval, sizeof(struct conn_param)))		return -EFAULT;	if (cp.e_count < 0)		return -EINVAL;	if (cp.e_count > 0) {		e_len = cp.e_count * sizeof(struct e_address);		if (optlen < sizeof(struct conn_param) + e_len)			return -EINVAL;		e_addr = kmalloc(e_len, GFP_KERNEL);		if (e_addr == NULL)			return -ENOMEM;		if (copy_from_user(e_addr, optval+sizeof(struct conn_param), e_len)) {			kfree(e_addr);			return -EFAULT;		}	}	dev = dev_get_by_name(&init_net, cp.devname);	if (dev == NULL) {		if (e_addr)			kfree(e_addr);		return -ENODEV;	}	write_lock_bh(&mode_lock);	tmp_addr = conn_e_addr;	conn_e_count = cp.e_count;	if (conn_e_count != 0) {		conn_e_addr = e_addr;		for(i=0; i<conn_e_count; i++) 			conn_e_addr[i].addr &= conn_e_addr[i].mask;	}	tmp_dev = track_dev;	track_dev = dev;	write_unlock_bh(&mode_lock);	if (tmp_addr)		kfree(tmp_addr);	if (tmp_dev)		dev_put(tmp_dev);	return 0;}static int conn_set_auth_cmd(struct sock *sk, int optname, void *optval, unsigned int optlen){	struct conn_auth_cmd cmd;	int hash_todo = 0;	if (optlen < sizeof(struct conn_auth_cmd))		return -EINVAL;	if (copy_from_user(&cmd, optval, sizeof(struct conn_auth_cmd)))		return -EFAULT;	rtnl_lock();	write_lock_bh(&mode_lock);	if (track_mode == CONN_MODE_NONE && cmd.cmd == CONN_MODE_AUTH) {		track_mode = cmd.cmd;		conn_pid = cmd.pid;		conn_autologout = cmd.autologout;		memcpy(conn_auth_data, cmd.auth_data, CONN_AUTH_DATA_LEN);		hash_todo = 1; /* conn_hooks_init() */	} else if (track_mode == CONN_MODE_AUTH && cmd.cmd == CONN_MODE_NONE) {		track_mode = cmd.cmd;		conn_pid = 0;		conn_autologout = 0;		memset(conn_auth_data, 0, CONN_AUTH_DATA_LEN);		hash_todo = 2; /* conn_hooks_cleanup */	} else {		DEBUGP("Same Auth Cmd\n");	}	write_unlock_bh(&mode_lock);	if (hash_todo == 1) {		init_keepalive_timer();		conn_hooks_init();		printk(KERN_INFO "Drcom-Kernel: Authentication Started.\n");	} else if (hash_todo == 2) {		del_keepalive_timer();		conn_hooks_cleanup();		conn_hash_cleanup();		printk(KERN_INFO "Drcom-Kernel: Authentication Stopped.\n");	}	rtnl_unlock();	return 0;}static int conn_set_sockopt(struct sock *sk, int optname, void *optval, unsigned int optlen){	switch (optname) {	case CONN_SO_SET_PARAMS: /* set addresses of no need to auth */		return conn_set_params(sk, optname, optval, optlen);	case CONN_SO_SET_AUTH_CMD: /* set auth data, and start auth */		return conn_set_auth_cmd(sk, optname, optval, optlen);	default:		return -ENOPROTOOPT;	}	return -ENOPROTOOPT;}static struct nf_sockopt_ops conn_so_ops = {	.pf	     = PF_INET,	.set_optmin     = CONN_SO_BASE_CTL,	.set_optmax     = CONN_SO_SET_MAX+1,	.set	    = &conn_set_sockopt,	.owner	  = THIS_MODULE,};static int __init init(void){	int ret;	int i;	for (i=0; i<TCP_CONN_HASH_SIZE; i++)		INIT_LIST_HEAD(&tcp_conn_hash[i]);	ret = nf_register_sockopt(&conn_so_ops);	if(ret != 0)		return ret;	printk(KERN_INFO "Drcom-Kernel " TCPTRACK_VERSION " module loaded\n");	return ret;}static void __exit fini(void){	int do_dirty_work=0;	nf_unregister_sockopt(&conn_so_ops);	rtnl_lock();	write_lock_bh(&mode_lock);	if (track_mode == CONN_MODE_AUTH)		do_dirty_work = 1;	track_mode = CONN_MODE_NONE;	write_unlock_bh(&mode_lock);	if (do_dirty_work) {		conn_hooks_cleanup();		conn_hash_cleanup();	}	rtnl_unlock();	if (conn_e_addr)		kfree(conn_e_addr);	if (track_dev)		dev_put(track_dev);	printk(KERN_INFO "Drcom-Kernel " TCPTRACK_VERSION " module unloaded\n");}module_init(init);module_exit(fini);

⌨️ 快捷键说明

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