/* * IPAddresses.java * Copyright (C) Apr 6, 2014 Wannes De Smet * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package be.neutrinet.ispng.vpn; import be.neutrinet.ispng.VPN; import com.googlecode.ipv6.IPv6Address; import com.googlecode.ipv6.IPv6Network; import com.googlecode.ipv6.IPv6NetworkMask; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.stmt.QueryBuilder; import com.j256.ormlite.table.TableUtils; import com.tufar.IPCalculator.IPv4; import org.apache.log4j.Logger; import java.sql.SQLException; import java.util.*; /** * @author wannes */ public class IPAddresses { public static Dao<IPAddress, String> dao; static { Class cls = IPAddress.class; try { dao = DaoManager.createDao(VPN.cs, cls); TableUtils.createTableIfNotExists(VPN.cs, cls); } catch (SQLException ex) { Logger.getLogger(cls).error("Failed to create DAO", ex); } } public static Optional<IPAddress> findUnused(int ipVersion) { return findUnused(ipVersion, IPAddress.Purpose.CLIENT_ASSIGN); } public static Optional<IPAddress> findUnused(int ipVersion, String purpose) { try { QueryBuilder<IPAddress, String> queryBuilder = dao.queryBuilder(); queryBuilder.limit(1L); queryBuilder.where().eq("client_id", -1).and() .eq("ipVersion", ipVersion).and().eq("purpose", purpose); List<IPAddress> query = dao.query(queryBuilder.prepare()); if (query.isEmpty()) { // Houston, we have a problem Logger.getLogger(IPAddresses.class).error("Ran out of IPv" + ipVersion + " addresses"); } else { return Optional.ofNullable(query.get(0)); } } catch (SQLException ex) { Logger.getLogger(IPAddresses.class).error("Failed to find IPv" + ipVersion + " address", ex); } return Optional.empty(); } public static List<IPAddress> forUser(UUID userId, int ipVersion) { try { ArrayList<IPAddress> addrs = new ArrayList<>(); List<Client> clients = Clients.dao.queryForEq("userId", UUID.fromString("" + userId)); for (Client client : clients) { addrs.addAll(client.leases); } return addrs; } catch (SQLException ex) { Logger.getLogger(IPAddresses.class).error("Failed to find IP address", ex); } return null; } public static List<IPAddress> forClient(Client client, int ipVersion) { return forClient(client, ipVersion, IPAddress.Purpose.CLIENT_ASSIGN); } public static List<IPAddress> forClient(Client client, int ipVersion, String purpose) { try { QueryBuilder<IPAddress, String> queryBuilder = dao.queryBuilder(); queryBuilder.where().eq("client_id", client.id).and() .eq("ipVersion", ipVersion).and() .eq("purpose", purpose); return dao.query(queryBuilder.prepare()); } catch (SQLException ex) { Logger.getLogger(IPAddresses.class).error("Failed to find IP address", ex); } return new ArrayList<>(); } public static List<IPAddress> addv4SubnetToPool(String subnetCIDR, String purpose) { ArrayList<IPAddress> addrs = new ArrayList<>(); IPv4 subnet = new IPv4(subnetCIDR); try { IPAddresses.dao.callBatchTasks(() -> { for (String addr : subnet.getAvailableIPs(subnet.getNumberOfHosts().intValue())) { try { IPAddress ipa = new IPAddress(); ipa.address = addr; ipa.ipVersion = 4; ipa.netmask = 32; ipa.purpose = purpose; IPAddresses.dao.createIfNotExists(ipa); addrs.add(ipa); } catch (Exception ex) { Logger.getLogger(IPAddresses.class).error("Failed to add IPv4 address to pool", ex); } } return null; }); } catch (Exception ex) { Logger.getLogger(IPAddresses.class).error("Failed to add subnet4 " + subnetCIDR + "to pool", ex); } return addrs; } public static List<IPAddress> addv6SubnetToPool(String subnetstr, String purpose) { ArrayList<IPAddress> addrs = new ArrayList<>(); IPv6Network subnet = IPv6Network.fromString(subnetstr); try { IPAddresses.dao.callBatchTasks(() -> { for (IPv6Address addr : subnet) { IPAddress ipa = new IPAddress(); ipa.address = addr.toString(); ipa.ipVersion = 6; ipa.netmask = 128; ipa.purpose = purpose; IPAddresses.dao.createIfNotExists(ipa); addrs.add(ipa); } return null; }); } catch (Exception ex) { Logger.getLogger(IPAddresses.class).error("Failed to add subnet6 " + subnetstr + "to pool", ex); } return addrs; } public static List<IPAddress> addv6SubnetToPool(String subnetstr, String purpose, int prefix) { ArrayList<IPAddress> addrs = new ArrayList<>(); IPv6Network subnet = IPv6Network.fromString(subnetstr); try { IPAddresses.dao.callBatchTasks(() -> { Iterator<IPv6Network> it = subnet.split(IPv6NetworkMask.fromPrefixLength(prefix)); IPv6Network net = it.next(); // skip first zero address for (; it.hasNext(); ) { net = it.next(); IPAddress ipa = new IPAddress(); ipa.address = net.toString().substring(0, net.toString().length() - ("" + prefix).length() - 1); ipa.ipVersion = 6; ipa.netmask = prefix; ipa.purpose = purpose; IPAddresses.dao.createIfNotExists(ipa); addrs.add(ipa); } return null; }); } catch (Exception ex) { Logger.getLogger(IPAddresses.class).error("Failed to add subnet6 " + subnetstr + "to pool", ex); } return addrs; } }