1 --- a/include/linux/netfilter/nf_conntrack_sip.h
2 +++ b/include/linux/netfilter/nf_conntrack_sip.h
5 #include <net/netfilter/nf_conntrack_expect.h>
7 +#include <linux/types.h>
10 #define SIP_TIMEOUT 3600
12 struct nf_ct_sip_master {
13 unsigned int register_cseq;
14 unsigned int invite_cseq;
15 + __be16 forced_dport;
18 enum sip_expectation_classes {
19 --- a/net/netfilter/nf_nat_sip.c
20 +++ b/net/netfilter/nf_nat_sip.c
21 @@ -95,6 +95,7 @@ static int map_addr(struct sk_buff *skb,
22 enum ip_conntrack_info ctinfo;
23 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
24 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
25 + struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
26 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
28 union nf_inet_addr newaddr;
29 @@ -107,7 +108,8 @@ static int map_addr(struct sk_buff *skb,
30 } else if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, addr) &&
31 ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
32 newaddr = ct->tuplehash[!dir].tuple.src.u3;
33 - newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
34 + newport = ct_sip_info->forced_dport ? ct_sip_info->forced_dport :
35 + ct->tuplehash[!dir].tuple.src.u.udp.port;
39 @@ -144,6 +146,7 @@ static unsigned int nf_nat_sip(struct sk
40 enum ip_conntrack_info ctinfo;
41 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
42 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
43 + struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
44 unsigned int coff, matchoff, matchlen;
45 enum sip_header_types hdr;
46 union nf_inet_addr addr;
47 @@ -258,6 +261,20 @@ next:
48 !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO))
51 + /* Mangle destination port for Cisco phones, then fix up checksums */
52 + if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) {
55 + if (!skb_make_writable(skb, skb->len))
58 + uh = (void *)skb->data + protoff;
59 + uh->dest = ct_sip_info->forced_dport;
61 + if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff, 0, 0, NULL, 0))
68 @@ -311,8 +328,10 @@ static unsigned int nf_nat_sip_expect(st
69 enum ip_conntrack_info ctinfo;
70 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
71 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
72 + struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
73 union nf_inet_addr newaddr;
76 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
79 @@ -326,8 +345,9 @@ static unsigned int nf_nat_sip_expect(st
80 /* If the signalling port matches the connection's source port in the
81 * original direction, try to use the destination port in the opposite
83 - if (exp->tuple.dst.u.udp.port ==
84 - ct->tuplehash[dir].tuple.src.u.udp.port)
85 + srcport = ct_sip_info->forced_dport ? ct_sip_info->forced_dport :
86 + ct->tuplehash[dir].tuple.src.u.udp.port;
87 + if (exp->tuple.dst.u.udp.port == srcport)
88 port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
90 port = ntohs(exp->tuple.dst.u.udp.port);
91 --- a/net/netfilter/nf_conntrack_sip.c
92 +++ b/net/netfilter/nf_conntrack_sip.c
93 @@ -1440,8 +1440,25 @@ static int process_sip_request(struct sk
95 enum ip_conntrack_info ctinfo;
96 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
97 + struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
98 + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
99 unsigned int matchoff, matchlen;
100 unsigned int cseq, i;
101 + union nf_inet_addr addr;
104 + /* Many Cisco IP phones use a high source port for SIP requests, but
105 + * listen for the response on port 5060. If we are the local
106 + * router for one of these phones, save the port number from the
107 + * Via: header so that nf_nat_sip can redirect the responses to
108 + * the correct port.
110 + if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
111 + SIP_HDR_VIA_UDP, NULL, &matchoff,
112 + &matchlen, &addr, &port) > 0 &&
113 + port != ct->tuplehash[dir].tuple.src.u.udp.port &&
114 + nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3))
115 + ct_sip_info->forced_dport = port;
117 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
118 const struct sip_handler *handler;