Loading net/netfilter/nf_conntrack_sip.c +43 −41 Original line number Diff line number Diff line Loading @@ -565,19 +565,49 @@ static int set_expected_rtp(struct sk_buff *skb, return ret; } static int process_sdp(struct sk_buff *skb, const char **dptr, unsigned int *datalen) { enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; unsigned int matchoff, matchlen; union nf_inet_addr addr; unsigned int port; enum sdp_header_types type; /* Get address and port from SDP packet. */ type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 : SDP_HDR_CONNECTION_IP6; if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, type, SDP_HDR_UNSPEC, &matchoff, &matchlen) <= 0) return NF_ACCEPT; /* We'll drop only if there are parse problems. */ if (!parse_addr(ct, *dptr + matchoff, NULL, &addr, *dptr + *datalen)) return NF_DROP; if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, SDP_HDR_MEDIA, SDP_HDR_UNSPEC, &matchoff, &matchlen) <= 0) return NF_ACCEPT; port = simple_strtoul(*dptr + matchoff, NULL, 10); if (port < 1024 || port > 65535) return NF_DROP; return set_expected_rtp(skb, dptr, datalen, &addr, htons(port)); } static int sip_help(struct sk_buff *skb, unsigned int protoff, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; union nf_inet_addr addr; unsigned int dataoff, datalen; const char *dptr; int ret = NF_ACCEPT; unsigned int matchoff, matchlen; u_int16_t port; enum sdp_header_types type; typeof(nf_nat_sip_hook) nf_nat_sip; /* No Data ? */ Loading @@ -591,56 +621,28 @@ static int sip_help(struct sk_buff *skb, dptr = skb->data + dataoff; else { pr_debug("Copy of skbuff not supported yet.\n"); goto out; return NF_ACCEPT; } nf_nat_sip = rcu_dereference(nf_nat_sip_hook); if (nf_nat_sip && ct->status & IPS_NAT_MASK) { if (!nf_nat_sip(skb, &dptr, &datalen)) { ret = NF_DROP; goto out; } if (!nf_nat_sip(skb, &dptr, &datalen)) return NF_DROP; } datalen = skb->len - dataoff; if (datalen < strlen("SIP/2.0 200")) goto out; return NF_ACCEPT; /* RTP info only in some SDP pkts */ if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 && strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 && strnicmp(dptr, "SIP/2.0 180", strlen("SIP/2.0 180")) != 0 && strnicmp(dptr, "SIP/2.0 183", strlen("SIP/2.0 183")) != 0 && strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) { goto out; } /* Get address and port from SDP packet. */ type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 : SDP_HDR_CONNECTION_IP6; if (ct_sip_get_sdp_header(ct, dptr, 0, datalen, type, SDP_HDR_UNSPEC, &matchoff, &matchlen) > 0) { /* We'll drop only if there are parse problems. */ if (!parse_addr(ct, dptr + matchoff, NULL, &addr, dptr + datalen)) { ret = NF_DROP; goto out; } if (ct_sip_get_sdp_header(ct, dptr, 0, datalen, SDP_HDR_MEDIA, SDP_HDR_UNSPEC, &matchoff, &matchlen) > 0) { strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) return NF_ACCEPT; port = simple_strtoul(dptr + matchoff, NULL, 10); if (port < 1024) { ret = NF_DROP; goto out; } ret = set_expected_rtp(skb, &dptr, &datalen, &addr, htons(port)); } } out: return ret; return process_sdp(skb, &dptr, &datalen); } static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly; Loading Loading
net/netfilter/nf_conntrack_sip.c +43 −41 Original line number Diff line number Diff line Loading @@ -565,19 +565,49 @@ static int set_expected_rtp(struct sk_buff *skb, return ret; } static int process_sdp(struct sk_buff *skb, const char **dptr, unsigned int *datalen) { enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; unsigned int matchoff, matchlen; union nf_inet_addr addr; unsigned int port; enum sdp_header_types type; /* Get address and port from SDP packet. */ type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 : SDP_HDR_CONNECTION_IP6; if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, type, SDP_HDR_UNSPEC, &matchoff, &matchlen) <= 0) return NF_ACCEPT; /* We'll drop only if there are parse problems. */ if (!parse_addr(ct, *dptr + matchoff, NULL, &addr, *dptr + *datalen)) return NF_DROP; if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, SDP_HDR_MEDIA, SDP_HDR_UNSPEC, &matchoff, &matchlen) <= 0) return NF_ACCEPT; port = simple_strtoul(*dptr + matchoff, NULL, 10); if (port < 1024 || port > 65535) return NF_DROP; return set_expected_rtp(skb, dptr, datalen, &addr, htons(port)); } static int sip_help(struct sk_buff *skb, unsigned int protoff, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; union nf_inet_addr addr; unsigned int dataoff, datalen; const char *dptr; int ret = NF_ACCEPT; unsigned int matchoff, matchlen; u_int16_t port; enum sdp_header_types type; typeof(nf_nat_sip_hook) nf_nat_sip; /* No Data ? */ Loading @@ -591,56 +621,28 @@ static int sip_help(struct sk_buff *skb, dptr = skb->data + dataoff; else { pr_debug("Copy of skbuff not supported yet.\n"); goto out; return NF_ACCEPT; } nf_nat_sip = rcu_dereference(nf_nat_sip_hook); if (nf_nat_sip && ct->status & IPS_NAT_MASK) { if (!nf_nat_sip(skb, &dptr, &datalen)) { ret = NF_DROP; goto out; } if (!nf_nat_sip(skb, &dptr, &datalen)) return NF_DROP; } datalen = skb->len - dataoff; if (datalen < strlen("SIP/2.0 200")) goto out; return NF_ACCEPT; /* RTP info only in some SDP pkts */ if (strnicmp(dptr, "INVITE", strlen("INVITE")) != 0 && strnicmp(dptr, "UPDATE", strlen("UPDATE")) != 0 && strnicmp(dptr, "SIP/2.0 180", strlen("SIP/2.0 180")) != 0 && strnicmp(dptr, "SIP/2.0 183", strlen("SIP/2.0 183")) != 0 && strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) { goto out; } /* Get address and port from SDP packet. */ type = family == AF_INET ? SDP_HDR_CONNECTION_IP4 : SDP_HDR_CONNECTION_IP6; if (ct_sip_get_sdp_header(ct, dptr, 0, datalen, type, SDP_HDR_UNSPEC, &matchoff, &matchlen) > 0) { /* We'll drop only if there are parse problems. */ if (!parse_addr(ct, dptr + matchoff, NULL, &addr, dptr + datalen)) { ret = NF_DROP; goto out; } if (ct_sip_get_sdp_header(ct, dptr, 0, datalen, SDP_HDR_MEDIA, SDP_HDR_UNSPEC, &matchoff, &matchlen) > 0) { strnicmp(dptr, "SIP/2.0 200", strlen("SIP/2.0 200")) != 0) return NF_ACCEPT; port = simple_strtoul(dptr + matchoff, NULL, 10); if (port < 1024) { ret = NF_DROP; goto out; } ret = set_expected_rtp(skb, &dptr, &datalen, &addr, htons(port)); } } out: return ret; return process_sdp(skb, &dptr, &datalen); } static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly; Loading