Setting private ioctls without iwpriv

1.5k Views Asked by At

I need to write function that will set private ioctls such as:

iwpriv wlan5 p2p_set enable=0
iwpriv wlan0 p2p_set intent=1 

I found in this code function which set integer private ioctls, so I tried to modify it but I have yet a poor understanding of this topic. Please look at the following code and say what is wrong:

set_CharPriv(const char *in_dev, const char *privcmd, const char* val1, int val2)
{
    #define IW_MAX_PRIV_DEF 128
    struct iwreq wrq;
    int skfd;
    struct iw_priv_args priv[IW_MAX_PRIV_DEF];
    u_char buffer[4096];
    int subcmd = 0;
    int offset = 0;

    memset(priv, 0, sizeof(priv));

    if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
    return -1;
    }

    memset(&wrq, 0, sizeof(struct iwreq));
    strncpy(wrq.ifr_name, in_dev, IFNAMSIZ);

    wrq.u.data.pointer = (caddr_t) priv;
    wrq.u.data.length = IW_MAX_PRIV_DEF;
    wrq.u.data.flags = 0;

    if (ioctl(skfd, SIOCGIWPRIV, &wrq) < 0)
    {
    return -1;
    }

    int pn = -1;
    while ((++pn < wrq.u.data.length) && strcmp(priv[pn].name, privcmd));

    if (pn == wrq.u.data.length)
    {
    cout() << "Unable to find private ioctl " << privcmd;
    close(skfd);
    return -2;
    }

    // Find subcmds, as if this isn't ugly enough already
    if (priv[pn].cmd < SIOCDEVPRIVATE) {
    int j = -1;

    while ((++j < wrq.u.data.length) && ((priv[j].name[0] != '\0') ||
                                         (priv[j].set_args != priv[pn].set_args) ||
                                         (priv[j].get_args != priv[pn].get_args)));

    if (j == wrq.u.data.length) {
        cout() << "Unable to find subioctl " << privcmd;
        close(skfd);
        return -2;
    }

    subcmd = priv[pn].cmd;
    offset = sizeof(__u32);
    pn = j;
    }

    // Make sure its an iwpriv we can set
    if ((priv[pn].set_args & IW_PRIV_TYPE_MASK) == 0 ||
    (priv[pn].set_args & IW_PRIV_SIZE_MASK) == 0)
    {
    cout() <<  "Unable to set values for private ioctl " << privcmd;
    close(skfd);
    return -1;
    }

    if ((priv[pn].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_CHAR)
    {
    cout() << privcmd <<  " does not accept char parameters.";
    cout() << "Arg type=" << (priv[pn].set_args & IW_PRIV_TYPE_MASK);
    close(skfd);
    return -1;
    }

    int nargs = (priv[pn].set_args & IW_PRIV_SIZE_MASK);

        cout() << "Private ioctl expects " << nargs << " arguments)"; //for example, it returns 64

    // Build the set request
    memset(&wrq, 0, sizeof(struct iwreq));
    strncpy(wrq.ifr_name, in_dev, IFNAMSIZ);

    // Assign the arguments
    wrq.u.data.length = nargs;
    ((const char**) buffer)[0] = val1;
    if (nargs > 1) {
    ((__s32 *) buffer)[1] = (__s32) val2;
    }

    if ((priv[pn].set_args & IW_PRIV_SIZE_FIXED) &&
    ((sizeof(__u32) * nargs) + offset <= IFNAMSIZ)) {
    if (offset)
        wrq.u.mode = subcmd;
    memcpy(wrq.u.name + offset, buffer, IFNAMSIZ - offset);
    } else {
    wrq.u.data.pointer = (caddr_t) buffer;
    wrq.u.data.flags = 0;
    }

    if (ioctl(skfd, priv[pn].cmd, &wrq) < 0)
    {
    cout() << "Failed to set private ioctl " << privcmd;
    close(skfd);
    return -1;
    }

    close(skfd);
    cout() << "Private ioctls set successfully";
    return 0;
}

I think that the part "Assign the arguments" and above is wrong. Is this right that first argument should be char* and second int when I set something like p2p_set intent=number? How should buffer look like?

EDIT: So main question is: how to write two arguments of different types? Number should be in a const char*?

0

There are 0 best solutions below