diff options
-rw-r--r-- | include/linux/netfilter/nf_conntrack_sip.h | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_sip.c | 4 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_sip.c | 87 |
3 files changed, 73 insertions, 20 deletions
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index 0dfc8b7210a3..89f2a627f3f0 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h | |||
@@ -164,7 +164,7 @@ extern int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr | |||
164 | unsigned int dataoff, unsigned int datalen, | 164 | unsigned int dataoff, unsigned int datalen, |
165 | const char *name, | 165 | const char *name, |
166 | unsigned int *matchoff, unsigned int *matchlen, | 166 | unsigned int *matchoff, unsigned int *matchlen, |
167 | union nf_inet_addr *addr); | 167 | union nf_inet_addr *addr, bool delim); |
168 | extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, | 168 | extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, |
169 | unsigned int off, unsigned int datalen, | 169 | unsigned int off, unsigned int datalen, |
170 | const char *name, | 170 | const char *name, |
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index ea4a23813d26..eef8f29e8bf8 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c | |||
@@ -173,7 +173,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, | |||
173 | * the reply. */ | 173 | * the reply. */ |
174 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, | 174 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, |
175 | "maddr=", &poff, &plen, | 175 | "maddr=", &poff, &plen, |
176 | &addr) > 0 && | 176 | &addr, true) > 0 && |
177 | addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && | 177 | addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && |
178 | addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { | 178 | addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { |
179 | buflen = sprintf(buffer, "%pI4", | 179 | buflen = sprintf(buffer, "%pI4", |
@@ -187,7 +187,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, | |||
187 | * from which the server received the request. */ | 187 | * from which the server received the request. */ |
188 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, | 188 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, |
189 | "received=", &poff, &plen, | 189 | "received=", &poff, &plen, |
190 | &addr) > 0 && | 190 | &addr, false) > 0 && |
191 | addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && | 191 | addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && |
192 | addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { | 192 | addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { |
193 | buflen = sprintf(buffer, "%pI4", | 193 | buflen = sprintf(buffer, "%pI4", |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 2fb666920cc9..5c0a112aeee6 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -183,12 +183,12 @@ static int media_len(const struct nf_conn *ct, const char *dptr, | |||
183 | return len + digits_len(ct, dptr, limit, shift); | 183 | return len + digits_len(ct, dptr, limit, shift); |
184 | } | 184 | } |
185 | 185 | ||
186 | static int parse_addr(const struct nf_conn *ct, const char *cp, | 186 | static int sip_parse_addr(const struct nf_conn *ct, const char *cp, |
187 | const char **endp, union nf_inet_addr *addr, | 187 | const char **endp, union nf_inet_addr *addr, |
188 | const char *limit) | 188 | const char *limit, bool delim) |
189 | { | 189 | { |
190 | const char *end; | 190 | const char *end; |
191 | int ret = 0; | 191 | int ret; |
192 | 192 | ||
193 | if (!ct) | 193 | if (!ct) |
194 | return 0; | 194 | return 0; |
@@ -197,16 +197,28 @@ static int parse_addr(const struct nf_conn *ct, const char *cp, | |||
197 | switch (nf_ct_l3num(ct)) { | 197 | switch (nf_ct_l3num(ct)) { |
198 | case AF_INET: | 198 | case AF_INET: |
199 | ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); | 199 | ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); |
200 | if (ret == 0) | ||
201 | return 0; | ||
200 | break; | 202 | break; |
201 | case AF_INET6: | 203 | case AF_INET6: |
204 | if (cp < limit && *cp == '[') | ||
205 | cp++; | ||
206 | else if (delim) | ||
207 | return 0; | ||
208 | |||
202 | ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); | 209 | ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); |
210 | if (ret == 0) | ||
211 | return 0; | ||
212 | |||
213 | if (end < limit && *end == ']') | ||
214 | end++; | ||
215 | else if (delim) | ||
216 | return 0; | ||
203 | break; | 217 | break; |
204 | default: | 218 | default: |
205 | BUG(); | 219 | BUG(); |
206 | } | 220 | } |
207 | 221 | ||
208 | if (ret == 0 || end == cp) | ||
209 | return 0; | ||
210 | if (endp) | 222 | if (endp) |
211 | *endp = end; | 223 | *endp = end; |
212 | return 1; | 224 | return 1; |
@@ -219,7 +231,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr, | |||
219 | union nf_inet_addr addr; | 231 | union nf_inet_addr addr; |
220 | const char *aux = dptr; | 232 | const char *aux = dptr; |
221 | 233 | ||
222 | if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { | 234 | if (!sip_parse_addr(ct, dptr, &dptr, &addr, limit, true)) { |
223 | pr_debug("ip: %s parse failed.!\n", dptr); | 235 | pr_debug("ip: %s parse failed.!\n", dptr); |
224 | return 0; | 236 | return 0; |
225 | } | 237 | } |
@@ -296,7 +308,7 @@ int ct_sip_parse_request(const struct nf_conn *ct, | |||
296 | return 0; | 308 | return 0; |
297 | dptr += shift; | 309 | dptr += shift; |
298 | 310 | ||
299 | if (!parse_addr(ct, dptr, &end, addr, limit)) | 311 | if (!sip_parse_addr(ct, dptr, &end, addr, limit, true)) |
300 | return -1; | 312 | return -1; |
301 | if (end < limit && *end == ':') { | 313 | if (end < limit && *end == ':') { |
302 | end++; | 314 | end++; |
@@ -550,7 +562,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr, | |||
550 | if (ret == 0) | 562 | if (ret == 0) |
551 | return ret; | 563 | return ret; |
552 | 564 | ||
553 | if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit)) | 565 | if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true)) |
554 | return -1; | 566 | return -1; |
555 | if (*c == ':') { | 567 | if (*c == ':') { |
556 | c++; | 568 | c++; |
@@ -599,7 +611,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, | |||
599 | unsigned int dataoff, unsigned int datalen, | 611 | unsigned int dataoff, unsigned int datalen, |
600 | const char *name, | 612 | const char *name, |
601 | unsigned int *matchoff, unsigned int *matchlen, | 613 | unsigned int *matchoff, unsigned int *matchlen, |
602 | union nf_inet_addr *addr) | 614 | union nf_inet_addr *addr, bool delim) |
603 | { | 615 | { |
604 | const char *limit = dptr + datalen; | 616 | const char *limit = dptr + datalen; |
605 | const char *start, *end; | 617 | const char *start, *end; |
@@ -613,7 +625,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, | |||
613 | return 0; | 625 | return 0; |
614 | 626 | ||
615 | start += strlen(name); | 627 | start += strlen(name); |
616 | if (!parse_addr(ct, start, &end, addr, limit)) | 628 | if (!sip_parse_addr(ct, start, &end, addr, limit, delim)) |
617 | return 0; | 629 | return 0; |
618 | *matchoff = start - dptr; | 630 | *matchoff = start - dptr; |
619 | *matchlen = end - start; | 631 | *matchlen = end - start; |
@@ -675,6 +687,47 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, | |||
675 | return 1; | 687 | return 1; |
676 | } | 688 | } |
677 | 689 | ||
690 | static int sdp_parse_addr(const struct nf_conn *ct, const char *cp, | ||
691 | const char **endp, union nf_inet_addr *addr, | ||
692 | const char *limit) | ||
693 | { | ||
694 | const char *end; | ||
695 | int ret; | ||
696 | |||
697 | memset(addr, 0, sizeof(*addr)); | ||
698 | switch (nf_ct_l3num(ct)) { | ||
699 | case AF_INET: | ||
700 | ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); | ||
701 | break; | ||
702 | case AF_INET6: | ||
703 | ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); | ||
704 | break; | ||
705 | default: | ||
706 | BUG(); | ||
707 | } | ||
708 | |||
709 | if (ret == 0) | ||
710 | return 0; | ||
711 | if (endp) | ||
712 | *endp = end; | ||
713 | return 1; | ||
714 | } | ||
715 | |||
716 | /* skip ip address. returns its length. */ | ||
717 | static int sdp_addr_len(const struct nf_conn *ct, const char *dptr, | ||
718 | const char *limit, int *shift) | ||
719 | { | ||
720 | union nf_inet_addr addr; | ||
721 | const char *aux = dptr; | ||
722 | |||
723 | if (!sdp_parse_addr(ct, dptr, &dptr, &addr, limit)) { | ||
724 | pr_debug("ip: %s parse failed.!\n", dptr); | ||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | return dptr - aux; | ||
729 | } | ||
730 | |||
678 | /* SDP header parsing: a SDP session description contains an ordered set of | 731 | /* SDP header parsing: a SDP session description contains an ordered set of |
679 | * headers, starting with a section containing general session parameters, | 732 | * headers, starting with a section containing general session parameters, |
680 | * optionally followed by multiple media descriptions. | 733 | * optionally followed by multiple media descriptions. |
@@ -686,10 +739,10 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, | |||
686 | */ | 739 | */ |
687 | static const struct sip_header ct_sdp_hdrs[] = { | 740 | static const struct sip_header ct_sdp_hdrs[] = { |
688 | [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), | 741 | [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), |
689 | [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len), | 742 | [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", sdp_addr_len), |
690 | [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len), | 743 | [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", sdp_addr_len), |
691 | [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len), | 744 | [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", sdp_addr_len), |
692 | [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len), | 745 | [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", sdp_addr_len), |
693 | [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), | 746 | [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), |
694 | }; | 747 | }; |
695 | 748 | ||
@@ -775,8 +828,8 @@ static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr, | |||
775 | if (ret <= 0) | 828 | if (ret <= 0) |
776 | return ret; | 829 | return ret; |
777 | 830 | ||
778 | if (!parse_addr(ct, dptr + *matchoff, NULL, addr, | 831 | if (!sdp_parse_addr(ct, dptr + *matchoff, NULL, addr, |
779 | dptr + *matchoff + *matchlen)) | 832 | dptr + *matchoff + *matchlen)) |
780 | return -1; | 833 | return -1; |
781 | return 1; | 834 | return 1; |
782 | } | 835 | } |