0

I'm completely new to netlink & co. and I am trying to establisch a connection from user space to the w1-kernel module of a raspberry pi. Unfortunately the documentation i found is spotty and contradictory.

Here some of the things not clear to me:

basic communication is:

  • generate a socket: socket()
    int s = socket(AF_NETLINK,SOCK_DGRAM, NETLINK_CONNECTOR);
  • bind it to a local name: bind() int b = bind(s,(sockaddr*)&sa,sizeof(sa)); with
    sa.nl_family=AF_NETLINK;
    sa.nl_pid=getpid();//0?
    sa.nl_groups=0; //23? -1?
  • create the message
  • send it: send()? sendmsg()?
  • wait for answer: poll()
  • read answer: recv()

+In examples i found (w1d.c and ucon.c) they use the send() command (not sendmsg) without a connect(), even though the man pages of send say that wouldnt work.

+I am not clear about the structure of the message:

  • send can send any buffer (char*)
  • netlink expects a struct nlmsghdr header;
  • connector expects a struct cn_msg header.
  • w1_netlink expects a w1_netlink_msg header and w1_netlink_cmd data.

Do i need all headers in a row? Ther are 2 sequence / message number variables, one in nlmsghdr and on in cn_msg???

The test program i wrote is not producing the result i expect: every thing works withour producing an error but i am getting no answer :-(

#include <iostream>
#include <linux/netlink.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<sys/poll.h>
#include <unistd.h>
#include<cstring>
#include "w1_netlink.h"

__u32 nl_seq;


static int netlink_send(int s, struct cn_msg *msg) //copy from (ucon.c)
{
    struct nlmsghdr *nlh;
    unsigned int size;
    int err;
    char buf[128];
    struct cn_msg *m;

    size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);

    nlh = (struct nlmsghdr *)buf;
    nlh->nlmsg_seq = nl_seq++;
    nlh->nlmsg_pid = getpid();
    nlh->nlmsg_type = NLMSG_DONE;
    nlh->nlmsg_len = size;
    nlh->nlmsg_flags = 0;

    m = (cn_msg*) NLMSG_DATA(nlh);
    memcpy(m, msg, sizeof(*m) + msg->len);

    err = send(s, nlh, size, 0);

    return err;
}

int main(int argc, char *argv[])
{
    nl_seq=0;
    int s = socket(AF_NETLINK,SOCK_DGRAM, NETLINK_CONNECTOR);
    if(s==-1) {std::cout<<"no socket"; return s;};
    std::cout<<"socket "<<s;

    sockaddr_nl sa;
    sa.nl_family=AF_NETLINK;
    sa.nl_pid=0;//getpid();
    sa.nl_groups=0;

    int b = bind(s,(sockaddr*)&sa,sizeof(sa));
    if(b==-1){std::cout<<"bind error";return b;};    //prints 3
    std::cout<<"bind "<<b;    //prints 0
    int si=sizeof(struct cn_msg)+sizeof(struct w1_netlink_msg)+sizeof(w1_netlink_cmd);

    char * buf;
    buf=(char *)malloc(1024);
    memset(buf,0,1024);
    cn_msg *cnh = (cn_msg*)buf;
    w1_netlink_msg* wnh=(w1_netlink_msg*)&cnh->data;
    w1_netlink_cmd* wcmd = (w1_netlink_cmd*)&wnh->data;  

    cnh->id.idx=CN_W1_IDX;
    cnh->id.val=CN_W1_VAL;
    cnh->seq=nl_seq;
    cnh->flags=0;

    wnh->type=W1_LIST_MASTERS;
    wnh->len=0;
    cnh->len=sizeof(struct w1_netlink_msg)+sizeof(w1_netlink_cmd);


    int len=netlink_send(s,cnh);
    std::cout<<"send "<<len<<" "<<(int)wnh->status;   //prints 52  0
    pollfd pfd;
    pfd.fd=s;
    pfd.events=POLLIN;
    pfd.revents=0;
    int p=0;
    while(p<1) {
        p=poll(&pfd,1,1000);
        std::cout<<"poll "<<p<<pfd.revents;   //prints 0 0  in infinite loop
        std::cout.flush();
    };
    memset(wcmd,0,128);
    len=recv(s,buf,255,0);
    std::cout<<"recv "<<len;
    close(s);
    return 0;
}

Result is socket 3 bind 0 send 52 0 poll 00 poll 00 ...

Thanks

  • I don't know what you are trying to accomplish, or what a w1-module is supposed to do (or in what way it is RPI specific). Is there a reason you are not using libnl, or another library? Is this about 1-wire and GPIO? https://www.kernel.org/doc/html/latest/w1/masters/w1-gpio.html says nothing about netlink, that I can see. – mcr Nov 29 '20 at 21:45
  • I am trying to get the 1-wire / w1 master to send a specific command on the w1-bus. As far as I know there are 2 pricipal possibilities to communicate with (the w1-master module in) the kernel from user space / my program: sysfs and netlink. The w1-gpio doc you mention doesnt say anything about how to adress the master from user space, but thanks anyhow for the hint. – Andi Wer Sonst Nov 29 '20 at 22:56

0 Answers0