nf_nat_sip.c (21280B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* SIP extension for NAT alteration. 3 * 4 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar> 5 * based on RR's ip_nat_ftp.c and other modules. 6 * (C) 2007 United Security Providers 7 * (C) 2007, 2008, 2011, 2012 Patrick McHardy <kaber@trash.net> 8 */ 9 10#include <linux/module.h> 11#include <linux/skbuff.h> 12#include <linux/inet.h> 13#include <linux/udp.h> 14#include <linux/tcp.h> 15 16#include <net/netfilter/nf_nat.h> 17#include <net/netfilter/nf_nat_helper.h> 18#include <net/netfilter/nf_conntrack_core.h> 19#include <net/netfilter/nf_conntrack_helper.h> 20#include <net/netfilter/nf_conntrack_expect.h> 21#include <net/netfilter/nf_conntrack_seqadj.h> 22#include <linux/netfilter/nf_conntrack_sip.h> 23 24#define NAT_HELPER_NAME "sip" 25 26MODULE_LICENSE("GPL"); 27MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); 28MODULE_DESCRIPTION("SIP NAT helper"); 29MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME); 30 31static struct nf_conntrack_nat_helper nat_helper_sip = 32 NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME); 33 34static unsigned int mangle_packet(struct sk_buff *skb, unsigned int protoff, 35 unsigned int dataoff, 36 const char **dptr, unsigned int *datalen, 37 unsigned int matchoff, unsigned int matchlen, 38 const char *buffer, unsigned int buflen) 39{ 40 enum ip_conntrack_info ctinfo; 41 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 42 struct tcphdr *th; 43 unsigned int baseoff; 44 45 if (nf_ct_protonum(ct) == IPPROTO_TCP) { 46 th = (struct tcphdr *)(skb->data + protoff); 47 baseoff = protoff + th->doff * 4; 48 matchoff += dataoff - baseoff; 49 50 if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo, 51 protoff, matchoff, matchlen, 52 buffer, buflen, false)) 53 return 0; 54 } else { 55 baseoff = protoff + sizeof(struct udphdr); 56 matchoff += dataoff - baseoff; 57 58 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, 59 protoff, matchoff, matchlen, 60 buffer, buflen)) 61 return 0; 62 } 63 64 /* Reload data pointer and adjust datalen value */ 65 *dptr = skb->data + dataoff; 66 *datalen += buflen - matchlen; 67 return 1; 68} 69 70static int sip_sprintf_addr(const struct nf_conn *ct, char *buffer, 71 const union nf_inet_addr *addr, bool delim) 72{ 73 if (nf_ct_l3num(ct) == NFPROTO_IPV4) 74 return sprintf(buffer, "%pI4", &addr->ip); 75 else { 76 if (delim) 77 return sprintf(buffer, "[%pI6c]", &addr->ip6); 78 else 79 return sprintf(buffer, "%pI6c", &addr->ip6); 80 } 81} 82 83static int sip_sprintf_addr_port(const struct nf_conn *ct, char *buffer, 84 const union nf_inet_addr *addr, u16 port) 85{ 86 if (nf_ct_l3num(ct) == NFPROTO_IPV4) 87 return sprintf(buffer, "%pI4:%u", &addr->ip, port); 88 else 89 return sprintf(buffer, "[%pI6c]:%u", &addr->ip6, port); 90} 91 92static int map_addr(struct sk_buff *skb, unsigned int protoff, 93 unsigned int dataoff, 94 const char **dptr, unsigned int *datalen, 95 unsigned int matchoff, unsigned int matchlen, 96 union nf_inet_addr *addr, __be16 port) 97{ 98 enum ip_conntrack_info ctinfo; 99 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 100 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 101 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct); 102 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")]; 103 unsigned int buflen; 104 union nf_inet_addr newaddr; 105 __be16 newport; 106 107 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, addr) && 108 ct->tuplehash[dir].tuple.src.u.udp.port == port) { 109 newaddr = ct->tuplehash[!dir].tuple.dst.u3; 110 newport = ct->tuplehash[!dir].tuple.dst.u.udp.port; 111 } else if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, addr) && 112 ct->tuplehash[dir].tuple.dst.u.udp.port == port) { 113 newaddr = ct->tuplehash[!dir].tuple.src.u3; 114 newport = ct_sip_info->forced_dport ? : 115 ct->tuplehash[!dir].tuple.src.u.udp.port; 116 } else 117 return 1; 118 119 if (nf_inet_addr_cmp(&newaddr, addr) && newport == port) 120 return 1; 121 122 buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, ntohs(newport)); 123 return mangle_packet(skb, protoff, dataoff, dptr, datalen, 124 matchoff, matchlen, buffer, buflen); 125} 126 127static int map_sip_addr(struct sk_buff *skb, unsigned int protoff, 128 unsigned int dataoff, 129 const char **dptr, unsigned int *datalen, 130 enum sip_header_types type) 131{ 132 enum ip_conntrack_info ctinfo; 133 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 134 unsigned int matchlen, matchoff; 135 union nf_inet_addr addr; 136 __be16 port; 137 138 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL, 139 &matchoff, &matchlen, &addr, &port) <= 0) 140 return 1; 141 return map_addr(skb, protoff, dataoff, dptr, datalen, 142 matchoff, matchlen, &addr, port); 143} 144 145static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, 146 unsigned int dataoff, 147 const char **dptr, unsigned int *datalen) 148{ 149 enum ip_conntrack_info ctinfo; 150 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 151 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 152 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct); 153 unsigned int coff, matchoff, matchlen; 154 enum sip_header_types hdr; 155 union nf_inet_addr addr; 156 __be16 port; 157 int request, in_header; 158 159 /* Basic rules: requests and responses. */ 160 if (strncasecmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) { 161 if (ct_sip_parse_request(ct, *dptr, *datalen, 162 &matchoff, &matchlen, 163 &addr, &port) > 0 && 164 !map_addr(skb, protoff, dataoff, dptr, datalen, 165 matchoff, matchlen, &addr, port)) { 166 nf_ct_helper_log(skb, ct, "cannot mangle SIP message"); 167 return NF_DROP; 168 } 169 request = 1; 170 } else 171 request = 0; 172 173 if (nf_ct_protonum(ct) == IPPROTO_TCP) 174 hdr = SIP_HDR_VIA_TCP; 175 else 176 hdr = SIP_HDR_VIA_UDP; 177 178 /* Translate topmost Via header and parameters */ 179 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, 180 hdr, NULL, &matchoff, &matchlen, 181 &addr, &port) > 0) { 182 unsigned int olen, matchend, poff, plen, buflen, n; 183 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")]; 184 185 /* We're only interested in headers related to this 186 * connection */ 187 if (request) { 188 if (!nf_inet_addr_cmp(&addr, 189 &ct->tuplehash[dir].tuple.src.u3) || 190 port != ct->tuplehash[dir].tuple.src.u.udp.port) 191 goto next; 192 } else { 193 if (!nf_inet_addr_cmp(&addr, 194 &ct->tuplehash[dir].tuple.dst.u3) || 195 port != ct->tuplehash[dir].tuple.dst.u.udp.port) 196 goto next; 197 } 198 199 olen = *datalen; 200 if (!map_addr(skb, protoff, dataoff, dptr, datalen, 201 matchoff, matchlen, &addr, port)) { 202 nf_ct_helper_log(skb, ct, "cannot mangle Via header"); 203 return NF_DROP; 204 } 205 206 matchend = matchoff + matchlen + *datalen - olen; 207 208 /* The maddr= parameter (RFC 2361) specifies where to send 209 * the reply. */ 210 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, 211 "maddr=", &poff, &plen, 212 &addr, true) > 0 && 213 nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3) && 214 !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3)) { 215 buflen = sip_sprintf_addr(ct, buffer, 216 &ct->tuplehash[!dir].tuple.dst.u3, 217 true); 218 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, 219 poff, plen, buffer, buflen)) { 220 nf_ct_helper_log(skb, ct, "cannot mangle maddr"); 221 return NF_DROP; 222 } 223 } 224 225 /* The received= parameter (RFC 2361) contains the address 226 * from which the server received the request. */ 227 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, 228 "received=", &poff, &plen, 229 &addr, false) > 0 && 230 nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.dst.u3) && 231 !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.src.u3)) { 232 buflen = sip_sprintf_addr(ct, buffer, 233 &ct->tuplehash[!dir].tuple.src.u3, 234 false); 235 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, 236 poff, plen, buffer, buflen)) { 237 nf_ct_helper_log(skb, ct, "cannot mangle received"); 238 return NF_DROP; 239 } 240 } 241 242 /* The rport= parameter (RFC 3581) contains the port number 243 * from which the server received the request. */ 244 if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen, 245 "rport=", &poff, &plen, 246 &n) > 0 && 247 htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port && 248 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { 249 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; 250 buflen = sprintf(buffer, "%u", ntohs(p)); 251 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, 252 poff, plen, buffer, buflen)) { 253 nf_ct_helper_log(skb, ct, "cannot mangle rport"); 254 return NF_DROP; 255 } 256 } 257 } 258 259next: 260 /* Translate Contact headers */ 261 coff = 0; 262 in_header = 0; 263 while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen, 264 SIP_HDR_CONTACT, &in_header, 265 &matchoff, &matchlen, 266 &addr, &port) > 0) { 267 if (!map_addr(skb, protoff, dataoff, dptr, datalen, 268 matchoff, matchlen, 269 &addr, port)) { 270 nf_ct_helper_log(skb, ct, "cannot mangle contact"); 271 return NF_DROP; 272 } 273 } 274 275 if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) || 276 !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) { 277 nf_ct_helper_log(skb, ct, "cannot mangle SIP from/to"); 278 return NF_DROP; 279 } 280 281 /* Mangle destination port for Cisco phones, then fix up checksums */ 282 if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) { 283 struct udphdr *uh; 284 285 if (skb_ensure_writable(skb, skb->len)) { 286 nf_ct_helper_log(skb, ct, "cannot mangle packet"); 287 return NF_DROP; 288 } 289 290 uh = (void *)skb->data + protoff; 291 uh->dest = ct_sip_info->forced_dport; 292 293 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff, 294 0, 0, NULL, 0)) { 295 nf_ct_helper_log(skb, ct, "cannot mangle packet"); 296 return NF_DROP; 297 } 298 } 299 300 return NF_ACCEPT; 301} 302 303static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff, 304 s16 off) 305{ 306 enum ip_conntrack_info ctinfo; 307 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 308 const struct tcphdr *th; 309 310 if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0) 311 return; 312 313 th = (struct tcphdr *)(skb->data + protoff); 314 nf_ct_seqadj_set(ct, ctinfo, th->seq, off); 315} 316 317/* Handles expected signalling connections and media streams */ 318static void nf_nat_sip_expected(struct nf_conn *ct, 319 struct nf_conntrack_expect *exp) 320{ 321 struct nf_conn_help *help = nfct_help(ct->master); 322 struct nf_conntrack_expect *pair_exp; 323 int range_set_for_snat = 0; 324 struct nf_nat_range2 range; 325 326 /* This must be a fresh one. */ 327 BUG_ON(ct->status & IPS_NAT_DONE_MASK); 328 329 /* For DST manip, map port here to where it's expected. */ 330 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); 331 range.min_proto = range.max_proto = exp->saved_proto; 332 range.min_addr = range.max_addr = exp->saved_addr; 333 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); 334 335 /* Do media streams SRC manip according with the parameters 336 * found in the paired expectation. 337 */ 338 if (exp->class != SIP_EXPECT_SIGNALLING) { 339 spin_lock_bh(&nf_conntrack_expect_lock); 340 hlist_for_each_entry(pair_exp, &help->expectations, lnode) { 341 if (pair_exp->tuple.src.l3num == nf_ct_l3num(ct) && 342 pair_exp->tuple.dst.protonum == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum && 343 nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, &pair_exp->saved_addr) && 344 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all == pair_exp->saved_proto.all) { 345 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); 346 range.min_proto.all = range.max_proto.all = pair_exp->tuple.dst.u.all; 347 range.min_addr = range.max_addr = pair_exp->tuple.dst.u3; 348 range_set_for_snat = 1; 349 break; 350 } 351 } 352 spin_unlock_bh(&nf_conntrack_expect_lock); 353 } 354 355 /* When no paired expectation has been found, change src to 356 * where master sends to, but only if the connection actually came 357 * from the same source. 358 */ 359 if (!range_set_for_snat && 360 nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, 361 &ct->master->tuplehash[exp->dir].tuple.src.u3)) { 362 range.flags = NF_NAT_RANGE_MAP_IPS; 363 range.min_addr = range.max_addr 364 = ct->master->tuplehash[!exp->dir].tuple.dst.u3; 365 range_set_for_snat = 1; 366 } 367 368 /* Perform SRC manip. */ 369 if (range_set_for_snat) 370 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); 371} 372 373static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff, 374 unsigned int dataoff, 375 const char **dptr, unsigned int *datalen, 376 struct nf_conntrack_expect *exp, 377 unsigned int matchoff, 378 unsigned int matchlen) 379{ 380 enum ip_conntrack_info ctinfo; 381 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 382 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 383 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct); 384 union nf_inet_addr newaddr; 385 u_int16_t port; 386 __be16 srcport; 387 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")]; 388 unsigned int buflen; 389 390 /* Connection will come from reply */ 391 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, 392 &ct->tuplehash[!dir].tuple.dst.u3)) 393 newaddr = exp->tuple.dst.u3; 394 else 395 newaddr = ct->tuplehash[!dir].tuple.dst.u3; 396 397 /* If the signalling port matches the connection's source port in the 398 * original direction, try to use the destination port in the opposite 399 * direction. */ 400 srcport = ct_sip_info->forced_dport ? : 401 ct->tuplehash[dir].tuple.src.u.udp.port; 402 if (exp->tuple.dst.u.udp.port == srcport) 403 port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port); 404 else 405 port = ntohs(exp->tuple.dst.u.udp.port); 406 407 exp->saved_addr = exp->tuple.dst.u3; 408 exp->tuple.dst.u3 = newaddr; 409 exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port; 410 exp->dir = !dir; 411 exp->expectfn = nf_nat_sip_expected; 412 413 for (; port != 0; port++) { 414 int ret; 415 416 exp->tuple.dst.u.udp.port = htons(port); 417 ret = nf_ct_expect_related(exp, NF_CT_EXP_F_SKIP_MASTER); 418 if (ret == 0) 419 break; 420 else if (ret != -EBUSY) { 421 port = 0; 422 break; 423 } 424 } 425 426 if (port == 0) { 427 nf_ct_helper_log(skb, ct, "all ports in use for SIP"); 428 return NF_DROP; 429 } 430 431 if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) || 432 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { 433 buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port); 434 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, 435 matchoff, matchlen, buffer, buflen)) { 436 nf_ct_helper_log(skb, ct, "cannot mangle packet"); 437 goto err; 438 } 439 } 440 return NF_ACCEPT; 441 442err: 443 nf_ct_unexpect_related(exp); 444 return NF_DROP; 445} 446 447static int mangle_content_len(struct sk_buff *skb, unsigned int protoff, 448 unsigned int dataoff, 449 const char **dptr, unsigned int *datalen) 450{ 451 enum ip_conntrack_info ctinfo; 452 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 453 unsigned int matchoff, matchlen; 454 char buffer[sizeof("65536")]; 455 int buflen, c_len; 456 457 /* Get actual SDP length */ 458 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, 459 SDP_HDR_VERSION, SDP_HDR_UNSPEC, 460 &matchoff, &matchlen) <= 0) 461 return 0; 462 c_len = *datalen - matchoff + strlen("v="); 463 464 /* Now, update SDP length */ 465 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CONTENT_LENGTH, 466 &matchoff, &matchlen) <= 0) 467 return 0; 468 469 buflen = sprintf(buffer, "%u", c_len); 470 return mangle_packet(skb, protoff, dataoff, dptr, datalen, 471 matchoff, matchlen, buffer, buflen); 472} 473 474static int mangle_sdp_packet(struct sk_buff *skb, unsigned int protoff, 475 unsigned int dataoff, 476 const char **dptr, unsigned int *datalen, 477 unsigned int sdpoff, 478 enum sdp_header_types type, 479 enum sdp_header_types term, 480 char *buffer, int buflen) 481{ 482 enum ip_conntrack_info ctinfo; 483 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 484 unsigned int matchlen, matchoff; 485 486 if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term, 487 &matchoff, &matchlen) <= 0) 488 return -ENOENT; 489 return mangle_packet(skb, protoff, dataoff, dptr, datalen, 490 matchoff, matchlen, buffer, buflen) ? 0 : -EINVAL; 491} 492 493static unsigned int nf_nat_sdp_addr(struct sk_buff *skb, unsigned int protoff, 494 unsigned int dataoff, 495 const char **dptr, unsigned int *datalen, 496 unsigned int sdpoff, 497 enum sdp_header_types type, 498 enum sdp_header_types term, 499 const union nf_inet_addr *addr) 500{ 501 enum ip_conntrack_info ctinfo; 502 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 503 char buffer[INET6_ADDRSTRLEN]; 504 unsigned int buflen; 505 506 buflen = sip_sprintf_addr(ct, buffer, addr, false); 507 if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, 508 sdpoff, type, term, buffer, buflen)) 509 return 0; 510 511 return mangle_content_len(skb, protoff, dataoff, dptr, datalen); 512} 513 514static unsigned int nf_nat_sdp_port(struct sk_buff *skb, unsigned int protoff, 515 unsigned int dataoff, 516 const char **dptr, unsigned int *datalen, 517 unsigned int matchoff, 518 unsigned int matchlen, 519 u_int16_t port) 520{ 521 char buffer[sizeof("nnnnn")]; 522 unsigned int buflen; 523 524 buflen = sprintf(buffer, "%u", port); 525 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, 526 matchoff, matchlen, buffer, buflen)) 527 return 0; 528 529 return mangle_content_len(skb, protoff, dataoff, dptr, datalen); 530} 531 532static unsigned int nf_nat_sdp_session(struct sk_buff *skb, unsigned int protoff, 533 unsigned int dataoff, 534 const char **dptr, unsigned int *datalen, 535 unsigned int sdpoff, 536 const union nf_inet_addr *addr) 537{ 538 enum ip_conntrack_info ctinfo; 539 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 540 char buffer[INET6_ADDRSTRLEN]; 541 unsigned int buflen; 542 543 /* Mangle session description owner and contact addresses */ 544 buflen = sip_sprintf_addr(ct, buffer, addr, false); 545 if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff, 546 SDP_HDR_OWNER, SDP_HDR_MEDIA, buffer, buflen)) 547 return 0; 548 549 switch (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff, 550 SDP_HDR_CONNECTION, SDP_HDR_MEDIA, 551 buffer, buflen)) { 552 case 0: 553 /* 554 * RFC 2327: 555 * 556 * Session description 557 * 558 * c=* (connection information - not required if included in all media) 559 */ 560 case -ENOENT: 561 break; 562 default: 563 return 0; 564 } 565 566 return mangle_content_len(skb, protoff, dataoff, dptr, datalen); 567} 568 569/* So, this packet has hit the connection tracking matching code. 570 Mangle it, and change the expectation to match the new version. */ 571static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff, 572 unsigned int dataoff, 573 const char **dptr, unsigned int *datalen, 574 struct nf_conntrack_expect *rtp_exp, 575 struct nf_conntrack_expect *rtcp_exp, 576 unsigned int mediaoff, 577 unsigned int medialen, 578 union nf_inet_addr *rtp_addr) 579{ 580 enum ip_conntrack_info ctinfo; 581 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 582 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 583 u_int16_t port; 584 585 /* Connection will come from reply */ 586 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, 587 &ct->tuplehash[!dir].tuple.dst.u3)) 588 *rtp_addr = rtp_exp->tuple.dst.u3; 589 else 590 *rtp_addr = ct->tuplehash[!dir].tuple.dst.u3; 591 592 rtp_exp->saved_addr = rtp_exp->tuple.dst.u3; 593 rtp_exp->tuple.dst.u3 = *rtp_addr; 594 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; 595 rtp_exp->dir = !dir; 596 rtp_exp->expectfn = nf_nat_sip_expected; 597 598 rtcp_exp->saved_addr = rtcp_exp->tuple.dst.u3; 599 rtcp_exp->tuple.dst.u3 = *rtp_addr; 600 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; 601 rtcp_exp->dir = !dir; 602 rtcp_exp->expectfn = nf_nat_sip_expected; 603 604 /* Try to get same pair of ports: if not, try to change them. */ 605 for (port = ntohs(rtp_exp->tuple.dst.u.udp.port); 606 port != 0; port += 2) { 607 int ret; 608 609 rtp_exp->tuple.dst.u.udp.port = htons(port); 610 ret = nf_ct_expect_related(rtp_exp, 611 NF_CT_EXP_F_SKIP_MASTER); 612 if (ret == -EBUSY) 613 continue; 614 else if (ret < 0) { 615 port = 0; 616 break; 617 } 618 rtcp_exp->tuple.dst.u.udp.port = htons(port + 1); 619 ret = nf_ct_expect_related(rtcp_exp, 620 NF_CT_EXP_F_SKIP_MASTER); 621 if (ret == 0) 622 break; 623 else if (ret == -EBUSY) { 624 nf_ct_unexpect_related(rtp_exp); 625 continue; 626 } else if (ret < 0) { 627 nf_ct_unexpect_related(rtp_exp); 628 port = 0; 629 break; 630 } 631 } 632 633 if (port == 0) { 634 nf_ct_helper_log(skb, ct, "all ports in use for SDP media"); 635 goto err1; 636 } 637 638 /* Update media port. */ 639 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && 640 !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen, 641 mediaoff, medialen, port)) { 642 nf_ct_helper_log(skb, ct, "cannot mangle SDP message"); 643 goto err2; 644 } 645 646 return NF_ACCEPT; 647 648err2: 649 nf_ct_unexpect_related(rtp_exp); 650 nf_ct_unexpect_related(rtcp_exp); 651err1: 652 return NF_DROP; 653} 654 655static struct nf_ct_helper_expectfn sip_nat = { 656 .name = "sip", 657 .expectfn = nf_nat_sip_expected, 658}; 659 660static void __exit nf_nat_sip_fini(void) 661{ 662 nf_nat_helper_unregister(&nat_helper_sip); 663 RCU_INIT_POINTER(nf_nat_sip_hooks, NULL); 664 nf_ct_helper_expectfn_unregister(&sip_nat); 665 synchronize_rcu(); 666} 667 668static const struct nf_nat_sip_hooks sip_hooks = { 669 .msg = nf_nat_sip, 670 .seq_adjust = nf_nat_sip_seq_adjust, 671 .expect = nf_nat_sip_expect, 672 .sdp_addr = nf_nat_sdp_addr, 673 .sdp_port = nf_nat_sdp_port, 674 .sdp_session = nf_nat_sdp_session, 675 .sdp_media = nf_nat_sdp_media, 676}; 677 678static int __init nf_nat_sip_init(void) 679{ 680 BUG_ON(nf_nat_sip_hooks != NULL); 681 nf_nat_helper_register(&nat_helper_sip); 682 RCU_INIT_POINTER(nf_nat_sip_hooks, &sip_hooks); 683 nf_ct_helper_expectfn_register(&sip_nat); 684 return 0; 685} 686 687module_init(nf_nat_sip_init); 688module_exit(nf_nat_sip_fini);