/* expect GRE connection in PNS->PAC 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 */ ip_ct_gre_keymap_add(&exp, &exp.tuple, 0); invert_tuplepr(&inv_tuple, &exp.tuple); ip_ct_gre_keymap_add(&exp, &inv_tuple, 1); ip_conntrack_expect_related(master, &exp); /* 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); ip_conntrack_expect_related(master, &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; }