From 9467ee380ae881443bc259fbbac9992baf523e2d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 25 Mar 2008 20:24:04 -0700 Subject: [PATCH] [NETFILTER]: nf_conntrack_sip: flush expectations on call termination Flush the RTP expectations we've created when a call is hung up or terminated otherwise. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_sip.c | 52 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 71f744ad..8e7e5b4 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -533,6 +534,22 @@ int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, } EXPORT_SYMBOL_GPL(ct_sip_get_sdp_header); +static void flush_expectations(struct nf_conn *ct) +{ + struct nf_conn_help *help = nfct_help(ct); + struct nf_conntrack_expect *exp; + struct hlist_node *n, *next; + + spin_lock_bh(&nf_conntrack_lock); + hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) { + if (!del_timer(&exp->timeout)) + continue; + nf_ct_unlink_expect(exp); + nf_ct_expect_put(exp); + } + spin_unlock_bh(&nf_conntrack_lock); +} + static int set_expected_rtp(struct sk_buff *skb, const char **dptr, unsigned int *datalen, union nf_inet_addr *addr, __be16 port) @@ -606,32 +623,58 @@ static int process_invite_response(struct sk_buff *skb, const char **dptr, unsigned int *datalen, unsigned int cseq, unsigned int code) { + enum ip_conntrack_info ctinfo; + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); + if ((code >= 100 && code <= 199) || (code >= 200 && code <= 299)) return process_sdp(skb, dptr, datalen, cseq); - - return NF_ACCEPT; + else { + flush_expectations(ct); + return NF_ACCEPT; + } } static int process_update_response(struct sk_buff *skb, const char **dptr, unsigned int *datalen, unsigned int cseq, unsigned int code) { + enum ip_conntrack_info ctinfo; + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); + if ((code >= 100 && code <= 199) || (code >= 200 && code <= 299)) return process_sdp(skb, dptr, datalen, cseq); - - return NF_ACCEPT; + else { + flush_expectations(ct); + return NF_ACCEPT; + } } static int process_prack_response(struct sk_buff *skb, const char **dptr, unsigned int *datalen, unsigned int cseq, unsigned int code) { + enum ip_conntrack_info ctinfo; + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); + if ((code >= 100 && code <= 199) || (code >= 200 && code <= 299)) return process_sdp(skb, dptr, datalen, cseq); + else { + flush_expectations(ct); + return NF_ACCEPT; + } +} + +static int process_bye_request(struct sk_buff *skb, + const char **dptr, unsigned int *datalen, + unsigned int cseq) +{ + enum ip_conntrack_info ctinfo; + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); + flush_expectations(ct); return NF_ACCEPT; } @@ -640,6 +683,7 @@ static const struct sip_handler sip_handlers[] = { SIP_HANDLER("UPDATE", process_sdp, process_update_response), SIP_HANDLER("ACK", process_sdp, NULL), SIP_HANDLER("PRACK", process_sdp, process_prack_response), + SIP_HANDLER("BYE", process_bye_request, NULL), }; static int process_sip_response(struct sk_buff *skb, -- 2.7.4