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