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