aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nf_conntrack_sip.h2
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c4
-rw-r--r--net/netfilter/nf_conntrack_sip.c87
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);
168extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, 168extern 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
186static int parse_addr(const struct nf_conn *ct, const char *cp, 186static 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
690static 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. */
717static 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 */
687static const struct sip_header ct_sdp_hdrs[] = { 740static 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}