/* timeout GRE data connections */ static int pptp_timeout_related(struct ip_conntrack *ct) { struct list_head *cur_item, *next; struct ip_conntrack_expect *exp; /* FIXME: do we have to lock something ? */ for (cur_item = ct->sibling_list.next; cur_item != &ct->sibling_list; cur_item = next) { next = cur_item->next; exp = list_entry(cur_item, struct ip_conntrack_expect, expected_list); ip_ct_gre_keymap_destroy(exp); if (!exp->sibling) { ip_conntrack_unexpect_related(exp); continue; } DEBUGP("setting timeout of conntrack %p to 0\n", exp->sibling); exp->sibling->proto.gre.timeout = 0; exp->sibling->proto.gre.stream_timeout = 0; ip_ct_refresh(exp->sibling, 0); } return 0; }
static int pptp_expectfn(struct ip_conntrack *ct) { struct ip_conntrack *master; struct ip_conntrack_expect *exp; #ifdef CONFIG_IFX_ALG_QOS // chandrav IFX_ALG_QOS_DBG("\nPPTP_ALG: Master conntracker ifx_alg_qos_mark is : %x \n",ct->ifx_alg_qos_mark ); /* * Mark the connection tracker with PPTP ALG Application Family type * (IFX_ALG_PROTO_DATA) and PPTP ALG Protocol Family type * (IFX_ALG_PROTO_DATA) */ ct->ifx_alg_qos_mark = IFX_ALG_APP_PPTP | IFX_ALG_PROTO_DATA; IFX_ALG_QOS_DBG("\nPPTP ALG:Marked the Child conntracker with:%x \n", ct->ifx_alg_qos_mark ); #endif /* CONFIG_IFX_ALG_QOS */ 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; master = master_ct(ct); if (!master) { DEBUGP(" no master!!!\n"); return 0; } exp = ct->master; if (!exp) { DEBUGP("no expectation!!\n"); return 0; } DEBUGP("completing tuples with ct info\n"); /* we can do this, since we're unconfirmed */ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == htonl(master->help.ct_pptp_info.pac_call_id)) { /* assume PNS->PAC */ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = htonl(master->help.ct_pptp_info.pns_call_id); ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = htonl(master->help.ct_pptp_info.pns_call_id); } else { /* assume PAC->PNS */ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = htonl(master->help.ct_pptp_info.pac_call_id); ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = htonl(master->help.ct_pptp_info.pac_call_id); } /* delete other expectation */ if (exp->expected_list.next != &exp->expected_list) { struct ip_conntrack_expect *other_exp; struct list_head *cur_item, *next; for (cur_item = master->sibling_list.next; cur_item != &master->sibling_list; cur_item = next) { next = cur_item->next; other_exp = list_entry(cur_item, struct ip_conntrack_expect, expected_list); /* remove only if occurred at same sequence number */ if (other_exp != exp && other_exp->seq == exp->seq) { DEBUGP("unexpecting other direction\n"); ip_ct_gre_keymap_destroy(other_exp); ip_conntrack_unexpect_related(other_exp); } } } return 0; }
/* expect GRE connections (PNS->PAC and PAC->PNS direction) */ static inline int exp_gre(struct ip_conntrack *master, u_int32_t seq, u_int16_t callid, u_int16_t peer_callid) { struct ip_conntrack_expect exp; struct ip_conntrack_tuple inv_tuple; memset(&exp, 0, sizeof(exp)); /* tuple in original direction, PNS->PAC */ exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid)); exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; exp.tuple.dst.u.gre.key = htonl(ntohs(callid)); exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP); exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP; exp.tuple.dst.protonum = IPPROTO_GRE; exp.mask.src.ip = 0xffffffff; exp.mask.src.u.all = 0; exp.mask.dst.u.all = 0; exp.mask.dst.u.gre.key = 0xffffffff; exp.mask.dst.u.gre.version = 0xff; exp.mask.dst.u.gre.protocol = 0xffff; exp.mask.dst.ip = 0xffffffff; exp.mask.dst.protonum = 0xffff; exp.seq = seq; exp.expectfn = pptp_expectfn; exp.help.exp_pptp_info.pac_call_id = ntohs(callid); exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid); DEBUGP("calling expect_related "); DUMP_TUPLE_RAW(&exp.tuple); /* Add GRE keymap entries */ if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0) return 1; invert_tuplepr(&inv_tuple, &exp.tuple); if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) { ip_ct_gre_keymap_destroy(&exp); return 1; } if (ip_conntrack_expect_related(master, &exp) != 0) { ip_ct_gre_keymap_destroy(&exp); DEBUGP("cannot expect_related()\n"); return 1; } /* tuple in reply direction, PAC->PNS */ exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; exp.tuple.src.u.gre.key = htonl(ntohs(callid)); exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid)); DEBUGP("calling expect_related "); DUMP_TUPLE_RAW(&exp.tuple); /* Add GRE keymap entries */ ip_ct_gre_keymap_add(&exp, &exp.tuple, 0); invert_tuplepr(&inv_tuple, &exp.tuple); ip_ct_gre_keymap_add(&exp, &inv_tuple, 1); /* FIXME: cannot handle error correctly, since we need to free * the above keymap :( */ if (ip_conntrack_expect_related(master, &exp) != 0) { /* free the second pair of keypmaps */ ip_ct_gre_keymap_destroy(&exp); DEBUGP("cannot expect_related():\n"); return 1; } return 0; }
static int pptp_exp_gre(struct ip_conntrack_expect *expect_orig, struct ip_conntrack_expect *expect_reply) { struct ip_ct_pptp_master *ct_pptp_info = &expect_orig->master->help.ct_pptp_info; struct ip_nat_pptp *nat_pptp_info = &expect_orig->master->nat.help.nat_pptp_info; struct ip_conntrack *ct = expect_orig->master; struct ip_conntrack_tuple inv_t; struct ip_conntrack_tuple *orig_t, *reply_t; /* save original PAC call ID in nat_info */ nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id; /* alter expectation */ orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; /* alter expectation for PNS->PAC direction */ invert_tuplepr(&inv_t, &expect_orig->tuple); 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); 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); inv_t.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); if (!ip_conntrack_expect_related(expect_orig)) { DEBUGP("successfully registered expect\n"); } else { DEBUGP("can't expect_related(expect_orig)\n"); ip_conntrack_expect_free(expect_orig); return 1; } /* alter expectation for PAC->PNS direction */ invert_tuplepr(&inv_t, &expect_reply->tuple); 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); 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); inv_t.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); if (!ip_conntrack_expect_related(expect_reply)) { DEBUGP("successfully registered expect\n"); } else { DEBUGP("can't expect_related(expect_reply)\n"); ip_conntrack_unexpect_related(expect_orig); ip_conntrack_expect_free(expect_reply); return 1; } if (ip_ct_gre_keymap_add(ct, &expect_reply->tuple, 0) < 0) { DEBUGP("can't register original keymap\n"); ip_conntrack_unexpect_related(expect_orig); ip_conntrack_unexpect_related(expect_reply); return 1; } if (ip_ct_gre_keymap_add(ct, &inv_t, 1) < 0) { DEBUGP("can't register reply keymap\n"); ip_conntrack_unexpect_related(expect_orig); ip_conntrack_unexpect_related(expect_reply); ip_ct_gre_keymap_destroy(ct); return 1; } return 0; }
static int pptp_expectfn(struct ip_conntrack *ct) { struct ip_conntrack *master; 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; master = master_ct(ct); if (!master) { DEBUGP(" no master!!!\n"); return 0; } exp = ct->master; if (!exp) { DEBUGP("no expectation!!\n"); return 0; } DEBUGP("completing tuples with ct info\n"); /* we can do this, since we're unconfirmed */ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == htonl(master->help.ct_pptp_info.pac_call_id)) { /* assume PNS->PAC */ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = htonl(master->help.ct_pptp_info.pns_call_id); ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = htonl(master->help.ct_pptp_info.pns_call_id); } else { /* assume PAC->PNS */ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = htonl(master->help.ct_pptp_info.pac_call_id); ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = htonl(master->help.ct_pptp_info.pac_call_id); } /* delete other expectation */ if (exp->expected_list.next != &exp->expected_list) { struct ip_conntrack_expect *other_exp; struct list_head *cur_item, *next; for (cur_item = master->sibling_list.next; cur_item != &master->sibling_list; cur_item = next) { next = cur_item->next; other_exp = list_entry(cur_item, struct ip_conntrack_expect, expected_list); /* remove only if occurred at same sequence number */ if (other_exp != exp && other_exp->seq == exp->seq) { DEBUGP("unexpecting other direction\n"); ip_ct_gre_keymap_destroy(other_exp); ip_conntrack_unexpect_related(other_exp); } } } return 0; }