/* FIXME: This should be in userspace. Later. */ static int help(const struct iphdr *iph, size_t len, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { #ifdef CONFIG_IP_NF_ALGCTRL if (!ip_ct_alg_ipsec) { return NF_ACCEPT; } #endif if(ipsec_flag == '1') /* tcplen not negative guaranteed by ip_conntrack_tcp.c */ ip_conntrack_protocol_register(&ip_conntrack_protocol_esp); return NF_ACCEPT; }
static int ip_inbound_pptp_tcp(const struct iphdr *iph, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { struct pptp_pkt_hdr *pptph; struct PptpControlHeader *ctlh; union { void *rawreq; struct PptpOutCallRequest *ocreq; struct PptpOutCallReply *ocack; struct PptpInCallRequest *icreq; struct PptpInCallReply *icack; struct PptpClearCallRequest *clrreq; struct PptpCallDisconnectNotify *disc; struct PptpWanErrorNotify *wanerr; struct PptpSetLinkInfo *setlink; } pptpReq; __u16 msg, *cid, *pcid; int dir = CTINFO2DIR(ctinfo); pptph = (struct pptp_pkt_hdr *) ((char *) iph + sizeof(struct iphdr) + sizeof(struct tcphdr)); DEBUGP("inbound_pptp_tcp(): CT=%lx, ", (unsigned long) ct); PRINTK_PPTP_HDR("", iph, pptph); ctlh = (struct PptpControlHeader *) ((char *) pptph + sizeof(struct pptp_pkt_hdr)); pptpReq.rawreq = (void *) ((char*) ctlh + sizeof(struct PptpControlHeader)); switch (msg = htons(ctlh->messageType)) { case PPTP_OUT_CALL_REPLY: /* server responding to masq'd client */ cid = &pptpReq.ocack->callID; pcid = &pptpReq.ocack->peersCallID; break; case PPTP_IN_CALL_REPLY: /* server responding to masq'd client */ cid = &pptpReq.icack->callID; pcid = &pptpReq.icack->peersCallID; break; case PPTP_WAN_ERROR_NOTIFY: /* server notifying masq'd client */ /* no need to alter conntrack */ return 0; case PPTP_SET_LINK_INFO: /* server notifying masq'd client */ /* no need to alter conntrack */ return 0; case PPTP_CALL_DISCONNECT_NOTIFY: /* server notifying masq'd client */ /* expire this connection */ ip_ct_refresh(ct, (30*HZ)); clear_gre_tuples(ct); return 0; default: DEBUGP("UNKNOWN inbound packet: "); DEBUGP("%s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? strMName[msg] : strMName[0], msg); /* fall through */ case PPTP_ECHO_REPLY: case PPTP_START_SESSION_REQUEST: case PPTP_START_SESSION_REPLY: case PPTP_STOP_SESSION_REQUEST: case PPTP_STOP_SESSION_REPLY: case PPTP_ECHO_REQUEST: /* no need to alter conntrack */ return 0; } LOCK_BH(&ip_pptp_lock); /* info for conntrack/NAT */ struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; struct ip_conntrack_expect expect, *exp = &expect; struct ip_ct_pptp_expect *exp_pptp_info = &exp->help.exp_pptp_info; exp_pptp_info->pptp_magic = PPTP_TCP_PORT; /* our magic number */ exp_pptp_info->orig_call_id = *cid; exp_pptp_info->peer_call_id = *pcid; INIT_LIST_HEAD(&(ct_pptp_info->list)); /* tuple for GRE packets (from server to masqed client) * Here src = pptp server, dst = ppp addr * !dir: src = masq client, dst = pptp server */ /* * masq client <--> pptp serv * new connection replaces any old ones. */ /* * populate our lists for peer call ID lookup */ put_gre_tuple(ct->tuplehash[!dir].tuple.src.ip, ct->tuplehash[!dir].tuple.dst.ip, *cid, *pcid, ct); put_gre_tuple(ct->tuplehash[!dir].tuple.dst.ip, ct->tuplehash[!dir].tuple.src.ip, *pcid, *cid, ct); put_gre_tuple(ct->tuplehash[dir].tuple.src.ip, ct->tuplehash[dir].tuple.dst.ip, *pcid, *cid, ct); put_gre_tuple(ct->tuplehash[dir].tuple.dst.ip, ct->tuplehash[dir].tuple.src.ip, *cid, *pcid, ct); if(ip_conntrack_protocol_register(&ip_conntrack_protocol_gre) == 0) DEBUGP("pptp: registered conntrack protocol GRE!\n"); else DEBUGP("pptp: failed to register conntrack protocol GRE!\n"); UNLOCK_BH(&ip_pptp_lock); return 0; }