/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <android/multinetwork.h>
#include <errno.h>
#include <NetdClient.h>    // the functions that communicate with netd
#include <resolv_netid.h>  // android_getaddrinfofornet()
#include <stdlib.h>
#include <sys/limits.h>


static int getnetidfromhandle(net_handle_t handle, unsigned *netid) {
    static const uint32_t k32BitMask = 0xffffffff;
    // This value MUST be kept in sync with the corresponding value in
    // the android.net.Network#getNetworkHandle() implementation.
    static const uint32_t kHandleMagic = 0xcafed00d;

    // Check for minimum acceptable version of the API in the low bits.
    if (handle != NETWORK_UNSPECIFIED &&
        (handle & k32BitMask) != kHandleMagic) {
        return 0;
    }

    if (netid != NULL) {
        *netid = ((handle >> (CHAR_BIT * sizeof(k32BitMask))) & k32BitMask);
    }
    return 1;
}


int android_setsocknetwork(net_handle_t network, int fd) {
    unsigned netid;
    if (!getnetidfromhandle(network, &netid)) {
        errno = EINVAL;
        return -1;
    }

    int rval = setNetworkForSocket(netid, fd);
    if (rval < 0) {
        errno = -rval;
        rval = -1;
    }
    return rval;
}

int android_setprocnetwork(net_handle_t network) {
    unsigned netid;
    if (!getnetidfromhandle(network, &netid)) {
        errno = EINVAL;
        return -1;
    }

    int rval = setNetworkForProcess(netid);
    if (rval < 0) {
        errno = -rval;
        rval = -1;
    }
    return rval;
}

int android_getaddrinfofornetwork(net_handle_t network,
        const char *node, const char *service,
        const struct addrinfo *hints, struct addrinfo **res) {
    unsigned netid;
    if (!getnetidfromhandle(network, &netid)) {
        errno = EINVAL;
        return EAI_SYSTEM;
    }

    return android_getaddrinfofornet(node, service, hints, netid, 0, res);
}

int android_res_nquery(net_handle_t network, const char *dname,
        int ns_class, int ns_type, enum ResNsendFlags flags) {
    unsigned netid;
    if (!getnetidfromhandle(network, &netid)) {
        return -ENONET;
    }

    return resNetworkQuery(netid, dname, ns_class, ns_type, flags);
}

int android_res_nresult(int fd, int *rcode, uint8_t *answer, size_t anslen) {
    return resNetworkResult(fd, rcode, answer, anslen);
}

int android_res_nsend(net_handle_t network, const uint8_t *msg, size_t msglen,
        enum ResNsendFlags flags) {
    unsigned netid;
    if (!getnetidfromhandle(network, &netid)) {
        return -ENONET;
    }

    return resNetworkSend(netid, msg, msglen, flags);
}

void android_res_cancel(int nsend_fd) {
    resNetworkCancel(nsend_fd);
}
