void GetLWPacketDirection(Packet *p, Stream5LWSession *ssn)
{
#ifndef SUP_IP6
    if (p->iph->ip_src.s_addr == ssn->client_ip)
    {
        if (p->iph->ip_proto == IPPROTO_TCP)
        {
            if (p->tcph->th_sport == ssn->client_port)
            {
                p->packet_flags |= PKT_FROM_CLIENT;
            }
            else
            {
                p->packet_flags |= PKT_FROM_SERVER;
            }
        }
        else if (p->iph->ip_proto == IPPROTO_UDP)
        {
            if (p->udph->uh_sport == ssn->client_port)
            {
                p->packet_flags |= PKT_FROM_CLIENT;
            }
            else
            {
                p->packet_flags |= PKT_FROM_SERVER;
            }
        }
        else if (p->iph->ip_proto == IPPROTO_ICMP)
        {
            p->packet_flags |= PKT_FROM_CLIENT;
        }
    }
    else if (p->iph->ip_dst.s_addr == ssn->client_ip)
    {
        if  (p->iph->ip_proto == IPPROTO_TCP)
        {
            if (p->tcph->th_dport == ssn->client_port)
            {
                p->packet_flags |= PKT_FROM_SERVER;
            }
            else
            {
                p->packet_flags |= PKT_FROM_CLIENT;
            }
        }
        else if (p->iph->ip_proto == IPPROTO_UDP)
        {
            if (p->udph->uh_dport == ssn->client_port)
            {
                p->packet_flags |= PKT_FROM_SERVER;
            }
            else
            {
                p->packet_flags |= PKT_FROM_CLIENT;
            }
        }
        else if (p->iph->ip_proto == IPPROTO_ICMP)
        {
            p->packet_flags |= PKT_FROM_CLIENT;
        }
    }
    else
    {
        /* Uh, no match of the packet to the session. */
        /* Probably should log an error */
    }
#else
    if(IS_IP4(p))
    {
        if (p->iph->ip_src.s_addr == *ssn->client_ip.ip32)
        {
            if (p->iph->ip_proto == IPPROTO_TCP)
            {
                if (p->tcph->th_sport == ssn->client_port)
                {
                    p->packet_flags |= PKT_FROM_CLIENT;
                }
                else
                {
                    p->packet_flags |= PKT_FROM_SERVER;
                }
            }
            else if (p->iph->ip_proto == IPPROTO_UDP)
            {
                if (p->udph->uh_sport == ssn->client_port)
                {
                    p->packet_flags |= PKT_FROM_CLIENT;
                }
                else
                {
                    p->packet_flags |= PKT_FROM_SERVER;
                }
            }
            else if (p->iph->ip_proto == IPPROTO_ICMP)
            {
                p->packet_flags |= PKT_FROM_CLIENT;
            }
        }
        else if (p->iph->ip_dst.s_addr == *ssn->client_ip.ip32)
        {
            if  (p->iph->ip_proto == IPPROTO_TCP)
            {
                if (p->tcph->th_dport == ssn->client_port)
                {
                    p->packet_flags |= PKT_FROM_SERVER;
                }
                else
                {
                    p->packet_flags |= PKT_FROM_CLIENT;
                }
            }
            else if (p->iph->ip_proto == IPPROTO_UDP)
            {
                if (p->udph->uh_dport == ssn->client_port)
                {
                    p->packet_flags |= PKT_FROM_SERVER;
                }
                else
                {
                    p->packet_flags |= PKT_FROM_CLIENT;
                }
            }
            else if (p->iph->ip_proto == IPPROTO_ICMP)
            {
                p->packet_flags |= PKT_FROM_CLIENT;
            }
        }
    }
    else /* IS_IP6(p) */
    {
        if (sfip_fast_eq6(&p->ip6h.ip_src, &ssn->client_ip))
        {
            if (p->ip6h.next == IPPROTO_TCP)
            {
                if (p->tcph->th_sport == ssn->client_port)
                {
                    p->packet_flags |= PKT_FROM_CLIENT;
                }
                else
                {
                    p->packet_flags |= PKT_FROM_SERVER;
                }
            }
            else if (p->ip6h.next == IPPROTO_UDP)
            {
                if (p->udph->uh_sport == ssn->client_port)
                {
                    p->packet_flags |= PKT_FROM_CLIENT;
                }
                else
                {
                    p->packet_flags |= PKT_FROM_SERVER;
                }
            }
            else if (p->ip6h.next == IPPROTO_ICMP)
            {
                p->packet_flags |= PKT_FROM_CLIENT;
            }
        }
        else if (sfip_fast_eq6(&p->ip6h.ip_dst, &ssn->client_ip))
        {
            if  (p->ip6h.next == IPPROTO_TCP)
            {
                if (p->tcph->th_dport == ssn->client_port)
                {
                    p->packet_flags |= PKT_FROM_SERVER;
                }
                else
                {
                    p->packet_flags |= PKT_FROM_CLIENT;
                }
            }
            else if (p->ip6h.next == IPPROTO_UDP)
            {
                if (p->udph->uh_dport == ssn->client_port)
                {
                    p->packet_flags |= PKT_FROM_SERVER;
                }
                else
                {
                    p->packet_flags |= PKT_FROM_CLIENT;
                }
            }
            else if (p->ip6h.next == IPPROTO_ICMP)
            {
                p->packet_flags |= PKT_FROM_CLIENT;
            }
        }
    }
#endif /* SUP_IP6 */
}
int GetLWSessionKey(Packet *p, SessionKey *key)
{
    u_int16_t sport;
    u_int16_t dport;
    int proto;
    /* Because the key is going to be used for hash lookups,
     * the lower of the values of the IP address field is
     * stored in the key->ip_l and the port for that ip is
     * stored in key->port_l.
     */

    if (!key)
        return 0;

#ifdef SUP_IP6
    if (IS_IP4(p))
    {
        u_int32_t *src;
        u_int32_t *dst;

        proto = p->iph->ip_proto;

        switch (proto)
        {
        case IPPROTO_TCP:
        case IPPROTO_UDP:
            sport = p->sp;
            dport = p->dp;
            break;
        case IPPROTO_ICMP:
        default:
            sport = dport = 0;
            break;
        }

        src = p->ip4h.ip_src.ip32;
        dst = p->ip4h.ip_dst.ip32;

        /* These comparisons are done in this fashion for performance reasons */
        if (*src < *dst)
        {
            COPY4(key->ip_l, src);
            COPY4(key->ip_h, dst);
            key->port_l = sport;
            key->port_h = dport;
        }
        else if (*src == *dst)
        {
            COPY4(key->ip_l, src);
            COPY4(key->ip_h, dst);
            if (sport < dport)
            {
                key->port_l = sport;
                key->port_h = dport;
            }
            else
            {
                key->port_l = dport;
                key->port_h = sport;
            }
        }
        else
        {
            COPY4(key->ip_l, dst);
            key->port_l = dport;
            COPY4(key->ip_h, src);
            key->port_h = sport;
        }
#ifdef MPLS
        if(pv.overlapping_IP && (p->mpls)
                && isPrivateIP(*src) && isPrivateIP(*dst) )
        {
            key->mplsLabel = p->mplsHdr.label;
        } else {
            key->mplsLabel = 0;
        }
#endif
    }
    else
    {
        /* IPv6 */
        sfip_t *src;
        sfip_t *dst;

        proto = p->ip6h.next;

        switch (proto)
        {
        case IPPROTO_TCP:
        case IPPROTO_UDP:
            sport = p->sp;
            dport = p->dp;
            break;
        case IPPROTO_ICMP:
        default:
            sport = dport = 0;
            break;
        }

        src = &p->ip6h.ip_src;
        dst = &p->ip6h.ip_dst;

        if (sfip_fast_lt6(src, dst))
        {
            COPY4(key->ip_l, src->ip32);
            key->port_l = sport;
            COPY4(key->ip_h, dst->ip32);
            key->port_h = dport;
        }
        else if (sfip_fast_eq6(src, dst))
        {
            COPY4(key->ip_l, src->ip32);
            COPY4(key->ip_h, dst->ip32);
            if (sport < dport)
            {
                key->port_l = sport;
                key->port_h = dport;
            }
            else
            {
                key->port_l = dport;
                key->port_h = sport;
            }
        }
        else
        {
            COPY4(key->ip_l, dst->ip32);
            key->port_l = dport;
            COPY4(key->ip_h, src->ip32);
            key->port_h = sport;
        }
#ifdef MPLS
        if(pv.overlapping_IP && (p->mpls))
        {
            key->mplsLabel = p->mplsHdr.label;
        } else {
            key->mplsLabel = 0;
        }
#endif
    }
#else
    proto = p->iph->ip_proto;

    switch (proto)
    {
    case IPPROTO_TCP:
    case IPPROTO_UDP:
        sport = p->sp;
        dport = p->dp;
        break;
    case IPPROTO_ICMP:
    default:
        sport = dport = 0;
        break;
    }

    /* These comparisons are done in this fashion for performance reasons */
    if (IP_LESSER(GET_SRC_IP(p), GET_DST_IP(p)))
    {
        IP_COPY_VALUE(key->ip_l, GET_SRC_IP(p));
        key->port_l = sport;
        IP_COPY_VALUE(key->ip_h, GET_DST_IP(p));
        key->port_h = dport;
    }
    else if (IP_EQUALITY(GET_SRC_IP(p), GET_DST_IP(p)))
    {
        IP_COPY_VALUE(key->ip_l, GET_SRC_IP(p));
        IP_COPY_VALUE(key->ip_h, GET_DST_IP(p));
        if (sport < dport)
        {
            key->port_l = sport;
            key->port_h = dport;
        }
        else
        {
            key->port_l = dport;
            key->port_h = sport;
        }
    }
    else
    {
        IP_COPY_VALUE(key->ip_l, GET_DST_IP(p));
        key->port_l = dport;
        IP_COPY_VALUE(key->ip_h, GET_SRC_IP(p));
        key->port_h = sport;
    }
#ifdef MPLS
    if(pv.overlapping_IP && (p->mpls)
            && isPrivateIP(key->ip_l) && isPrivateIP(key->ip_h))
    {
        key->mplsLabel = p->mplsHdr.label;
    } else {
        key->mplsLabel = 0;
    }
#endif
#endif

    key->protocol = proto;

    if (p->vh)
        key->vlan_tag = (u_int16_t)VTH_VLAN(p->vh);
    else
        key->vlan_tag = 0;

    key->pad = 0;
#ifdef MPLS
    key->mplsPad = 0;
#endif
    return 1;
}
Exemplo n.º 3
0
/**Either expect or expect future session.
 *
 * Preprocessors may add sessions to be expected altogether or to be associated with some data. For example,
 * FTP preprocessor may add data channel that should be expected. Alternatively, FTP preprocessor may add
 * session with appId FTP-DATA.
 *
 * It is assumed that only one of cliPort or srvPort should be known (!0). This violation of this assumption
 * will cause hash collision that will cause some session to be not expected and expected. This will occur only
 * rarely and therefore acceptable design optimization.
 *
 * Also, appId is assumed to be consistent between different preprocessors. Each session can be assigned only
 * one AppId. When new appId mismatches existing appId, new appId and associated data is not stored.
 *
 * @param cliIP - client IP address. All preprocessors must have consistent view of client side of a session.
 * @param cliPort - client port number
 * @param srvIP - server IP address. All preprocessors must have consisten view of server side of a session.
 * @param srcPort - server port number
 * @param protocol - IPPROTO_TCP or IPPROTO_UDP.
 * @param direction - direction of session. Assumed that direction value for session being expected or expected will
 * remain same across different calls to this function.
 * @param expiry - session expiry in seconds.
 */
int StreamExpectAddChannel(snort_ip_p cliIP, uint16_t cliPort,
                           snort_ip_p srvIP, uint16_t srvPort,
                           uint8_t protocol, time_t now, char direction, uint8_t flags,
                           uint32_t timeout, int16_t appId, uint32_t preprocId,
                           void *appData, void (*appDataFreeFn)(void*))
{
    ExpectHashKey hashKey;
    SFXHASH_NODE *hash_node;
    ExpectNode new_node;
    ExpectNode *node;
    ExpectedSessionDataList *data_list;
    ExpectedSessionData *data;
    int reversed_key;
    SFIP_RET rval;

    if (cliPort != UNKNOWN_PORT)
        srvPort = UNKNOWN_PORT;

#if defined(DEBUG_MSGS)
    {
        char src_ip[INET6_ADDRSTRLEN];
        char dst_ip[INET6_ADDRSTRLEN];

        sfip_ntop(cliIP, src_ip, sizeof(src_ip));
        sfip_ntop(srvIP, dst_ip, sizeof(dst_ip));
        DebugMessage(DEBUG_STREAM, "Creating expected %s-%u -> %s-%u %u appid %d  preproc %u\n", src_ip,
                     cliPort, dst_ip, srvPort, protocol, appId, preprocId);
    }
#endif

    /* Add the info to a tree that marks this channel as one to expect.
     * Only one of the port values may be UNKNOWN_PORT.
     * As a sanity check, the IP addresses may not be 0 or 255.255.255.255.
     */
    if ((cliPort == UNKNOWN_PORT) && (srvPort == UNKNOWN_PORT))
        return -1;

    if (cliIP->family == AF_INET)
    {
        if (!cliIP->ip.u6_addr32[0] || cliIP->ip.u6_addr32[0] == 0xFFFFFFFF ||
            !srvIP->ip.u6_addr32[0] || srvIP->ip.u6_addr32[0] == 0xFFFFFFFF)
        {
            return -1;
        }
    }
    else if (sfip_fast_eq6(cliIP, IP_ARG(zeroed)) || sfip_fast_eq6(srvIP, IP_ARG(zeroed)))
    {
        return -1;
    }

    rval = sfip_compare(cliIP, srvIP);
    if (rval == SFIP_LESSER || (rval == SFIP_EQUAL && cliPort < srvPort))
    {
        IP_COPY_VALUE(hashKey.ip1, cliIP);
        hashKey.port1 = cliPort;
        IP_COPY_VALUE(hashKey.ip2, srvIP);
        hashKey.port2 = srvPort;
        reversed_key = 0;
    }
    else
    {
        IP_COPY_VALUE(hashKey.ip1, srvIP);
        hashKey.port1 = srvPort;
        IP_COPY_VALUE(hashKey.ip2, cliIP);
        hashKey.port2 = cliPort;
        reversed_key = 1;
        DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "reversed\n"););
    }