ipv6 地址范围判断

15 阅读2分钟

32位循环比较的时候需要注意转为主机字节序

  • 代码
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <stdlib.h>



// ok
static inline int isIPv6InRangev1(void *src_addr, const uint32_t *startIp, const uint32_t *endIp) {
    uint32_t ip[4];

    memcpy(ip, src_addr, sizeof(ip));
    printf("v1 ok\n");
    // ip < startIp
    if (memcmp(ip, startIp, 16) < 0) {
        return -1;
    }

    // ip > endIp
    if (memcmp(ip, endIp, 16) > 0) {
        return -1;
    }

    return 0;
}


// no
static inline int isIPv6InRangev2(void *src_addr, const uint32_t *startIp, const uint32_t *endIp) {
    uint32_t ip[4];
    uint32_t startip,endip;

    memcpy(ip, src_addr, sizeof(ip));
    printf("v2 ok \n");
    for (int i = 0; i < 4; i++) {
        ip[i] = ntohl(ip[i]);
        startip = ntohl(startIp[i]);
        endip = ntohl(endIp[i]);
        printf("ip[%d]: %x\n", i, ip[i]);
        if (ip[i] < startip || ip[i] > endip) {
            return -1;
        }
    }

    return 0;
}

// no
static inline int isIPv6InRangev3(void *src_addr, const uint32_t *startIp, const uint32_t *endIp) {
    uint32_t ip[4];
    uint32_t startip,endip;

    memcpy(ip, src_addr, sizeof(ip));
    printf("v3 no \n");
    for (int i = 0; i < 4; i++) {
        printf("ip[%d]: %x\n", i, ip[i]);
        if (ip[i] < startip || ip[i] > endip) {
            return -1;
        }
    }

    return 0;
}

int main()
{
    // 源IP范围
    uint32_t src_ip_low[4] = {0};
    uint32_t src_ip_high[4] = {0};
    inet_pton(AF_INET6, "f16a:f7ec:cfa2:e1c5:9a3c:cb08:801f:36b2", src_ip_low);
    inet_pton(AF_INET6, "f16c:f7ec:cfa2:e1c5:9a3c:cb08:801f:36b8", src_ip_high);

    // 报文IP
    uint8_t  src_addr[16];
    inet_pton(AF_INET6, "f16b:f7ed:cfa2:e1c5:9a3c:cb08:801f:36b6", src_addr);

    // 比较判断
    int ret = 0;
    ret = isIPv6InRangev1(src_addr, src_ip_low, src_ip_high);
    if (ret < 0) {
        printf("src_addr is not in range\n");
    } else {
        printf("src_addr is in range\n");
    }

    ret = isIPv6InRangev2(src_addr, src_ip_low, src_ip_high);
    if (ret < 0) {
        printf("src_addr is not in range\n");
    } else {
        printf("src_addr is in range\n");
    }

    ret = isIPv6InRangev3(src_addr, src_ip_low, src_ip_high);
    if (ret < 0) {
        printf("src_addr is not in range\n");
    } else {
        printf("src_addr is in range\n");
    }

    return 0;
}
  • 结果
$ ./a.out 
v1 ok
src_addr is in range
v2 ok 
ip[0]: f16bf7ed
ip[1]: cfa2e1c5
ip[2]: 9a3ccb08
ip[3]: 801f36b6
src_addr is in range
v3 no 
ip[0]: edf76bf1
src_addr is not in range