static void pptp_expectfn(struct ip_conntrack *ct, struct ip_conntrack_expect *exp) { DEBUGP("increasing timeouts\n"); /* increase timeout of GRE data channel conntrack entry */ ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT; /* Can you see how rusty this code is, compared with the pre-2.6.11 * one? That's what happened to my shiny newnat of 2002 ;( -HW */ if (!ip_nat_pptp_hook_expectfn) { struct ip_conntrack_tuple inv_t; struct ip_conntrack_expect *exp_other; /* obviously this tuple inversion only works until you do NAT */ invert_tuplepr(&inv_t, &exp->tuple); DEBUGP("trying to unexpect other dir: "); DUMP_TUPLE(&inv_t); exp_other = ip_conntrack_expect_find(&inv_t); if (exp_other) { /* delete other expectation. */ DEBUGP("found\n"); ip_conntrack_unexpect_related(exp_other); ip_conntrack_expect_put(exp_other); } else { DEBUGP("not found\n"); } } else { /* we need more than simple inversion */ ip_nat_pptp_hook_expectfn(ct, exp); } }
static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) { struct ip_conntrack_tuple_hash *h; struct ip_conntrack_expect *exp; DEBUGP("trying to timeout ct or exp for tuple "); DUMP_TUPLE(t); h = ip_conntrack_find_get(t, NULL); if (h) { struct ip_conntrack *sibling = tuplehash_to_ctrack(h); DEBUGP("setting timeout of conntrack %p to 0\n", sibling); sibling->proto.gre.timeout = 0; sibling->proto.gre.stream_timeout = 0; if (del_timer(&sibling->timeout)) sibling->timeout.function((unsigned long)sibling); ip_conntrack_put(sibling); return 1; } else { exp = ip_conntrack_expect_find(t); if (exp) { DEBUGP("unexpect_related of expect %p\n", exp); ip_conntrack_unexpect_related(exp); ip_conntrack_expect_put(exp); return 1; } } return 0; }
static void pptp_nat_expected(struct ip_conntrack *ct, struct ip_conntrack_expect *exp) { struct ip_conntrack *master = ct->master; struct ip_conntrack_expect *other_exp; 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; /* And here goes the grand finale of corrosion... */ if (exp->dir == IP_CT_DIR_ORIGINAL) { DEBUGP("we are PNS->PAC\n"); /* therefore, build tuple for PAC->PNS */ t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; t.src.u.gre.key = htons(master->help.ct_pptp_info.pac_call_id); t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; t.dst.u.gre.key = htons(master->help.ct_pptp_info.pns_call_id); t.dst.protonum = IPPROTO_GRE; } else { DEBUGP("we are PAC->PNS\n"); /* build tuple for PNS->PAC */ t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; t.src.u.gre.key = htons(master->nat.help.nat_pptp_info.pns_call_id); t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; t.dst.u.gre.key = htons(master->nat.help.nat_pptp_info.pac_call_id); t.dst.protonum = IPPROTO_GRE; } DEBUGP("trying to unexpect other dir: "); DUMP_TUPLE(&t); other_exp = ip_conntrack_expect_find(&t); if (other_exp) { ip_conntrack_unexpect_related(other_exp); ip_conntrack_expect_put(other_exp); DEBUGP("success\n"); } else { DEBUGP("not found!\n"); } /* 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); }