|
@@ -183,12 +183,12 @@ static int media_len(const struct nf_conn *ct, const char *dptr,
|
|
|
return len + digits_len(ct, dptr, limit, shift);
|
|
|
}
|
|
|
|
|
|
-static int parse_addr(const struct nf_conn *ct, const char *cp,
|
|
|
- const char **endp, union nf_inet_addr *addr,
|
|
|
- const char *limit)
|
|
|
+static int sip_parse_addr(const struct nf_conn *ct, const char *cp,
|
|
|
+ const char **endp, union nf_inet_addr *addr,
|
|
|
+ const char *limit, bool delim)
|
|
|
{
|
|
|
const char *end;
|
|
|
- int ret = 0;
|
|
|
+ int ret;
|
|
|
|
|
|
if (!ct)
|
|
|
return 0;
|
|
@@ -197,16 +197,28 @@ static int parse_addr(const struct nf_conn *ct, const char *cp,
|
|
|
switch (nf_ct_l3num(ct)) {
|
|
|
case AF_INET:
|
|
|
ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
|
|
|
+ if (ret == 0)
|
|
|
+ return 0;
|
|
|
break;
|
|
|
case AF_INET6:
|
|
|
+ if (cp < limit && *cp == '[')
|
|
|
+ cp++;
|
|
|
+ else if (delim)
|
|
|
+ return 0;
|
|
|
+
|
|
|
ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end);
|
|
|
+ if (ret == 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (end < limit && *end == ']')
|
|
|
+ end++;
|
|
|
+ else if (delim)
|
|
|
+ return 0;
|
|
|
break;
|
|
|
default:
|
|
|
BUG();
|
|
|
}
|
|
|
|
|
|
- if (ret == 0 || end == cp)
|
|
|
- return 0;
|
|
|
if (endp)
|
|
|
*endp = end;
|
|
|
return 1;
|
|
@@ -219,7 +231,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr,
|
|
|
union nf_inet_addr addr;
|
|
|
const char *aux = dptr;
|
|
|
|
|
|
- if (!parse_addr(ct, dptr, &dptr, &addr, limit)) {
|
|
|
+ if (!sip_parse_addr(ct, dptr, &dptr, &addr, limit, true)) {
|
|
|
pr_debug("ip: %s parse failed.!\n", dptr);
|
|
|
return 0;
|
|
|
}
|
|
@@ -296,7 +308,7 @@ int ct_sip_parse_request(const struct nf_conn *ct,
|
|
|
return 0;
|
|
|
dptr += shift;
|
|
|
|
|
|
- if (!parse_addr(ct, dptr, &end, addr, limit))
|
|
|
+ if (!sip_parse_addr(ct, dptr, &end, addr, limit, true))
|
|
|
return -1;
|
|
|
if (end < limit && *end == ':') {
|
|
|
end++;
|
|
@@ -550,7 +562,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
|
|
|
if (ret == 0)
|
|
|
return ret;
|
|
|
|
|
|
- if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit))
|
|
|
+ if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true))
|
|
|
return -1;
|
|
|
if (*c == ':') {
|
|
|
c++;
|
|
@@ -599,7 +611,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
|
|
|
unsigned int dataoff, unsigned int datalen,
|
|
|
const char *name,
|
|
|
unsigned int *matchoff, unsigned int *matchlen,
|
|
|
- union nf_inet_addr *addr)
|
|
|
+ union nf_inet_addr *addr, bool delim)
|
|
|
{
|
|
|
const char *limit = dptr + datalen;
|
|
|
const char *start, *end;
|
|
@@ -613,7 +625,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
|
|
|
return 0;
|
|
|
|
|
|
start += strlen(name);
|
|
|
- if (!parse_addr(ct, start, &end, addr, limit))
|
|
|
+ if (!sip_parse_addr(ct, start, &end, addr, limit, delim))
|
|
|
return 0;
|
|
|
*matchoff = start - dptr;
|
|
|
*matchlen = end - start;
|
|
@@ -675,6 +687,47 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr,
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+static int sdp_parse_addr(const struct nf_conn *ct, const char *cp,
|
|
|
+ const char **endp, union nf_inet_addr *addr,
|
|
|
+ const char *limit)
|
|
|
+{
|
|
|
+ const char *end;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ memset(addr, 0, sizeof(*addr));
|
|
|
+ switch (nf_ct_l3num(ct)) {
|
|
|
+ case AF_INET:
|
|
|
+ ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ BUG();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ret == 0)
|
|
|
+ return 0;
|
|
|
+ if (endp)
|
|
|
+ *endp = end;
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+/* skip ip address. returns its length. */
|
|
|
+static int sdp_addr_len(const struct nf_conn *ct, const char *dptr,
|
|
|
+ const char *limit, int *shift)
|
|
|
+{
|
|
|
+ union nf_inet_addr addr;
|
|
|
+ const char *aux = dptr;
|
|
|
+
|
|
|
+ if (!sdp_parse_addr(ct, dptr, &dptr, &addr, limit)) {
|
|
|
+ pr_debug("ip: %s parse failed.!\n", dptr);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return dptr - aux;
|
|
|
+}
|
|
|
+
|
|
|
/* SDP header parsing: a SDP session description contains an ordered set of
|
|
|
* headers, starting with a section containing general session parameters,
|
|
|
* optionally followed by multiple media descriptions.
|
|
@@ -686,10 +739,10 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr,
|
|
|
*/
|
|
|
static const struct sip_header ct_sdp_hdrs[] = {
|
|
|
[SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len),
|
|
|
- [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len),
|
|
|
- [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len),
|
|
|
- [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len),
|
|
|
- [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len),
|
|
|
+ [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", sdp_addr_len),
|
|
|
+ [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", sdp_addr_len),
|
|
|
+ [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", sdp_addr_len),
|
|
|
+ [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", sdp_addr_len),
|
|
|
[SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len),
|
|
|
};
|
|
|
|
|
@@ -775,8 +828,8 @@ static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr,
|
|
|
if (ret <= 0)
|
|
|
return ret;
|
|
|
|
|
|
- if (!parse_addr(ct, dptr + *matchoff, NULL, addr,
|
|
|
- dptr + *matchoff + *matchlen))
|
|
|
+ if (!sdp_parse_addr(ct, dptr + *matchoff, NULL, addr,
|
|
|
+ dptr + *matchoff + *matchlen))
|
|
|
return -1;
|
|
|
return 1;
|
|
|
}
|
|
@@ -1515,7 +1568,6 @@ static int sip_help_udp(struct sk_buff *skb, unsigned int protoff,
|
|
|
}
|
|
|
|
|
|
static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly;
|
|
|
-static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly;
|
|
|
|
|
|
static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {
|
|
|
[SIP_EXPECT_SIGNALLING] = {
|
|
@@ -1585,9 +1637,9 @@ static int __init nf_conntrack_sip_init(void)
|
|
|
sip[i][j].me = THIS_MODULE;
|
|
|
|
|
|
if (ports[i] == SIP_PORT)
|
|
|
- sprintf(sip_names[i][j], "sip");
|
|
|
+ sprintf(sip[i][j].name, "sip");
|
|
|
else
|
|
|
- sprintf(sip_names[i][j], "sip-%u", i);
|
|
|
+ sprintf(sip[i][j].name, "sip-%u", i);
|
|
|
|
|
|
pr_debug("port #%u: %u\n", i, ports[i]);
|
|
|
|