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; }
/**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");); }