001/*
002 * Copyright 2015-2024 the original author or authors
003 *
004 * This software is licensed under the Apache License, Version 2.0,
005 * the GNU Lesser General Public License version 2 or later ("LGPL")
006 * and the WTFPL.
007 * You may choose either license to govern your use of this software only
008 * upon the condition that you accept all of the terms of either
009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL.
010 */
011package org.minidns.constants;
012
013import java.net.Inet4Address;
014import java.net.Inet6Address;
015import java.net.InetAddress;
016import java.net.UnknownHostException;
017import java.util.HashMap;
018import java.util.Map;
019import java.util.Random;
020
021public class DnsRootServer {
022
023    private static final Map<Character, Inet4Address> IPV4_ROOT_SERVER_MAP = new HashMap<>();
024
025    private static final Map<Character, Inet6Address> IPV6_ROOT_SERVER_MAP = new HashMap<>();
026
027    protected static final Inet4Address[] IPV4_ROOT_SERVERS = new Inet4Address[] {
028            rootServerInet4Address('a', 198,  41,   0,   4),
029            rootServerInet4Address('b', 192, 228,  79, 201),
030            rootServerInet4Address('c', 192,  33,   4,  12),
031            rootServerInet4Address('d', 199,   7,  91 , 13),
032            rootServerInet4Address('e', 192, 203, 230,  10),
033            rootServerInet4Address('f', 192,   5,   5, 241),
034            rootServerInet4Address('g', 192, 112,  36,   4),
035            rootServerInet4Address('h', 198,  97, 190,  53),
036            rootServerInet4Address('i', 192,  36, 148,  17),
037            rootServerInet4Address('j', 192,  58, 128,  30),
038            rootServerInet4Address('k', 193,   0,  14, 129),
039            rootServerInet4Address('l', 199,   7,  83,  42),
040            rootServerInet4Address('m', 202,  12,  27,  33),
041        };
042
043        protected static final Inet6Address[] IPV6_ROOT_SERVERS = new Inet6Address[] {
044            rootServerInet6Address('a', 0x2001, 0x0503, 0xba3e, 0x0000, 0x0000, 0x000, 0x0002, 0x0030),
045            rootServerInet6Address('b', 0x2001, 0x0500, 0x0084, 0x0000, 0x0000, 0x000, 0x0000, 0x000b),
046            rootServerInet6Address('c', 0x2001, 0x0500, 0x0002, 0x0000, 0x0000, 0x000, 0x0000, 0x000c),
047            rootServerInet6Address('d', 0x2001, 0x0500, 0x002d, 0x0000, 0x0000, 0x000, 0x0000, 0x000d),
048            rootServerInet6Address('f', 0x2001, 0x0500, 0x002f, 0x0000, 0x0000, 0x000, 0x0000, 0x000f),
049            rootServerInet6Address('h', 0x2001, 0x0500, 0x0001, 0x0000, 0x0000, 0x000, 0x0000, 0x0053),
050            rootServerInet6Address('i', 0x2001, 0x07fe, 0x0000, 0x0000, 0x0000, 0x000, 0x0000, 0x0053),
051            rootServerInet6Address('j', 0x2001, 0x0503, 0x0c27, 0x0000, 0x0000, 0x000, 0x0002, 0x0030),
052            rootServerInet6Address('l', 0x2001, 0x0500, 0x0003, 0x0000, 0x0000, 0x000, 0x0000, 0x0042),
053            rootServerInet6Address('m', 0x2001, 0x0dc3, 0x0000, 0x0000, 0x0000, 0x000, 0x0000, 0x0035),
054        };
055
056        private static Inet4Address rootServerInet4Address(char rootServerId, int addr0, int addr1, int addr2, int addr3) {
057            Inet4Address inetAddress;
058            String name = rootServerId + ".root-servers.net";
059                try {
060                    inetAddress = (Inet4Address) InetAddress.getByAddress(name, new byte[] { (byte) addr0, (byte) addr1, (byte) addr2,
061                            (byte) addr3 });
062                    IPV4_ROOT_SERVER_MAP.put(rootServerId, inetAddress);
063                } catch (UnknownHostException e) {
064                    // This should never happen, if it does it's our fault!
065                    throw new RuntimeException(e);
066                }
067
068            return inetAddress;
069        }
070
071        private static Inet6Address rootServerInet6Address(char rootServerId, int addr0, int addr1, int addr2, int addr3, int addr4, int addr5, int addr6, int addr7) {
072            Inet6Address inetAddress;
073            String name = rootServerId + ".root-servers.net";
074                try {
075                    inetAddress = (Inet6Address) InetAddress.getByAddress(name, new byte[] {
076                            // @formatter:off
077                            (byte) (addr0 >> 8), (byte) addr0, (byte) (addr1 >> 8), (byte) addr1,
078                            (byte) (addr2 >> 8), (byte) addr2, (byte) (addr3 >> 8), (byte) addr3,
079                            (byte) (addr4 >> 8), (byte) addr4, (byte) (addr5 >> 8), (byte) addr5,
080                            (byte) (addr6 >> 8), (byte) addr6, (byte) (addr7 >> 8), (byte) addr7
081                            // @formatter:on
082                    });
083                    IPV6_ROOT_SERVER_MAP.put(rootServerId, inetAddress);
084                } catch (UnknownHostException e) {
085                    // This should never happen, if it does it's our fault!
086                    throw new RuntimeException(e);
087                }
088            return inetAddress;
089        }
090
091        public static Inet4Address getRandomIpv4RootServer(Random random) {
092            return IPV4_ROOT_SERVERS[random.nextInt(IPV4_ROOT_SERVERS.length)];
093        }
094
095        public static Inet6Address getRandomIpv6RootServer(Random random) {
096            return IPV6_ROOT_SERVERS[random.nextInt(IPV6_ROOT_SERVERS.length)];
097        }
098
099        public static Inet4Address getIpv4RootServerById(char id) {
100            return IPV4_ROOT_SERVER_MAP.get(id);
101        }
102
103        public static Inet6Address getIpv6RootServerById(char id) {
104            return IPV6_ROOT_SERVER_MAP.get(id);
105        }
106
107}