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

📄 nf_conntrack_pptp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		pcid = pptpReq->ocack.peersCallID;		if (info->pns_call_id != pcid)			goto invalid;		pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],			 ntohs(cid), ntohs(pcid));		if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) {			info->cstate = PPTP_CALL_OUT_CONF;			info->pac_call_id = cid;			exp_gre(ct, cid, pcid);		} else			info->cstate = PPTP_CALL_NONE;		break;	case PPTP_IN_CALL_REQUEST:		/* server tells us about incoming call request */		if (info->sstate != PPTP_SESSION_CONFIRMED)			goto invalid;		cid = pptpReq->icreq.callID;		pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));		info->cstate = PPTP_CALL_IN_REQ;		info->pac_call_id = cid;		break;	case PPTP_IN_CALL_CONNECT:		/* server tells us about incoming call established */		if (info->sstate != PPTP_SESSION_CONFIRMED)			goto invalid;		if (info->cstate != PPTP_CALL_IN_REP &&		    info->cstate != PPTP_CALL_IN_CONF)			goto invalid;		pcid = pptpReq->iccon.peersCallID;		cid = info->pac_call_id;		if (info->pns_call_id != pcid)			goto invalid;		pr_debug("%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 */		exp_gre(ct, cid, pcid);		break;	case PPTP_CALL_DISCONNECT_NOTIFY:		/* server confirms disconnect */		cid = pptpReq->disc.callID;		pr_debug("%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:	case PPTP_ECHO_REQUEST:	case PPTP_ECHO_REPLY:		/* I don't have to explain these ;) */		break;	default:		goto invalid;	}	nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound);	if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK)		return nf_nat_pptp_inbound(skb, ct, ctinfo, ctlh, pptpReq);	return NF_ACCEPT;invalid:	pr_debug("invalid %s: type=%d cid=%u pcid=%u "		 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",		 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],		 msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,		 ntohs(info->pns_call_id), ntohs(info->pac_call_id));	return NF_ACCEPT;}static inline intpptp_outbound_pkt(struct sk_buff *skb,		  struct PptpControlHeader *ctlh,		  union pptp_ctrl_union *pptpReq,		  unsigned int reqlen,		  struct nf_conn *ct,		  enum ip_conntrack_info ctinfo){	struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info;	u_int16_t msg;	__be16 cid = 0, pcid = 0;	typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound;	msg = ntohs(ctlh->messageType);	pr_debug("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)			goto invalid;		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:		/* client initiating connection to server */		if (info->sstate != PPTP_SESSION_CONFIRMED)			goto invalid;		info->cstate = PPTP_CALL_OUT_REQ;		/* track PNS call id */		cid = pptpReq->ocreq.callID;		pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));		info->pns_call_id = cid;		break;	case PPTP_IN_CALL_REPLY:		/* client answers incoming call */		if (info->cstate != PPTP_CALL_IN_REQ &&		    info->cstate != PPTP_CALL_IN_REP)			goto invalid;		cid = pptpReq->icack.callID;		pcid = pptpReq->icack.peersCallID;		if (info->pac_call_id != pcid)			goto invalid;		pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],			 ntohs(cid), ntohs(pcid));		if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) {			/* part two of the three-way handshake */			info->cstate = PPTP_CALL_IN_REP;			info->pns_call_id = cid;		} else			info->cstate = PPTP_CALL_NONE;		break;	case PPTP_CALL_CLEAR_REQUEST:		/* client requests hangup of call */		if (info->sstate != PPTP_SESSION_CONFIRMED)			goto invalid;		/* 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:	case PPTP_ECHO_REQUEST:	case PPTP_ECHO_REPLY:		/* I don't have to explain these ;) */		break;	default:		goto invalid;	}	nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound);	if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK)		return nf_nat_pptp_outbound(skb, ct, ctinfo, ctlh, pptpReq);	return NF_ACCEPT;invalid:	pr_debug("invalid %s: type=%d cid=%u pcid=%u "		 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",		 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],		 msg, ntohs(cid), ntohs(pcid),  info->cstate, info->sstate,		 ntohs(info->pns_call_id), ntohs(info->pac_call_id));	return NF_ACCEPT;}static const unsigned int pptp_msg_size[] = {	[PPTP_START_SESSION_REQUEST]  = sizeof(struct PptpStartSessionRequest),	[PPTP_START_SESSION_REPLY]    = sizeof(struct PptpStartSessionReply),	[PPTP_STOP_SESSION_REQUEST]   = sizeof(struct PptpStopSessionRequest),	[PPTP_STOP_SESSION_REPLY]     = sizeof(struct PptpStopSessionReply),	[PPTP_OUT_CALL_REQUEST]       = sizeof(struct PptpOutCallRequest),	[PPTP_OUT_CALL_REPLY]	      = sizeof(struct PptpOutCallReply),	[PPTP_IN_CALL_REQUEST]	      = sizeof(struct PptpInCallRequest),	[PPTP_IN_CALL_REPLY]	      = sizeof(struct PptpInCallReply),	[PPTP_IN_CALL_CONNECT]	      = sizeof(struct PptpInCallConnected),	[PPTP_CALL_CLEAR_REQUEST]     = sizeof(struct PptpClearCallRequest),	[PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify),	[PPTP_WAN_ERROR_NOTIFY]	      = sizeof(struct PptpWanErrorNotify),	[PPTP_SET_LINK_INFO]	      = sizeof(struct PptpSetLinkInfo),};/* track caller id inside control connection, call expect_related */static intconntrack_pptp_help(struct sk_buff *skb, unsigned int protoff,		    struct nf_conn *ct, enum ip_conntrack_info ctinfo){	int dir = CTINFO2DIR(ctinfo);	struct nf_ct_pptp_master *info = &nfct_help(ct)->help.ct_pptp_info;	struct tcphdr _tcph, *tcph;	struct pptp_pkt_hdr _pptph, *pptph;	struct PptpControlHeader _ctlh, *ctlh;	union pptp_ctrl_union _pptpReq, *pptpReq;	unsigned int tcplen = skb->len - protoff;	unsigned int datalen, reqlen, nexthdr_off;	int oldsstate, oldcstate;	int ret;	u_int16_t msg;	/* don't do any tracking before tcp handshake complete */	if (ctinfo != IP_CT_ESTABLISHED &&	    ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)		return NF_ACCEPT;	nexthdr_off = protoff;	tcph = skb_header_pointer(skb, nexthdr_off, sizeof(_tcph), &_tcph);	BUG_ON(!tcph);	nexthdr_off += tcph->doff * 4;	datalen = tcplen - tcph->doff * 4;	pptph = skb_header_pointer(skb, nexthdr_off, sizeof(_pptph), &_pptph);	if (!pptph) {		pr_debug("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) {		pr_debug("not a control packet\n");		return NF_ACCEPT;	}	ctlh = skb_header_pointer(skb, nexthdr_off, sizeof(_ctlh), &_ctlh);	if (!ctlh)		return NF_ACCEPT;	nexthdr_off += sizeof(_ctlh);	datalen -= sizeof(_ctlh);	reqlen = datalen;	msg = ntohs(ctlh->messageType);	if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])		return NF_ACCEPT;	if (reqlen > sizeof(*pptpReq))		reqlen = sizeof(*pptpReq);	pptpReq = skb_header_pointer(skb, nexthdr_off, reqlen, &_pptpReq);	if (!pptpReq)		return NF_ACCEPT;	oldsstate = info->sstate;	oldcstate = info->cstate;	spin_lock_bh(&nf_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(skb, ctlh, pptpReq, reqlen, ct,					ctinfo);	else		/* server -> client (PAC -> PNS) */		ret = pptp_inbound_pkt(skb, ctlh, pptpReq, reqlen, ct,				       ctinfo);	pr_debug("sstate: %d->%d, cstate: %d->%d\n",		 oldsstate, info->sstate, oldcstate, info->cstate);	spin_unlock_bh(&nf_pptp_lock);	return ret;}/* control protocol helper */static struct nf_conntrack_helper pptp __read_mostly = {	.name			= "pptp",	.me			= THIS_MODULE,	.max_expected		= 2,	.timeout		= 5 * 60,	.tuple.src.l3num	= AF_INET,	.tuple.src.u.tcp.port	= __constant_htons(PPTP_CONTROL_PORT),	.tuple.dst.protonum	= IPPROTO_TCP,	.help			= conntrack_pptp_help,	.destroy		= pptp_destroy_siblings,};static int __init nf_conntrack_pptp_init(void){	return nf_conntrack_helper_register(&pptp);}static void __exit nf_conntrack_pptp_fini(void){	nf_conntrack_helper_unregister(&pptp);	nf_ct_gre_keymap_flush();}module_init(nf_conntrack_pptp_init);module_exit(nf_conntrack_pptp_fini);

⌨️ 快捷键说明

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