aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c121
1 files changed, 84 insertions, 37 deletions
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index f73ab4883b75..4429069d9b42 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -316,45 +316,77 @@ static int mangle_content_len(struct sk_buff *skb,
316 buffer, buflen); 316 buffer, buflen);
317} 317}
318 318
319static unsigned mangle_sdp_packet(struct sk_buff *skb, 319static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
320 const char **dptr, unsigned int *datalen, 320 unsigned int dataoff, unsigned int *datalen,
321 enum sdp_header_types type, 321 enum sdp_header_types type,
322 enum sdp_header_types term,
322 char *buffer, int buflen) 323 char *buffer, int buflen)
323{ 324{
324 enum ip_conntrack_info ctinfo; 325 enum ip_conntrack_info ctinfo;
325 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 326 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
326 unsigned int matchlen, matchoff; 327 unsigned int matchlen, matchoff;
327 328
328 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, type, SDP_HDR_UNSPEC, 329 if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term,
329 &matchoff, &matchlen) <= 0) 330 &matchoff, &matchlen) <= 0)
330 return 0; 331 return 0;
331 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 332 return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
332 buffer, buflen); 333 buffer, buflen);
333} 334}
334 335
335static unsigned int mangle_sdp(struct sk_buff *skb, 336static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
336 enum ip_conntrack_info ctinfo, 337 unsigned int dataoff,
337 struct nf_conn *ct, 338 unsigned int *datalen,
338 __be32 newip, u_int16_t port, 339 enum sdp_header_types type,
339 const char **dptr, unsigned int *datalen) 340 enum sdp_header_types term,
341 const union nf_inet_addr *addr)
340{ 342{
341 char buffer[sizeof("nnn.nnn.nnn.nnn")]; 343 char buffer[sizeof("nnn.nnn.nnn.nnn")];
342 unsigned int bufflen; 344 unsigned int buflen;
343 345
344 /* Mangle owner and contact info. */ 346 buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip));
345 bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); 347 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
346 if (!mangle_sdp_packet(skb, dptr, datalen, SDP_HDR_OWNER_IP4, 348 buffer, buflen))
347 buffer, bufflen))
348 return 0; 349 return 0;
349 350
350 if (!mangle_sdp_packet(skb, dptr, datalen, SDP_HDR_CONNECTION_IP4, 351 return mangle_content_len(skb, dptr, datalen);
351 buffer, bufflen)) 352}
353
354static unsigned int ip_nat_sdp_port(struct sk_buff *skb,
355 const char **dptr,
356 unsigned int *datalen,
357 unsigned int matchoff,
358 unsigned int matchlen,
359 u_int16_t port)
360{
361 char buffer[sizeof("nnnnn")];
362 unsigned int buflen;
363
364 buflen = sprintf(buffer, "%u", port);
365 if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen,
366 buffer, buflen))
352 return 0; 367 return 0;
353 368
354 /* Mangle media port. */ 369 return mangle_content_len(skb, dptr, datalen);
355 bufflen = sprintf(buffer, "%u", port); 370}
356 if (!mangle_sdp_packet(skb, dptr, datalen, SDP_HDR_MEDIA, 371
357 buffer, bufflen)) 372static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
373 unsigned int dataoff,
374 unsigned int *datalen,
375 const union nf_inet_addr *addr)
376{
377 char buffer[sizeof("nnn.nnn.nnn.nnn")];
378 unsigned int buflen;
379
380 /* Mangle session description owner and contact addresses */
381 buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip));
382 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
383 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
384 buffer, buflen))
385 return 0;
386
387 if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
388 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
389 buffer, buflen))
358 return 0; 390 return 0;
359 391
360 return mangle_content_len(skb, dptr, datalen); 392 return mangle_content_len(skb, dptr, datalen);
@@ -362,32 +394,35 @@ static unsigned int mangle_sdp(struct sk_buff *skb,
362 394
363/* So, this packet has hit the connection tracking matching code. 395/* So, this packet has hit the connection tracking matching code.
364 Mangle it, and change the expectation to match the new version. */ 396 Mangle it, and change the expectation to match the new version. */
365static unsigned int ip_nat_sdp(struct sk_buff *skb, 397static unsigned int ip_nat_sdp_media(struct sk_buff *skb,
366 const char **dptr, unsigned int *datalen, 398 const char **dptr,
367 struct nf_conntrack_expect *rtp_exp, 399 unsigned int *datalen,
368 struct nf_conntrack_expect *rtcp_exp) 400 struct nf_conntrack_expect *rtp_exp,
401 struct nf_conntrack_expect *rtcp_exp,
402 unsigned int mediaoff,
403 unsigned int medialen,
404 union nf_inet_addr *rtp_addr)
369{ 405{
370 enum ip_conntrack_info ctinfo; 406 enum ip_conntrack_info ctinfo;
371 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 407 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
372 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 408 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
373 __be32 newip;
374 u_int16_t port; 409 u_int16_t port;
375 410
376 /* Connection will come from reply */ 411 /* Connection will come from reply */
377 if (ct->tuplehash[dir].tuple.src.u3.ip == 412 if (ct->tuplehash[dir].tuple.src.u3.ip ==
378 ct->tuplehash[!dir].tuple.dst.u3.ip) 413 ct->tuplehash[!dir].tuple.dst.u3.ip)
379 newip = rtp_exp->tuple.dst.u3.ip; 414 rtp_addr->ip = rtp_exp->tuple.dst.u3.ip;
380 else 415 else
381 newip = ct->tuplehash[!dir].tuple.dst.u3.ip; 416 rtp_addr->ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
382 417
383 rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip; 418 rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip;
384 rtp_exp->tuple.dst.u3.ip = newip; 419 rtp_exp->tuple.dst.u3.ip = rtp_addr->ip;
385 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; 420 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
386 rtp_exp->dir = !dir; 421 rtp_exp->dir = !dir;
387 rtp_exp->expectfn = ip_nat_sip_expected; 422 rtp_exp->expectfn = ip_nat_sip_expected;
388 423
389 rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip; 424 rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip;
390 rtcp_exp->tuple.dst.u3.ip = newip; 425 rtcp_exp->tuple.dst.u3.ip = rtp_addr->ip;
391 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; 426 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
392 rtcp_exp->dir = !dir; 427 rtcp_exp->dir = !dir;
393 rtcp_exp->expectfn = ip_nat_sip_expected; 428 rtcp_exp->expectfn = ip_nat_sip_expected;
@@ -405,21 +440,29 @@ static unsigned int ip_nat_sdp(struct sk_buff *skb,
405 } 440 }
406 441
407 if (port == 0) 442 if (port == 0)
408 return NF_DROP; 443 goto err1;
444
445 /* Update media port. */
446 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
447 !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port))
448 goto err2;
409 449
410 if (!mangle_sdp(skb, ctinfo, ct, newip, port, dptr, datalen)) {
411 nf_ct_unexpect_related(rtp_exp);
412 nf_ct_unexpect_related(rtcp_exp);
413 return NF_DROP;
414 }
415 return NF_ACCEPT; 450 return NF_ACCEPT;
451
452err2:
453 nf_ct_unexpect_related(rtp_exp);
454 nf_ct_unexpect_related(rtcp_exp);
455err1:
456 return NF_DROP;
416} 457}
417 458
418static void __exit nf_nat_sip_fini(void) 459static void __exit nf_nat_sip_fini(void)
419{ 460{
420 rcu_assign_pointer(nf_nat_sip_hook, NULL); 461 rcu_assign_pointer(nf_nat_sip_hook, NULL);
421 rcu_assign_pointer(nf_nat_sip_expect_hook, NULL); 462 rcu_assign_pointer(nf_nat_sip_expect_hook, NULL);
422 rcu_assign_pointer(nf_nat_sdp_hook, NULL); 463 rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL);
464 rcu_assign_pointer(nf_nat_sdp_session_hook, NULL);
465 rcu_assign_pointer(nf_nat_sdp_media_hook, NULL);
423 synchronize_rcu(); 466 synchronize_rcu();
424} 467}
425 468
@@ -427,10 +470,14 @@ static int __init nf_nat_sip_init(void)
427{ 470{
428 BUG_ON(nf_nat_sip_hook != NULL); 471 BUG_ON(nf_nat_sip_hook != NULL);
429 BUG_ON(nf_nat_sip_expect_hook != NULL); 472 BUG_ON(nf_nat_sip_expect_hook != NULL);
430 BUG_ON(nf_nat_sdp_hook != NULL); 473 BUG_ON(nf_nat_sdp_addr_hook != NULL);
474 BUG_ON(nf_nat_sdp_session_hook != NULL);
475 BUG_ON(nf_nat_sdp_media_hook != NULL);
431 rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip); 476 rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
432 rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect); 477 rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect);
433 rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp); 478 rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
479 rcu_assign_pointer(nf_nat_sdp_session_hook, ip_nat_sdp_session);
480 rcu_assign_pointer(nf_nat_sdp_media_hook, ip_nat_sdp_media);
434 return 0; 481 return 0;
435} 482}
436 483