Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* SIP extension for NAT alteration.
0003  *
0004  * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
0005  * based on RR's ip_nat_ftp.c and other modules.
0006  * (C) 2007 United Security Providers
0007  * (C) 2007, 2008, 2011, 2012 Patrick McHardy <kaber@trash.net>
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     /* Reload data pointer and adjust datalen value */
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     /* Basic rules: requests and responses. */
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     /* Translate topmost Via header and parameters */
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         /* We're only interested in headers related to this
0186          * connection */
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         /* The maddr= parameter (RFC 2361) specifies where to send
0209          * the reply. */
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         /* The received= parameter (RFC 2361) contains the address
0226          * from which the server received the request. */
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         /* The rport= parameter (RFC 3581) contains the port number
0243          * from which the server received the request. */
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     /* Translate Contact headers */
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     /* Mangle destination port for Cisco phones, then fix up checksums */
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 /* Handles expected signalling connections and media streams */
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     /* This must be a fresh one. */
0327     BUG_ON(ct->status & IPS_NAT_DONE_MASK);
0328 
0329     /* For DST manip, map port here to where it's expected. */
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     /* Do media streams SRC manip according with the parameters
0336      * found in the paired expectation.
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     /* When no paired expectation has been found, change src to
0356      * where master sends to, but only if the connection actually came
0357      * from the same source.
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     /* Perform SRC manip. */
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     /* Connection will come from reply */
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     /* If the signalling port matches the connection's source port in the
0398      * original direction, try to use the destination port in the opposite
0399      * direction. */
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     /* Get actual SDP length */
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     /* Now, update SDP length */
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     /* Mangle session description owner and contact addresses */
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      * RFC 2327:
0555      *
0556      * Session description
0557      *
0558      * c=* (connection information - not required if included in all media)
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 /* So, this packet has hit the connection tracking matching code.
0570    Mangle it, and change the expectation to match the new version. */
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     /* Connection will come from reply */
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     /* Try to get same pair of ports: if not, try to change them. */
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     /* Update media port. */
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);