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

📄 ip_conntrack_helper_pptp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		/* server accepted call, we now expect GRE frames */		if (info->sstate != PPTP_SESSION_CONFIRMED) {			DEBUGP("%s but no session\n", pptp_msg_name[msg]);			break;		}		if (info->cstate != PPTP_CALL_OUT_REQ &&		    info->cstate != PPTP_CALL_OUT_CONF) {			DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]);			break;		}		if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) {			info->cstate = PPTP_CALL_NONE;			break;		}		cid = &pptpReq->ocack.callID;		pcid = &pptpReq->ocack.peersCallID;		info->pac_call_id = ntohs(*cid);				if (htons(info->pns_call_id) != *pcid) {			DEBUGP("%s for unknown callid %u\n",				pptp_msg_name[msg], ntohs(*pcid));			break;		}		DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], 			ntohs(*cid), ntohs(*pcid));				info->cstate = PPTP_CALL_OUT_CONF;		seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)				       + sizeof(struct PptpControlHeader)				       + ((void *)pcid - (void *)pptpReq);					if (exp_gre(ct, seq, *cid, *pcid) != 0)			printk("ip_conntrack_pptp: error during exp_gre\n");		break;	case PPTP_IN_CALL_REQUEST:		if (reqlen < sizeof(_pptpReq.icack)) {			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);			break;		}		/* server tells us about incoming call request */		if (info->sstate != PPTP_SESSION_CONFIRMED) {			DEBUGP("%s but no session\n", pptp_msg_name[msg]);			break;		}		pcid = &pptpReq->icack.peersCallID;		DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));		info->cstate = PPTP_CALL_IN_REQ;		info->pac_call_id = ntohs(*pcid);		break;	case PPTP_IN_CALL_CONNECT:		if (reqlen < sizeof(_pptpReq.iccon)) {			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);			break;		}		/* server tells us about incoming call established */		if (info->sstate != PPTP_SESSION_CONFIRMED) {			DEBUGP("%s but no session\n", pptp_msg_name[msg]);			break;		}		if (info->sstate != PPTP_CALL_IN_REP		    && info->sstate != PPTP_CALL_IN_CONF) {			DEBUGP("%s but never sent IN_CALL_REPLY\n",				pptp_msg_name[msg]);			break;		}		pcid = &pptpReq->iccon.peersCallID;		cid = &info->pac_call_id;		if (info->pns_call_id != ntohs(*pcid)) {			DEBUGP("%s for unknown CallID %u\n", 				pptp_msg_name[msg], ntohs(*pcid));			break;		}		DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));		info->cstate = PPTP_CALL_IN_CONF;		/* we expect a GRE connection from PAC to PNS */		seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)				       + sizeof(struct PptpControlHeader)				       + ((void *)pcid - (void *)pptpReq);					if (exp_gre(ct, seq, *cid, *pcid) != 0)			printk("ip_conntrack_pptp: error during exp_gre\n");		break;	case PPTP_CALL_DISCONNECT_NOTIFY:		if (reqlen < sizeof(_pptpReq.disc)) {			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);			break;		}		/* server confirms disconnect */		cid = &pptpReq->disc.callID;		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));		info->cstate = PPTP_CALL_NONE;		/* untrack this call id, unexpect GRE packets */		pptp_destroy_siblings(ct);		break;	case PPTP_WAN_ERROR_NOTIFY:		break;	case PPTP_ECHO_REQUEST:	case PPTP_ECHO_REPLY:		/* I don't have to explain these ;) */		break;	default:		DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)			? pptp_msg_name[msg]:pptp_msg_name[0], msg);		break;	}	if (ip_nat_pptp_hook_inbound)		return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,						pptpReq);	return NF_ACCEPT;}static inline intpptp_outbound_pkt(struct sk_buff **pskb,		  struct tcphdr *tcph,		  unsigned int nexthdr_off,		  unsigned int datalen,		  struct ip_conntrack *ct,		  enum ip_conntrack_info ctinfo){	struct PptpControlHeader _ctlh, *ctlh;	unsigned int reqlen;	union pptp_ctrl_union _pptpReq, *pptpReq;	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;	u_int16_t msg;	__be16 *cid, *pcid;	ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);	if (!ctlh)		return NF_ACCEPT;	nexthdr_off += sizeof(_ctlh);	datalen -= sizeof(_ctlh);		reqlen = datalen;	if (reqlen > sizeof(*pptpReq))		reqlen = sizeof(*pptpReq);	pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);	if (!pptpReq)		return NF_ACCEPT;	msg = ntohs(ctlh->messageType);	DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);	switch (msg) {	case PPTP_START_SESSION_REQUEST:		/* client requests for new control session */		if (info->sstate != PPTP_SESSION_NONE) {			DEBUGP("%s but we already have one",				pptp_msg_name[msg]);		}		info->sstate = PPTP_SESSION_REQUESTED;		break;	case PPTP_STOP_SESSION_REQUEST:		/* client requests end of control session */		info->sstate = PPTP_SESSION_STOPREQ;		break;	case PPTP_OUT_CALL_REQUEST:		if (reqlen < sizeof(_pptpReq.ocreq)) {			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);			/* FIXME: break; */		}		/* client initiating connection to server */		if (info->sstate != PPTP_SESSION_CONFIRMED) {			DEBUGP("%s but no session\n",				pptp_msg_name[msg]);			break;		}		info->cstate = PPTP_CALL_OUT_REQ;		/* track PNS call id */		cid = &pptpReq->ocreq.callID;		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));		info->pns_call_id = ntohs(*cid);		break;	case PPTP_IN_CALL_REPLY:		if (reqlen < sizeof(_pptpReq.icack)) {			DEBUGP("%s: short packet\n", pptp_msg_name[msg]);			break;		}		/* client answers incoming call */		if (info->cstate != PPTP_CALL_IN_REQ		    && info->cstate != PPTP_CALL_IN_REP) {			DEBUGP("%s without incall_req\n", 				pptp_msg_name[msg]);			break;		}		if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) {			info->cstate = PPTP_CALL_NONE;			break;		}		pcid = &pptpReq->icack.peersCallID;		if (info->pac_call_id != ntohs(*pcid)) {			DEBUGP("%s for unknown call %u\n", 				pptp_msg_name[msg], ntohs(*pcid));			break;		}		DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*pcid));		/* part two of the three-way handshake */		info->cstate = PPTP_CALL_IN_REP;		info->pns_call_id = ntohs(pptpReq->icack.callID);		break;	case PPTP_CALL_CLEAR_REQUEST:		/* client requests hangup of call */		if (info->sstate != PPTP_SESSION_CONFIRMED) {			DEBUGP("CLEAR_CALL but no session\n");			break;		}		/* FUTURE: iterate over all calls and check if		 * call ID is valid.  We don't do this without newnat,		 * because we only know about last call */		info->cstate = PPTP_CALL_CLEAR_REQ;		break;	case PPTP_SET_LINK_INFO:		break;	case PPTP_ECHO_REQUEST:	case PPTP_ECHO_REPLY:		/* I don't have to explain these ;) */		break;	default:		DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? 			pptp_msg_name[msg]:pptp_msg_name[0], msg);		/* unknown: no need to create GRE masq table entry */		break;	}		if (ip_nat_pptp_hook_outbound)		return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,						 pptpReq);	return NF_ACCEPT;}/* track caller id inside control connection, call expect_related */static int conntrack_pptp_help(struct sk_buff **pskb,		    struct ip_conntrack *ct, enum ip_conntrack_info ctinfo){	struct pptp_pkt_hdr _pptph, *pptph;	struct tcphdr _tcph, *tcph;	u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;	u_int32_t datalen;	int dir = CTINFO2DIR(ctinfo);	struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;	unsigned int nexthdr_off;	int oldsstate, oldcstate;	int ret;	/* don't do any tracking before tcp handshake complete */	if (ctinfo != IP_CT_ESTABLISHED 	    && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {		DEBUGP("ctinfo = %u, skipping\n", ctinfo);		return NF_ACCEPT;	}		nexthdr_off = (*pskb)->nh.iph->ihl*4;	tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);	BUG_ON(!tcph);	nexthdr_off += tcph->doff * 4; 	datalen = tcplen - tcph->doff * 4;	if (tcph->fin || tcph->rst) {		DEBUGP("RST/FIN received, timeouting GRE\n");		/* can't do this after real newnat */		info->cstate = PPTP_CALL_NONE;		/* untrack this call id, unexpect GRE packets */		pptp_destroy_siblings(ct);	}	pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);	if (!pptph) {		DEBUGP("no full PPTP header, can't track\n");		return NF_ACCEPT;	}	nexthdr_off += sizeof(_pptph);	datalen -= sizeof(_pptph);	/* if it's not a control message we can't do anything with it */	if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||	    ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {		DEBUGP("not a control packet\n");		return NF_ACCEPT;	}	oldsstate = info->sstate;	oldcstate = info->cstate;	spin_lock_bh(&ip_pptp_lock);	/* FIXME: We just blindly assume that the control connection is always	 * established from PNS->PAC.  However, RFC makes no guarantee */	if (dir == IP_CT_DIR_ORIGINAL)		/* client -> server (PNS -> PAC) */		ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,					ctinfo);	else		/* server -> client (PAC -> PNS) */		ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,				       ctinfo);	DEBUGP("sstate: %d->%d, cstate: %d->%d\n",		oldsstate, info->sstate, oldcstate, info->cstate);	spin_unlock_bh(&ip_pptp_lock);	return ret;}/* control protocol helper */static struct ip_conntrack_helper pptp = { 	.list = { NULL, NULL },	.name = "pptp", 	.me = THIS_MODULE,	.max_expected = 2,	.timeout = 5 * 60,	.tuple = { .src = { .ip = 0, 		 	    .u = { .tcp = { .port =  				    __constant_htons(PPTP_CONTROL_PORT) } } 			  }, 		   .dst = { .ip = 0, 			    .u = { .all = 0 },			    .protonum = IPPROTO_TCP			  } 		 },	.mask = { .src = { .ip = 0, 			   .u = { .tcp = { .port = __constant_htons(0xffff) } } 			 }, 		  .dst = { .ip = 0, 			   .u = { .all = 0 },			   .protonum = 0xff 		 	 } 		},	.help = conntrack_pptp_help};extern void __exit ip_ct_proto_gre_fini(void);extern int __init ip_ct_proto_gre_init(void);/* ip_conntrack_pptp initialization */static int __init init(void){	int retcode; 	retcode = ip_ct_proto_gre_init();	if (retcode < 0)		return retcode;	DEBUGP(" registering helper\n");	if ((retcode = ip_conntrack_helper_register(&pptp))) {		printk(KERN_ERR "Unable to register conntrack application "				"helper for pptp: %d\n", retcode);		ip_ct_proto_gre_fini();		return retcode;	}	printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);	return 0;}static void __exit fini(void){	ip_conntrack_helper_unregister(&pptp);	ip_ct_proto_gre_fini();	printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);}module_init(init);module_exit(fini);EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre);EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn);

⌨️ 快捷键说明

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