D-如何验证IP地址是否有效

时间:2012-02-22 21:26:51

标签: ipv6 ipv4 d phobos

我正在写一个HTTP解析库(因为我在纯D中找不到好的),我需要能够验证IP地址(对于URI字段),所以我写了几个函数来验证IP地址:

对于IPv4:

bool isIPv4(string addr) {
    int parts;
    ulong idx;

    foreach (i, c; addr) {
        if (c == '.') {
            if (i == 0) {
                return false;
            }

            if (to!int(addr[idx..i]) > 255) {
                return false;
            }

            parts++;
            if (parts > 3) {
                return false;
            }

            idx = i + 1;
        } else if (!isDigit(c)) {
            return false;
        }
    }

    if (to!int(addr[idx..addr.length]) > 255) {
        return false;
    }

    if (parts != 3) {
        return false;
    }

    return true;
}

对于IPv6:

bool isIPv6(string addr) {
    bool isColon, hasSeparator, hasIPv4;
    int leftChunks, rightChunks, digits;

    foreach (i, c; addr) {
        if (isHexDigit(c)) {
            digits = isColon ? 1 : digits + 1;
            isColon = false;

            if (digits == 1) {
                if (hasSeparator) {
                    rightChunks++;
                } else {
                    leftChunks++;
                }
            } else if (digits > 4) {
                return false;
            }
        } else if (c == ':') {
            if (isColon) {
                // multiple :: separators not allowed
                // as is :::
                if (hasSeparator) {
                    return false;
                }
                hasSeparator = true;
            } else {
                isColon = true;
            }
        } else if (c == '.') {
            if (hasSeparator) {
                rightChunks--;
            } else {
                leftChunks--;
            }

            if (!isIPv4(addr[i - digits .. addr.length])) {
                return false;
            }

            hasIPv4 = true;
            break;
        }
    }

    if (hasIPv4) {
        if (hasSeparator) {
            if (rightChunks + leftChunks > 5) {
                return false;
            }
        } else if (leftChunks != 6) {
            return false;
        }
    } else if (digits > 0) {
        if (hasSeparator) {
            if (rightChunks + leftChunks > 7) {
                return false;
            }
        } else if (leftChunks != 8) {
            return false;
        }
    }

    return true;
}

我最初尝试为IPv6制作一个正则表达式,但这很痛苦,特别是因为有很多特殊情况(::),我想我遇到了一个正则表达式编译错误,因为它太长了。显然,我想用一些标准函数为我做这个。

FWIW,我使用std.arrays.split实现了IPv4验证器,然后我决定这样做,因为否则我将不得不检测或捕获std.conv.to!int中的异常。

非常感谢!

注意

我最终想尝试获取一些我写入Phobos的代码,所以我希望代码尽可能的稳定。

4 个答案:

答案 0 :(得分:2)

答案 1 :(得分:1)

@tjameson:很久以前,我已经攻击了我自己的uri模块。以下是代码:http://codepad.org/PBm5BEVP。我一直想回到那个模块,改进它,并在GitHub上提交一个pull请求,但从来没有时间去做... URI RFC也有一个正则表达式来解析URI中的IPv6地址,这绝对是一些东西我会输入这段代码。

答案 2 :(得分:0)

您可以使用OS提供的inet_pton()函数。它将解析一个地址并告诉你它是否错误。见http://www.kernel.org/doc/man-pages/online/pages/man3/inet_pton.3.html

它将解析IPv4和IPv6地址,并且inet_ntop()可用于将解析后的地址转换回其规范表示法。

答案 3 :(得分:0)

尝试:

的IPv4

/^(((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?!$)|$)){4}$

的IPv6

/^((?=(?=(.*?::))\2(?!.+::))(::)?([\dA-F]{1,4}:(:|(?!$))|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:(?!$)|$))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?!$)|$)){4})$/i

(使用ECMAscript语法)

自: http://home.deds.nl/~aeron/regex/