Skip to content
This repository has been archived by the owner on Nov 28, 2024. It is now read-only.

OCPBUGS-16087: Search by CIDR address with ipv4 and ipv6 #82

Merged
merged 1 commit into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/views/states/list/components/utils.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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;

Expand Down
8 changes: 2 additions & 6 deletions src/views/states/list/hooks/useStateFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<V1beta1NodeNetworkState>[] => {
const { t } = useNMStateTranslation();
Expand All @@ -19,11 +19,7 @@ const useStateFilters = (): RowFilter<V1beta1NodeNetworkState>[] => {
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'),
Expand Down
59 changes: 59 additions & 0 deletions src/views/states/list/utilts.ts
Original file line number Diff line number Diff line change
@@ -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));
};