Esempio n. 1
0
static int
parse_address(struct nlmsghdr *nh)
{
    int len;
    struct kernel_address kaddr;
    struct ifaddrmsg *ifa = NULL;
    struct rtattr *rta = NULL;
    unsigned int rta_len;
    int is_v4 = 0;

    len = nh->nlmsg_len;

    ifa = (struct ifaddrmsg*)NLMSG_DATA(nh);
    len -= NLMSG_LENGTH(0);

    memset(&kaddr, 0, sizeof(kaddr));
    kaddr.sa.sa_family = ifa->ifa_family;

    if (kaddr.sa.sa_family != AF_INET && kaddr.sa.sa_family != AF_INET6) {
        log_dbg(LOG_DEBUG_KERNEL, "Unknown family: %d\n", kaddr.sa.sa_family);
        return -1;
    }
    is_v4 = kaddr.sa.sa_family == AF_INET;

    rta = IFA_RTA(ifa);
    len -= NLMSG_ALIGN(sizeof(*ifa));

#define COPY_ADDR(d, s)                                                 \
    do {                                                                \
        if(!is_v4) {                                                    \
            assert(rta_len >= 16);                                      \
            memcpy(&d.sin6.sin6_addr, s, 16);                           \
        }else {                                                         \
            assert(rta_len >= 4);                                       \
            memcpy(&d.sin.sin_addr, s, 4);                              \
        }                                                               \
    } while(0)

    for(; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
        rta_len = RTA_PAYLOAD(rta);
        switch (rta->rta_type) {
        case IFA_UNSPEC: break;
        case IFA_ADDRESS:
            COPY_ADDR(kaddr, RTA_DATA(rta));
            break;

        case IFA_LOCAL:
            COPY_ADDR(kaddr, RTA_DATA(rta));
            kaddr.flags |= ADDR_LOCAL;
            break;
        default:
            break;
        }
    }
#undef COPY_ADDR
#undef GET_PLEN

    if (nh->nlmsg_type == RTM_NEWADDR)
        addr_add(&addresses, &kaddr);
    else
        addr_del(addresses, &kaddr);

    return 0;
}
Esempio n. 2
0
static int
parse_kernel_route_rta(struct rtmsg *rtm, int len, struct kernel_route *route)
{
    int table = rtm->rtm_table;
    struct rtattr *rta= RTM_RTA(rtm);;
    len -= NLMSG_ALIGN(sizeof(*rtm));

    memset(&route->prefix, 0, sizeof(struct in6_addr));
    memset(&route->gw, 0, sizeof(struct in6_addr));
    route->plen = rtm->rtm_dst_len;
    if(rtm->rtm_family == AF_INET) {
        const unsigned char zeroes[4] = {0, 0, 0, 0};
        v4tov6(route->prefix, zeroes);
        route->plen += 96;
    }

    route->metric = 0;
    route->ifindex = 0;
    route->proto = rtm->rtm_protocol;

#define COPY_ADDR(d, s) \
    do { \
        if(rtm->rtm_family == AF_INET6) \
            memcpy(d, s, 16); \
        else if(rtm->rtm_family == AF_INET) \
            v4tov6(d, s); \
        else \
            return -1; \
    } while(0)

    while(RTA_OK(rta, len)) {
        switch (rta->rta_type) {
        case RTA_DST:
            COPY_ADDR(route->prefix, RTA_DATA(rta));
            break;
        case RTA_GATEWAY:
            COPY_ADDR(route->gw, RTA_DATA(rta));
            break;
        case RTA_OIF:
            route->ifindex = *(int*)RTA_DATA(rta);
            break;
        case RTA_PRIORITY:
            route->metric = *(int*)RTA_DATA(rta);
            if(route->metric < 0 || route->metric > KERNEL_INFINITY)
                route->metric = KERNEL_INFINITY;
            break;
       case RTA_TABLE:
            table = *(int*)RTA_DATA(rta);
            break;
        default:
            break;
        }
        rta = RTA_NEXT(rta, len);
    }
#undef COPY_ADDR

    if(table != import_table)
        return -1;

    return 0;
}