diff options
author | Patrick McHardy <kaber@trash.net> | 2008-03-25 23:24:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-25 23:24:41 -0400 |
commit | 720ac7085ce815ea4caec24396575fed7bd711aa (patch) | |
tree | 313932792e1f633035f4ad6005cadd7aff7a74fc | |
parent | 2bbb21168a90c788e12fe722eb66f27e611e7df7 (diff) |
[NETFILTER]: nf_nat_sip: translate all Via headers
Update maddr=, received= and rport= Via-header parameters refering to
the signalling connection.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/netfilter/nf_nat_sip.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index b44281011d6d..71a4adcfd576 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c | |||
@@ -100,9 +100,11 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, | |||
100 | { | 100 | { |
101 | enum ip_conntrack_info ctinfo; | 101 | enum ip_conntrack_info ctinfo; |
102 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); | 102 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
103 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
103 | unsigned int matchoff, matchlen; | 104 | unsigned int matchoff, matchlen; |
104 | union nf_inet_addr addr; | 105 | union nf_inet_addr addr; |
105 | __be16 port; | 106 | __be16 port; |
107 | int request; | ||
106 | 108 | ||
107 | /* Basic rules: requests and responses. */ | 109 | /* Basic rules: requests and responses. */ |
108 | if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) { | 110 | if (strnicmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) { |
@@ -112,11 +114,81 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, | |||
112 | !map_addr(skb, dptr, datalen, matchoff, matchlen, | 114 | !map_addr(skb, dptr, datalen, matchoff, matchlen, |
113 | &addr, port)) | 115 | &addr, port)) |
114 | return NF_DROP; | 116 | return NF_DROP; |
117 | request = 1; | ||
118 | } else | ||
119 | request = 0; | ||
120 | |||
121 | /* Translate topmost Via header and parameters */ | ||
122 | if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, | ||
123 | SIP_HDR_VIA, NULL, &matchoff, &matchlen, | ||
124 | &addr, &port) > 0) { | ||
125 | unsigned int matchend, poff, plen, buflen, n; | ||
126 | char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; | ||
127 | |||
128 | /* We're only interested in headers related to this | ||
129 | * connection */ | ||
130 | if (request) { | ||
131 | if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip || | ||
132 | port != ct->tuplehash[dir].tuple.src.u.udp.port) | ||
133 | goto next; | ||
134 | } else { | ||
135 | if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip || | ||
136 | port != ct->tuplehash[dir].tuple.dst.u.udp.port) | ||
137 | goto next; | ||
138 | } | ||
139 | |||
140 | if (!map_addr(skb, dptr, datalen, matchoff, matchlen, | ||
141 | &addr, port)) | ||
142 | return NF_DROP; | ||
143 | |||
144 | matchend = matchoff + matchlen; | ||
145 | |||
146 | /* The maddr= parameter (RFC 2361) specifies where to send | ||
147 | * the reply. */ | ||
148 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, | ||
149 | "maddr=", &poff, &plen, | ||
150 | &addr) > 0 && | ||
151 | addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && | ||
152 | addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { | ||
153 | __be32 ip = ct->tuplehash[!dir].tuple.dst.u3.ip; | ||
154 | buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip)); | ||
155 | if (!mangle_packet(skb, dptr, datalen, poff, plen, | ||
156 | buffer, buflen)) | ||
157 | return NF_DROP; | ||
158 | } | ||
159 | |||
160 | /* The received= parameter (RFC 2361) contains the address | ||
161 | * from which the server received the request. */ | ||
162 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, | ||
163 | "received=", &poff, &plen, | ||
164 | &addr) > 0 && | ||
165 | addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && | ||
166 | addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { | ||
167 | __be32 ip = ct->tuplehash[!dir].tuple.src.u3.ip; | ||
168 | buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip)); | ||
169 | if (!mangle_packet(skb, dptr, datalen, poff, plen, | ||
170 | buffer, buflen)) | ||
171 | return NF_DROP; | ||
172 | } | ||
173 | |||
174 | /* The rport= parameter (RFC 3581) contains the port number | ||
175 | * from which the server received the request. */ | ||
176 | if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen, | ||
177 | "rport=", &poff, &plen, | ||
178 | &n) > 0 && | ||
179 | htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port && | ||
180 | htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { | ||
181 | __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; | ||
182 | buflen = sprintf(buffer, "%u", ntohs(p)); | ||
183 | if (!mangle_packet(skb, dptr, datalen, poff, plen, | ||
184 | buffer, buflen)) | ||
185 | return NF_DROP; | ||
186 | } | ||
115 | } | 187 | } |
116 | 188 | ||
189 | next: | ||
117 | if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) || | 190 | if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) || |
118 | !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO) || | 191 | !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO) || |
119 | !map_sip_addr(skb, dptr, datalen, SIP_HDR_VIA) || | ||
120 | !map_sip_addr(skb, dptr, datalen, SIP_HDR_CONTACT)) | 192 | !map_sip_addr(skb, dptr, datalen, SIP_HDR_CONTACT)) |
121 | return NF_DROP; | 193 | return NF_DROP; |
122 | return NF_ACCEPT; | 194 | return NF_ACCEPT; |