Esempio n. 1
0
static int ProcessIcmpUnreach(Packet *p)
{
    /* Handle ICMP unreachable */
    SessionKey skey;
    Stream5LWSession *ssn = NULL;
    u_int16_t sport;
    u_int16_t dport;

    /* No "orig" IP Header */
    if (!p->orig_iph)
        return 0;

    /* Get TCP/UDP/ICMP session from original protocol/port info
     * embedded in the ICMP Unreach message.  This is already decoded
     * in p->orig_foo.  TCP/UDP ports are decoded as p->orig_sp/dp.
     */
    skey.protocol = p->orig_iph->ip_proto;
    sport = p->orig_sp;
    dport = p->orig_dp;

    if (p->orig_iph->ip_src.s_addr < p->orig_iph->ip_dst.s_addr)
    {
        skey.ip_l = p->orig_iph->ip_src.s_addr;
        skey.port_l = sport;
        skey.ip_h = p->orig_iph->ip_dst.s_addr;
        skey.port_h = dport;
    }
    else if (p->orig_iph->ip_dst.s_addr == p->orig_iph->ip_src.s_addr)
    {
        skey.ip_l = p->orig_iph->ip_src.s_addr;
        skey.ip_h = p->orig_iph->ip_src.s_addr;
        if (sport < dport)
        {
            skey.port_l = sport;
            skey.port_h = dport;
        }
        else
        {
            skey.port_l = dport;
            skey.port_h = sport;
        }
    }
    else
    {
        skey.ip_l = p->orig_iph->ip_dst.s_addr;
        skey.port_l = dport;
        skey.ip_h = p->orig_iph->ip_src.s_addr;
        skey.port_h = sport;
    }

    if (p->vh)
        skey.vlan_tag = VTH_VLAN(p->vh);
    else
        skey.vlan_tag = 0;

    switch (skey.protocol)
    {
    case IPPROTO_TCP:
        /* Lookup a TCP session */
        ssn = GetLWTcpSession(&skey);
        break;
    case IPPROTO_UDP:
        /* Lookup a UDP session */
        ssn = GetLWUdpSession(&skey);
        break;
    case IPPROTO_ICMP:
        /* Lookup a ICMP session */
        ssn = GetLWSessionFromKey(icmp_lws_cache, &skey);
        break;
    }

    if (ssn)
    {
        /* Mark this session as dead. */
        DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
            "Marking session as dead, per ICMP Unreachable!\n"););
        ssn->session_flags |= STREAM5_STATE_DROP_CLIENT;
        ssn->session_flags |= STREAM5_STATE_DROP_SERVER;
        ssn->session_flags |= STREAM5_STATE_UNREACH;
    }
Esempio n. 2
0
static int ProcessIcmpUnreach(Packet *p)
{
    /* Handle ICMP unreachable */
    SessionKey skey;
    SessionControlBlock *ssn = NULL;
    uint16_t sport;
    uint16_t dport;
    sfip_t *src;
    sfip_t *dst;

    /* No "orig" IP Header */
    if (!p->orig_iph)
        return 0;

    /* Get TCP/UDP/ICMP session from original protocol/port info
     * embedded in the ICMP Unreach message.  This is already decoded
     * in p->orig_foo.  TCP/UDP ports are decoded as p->orig_sp/dp.
     */
    skey.protocol = GET_ORIG_IPH_PROTO(p);
    sport = p->orig_sp;
    dport = p->orig_dp;

    src = GET_ORIG_SRC(p);
    dst = GET_ORIG_DST(p);

    if (sfip_fast_lt6(src, dst))
    {
        COPY4(skey.ip_l, src->ip32);
        skey.port_l = sport;
        COPY4(skey.ip_h, dst->ip32);
        skey.port_h = dport;
    }
    else if (IP_EQUALITY(GET_ORIG_SRC(p), GET_ORIG_DST(p)))
    {
        COPY4(skey.ip_l, src->ip32);
        COPY4(skey.ip_h, skey.ip_l);
        if (sport < dport)
        {
            skey.port_l = sport;
            skey.port_h = dport;
        }
        else
        {
            skey.port_l = dport;
            skey.port_h = sport;
        }
    }
    else
    {
        COPY4(skey.ip_l, dst->ip32);
        COPY4(skey.ip_h, src->ip32);
        skey.port_l = dport;
        skey.port_h = sport;
    }

    if (p->vh)
        skey.vlan_tag = (uint16_t)VTH_VLAN(p->vh);
    else
        skey.vlan_tag = 0;

    switch (skey.protocol)
    {
    case IPPROTO_TCP:
        /* Lookup a TCP session */
        ssn = GetLWTcpSession(&skey);
        break;
    case IPPROTO_UDP:
        /* Lookup a UDP session */
        ssn = GetLWUdpSession(&skey);
        break;
    case IPPROTO_ICMP:
        /* Lookup a ICMP session */
        ssn = session_api->get_session_by_key(icmp_lws_cache, &skey);
        break;
    }

    if (ssn)
    {
        /* Mark this session as dead. */
        DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
            "Marking session as dead, per ICMP Unreachable!\n"););
        ssn->ha_state.session_flags |= SSNFLAG_DROP_CLIENT;
        ssn->ha_state.session_flags |= SSNFLAG_DROP_SERVER;
        ssn->session_state |= STREAM_STATE_UNREACH;
    }