0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/skbuff.h>
0012 #include <linux/inet.h>
0013 #include <linux/udp.h>
0014 #include <linux/tcp.h>
0015
0016 #include <net/netfilter/nf_nat.h>
0017 #include <net/netfilter/nf_nat_helper.h>
0018 #include <net/netfilter/nf_conntrack_core.h>
0019 #include <net/netfilter/nf_conntrack_helper.h>
0020 #include <net/netfilter/nf_conntrack_expect.h>
0021 #include <net/netfilter/nf_conntrack_seqadj.h>
0022 #include <linux/netfilter/nf_conntrack_sip.h>
0023
0024 #define NAT_HELPER_NAME "sip"
0025
0026 MODULE_LICENSE("GPL");
0027 MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
0028 MODULE_DESCRIPTION("SIP NAT helper");
0029 MODULE_ALIAS_NF_NAT_HELPER(NAT_HELPER_NAME);
0030
0031 static struct nf_conntrack_nat_helper nat_helper_sip =
0032 NF_CT_NAT_HELPER_INIT(NAT_HELPER_NAME);
0033
0034 static unsigned int mangle_packet(struct sk_buff *skb, unsigned int protoff,
0035 unsigned int dataoff,
0036 const char **dptr, unsigned int *datalen,
0037 unsigned int matchoff, unsigned int matchlen,
0038 const char *buffer, unsigned int buflen)
0039 {
0040 enum ip_conntrack_info ctinfo;
0041 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0042 struct tcphdr *th;
0043 unsigned int baseoff;
0044
0045 if (nf_ct_protonum(ct) == IPPROTO_TCP) {
0046 th = (struct tcphdr *)(skb->data + protoff);
0047 baseoff = protoff + th->doff * 4;
0048 matchoff += dataoff - baseoff;
0049
0050 if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
0051 protoff, matchoff, matchlen,
0052 buffer, buflen, false))
0053 return 0;
0054 } else {
0055 baseoff = protoff + sizeof(struct udphdr);
0056 matchoff += dataoff - baseoff;
0057
0058 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
0059 protoff, matchoff, matchlen,
0060 buffer, buflen))
0061 return 0;
0062 }
0063
0064
0065 *dptr = skb->data + dataoff;
0066 *datalen += buflen - matchlen;
0067 return 1;
0068 }
0069
0070 static int sip_sprintf_addr(const struct nf_conn *ct, char *buffer,
0071 const union nf_inet_addr *addr, bool delim)
0072 {
0073 if (nf_ct_l3num(ct) == NFPROTO_IPV4)
0074 return sprintf(buffer, "%pI4", &addr->ip);
0075 else {
0076 if (delim)
0077 return sprintf(buffer, "[%pI6c]", &addr->ip6);
0078 else
0079 return sprintf(buffer, "%pI6c", &addr->ip6);
0080 }
0081 }
0082
0083 static int sip_sprintf_addr_port(const struct nf_conn *ct, char *buffer,
0084 const union nf_inet_addr *addr, u16 port)
0085 {
0086 if (nf_ct_l3num(ct) == NFPROTO_IPV4)
0087 return sprintf(buffer, "%pI4:%u", &addr->ip, port);
0088 else
0089 return sprintf(buffer, "[%pI6c]:%u", &addr->ip6, port);
0090 }
0091
0092 static int map_addr(struct sk_buff *skb, unsigned int protoff,
0093 unsigned int dataoff,
0094 const char **dptr, unsigned int *datalen,
0095 unsigned int matchoff, unsigned int matchlen,
0096 union nf_inet_addr *addr, __be16 port)
0097 {
0098 enum ip_conntrack_info ctinfo;
0099 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0100 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
0101 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
0102 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
0103 unsigned int buflen;
0104 union nf_inet_addr newaddr;
0105 __be16 newport;
0106
0107 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, addr) &&
0108 ct->tuplehash[dir].tuple.src.u.udp.port == port) {
0109 newaddr = ct->tuplehash[!dir].tuple.dst.u3;
0110 newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
0111 } else if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, addr) &&
0112 ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
0113 newaddr = ct->tuplehash[!dir].tuple.src.u3;
0114 newport = ct_sip_info->forced_dport ? :
0115 ct->tuplehash[!dir].tuple.src.u.udp.port;
0116 } else
0117 return 1;
0118
0119 if (nf_inet_addr_cmp(&newaddr, addr) && newport == port)
0120 return 1;
0121
0122 buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, ntohs(newport));
0123 return mangle_packet(skb, protoff, dataoff, dptr, datalen,
0124 matchoff, matchlen, buffer, buflen);
0125 }
0126
0127 static int map_sip_addr(struct sk_buff *skb, unsigned int protoff,
0128 unsigned int dataoff,
0129 const char **dptr, unsigned int *datalen,
0130 enum sip_header_types type)
0131 {
0132 enum ip_conntrack_info ctinfo;
0133 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0134 unsigned int matchlen, matchoff;
0135 union nf_inet_addr addr;
0136 __be16 port;
0137
0138 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
0139 &matchoff, &matchlen, &addr, &port) <= 0)
0140 return 1;
0141 return map_addr(skb, protoff, dataoff, dptr, datalen,
0142 matchoff, matchlen, &addr, port);
0143 }
0144
0145 static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
0146 unsigned int dataoff,
0147 const char **dptr, unsigned int *datalen)
0148 {
0149 enum ip_conntrack_info ctinfo;
0150 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0151 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
0152 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
0153 unsigned int coff, matchoff, matchlen;
0154 enum sip_header_types hdr;
0155 union nf_inet_addr addr;
0156 __be16 port;
0157 int request, in_header;
0158
0159
0160 if (strncasecmp(*dptr, "SIP/2.0", strlen("SIP/2.0")) != 0) {
0161 if (ct_sip_parse_request(ct, *dptr, *datalen,
0162 &matchoff, &matchlen,
0163 &addr, &port) > 0 &&
0164 !map_addr(skb, protoff, dataoff, dptr, datalen,
0165 matchoff, matchlen, &addr, port)) {
0166 nf_ct_helper_log(skb, ct, "cannot mangle SIP message");
0167 return NF_DROP;
0168 }
0169 request = 1;
0170 } else
0171 request = 0;
0172
0173 if (nf_ct_protonum(ct) == IPPROTO_TCP)
0174 hdr = SIP_HDR_VIA_TCP;
0175 else
0176 hdr = SIP_HDR_VIA_UDP;
0177
0178
0179 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
0180 hdr, NULL, &matchoff, &matchlen,
0181 &addr, &port) > 0) {
0182 unsigned int olen, matchend, poff, plen, buflen, n;
0183 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
0184
0185
0186
0187 if (request) {
0188 if (!nf_inet_addr_cmp(&addr,
0189 &ct->tuplehash[dir].tuple.src.u3) ||
0190 port != ct->tuplehash[dir].tuple.src.u.udp.port)
0191 goto next;
0192 } else {
0193 if (!nf_inet_addr_cmp(&addr,
0194 &ct->tuplehash[dir].tuple.dst.u3) ||
0195 port != ct->tuplehash[dir].tuple.dst.u.udp.port)
0196 goto next;
0197 }
0198
0199 olen = *datalen;
0200 if (!map_addr(skb, protoff, dataoff, dptr, datalen,
0201 matchoff, matchlen, &addr, port)) {
0202 nf_ct_helper_log(skb, ct, "cannot mangle Via header");
0203 return NF_DROP;
0204 }
0205
0206 matchend = matchoff + matchlen + *datalen - olen;
0207
0208
0209
0210 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
0211 "maddr=", &poff, &plen,
0212 &addr, true) > 0 &&
0213 nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3) &&
0214 !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3)) {
0215 buflen = sip_sprintf_addr(ct, buffer,
0216 &ct->tuplehash[!dir].tuple.dst.u3,
0217 true);
0218 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
0219 poff, plen, buffer, buflen)) {
0220 nf_ct_helper_log(skb, ct, "cannot mangle maddr");
0221 return NF_DROP;
0222 }
0223 }
0224
0225
0226
0227 if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,
0228 "received=", &poff, &plen,
0229 &addr, false) > 0 &&
0230 nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.dst.u3) &&
0231 !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.src.u3)) {
0232 buflen = sip_sprintf_addr(ct, buffer,
0233 &ct->tuplehash[!dir].tuple.src.u3,
0234 false);
0235 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
0236 poff, plen, buffer, buflen)) {
0237 nf_ct_helper_log(skb, ct, "cannot mangle received");
0238 return NF_DROP;
0239 }
0240 }
0241
0242
0243
0244 if (ct_sip_parse_numerical_param(ct, *dptr, matchend, *datalen,
0245 "rport=", &poff, &plen,
0246 &n) > 0 &&
0247 htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port &&
0248 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
0249 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
0250 buflen = sprintf(buffer, "%u", ntohs(p));
0251 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
0252 poff, plen, buffer, buflen)) {
0253 nf_ct_helper_log(skb, ct, "cannot mangle rport");
0254 return NF_DROP;
0255 }
0256 }
0257 }
0258
0259 next:
0260
0261 coff = 0;
0262 in_header = 0;
0263 while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
0264 SIP_HDR_CONTACT, &in_header,
0265 &matchoff, &matchlen,
0266 &addr, &port) > 0) {
0267 if (!map_addr(skb, protoff, dataoff, dptr, datalen,
0268 matchoff, matchlen,
0269 &addr, port)) {
0270 nf_ct_helper_log(skb, ct, "cannot mangle contact");
0271 return NF_DROP;
0272 }
0273 }
0274
0275 if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) ||
0276 !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) {
0277 nf_ct_helper_log(skb, ct, "cannot mangle SIP from/to");
0278 return NF_DROP;
0279 }
0280
0281
0282 if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) {
0283 struct udphdr *uh;
0284
0285 if (skb_ensure_writable(skb, skb->len)) {
0286 nf_ct_helper_log(skb, ct, "cannot mangle packet");
0287 return NF_DROP;
0288 }
0289
0290 uh = (void *)skb->data + protoff;
0291 uh->dest = ct_sip_info->forced_dport;
0292
0293 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff,
0294 0, 0, NULL, 0)) {
0295 nf_ct_helper_log(skb, ct, "cannot mangle packet");
0296 return NF_DROP;
0297 }
0298 }
0299
0300 return NF_ACCEPT;
0301 }
0302
0303 static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff,
0304 s16 off)
0305 {
0306 enum ip_conntrack_info ctinfo;
0307 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0308 const struct tcphdr *th;
0309
0310 if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0)
0311 return;
0312
0313 th = (struct tcphdr *)(skb->data + protoff);
0314 nf_ct_seqadj_set(ct, ctinfo, th->seq, off);
0315 }
0316
0317
0318 static void nf_nat_sip_expected(struct nf_conn *ct,
0319 struct nf_conntrack_expect *exp)
0320 {
0321 struct nf_conn_help *help = nfct_help(ct->master);
0322 struct nf_conntrack_expect *pair_exp;
0323 int range_set_for_snat = 0;
0324 struct nf_nat_range2 range;
0325
0326
0327 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
0328
0329
0330 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
0331 range.min_proto = range.max_proto = exp->saved_proto;
0332 range.min_addr = range.max_addr = exp->saved_addr;
0333 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
0334
0335
0336
0337
0338 if (exp->class != SIP_EXPECT_SIGNALLING) {
0339 spin_lock_bh(&nf_conntrack_expect_lock);
0340 hlist_for_each_entry(pair_exp, &help->expectations, lnode) {
0341 if (pair_exp->tuple.src.l3num == nf_ct_l3num(ct) &&
0342 pair_exp->tuple.dst.protonum == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum &&
0343 nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, &pair_exp->saved_addr) &&
0344 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all == pair_exp->saved_proto.all) {
0345 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
0346 range.min_proto.all = range.max_proto.all = pair_exp->tuple.dst.u.all;
0347 range.min_addr = range.max_addr = pair_exp->tuple.dst.u3;
0348 range_set_for_snat = 1;
0349 break;
0350 }
0351 }
0352 spin_unlock_bh(&nf_conntrack_expect_lock);
0353 }
0354
0355
0356
0357
0358
0359 if (!range_set_for_snat &&
0360 nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
0361 &ct->master->tuplehash[exp->dir].tuple.src.u3)) {
0362 range.flags = NF_NAT_RANGE_MAP_IPS;
0363 range.min_addr = range.max_addr
0364 = ct->master->tuplehash[!exp->dir].tuple.dst.u3;
0365 range_set_for_snat = 1;
0366 }
0367
0368
0369 if (range_set_for_snat)
0370 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
0371 }
0372
0373 static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
0374 unsigned int dataoff,
0375 const char **dptr, unsigned int *datalen,
0376 struct nf_conntrack_expect *exp,
0377 unsigned int matchoff,
0378 unsigned int matchlen)
0379 {
0380 enum ip_conntrack_info ctinfo;
0381 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0382 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
0383 struct nf_ct_sip_master *ct_sip_info = nfct_help_data(ct);
0384 union nf_inet_addr newaddr;
0385 u_int16_t port;
0386 __be16 srcport;
0387 char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")];
0388 unsigned int buflen;
0389
0390
0391 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
0392 &ct->tuplehash[!dir].tuple.dst.u3))
0393 newaddr = exp->tuple.dst.u3;
0394 else
0395 newaddr = ct->tuplehash[!dir].tuple.dst.u3;
0396
0397
0398
0399
0400 srcport = ct_sip_info->forced_dport ? :
0401 ct->tuplehash[dir].tuple.src.u.udp.port;
0402 if (exp->tuple.dst.u.udp.port == srcport)
0403 port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
0404 else
0405 port = ntohs(exp->tuple.dst.u.udp.port);
0406
0407 exp->saved_addr = exp->tuple.dst.u3;
0408 exp->tuple.dst.u3 = newaddr;
0409 exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
0410 exp->dir = !dir;
0411 exp->expectfn = nf_nat_sip_expected;
0412
0413 for (; port != 0; port++) {
0414 int ret;
0415
0416 exp->tuple.dst.u.udp.port = htons(port);
0417 ret = nf_ct_expect_related(exp, NF_CT_EXP_F_SKIP_MASTER);
0418 if (ret == 0)
0419 break;
0420 else if (ret != -EBUSY) {
0421 port = 0;
0422 break;
0423 }
0424 }
0425
0426 if (port == 0) {
0427 nf_ct_helper_log(skb, ct, "all ports in use for SIP");
0428 return NF_DROP;
0429 }
0430
0431 if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) ||
0432 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
0433 buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port);
0434 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
0435 matchoff, matchlen, buffer, buflen)) {
0436 nf_ct_helper_log(skb, ct, "cannot mangle packet");
0437 goto err;
0438 }
0439 }
0440 return NF_ACCEPT;
0441
0442 err:
0443 nf_ct_unexpect_related(exp);
0444 return NF_DROP;
0445 }
0446
0447 static int mangle_content_len(struct sk_buff *skb, unsigned int protoff,
0448 unsigned int dataoff,
0449 const char **dptr, unsigned int *datalen)
0450 {
0451 enum ip_conntrack_info ctinfo;
0452 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0453 unsigned int matchoff, matchlen;
0454 char buffer[sizeof("65536")];
0455 int buflen, c_len;
0456
0457
0458 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
0459 SDP_HDR_VERSION, SDP_HDR_UNSPEC,
0460 &matchoff, &matchlen) <= 0)
0461 return 0;
0462 c_len = *datalen - matchoff + strlen("v=");
0463
0464
0465 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CONTENT_LENGTH,
0466 &matchoff, &matchlen) <= 0)
0467 return 0;
0468
0469 buflen = sprintf(buffer, "%u", c_len);
0470 return mangle_packet(skb, protoff, dataoff, dptr, datalen,
0471 matchoff, matchlen, buffer, buflen);
0472 }
0473
0474 static int mangle_sdp_packet(struct sk_buff *skb, unsigned int protoff,
0475 unsigned int dataoff,
0476 const char **dptr, unsigned int *datalen,
0477 unsigned int sdpoff,
0478 enum sdp_header_types type,
0479 enum sdp_header_types term,
0480 char *buffer, int buflen)
0481 {
0482 enum ip_conntrack_info ctinfo;
0483 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0484 unsigned int matchlen, matchoff;
0485
0486 if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term,
0487 &matchoff, &matchlen) <= 0)
0488 return -ENOENT;
0489 return mangle_packet(skb, protoff, dataoff, dptr, datalen,
0490 matchoff, matchlen, buffer, buflen) ? 0 : -EINVAL;
0491 }
0492
0493 static unsigned int nf_nat_sdp_addr(struct sk_buff *skb, unsigned int protoff,
0494 unsigned int dataoff,
0495 const char **dptr, unsigned int *datalen,
0496 unsigned int sdpoff,
0497 enum sdp_header_types type,
0498 enum sdp_header_types term,
0499 const union nf_inet_addr *addr)
0500 {
0501 enum ip_conntrack_info ctinfo;
0502 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0503 char buffer[INET6_ADDRSTRLEN];
0504 unsigned int buflen;
0505
0506 buflen = sip_sprintf_addr(ct, buffer, addr, false);
0507 if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen,
0508 sdpoff, type, term, buffer, buflen))
0509 return 0;
0510
0511 return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
0512 }
0513
0514 static unsigned int nf_nat_sdp_port(struct sk_buff *skb, unsigned int protoff,
0515 unsigned int dataoff,
0516 const char **dptr, unsigned int *datalen,
0517 unsigned int matchoff,
0518 unsigned int matchlen,
0519 u_int16_t port)
0520 {
0521 char buffer[sizeof("nnnnn")];
0522 unsigned int buflen;
0523
0524 buflen = sprintf(buffer, "%u", port);
0525 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
0526 matchoff, matchlen, buffer, buflen))
0527 return 0;
0528
0529 return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
0530 }
0531
0532 static unsigned int nf_nat_sdp_session(struct sk_buff *skb, unsigned int protoff,
0533 unsigned int dataoff,
0534 const char **dptr, unsigned int *datalen,
0535 unsigned int sdpoff,
0536 const union nf_inet_addr *addr)
0537 {
0538 enum ip_conntrack_info ctinfo;
0539 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0540 char buffer[INET6_ADDRSTRLEN];
0541 unsigned int buflen;
0542
0543
0544 buflen = sip_sprintf_addr(ct, buffer, addr, false);
0545 if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff,
0546 SDP_HDR_OWNER, SDP_HDR_MEDIA, buffer, buflen))
0547 return 0;
0548
0549 switch (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff,
0550 SDP_HDR_CONNECTION, SDP_HDR_MEDIA,
0551 buffer, buflen)) {
0552 case 0:
0553
0554
0555
0556
0557
0558
0559
0560 case -ENOENT:
0561 break;
0562 default:
0563 return 0;
0564 }
0565
0566 return mangle_content_len(skb, protoff, dataoff, dptr, datalen);
0567 }
0568
0569
0570
0571 static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
0572 unsigned int dataoff,
0573 const char **dptr, unsigned int *datalen,
0574 struct nf_conntrack_expect *rtp_exp,
0575 struct nf_conntrack_expect *rtcp_exp,
0576 unsigned int mediaoff,
0577 unsigned int medialen,
0578 union nf_inet_addr *rtp_addr)
0579 {
0580 enum ip_conntrack_info ctinfo;
0581 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
0582 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
0583 u_int16_t port;
0584
0585
0586 if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
0587 &ct->tuplehash[!dir].tuple.dst.u3))
0588 *rtp_addr = rtp_exp->tuple.dst.u3;
0589 else
0590 *rtp_addr = ct->tuplehash[!dir].tuple.dst.u3;
0591
0592 rtp_exp->saved_addr = rtp_exp->tuple.dst.u3;
0593 rtp_exp->tuple.dst.u3 = *rtp_addr;
0594 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
0595 rtp_exp->dir = !dir;
0596 rtp_exp->expectfn = nf_nat_sip_expected;
0597
0598 rtcp_exp->saved_addr = rtcp_exp->tuple.dst.u3;
0599 rtcp_exp->tuple.dst.u3 = *rtp_addr;
0600 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
0601 rtcp_exp->dir = !dir;
0602 rtcp_exp->expectfn = nf_nat_sip_expected;
0603
0604
0605 for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
0606 port != 0; port += 2) {
0607 int ret;
0608
0609 rtp_exp->tuple.dst.u.udp.port = htons(port);
0610 ret = nf_ct_expect_related(rtp_exp,
0611 NF_CT_EXP_F_SKIP_MASTER);
0612 if (ret == -EBUSY)
0613 continue;
0614 else if (ret < 0) {
0615 port = 0;
0616 break;
0617 }
0618 rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
0619 ret = nf_ct_expect_related(rtcp_exp,
0620 NF_CT_EXP_F_SKIP_MASTER);
0621 if (ret == 0)
0622 break;
0623 else if (ret == -EBUSY) {
0624 nf_ct_unexpect_related(rtp_exp);
0625 continue;
0626 } else if (ret < 0) {
0627 nf_ct_unexpect_related(rtp_exp);
0628 port = 0;
0629 break;
0630 }
0631 }
0632
0633 if (port == 0) {
0634 nf_ct_helper_log(skb, ct, "all ports in use for SDP media");
0635 goto err1;
0636 }
0637
0638
0639 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
0640 !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen,
0641 mediaoff, medialen, port)) {
0642 nf_ct_helper_log(skb, ct, "cannot mangle SDP message");
0643 goto err2;
0644 }
0645
0646 return NF_ACCEPT;
0647
0648 err2:
0649 nf_ct_unexpect_related(rtp_exp);
0650 nf_ct_unexpect_related(rtcp_exp);
0651 err1:
0652 return NF_DROP;
0653 }
0654
0655 static struct nf_ct_helper_expectfn sip_nat = {
0656 .name = "sip",
0657 .expectfn = nf_nat_sip_expected,
0658 };
0659
0660 static void __exit nf_nat_sip_fini(void)
0661 {
0662 nf_nat_helper_unregister(&nat_helper_sip);
0663 RCU_INIT_POINTER(nf_nat_sip_hooks, NULL);
0664 nf_ct_helper_expectfn_unregister(&sip_nat);
0665 synchronize_rcu();
0666 }
0667
0668 static const struct nf_nat_sip_hooks sip_hooks = {
0669 .msg = nf_nat_sip,
0670 .seq_adjust = nf_nat_sip_seq_adjust,
0671 .expect = nf_nat_sip_expect,
0672 .sdp_addr = nf_nat_sdp_addr,
0673 .sdp_port = nf_nat_sdp_port,
0674 .sdp_session = nf_nat_sdp_session,
0675 .sdp_media = nf_nat_sdp_media,
0676 };
0677
0678 static int __init nf_nat_sip_init(void)
0679 {
0680 BUG_ON(nf_nat_sip_hooks != NULL);
0681 nf_nat_helper_register(&nat_helper_sip);
0682 RCU_INIT_POINTER(nf_nat_sip_hooks, &sip_hooks);
0683 nf_ct_helper_expectfn_register(&sip_nat);
0684 return 0;
0685 }
0686
0687 module_init(nf_nat_sip_init);
0688 module_exit(nf_nat_sip_fini);