aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-03-25 23:16:54 -0400
committerDavid S. Miller <davem@davemloft.net>2008-03-25 23:16:54 -0400
commit2a6cfb22ae002330d445f734668d9158db9e90de (patch)
tree5d05dcfcfdc1df571b5c502b5df314debd7a19ce /net
parentb1ec488b1fb3c7a8819857e3506787516ca1ed4d (diff)
[NETFILTER]: nf_conntrack_sip: adjust dptr and datalen after packet mangling
After mangling the packet, the pointer to the data and the length of the data portion may change and need to be adjusted. Use double data pointers and a pointer to the length everywhere and add a helper function to the NAT helper for performing the adjustments. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c91
-rw-r--r--net/netfilter/nf_conntrack_sip.c14
2 files changed, 56 insertions, 49 deletions
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 84d8b4982cdf..e77122e65283 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -60,15 +60,35 @@ static void addr_map_init(const struct nf_conn *ct, struct addr_map *map)
60 } 60 }
61} 61}
62 62
63static unsigned int mangle_packet(struct sk_buff *skb,
64 const char **dptr, unsigned int *datalen,
65 unsigned int matchoff, unsigned int matchlen,
66 const char *buffer, unsigned int buflen)
67{
68 enum ip_conntrack_info ctinfo;
69 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
70
71 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, matchoff, matchlen,
72 buffer, buflen))
73 return 0;
74
75 /* Reload data pointer and adjust datalen value */
76 *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
77 *datalen += buflen - matchlen;
78 return 1;
79}
80
63static int map_sip_addr(struct sk_buff *skb, enum ip_conntrack_info ctinfo, 81static int map_sip_addr(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
64 struct nf_conn *ct, const char **dptr, size_t dlen, 82 struct nf_conn *ct,
83 const char **dptr, unsigned int *datalen,
65 enum sip_header_pos pos, struct addr_map *map) 84 enum sip_header_pos pos, struct addr_map *map)
66{ 85{
67 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 86 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
68 unsigned int matchlen, matchoff, addrlen; 87 unsigned int matchlen, matchoff, addrlen;
69 char *addr; 88 char *addr;
70 89
71 if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) 90 if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff, &matchlen,
91 pos) <= 0)
72 return 1; 92 return 1;
73 93
74 if ((matchlen == map->addr[dir].srciplen || 94 if ((matchlen == map->addr[dir].srciplen ||
@@ -84,26 +104,19 @@ static int map_sip_addr(struct sk_buff *skb, enum ip_conntrack_info ctinfo,
84 } else 104 } else
85 return 1; 105 return 1;
86 106
87 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, 107 return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
88 matchoff, matchlen, addr, addrlen)) 108 addr, addrlen);
89 return 0;
90 *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
91 return 1;
92
93} 109}
94 110
95static unsigned int ip_nat_sip(struct sk_buff *skb, 111static unsigned int ip_nat_sip(struct sk_buff *skb,
96 enum ip_conntrack_info ctinfo, 112 enum ip_conntrack_info ctinfo,
97 struct nf_conn *ct, 113 struct nf_conn *ct,
98 const char **dptr) 114 const char **dptr, unsigned int *datalen)
99{ 115{
100 enum sip_header_pos pos; 116 enum sip_header_pos pos;
101 struct addr_map map; 117 struct addr_map map;
102 int dataoff, datalen;
103 118
104 dataoff = ip_hdrlen(skb) + sizeof(struct udphdr); 119 if (*datalen < sizeof("SIP/2.0") - 1)
105 datalen = skb->len - dataoff;
106 if (datalen < sizeof("SIP/2.0") - 1)
107 return NF_ACCEPT; 120 return NF_ACCEPT;
108 121
109 addr_map_init(ct, &map); 122 addr_map_init(ct, &map);
@@ -115,7 +128,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
115 * The "userinfo" and "@" components of the SIP URI MUST NOT 128 * The "userinfo" and "@" components of the SIP URI MUST NOT
116 * be present. 129 * be present.
117 */ 130 */
118 if (datalen >= sizeof("REGISTER") - 1 && 131 if (*datalen >= sizeof("REGISTER") - 1 &&
119 strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0) 132 strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
120 pos = POS_REG_REQ_URI; 133 pos = POS_REG_REQ_URI;
121 else 134 else
@@ -136,51 +149,45 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
136static unsigned int mangle_sip_packet(struct sk_buff *skb, 149static unsigned int mangle_sip_packet(struct sk_buff *skb,
137 enum ip_conntrack_info ctinfo, 150 enum ip_conntrack_info ctinfo,
138 struct nf_conn *ct, 151 struct nf_conn *ct,
139 const char **dptr, size_t dlen, 152 const char **dptr, unsigned int *datalen,
140 char *buffer, int bufflen, 153 char *buffer, int bufflen,
141 enum sip_header_pos pos) 154 enum sip_header_pos pos)
142{ 155{
143 unsigned int matchlen, matchoff; 156 unsigned int matchlen, matchoff;
144 157
145 if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0) 158 if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff, &matchlen,
146 return 0; 159 pos) <= 0)
147
148 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
149 matchoff, matchlen, buffer, bufflen))
150 return 0; 160 return 0;
151 161
152 /* We need to reload this. Thanks Patrick. */ 162 return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
153 *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); 163 buffer, bufflen);
154 return 1;
155} 164}
156 165
157static int mangle_content_len(struct sk_buff *skb, 166static int mangle_content_len(struct sk_buff *skb,
158 enum ip_conntrack_info ctinfo, 167 enum ip_conntrack_info ctinfo,
159 struct nf_conn *ct, 168 struct nf_conn *ct,
160 const char *dptr) 169 const char **dptr, unsigned int *datalen)
161{ 170{
162 unsigned int dataoff, matchoff, matchlen; 171 unsigned int matchoff, matchlen;
163 char buffer[sizeof("65536")]; 172 char buffer[sizeof("65536")];
164 int bufflen; 173 int bufflen;
165 174
166 dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
167
168 /* Get actual SDP length */ 175 /* Get actual SDP length */
169 if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff, 176 if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff,
170 &matchlen, POS_SDP_HEADER) > 0) { 177 &matchlen, POS_SDP_HEADER) > 0) {
171 178
172 /* since ct_sip_get_info() give us a pointer passing 'v=' 179 /* since ct_sip_get_info() give us a pointer passing 'v='
173 we need to add 2 bytes in this count. */ 180 we need to add 2 bytes in this count. */
174 int c_len = skb->len - dataoff - matchoff + 2; 181 int c_len = *datalen - matchoff + 2;
175 182
176 /* Now, update SDP length */ 183 /* Now, update SDP length */
177 if (ct_sip_get_info(ct, dptr, skb->len - dataoff, &matchoff, 184 if (ct_sip_get_info(ct, *dptr, *datalen, &matchoff,
178 &matchlen, POS_CONTENT) > 0) { 185 &matchlen, POS_CONTENT) > 0) {
179 186
180 bufflen = sprintf(buffer, "%u", c_len); 187 bufflen = sprintf(buffer, "%u", c_len);
181 return nf_nat_mangle_udp_packet(skb, ct, ctinfo, 188 return mangle_packet(skb, dptr, datalen,
182 matchoff, matchlen, 189 matchoff, matchlen,
183 buffer, bufflen); 190 buffer, bufflen);
184 } 191 }
185 } 192 }
186 return 0; 193 return 0;
@@ -190,30 +197,28 @@ static unsigned int mangle_sdp(struct sk_buff *skb,
190 enum ip_conntrack_info ctinfo, 197 enum ip_conntrack_info ctinfo,
191 struct nf_conn *ct, 198 struct nf_conn *ct,
192 __be32 newip, u_int16_t port, 199 __be32 newip, u_int16_t port,
193 const char *dptr) 200 const char **dptr, unsigned int *datalen)
194{ 201{
195 char buffer[sizeof("nnn.nnn.nnn.nnn")]; 202 char buffer[sizeof("nnn.nnn.nnn.nnn")];
196 unsigned int dataoff, bufflen; 203 unsigned int bufflen;
197
198 dataoff = ip_hdrlen(skb) + sizeof(struct udphdr);
199 204
200 /* Mangle owner and contact info. */ 205 /* Mangle owner and contact info. */
201 bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); 206 bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
202 if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, 207 if (!mangle_sip_packet(skb, ctinfo, ct, dptr, datalen,
203 buffer, bufflen, POS_OWNER_IP4)) 208 buffer, bufflen, POS_OWNER_IP4))
204 return 0; 209 return 0;
205 210
206 if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, 211 if (!mangle_sip_packet(skb, ctinfo, ct, dptr, datalen,
207 buffer, bufflen, POS_CONNECTION_IP4)) 212 buffer, bufflen, POS_CONNECTION_IP4))
208 return 0; 213 return 0;
209 214
210 /* Mangle media port. */ 215 /* Mangle media port. */
211 bufflen = sprintf(buffer, "%u", port); 216 bufflen = sprintf(buffer, "%u", port);
212 if (!mangle_sip_packet(skb, ctinfo, ct, &dptr, skb->len - dataoff, 217 if (!mangle_sip_packet(skb, ctinfo, ct, dptr, datalen,
213 buffer, bufflen, POS_MEDIA)) 218 buffer, bufflen, POS_MEDIA))
214 return 0; 219 return 0;
215 220
216 return mangle_content_len(skb, ctinfo, ct, dptr); 221 return mangle_content_len(skb, ctinfo, ct, dptr, datalen);
217} 222}
218 223
219static void ip_nat_sdp_expect(struct nf_conn *ct, 224static void ip_nat_sdp_expect(struct nf_conn *ct,
@@ -242,7 +247,7 @@ static void ip_nat_sdp_expect(struct nf_conn *ct,
242static unsigned int ip_nat_sdp(struct sk_buff *skb, 247static unsigned int ip_nat_sdp(struct sk_buff *skb,
243 enum ip_conntrack_info ctinfo, 248 enum ip_conntrack_info ctinfo,
244 struct nf_conntrack_expect *exp, 249 struct nf_conntrack_expect *exp,
245 const char *dptr) 250 const char **dptr, unsigned int *datalen)
246{ 251{
247 struct nf_conn *ct = exp->master; 252 struct nf_conn *ct = exp->master;
248 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 253 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@@ -275,7 +280,7 @@ static unsigned int ip_nat_sdp(struct sk_buff *skb,
275 if (port == 0) 280 if (port == 0)
276 return NF_DROP; 281 return NF_DROP;
277 282
278 if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr)) { 283 if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr, datalen)) {
279 nf_ct_unexpect_related(exp); 284 nf_ct_unexpect_related(exp);
280 return NF_DROP; 285 return NF_DROP;
281 } 286 }
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 016e1c1aafe4..fa0d5599ff24 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -39,13 +39,15 @@ MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
39unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, 39unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
40 enum ip_conntrack_info ctinfo, 40 enum ip_conntrack_info ctinfo,
41 struct nf_conn *ct, 41 struct nf_conn *ct,
42 const char **dptr) __read_mostly; 42 const char **dptr,
43 unsigned int *datalen) __read_mostly;
43EXPORT_SYMBOL_GPL(nf_nat_sip_hook); 44EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
44 45
45unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb, 46unsigned int (*nf_nat_sdp_hook)(struct sk_buff *skb,
46 enum ip_conntrack_info ctinfo, 47 enum ip_conntrack_info ctinfo,
47 struct nf_conntrack_expect *exp, 48 struct nf_conntrack_expect *exp,
48 const char *dptr) __read_mostly; 49 const char **dptr,
50 unsigned int *datalen) __read_mostly;
49EXPORT_SYMBOL_GPL(nf_nat_sdp_hook); 51EXPORT_SYMBOL_GPL(nf_nat_sdp_hook);
50 52
51static int digits_len(const struct nf_conn *, const char *, const char *, int *); 53static int digits_len(const struct nf_conn *, const char *, const char *, int *);
@@ -369,7 +371,7 @@ static int set_expected_rtp(struct sk_buff *skb,
369 enum ip_conntrack_info ctinfo, 371 enum ip_conntrack_info ctinfo,
370 union nf_inet_addr *addr, 372 union nf_inet_addr *addr,
371 __be16 port, 373 __be16 port,
372 const char *dptr) 374 const char **dptr, unsigned int *datalen)
373{ 375{
374 struct nf_conntrack_expect *exp; 376 struct nf_conntrack_expect *exp;
375 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 377 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@@ -386,7 +388,7 @@ static int set_expected_rtp(struct sk_buff *skb,
386 388
387 nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook); 389 nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
388 if (nf_nat_sdp && ct->status & IPS_NAT_MASK) 390 if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
389 ret = nf_nat_sdp(skb, ctinfo, exp, dptr); 391 ret = nf_nat_sdp(skb, ctinfo, exp, dptr, datalen);
390 else { 392 else {
391 if (nf_ct_expect_related(exp) != 0) 393 if (nf_ct_expect_related(exp) != 0)
392 ret = NF_DROP; 394 ret = NF_DROP;
@@ -429,7 +431,7 @@ static int sip_help(struct sk_buff *skb,
429 431
430 nf_nat_sip = rcu_dereference(nf_nat_sip_hook); 432 nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
431 if (nf_nat_sip && ct->status & IPS_NAT_MASK) { 433 if (nf_nat_sip && ct->status & IPS_NAT_MASK) {
432 if (!nf_nat_sip(skb, ctinfo, ct, &dptr)) { 434 if (!nf_nat_sip(skb, ctinfo, ct, &dptr, &datalen)) {
433 ret = NF_DROP; 435 ret = NF_DROP;
434 goto out; 436 goto out;
435 } 437 }
@@ -466,7 +468,7 @@ static int sip_help(struct sk_buff *skb,
466 goto out; 468 goto out;
467 } 469 }
468 ret = set_expected_rtp(skb, ct, ctinfo, &addr, 470 ret = set_expected_rtp(skb, ct, ctinfo, &addr,
469 htons(port), dptr); 471 htons(port), &dptr, &datalen);
470 } 472 }
471 } 473 }
472out: 474out: