0

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*?

trivelt
  • 1,913
  • 3
  • 22
  • 44
  • Can you please elaborate more on your problems? Does it build? If not, what errors/warnings do you get? Does it run? If not, what errors do you get? Also, you should modify the code to print the actual error you have when a system call fail (use e.g. [`strerror`](http://man7.org/linux/man-pages/man3/strerror.3.html)) if that's your problem. – Some programmer dude Nov 17 '14 at 09:50
  • Oh, and if you're using `std::cout` then you're not progamming C, so you should remove that tag. And `cout` is not a function, it's an object (maybe you need to go back and read a basic C++ tutorial, from the beginning?) – Some programmer dude Nov 17 '14 at 09:51
  • Yes, it builds and runs, output is "Private ioctls set successfully", but I'm pretty sure that something wrong. Buffer for `char*` and `int` arguments doesn't look good for me. And I know about `cout`, it's not a problem, because really I use other logging function. I asked about corectness, because `iwpriv wlanX p2p_get intent` doesn't work and I can't check if I set parameter. – trivelt Nov 17 '14 at 09:54
  • Which `char*` and `int` arguments are you talking about? Do they have values you think is wrong? If so then what are their values and what would you expect them to be? – Some programmer dude Nov 17 '14 at 10:08
  • I'm calling this function with for example `set_CharPriv("wlan0", "p2p_set", "intent", 10)` - the two lasts are arguments for `p2p_set`. I suppose that `((const char**) buffer)[0] = val1;` and `((__s32 *) buffer)[1] = (__s32) val2;` isn't a good way of writing arguments to the buffer. Maybe buffer should be u_char* in this case? – trivelt Nov 17 '14 at 10:17

0 Answers0