X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fip_nat_helper_pptp.c;h=50960cb681f8ec688498b4ce4b75ffb297e3dd80;hb=03b9feca89366952ae5dfe4ad8107b1ece50b710;hp=3cdd0684d30d32242963309f35941c123f041504;hpb=a1e78db3f54d3481726ed2d3d58d8ad5b19b13d0;p=powerpc.git diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c index 3cdd0684d3..50960cb681 100644 --- a/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c @@ -73,6 +73,7 @@ static void pptp_nat_expected(struct ip_conntrack *ct, struct ip_conntrack_tuple t; struct ip_ct_pptp_master *ct_pptp_info; struct ip_nat_pptp *nat_pptp_info; + struct ip_nat_range range; ct_pptp_info = &master->help.ct_pptp_info; nat_pptp_info = &master->nat.help.nat_pptp_info; @@ -110,7 +111,30 @@ static void pptp_nat_expected(struct ip_conntrack *ct, DEBUGP("not found!\n"); } - ip_nat_follow_master(ct, exp); + /* This must be a fresh one. */ + BUG_ON(ct->status & IPS_NAT_DONE_MASK); + + /* Change src to where master sends to */ + range.flags = IP_NAT_RANGE_MAP_IPS; + range.min_ip = range.max_ip + = ct->master->tuplehash[!exp->dir].tuple.dst.ip; + if (exp->dir == IP_CT_DIR_ORIGINAL) { + range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + range.min = range.max = exp->saved_proto; + } + /* hook doesn't matter, but it has to do source manip */ + ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); + + /* For DST manip, map port here to where it's expected. */ + range.flags = IP_NAT_RANGE_MAP_IPS; + range.min_ip = range.max_ip + = ct->master->tuplehash[!exp->dir].tuple.src.ip; + if (exp->dir == IP_CT_DIR_REPLY) { + range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + range.min = range.max = exp->saved_proto; + } + /* hook doesn't matter, but it has to do destination manip */ + ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); } /* outbound packets == from PNS to PAC */ @@ -124,14 +148,14 @@ pptp_outbound_pkt(struct sk_buff **pskb, { struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; - - u_int16_t msg, *cid = NULL, new_callid; + u_int16_t msg, new_callid; + unsigned int cid_off; new_callid = htons(ct_pptp_info->pns_call_id); switch (msg = ntohs(ctlh->messageType)) { case PPTP_OUT_CALL_REQUEST: - cid = &pptpReq->ocreq.callID; + cid_off = offsetof(union pptp_ctrl_union, ocreq.callID); /* FIXME: ideally we would want to reserve a call ID * here. current netfilter NAT core is not able to do * this :( For now we use TCP source port. This breaks @@ -148,10 +172,10 @@ pptp_outbound_pkt(struct sk_buff **pskb, ct_pptp_info->pns_call_id = ntohs(new_callid); break; case PPTP_IN_CALL_REPLY: - cid = &pptpReq->icreq.callID; + cid_off = offsetof(union pptp_ctrl_union, icreq.callID); break; case PPTP_CALL_CLEAR_REQUEST: - cid = &pptpReq->clrreq.callID; + cid_off = offsetof(union pptp_ctrl_union, clrreq.callID); break; default: DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, @@ -173,18 +197,15 @@ pptp_outbound_pkt(struct sk_buff **pskb, /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass * down to here */ - - IP_NF_ASSERT(cid); - DEBUGP("altering call id from 0x%04x to 0x%04x\n", - ntohs(*cid), ntohs(new_callid)); + ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_callid)); /* mangle packet */ if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, - (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), - sizeof(new_callid), - (char *)&new_callid, - sizeof(new_callid)) == 0) + cid_off + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader), + sizeof(new_callid), (char *)&new_callid, + sizeof(new_callid)) == 0) return NF_DROP; return NF_ACCEPT; @@ -213,9 +234,10 @@ pptp_exp_gre(struct ip_conntrack_expect *expect_orig, /* alter expectation for PNS->PAC direction */ invert_tuplepr(&inv_t, &expect_orig->tuple); - expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id); + expect_orig->saved_proto.gre.key = htons(ct_pptp_info->pns_call_id); expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); + expect_orig->dir = IP_CT_DIR_ORIGINAL; inv_t.src.ip = reply_t->src.ip; inv_t.dst.ip = reply_t->dst.ip; inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id); @@ -233,6 +255,7 @@ pptp_exp_gre(struct ip_conntrack_expect *expect_orig, expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id); expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id); expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); + expect_reply->dir = IP_CT_DIR_REPLY; inv_t.src.ip = orig_t->src.ip; inv_t.dst.ip = orig_t->dst.ip; inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id); @@ -273,7 +296,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, union pptp_ctrl_union *pptpReq) { struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; - u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL; + u_int16_t msg, new_cid = 0, new_pcid; + unsigned int pcid_off, cid_off = 0; int ret = NF_ACCEPT, rv; @@ -281,23 +305,23 @@ pptp_inbound_pkt(struct sk_buff **pskb, switch (msg = ntohs(ctlh->messageType)) { case PPTP_OUT_CALL_REPLY: - pcid = &pptpReq->ocack.peersCallID; - cid = &pptpReq->ocack.callID; + pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID); + cid_off = offsetof(union pptp_ctrl_union, ocack.callID); break; case PPTP_IN_CALL_CONNECT: - pcid = &pptpReq->iccon.peersCallID; + pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID); break; case PPTP_IN_CALL_REQUEST: /* only need to nat in case PAC is behind NAT box */ - break; + return NF_ACCEPT; case PPTP_WAN_ERROR_NOTIFY: - pcid = &pptpReq->wanerr.peersCallID; + pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID); break; case PPTP_CALL_DISCONNECT_NOTIFY: - pcid = &pptpReq->disc.callID; + pcid_off = offsetof(union pptp_ctrl_union, disc.callID); break; case PPTP_SET_LINK_INFO: - pcid = &pptpReq->setlink.peersCallID; + pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID); break; default: @@ -319,25 +343,24 @@ pptp_inbound_pkt(struct sk_buff **pskb, * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */ /* mangle packet */ - IP_NF_ASSERT(pcid); DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", - ntohs(*pcid), ntohs(new_pcid)); + ntohs(*(u_int16_t *)pptpReq + pcid_off), ntohs(new_pcid)); - rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, - (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), + rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + pcid_off + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader), sizeof(new_pcid), (char *)&new_pcid, sizeof(new_pcid)); if (rv != NF_ACCEPT) return rv; if (new_cid) { - IP_NF_ASSERT(cid); DEBUGP("altering call id from 0x%04x to 0x%04x\n", - ntohs(*cid), ntohs(new_cid)); - rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, - (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), - sizeof(new_cid), - (char *)&new_cid, + ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_cid)); + rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + cid_off + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader), + sizeof(new_cid), (char *)&new_cid, sizeof(new_cid)); if (rv != NF_ACCEPT) return rv;