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