aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-03-25 23:24:41 -0400
committerDavid S. Miller <davem@davemloft.net>2008-03-25 23:24:41 -0400
commit720ac7085ce815ea4caec24396575fed7bd711aa (patch)
tree313932792e1f633035f4ad6005cadd7aff7a74fc
parent2bbb21168a90c788e12fe722eb66f27e611e7df7 (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.c74
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
189next:
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;