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; }
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; }