diff --git a/src/views/states/list/components/utils.ts b/src/views/states/list/components/utils.ts index 6e6010ab..b9fadae1 100644 --- a/src/views/states/list/components/utils.ts +++ b/src/views/states/list/components/utils.ts @@ -1,7 +1,7 @@ import { InterfaceType, NodeNetworkConfigurationInterface } from '@types'; -import { getIPV4Address, getIPV6Address } from '@utils/interfaces/getters'; import { FILTER_TYPES } from '../constants'; +import { searchInterfaceByIP } from '../utilts'; export const interfaceFilters: Record< string, @@ -21,11 +21,8 @@ export const interfaceFilters: Record< }, [FILTER_TYPES.IP_ADDRESS]: (selectedInput, obj) => { const searchIPAddress = selectedInput?.[0]; - if (!searchIPAddress) return true; - const addresses = [getIPV4Address(obj), getIPV6Address(obj)].filter(Boolean); - - return addresses?.some((address) => address?.toLowerCase().includes(searchIPAddress)); + return searchInterfaceByIP(searchIPAddress, obj); }, } as const; diff --git a/src/views/states/list/hooks/useStateFilters.ts b/src/views/states/list/hooks/useStateFilters.ts index 7b28bb04..8bd085bc 100644 --- a/src/views/states/list/hooks/useStateFilters.ts +++ b/src/views/states/list/hooks/useStateFilters.ts @@ -2,9 +2,9 @@ import { useNMStateTranslation } from 'src/utils/hooks/useNMStateTranslation'; import { RowFilter } from '@openshift-console/dynamic-plugin-sdk'; import { InterfaceType, NodeNetworkConfigurationInterface, V1beta1NodeNetworkState } from '@types'; -import { getIPV4Address, getIPV6Address } from '@utils/interfaces/getters'; import { FILTER_TYPES } from '../constants'; +import { searchInterfaceByIP } from '../utilts'; const useStateFilters = (): RowFilter[] => { const { t } = useNMStateTranslation(); @@ -19,11 +19,7 @@ const useStateFilters = (): RowFilter[] => { const interfaces = obj?.status?.currentState ?.interfaces as NodeNetworkConfigurationInterface[]; - const addresses = interfaces - ?.reduce((acc, iface) => [...acc, getIPV4Address(iface), getIPV6Address(iface)], []) - .filter(Boolean); - - return addresses?.some((address) => address?.toLowerCase().includes(searchIPAddress)); + return interfaces?.some((iface) => searchInterfaceByIP(searchIPAddress, iface)); }, isMatch: () => true, filterGroupName: t('Search IP address'), diff --git a/src/views/states/list/utilts.ts b/src/views/states/list/utilts.ts new file mode 100644 index 00000000..dc68ce00 --- /dev/null +++ b/src/views/states/list/utilts.ts @@ -0,0 +1,59 @@ +import { NodeNetworkConfigurationInterface } from '@types'; +import { getIPV4Address, getIPV6Address } from '@utils/interfaces/getters'; + +const decimalToBinary = (decimalNumber: number) => (decimalNumber >>> 0).toString(2); + +const ipv4StringToBinary = (ip: string) => + ip + .split('.') + .map((classes) => decimalToBinary(parseInt(classes)).padStart(8, '0')) + .join(''); + +const convertIPv6ToBinary = (ip: string) => { + const ipBinary = ip + .toLowerCase() + .replaceAll('::', ':0000:') + .split(':') + .map((ip) => parseInt(ip, 16).toString(2).padStart(16, '0')); + return ipBinary.join(''); +}; + +export const compareCIDR = (ipSearch: string, ip: string, isIPv4 = true) => { + const [baseIp, range] = ipSearch.split('/'); + + const baseIpBinary = isIPv4 ? ipv4StringToBinary(baseIp) : convertIPv6ToBinary(baseIp); + + const ipBinary = isIPv4 ? ipv4StringToBinary(ip) : convertIPv6ToBinary(baseIp); + + const rangeNumber = parseInt(range); + + const baseIpBinarySlice = baseIpBinary.slice(0, rangeNumber); + const ipBinarySlice = ipBinary.slice(0, rangeNumber); + + return baseIpBinarySlice === ipBinarySlice; +}; + +export const searchInterfaceByIP = ( + searchIPAddress: string, + iface: NodeNetworkConfigurationInterface, +) => { + if (!searchIPAddress) return true; + + const isSearchByIpv4 = searchIPAddress.includes('.'); + + if (searchIPAddress.includes('/')) { + const ipv4Address = getIPV4Address(iface); + const ipv6Address = getIPV6Address(iface); + + if (ipv4Address && isSearchByIpv4 && compareCIDR(searchIPAddress, ipv4Address)) { + return true; + } + if (ipv6Address && !isSearchByIpv4 && compareCIDR(searchIPAddress, ipv6Address, false)) { + return true; + } + } + + const addresses = [getIPV4Address(iface), getIPV6Address(iface)].filter(Boolean); + + return addresses?.some((address) => address?.toLowerCase().includes(searchIPAddress)); +};