All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.ripe.db.whois.common.rpsl.ParserHelper Maven / Gradle / Ivy

package net.ripe.db.whois.common.rpsl;

import net.ripe.db.whois.common.ip.Ipv4Resource;
import net.ripe.db.whois.common.ip.Ipv6Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ParserHelper {

    private ParserHelper() {}

    private static final Logger LOGGER = LoggerFactory.getLogger(ParserHelper.class);
    static final long MAX_32BIT_NUMBER = (1L << 32) - 1;
    static final long MAX_16BIT_NUMBER = (1L << 16) - 1;

    private static final int DOMAIN_NAME_MAX_LENGTH = 255;
    private static final int DOMAIN_NAME_LABEL_MAX_LENGTH = 63;

    private static final int MAX_BIT_LENGTH_IPV4 = 32;
    private static final int MAX_BIT_LENGTH_IPV6 = 128;

    private static final Pattern ADDRESS_PREFIX_RANGE_PATTERN = Pattern.compile("^(.*)/(\\d+)[\\^][\\+]??(\\d+)*[-]??(\\d+)*$");
    private static final Pattern AS_RANGE_PATTERN = Pattern.compile("(?i)AS([0-9]+)[ ]*[-][ ]*AS([0-9]+)");

    public static void check16bit(final String number) {
        final long value = Long.parseLong(number);
        if (value < 0 || value > MAX_16BIT_NUMBER) {
            syntaxError("dpa value " + value +" is not between 0 and " + MAX_16BIT_NUMBER);
        }
    }

    public static void check32bit(final String number) {
        final long value = Long.parseLong(number);
        if (value < 0 || value > MAX_32BIT_NUMBER) {
            syntaxError("dpa value " + value +" is not between 0 and " + MAX_32BIT_NUMBER);
        }
    }

    public static void checkMaskLength(final String maskLength) {
        if (Integer.parseInt(maskLength) > MAX_BIT_LENGTH_IPV4) {
            syntaxError("masklen " + maskLength + " is not between 0 and 32");
        }
    }

    public static void checkMaskLengthv6(final String maskLength) {
        if (Integer.parseInt(maskLength) > MAX_BIT_LENGTH_IPV6) {
            syntaxError("masklen " + maskLength + " is not between 0 and 128");
        }
    }

    public static void checkStringLength(final String ip, final int maxAllowedLength) {
        int length = ip.length();
        if (length > maxAllowedLength) {
            syntaxError("Domain name " + length + " is longer than " + maxAllowedLength + " characters");
        }
    }

    public static void validateMoreSpecificsOperator(final String yytext) {
        int val = Integer.valueOf(yytext.substring(1));
        if (val > MAX_BIT_LENGTH_IPV4) {
            syntaxError("more specifics operator " + yytext.substring(1) + " not 0 to 32 bits");
        }
    }

    public static void validateRangeMoreSpecificsOperators(final String yytext) {
        final int dash = yytext.indexOf('-');

        int from = Integer.valueOf(yytext.substring(1, dash));
        if (from > MAX_BIT_LENGTH_IPV4) {
            syntaxError("more specifics operator " + yytext + " not 0 to 32 bits");
        }

        int to = Integer.valueOf(yytext.substring(dash + 1));
        if (to > MAX_BIT_LENGTH_IPV4) {
            syntaxError("more specifics operator " + yytext + " not 0 to 32 bits");
        }

        if (to < from) {
            syntaxError("more specifics operator " + yytext + " not 0 to 32 bits");
        }
    }

    public static void validateAsNumber(final String yytext) {
        final long value = Long.valueOf(yytext.substring(2));
        if (value > MAX_32BIT_NUMBER) {
            syntaxError("AS Number " + yytext + " length is invalid");
        }
    }

    /** check each number of 1.2.3.4/5 in prefix is valid, as
     *   well as any bit ranges specified
     * @param yytext
     */
    public static void validateIpv4PrefixRange(final String yytext) {
        Matcher m = ADDRESS_PREFIX_RANGE_PATTERN.matcher(yytext);
        if (m.matches()) {
            try {
                Ipv4Resource.parse(m.group(1));
            } catch (IllegalArgumentException e) {
                syntaxError("IP prefix " + yytext + " contains an invalid octet");
            }

            int prefix = Integer.valueOf(m.group(2));
            if (prefix > MAX_BIT_LENGTH_IPV4) {
                syntaxError("IP prefix range " + yytext + " contains an invalid prefix length");
            }

            String fromString = m.group(3);
            int from = 0;
            if (fromString != null) {
                from = Integer.valueOf(fromString);
                if (from > MAX_BIT_LENGTH_IPV4) {
                    syntaxError("IP prefix range " + yytext + " contains an invalid range");
                }
            }

            String toString = m.group(4);
            if (toString != null) {
                int to = Integer.valueOf(toString);
                if (to > MAX_BIT_LENGTH_IPV4) {
                    syntaxError("IP prefix range " + yytext + " contains an invalid range");
                }

                if (to < from) {
                    syntaxError("IP prefix " + yytext + " range end is less than range start");
                }
            }
        }
    }

    /**
     * check IPv6 address and prefix range is valid
     * @param yytext
     */
    public static void validateIpv6PrefixRange(final String yytext) {
        Matcher m = ADDRESS_PREFIX_RANGE_PATTERN.matcher(yytext);
        if (m.matches()) {
            try {
                Ipv6Resource.parse(m.group(1));
            } catch (IllegalArgumentException e) {
                syntaxError("IP prefix " + yytext + " contains an invalid quad");
            }

            int prefix = Integer.valueOf(m.group(2));
            if (prefix > MAX_BIT_LENGTH_IPV6) {
                syntaxError("IP prefix range " + yytext + " contains an invalid prefix length");
            }

            String fromString = m.group(3);
            int from = 0;
            if (fromString != null) {
                from = Integer.valueOf(fromString);
                if (from > MAX_BIT_LENGTH_IPV6) {
                    syntaxError("IP prefix range " + yytext + " contains an invalid range");
                }
            }

            String toString = m.group(4);
            if (toString != null) {
                int to = Integer.valueOf(toString);
                if (to > MAX_BIT_LENGTH_IPV6) {
                    syntaxError("IP prefix range " + yytext + " contains an invalid range");
                }

                if (to < from) {
                    syntaxError("IP prefix " + yytext + " range end is less than range start");
                }
            }
        }
    }

    /**
     * check each number of 1.2.3.4/5 in prefix is valid
     * @param yytext
     */
    public static void validateIpv4Prefix(final String yytext) {
        final int slash = yytext.indexOf('/');
        try {
            Ipv4Resource.parse(yytext.substring(0, slash));
        } catch (IllegalArgumentException e) {
            syntaxError("IP prefix " + yytext + " contains an invalid octet");
        }

        final int length = Integer.valueOf(yytext.substring(slash + 1));
        if (length > MAX_BIT_LENGTH_IPV4) {
            syntaxError("IP prefix " + yytext + " contains an invalid prefix length");
        }
    }

    /**
     * check each quad of 1A:3:7:8:AAAA:BBBB:DEAD:BEEF/55 in prefix is valid
     * @param yytext
     */
    public static void validateIpv6Prefix(final String yytext) {
        final int slash = yytext.indexOf('/');
        try {
            Ipv6Resource.parse(yytext.substring(0, slash));
        } catch (IllegalArgumentException e) {
            syntaxError("IPv6 prefix " + yytext + " contains an invalid quad");
        }

        final int length = Integer.valueOf(yytext.substring(slash + 1));
        if (length > MAX_BIT_LENGTH_IPV6) {
            syntaxError("IPv6 prefix " + yytext + " contains an invalid prefix length");
        }
    }

    public static void validateIpv4(final String yytext) {
        try {
            Ipv4Resource.parse(yytext);
        } catch (IllegalArgumentException e) {
            syntaxError("IP address " + yytext + " contains an invalid octet");
        }
    }

    /**
     * Validate an IPv6 address
     * @param yytext
     */
    public static void validateIpv6(final String yytext) {
        try {
            Ipv6Resource.parse(yytext);
        } catch (IllegalArgumentException e) {
            syntaxError("IP address " + yytext + " contains an invalid quad");
        }
    }

    /**
     * Verify a community number.
     * The definition is (2-octet):(2-octet), only 16-bit AS numbers are allowed.
     * @param yytext
     */
    public static void validateCommunity(final String yytext) {
        final int colon = yytext.indexOf(':');

        final long from = Long.valueOf(yytext.substring(0, colon));
        if (from > MAX_16BIT_NUMBER) {
            syntaxError("Community number " + yytext + " contains an invalid number");
        }

        final long to = Long.valueOf(yytext.substring(colon + 1));
        if (to > MAX_16BIT_NUMBER) {
            // TODO: allow invalid > 16 bit user-defined number for now, but log warning
            syntaxError("Community number " + yytext + " contains an invalid number");
        }
    }

    /**
     * Validate the total length of a domain name (ref. RFC833).
     * @param yytext
     */
    public static void validateDomainName(final String yytext) {
        if (yytext.length() > DOMAIN_NAME_MAX_LENGTH) {
            syntaxError("Domain name " + yytext + " is longer than 255 characters");
        }
    }

    /**
     * Validate the length of a portion of a domain name (aka 'label' in RFC833).
     * @param yytext
     */
    public static void validateDomainNameLabel(final String yytext) {
        if (yytext.length() > DOMAIN_NAME_LABEL_MAX_LENGTH) {
            syntaxError("Domain name label " + yytext + " is longer than 63 characters");
        }
    }

    public static void validateSmallInt(final String yytext) {
        final int value = Integer.valueOf(yytext);
        if (value < 0 || value > MAX_16BIT_NUMBER) {
            syntaxError("Numeric value " + yytext + " must be between 0 and 65535");
        }
    }

    public static void validateAsRange(final String yytext) {
        Matcher matcher = AS_RANGE_PATTERN.matcher(yytext);
        if (matcher.find()) {
            long begin = Long.valueOf(matcher.group(1));
            if (begin > MAX_32BIT_NUMBER) {
                syntaxError("AS Number " + yytext + " is invalid");
            }

            long end = Long.valueOf(matcher.group(2));
            if (end > MAX_32BIT_NUMBER) {
                syntaxError("AS Number " + yytext + " is invalid");
            }

            if (end < begin) {
                syntaxError("AS Range " + yytext + " is invalid");
            }
        }
    }

    public static void log(final String message) {
        LOGGER.debug(message);
    }

    public static void log(final Exception exception) {
        LOGGER.debug(exception.getMessage(), exception);
    }

    public static void syntaxError(final String message) {
    	LOGGER.debug("syntax error: {}", message);
        throw new IllegalArgumentException(message);
    }

    public static void parserError(final String message) {
    	LOGGER.debug("parser error: {}", message);

        if (message.equalsIgnoreCase("syntax error")) {
            throw new IllegalArgumentException("invalid syntax");
        }
        throw new IllegalArgumentException(message);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy