LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Netlink Sockets Problem (https://www.linuxquestions.org/questions/programming-9/netlink-sockets-problem-229095/)

gio123 09-10-2004 05:34 PM

Netlink Sockets Problem
 
Hi all.

I'm trying to make a function that will take an IPv6 IP address as an argument (RTA_DST), send it to the Kernel via Netlink, and return its gateway from the routing table (RTA_GATEWAY). Unfortunatelly it only returns part of the Gateway address (although it is the correct one) any suggestions?

For example I've set a route in the IPv6 table where the address ee81::21c:76ff:fe51:74d2 has the gateway 4ffe:ffff:0:f102::2 When I use my code Netlink returns that the Gateway for this address is 4ffe:ffff:: which is half of what I actually wanted...
Below is the output of the code. Just ignore the last 3 lines.


SPLIT message received from -> ::1
MN Address Sent To Kernel is -> ee81::21c:76ff:fe51:74d2
Gateway Received for MN from Kernel is -> 4ffe:ffff::
Default Gateway is -> 4ffe:ffff:0:f102::2
Destination Gateway for MN is NOT the Deafult Gateway
Direct Route Found for MN


Below is the code (parts of which were found on the internet but for IPv4). Any help will be really appreciated.


void
*route_find(arg)
void *arg;
{
int nlsockfd, len;
static char errbuf[256];
char temp[MAXLINE];
struct split *split_arga = NULL;
struct sockaddr_in6 mnaddr, addr;

struct {
struct nlmsghdr n;
struct rtmsg r;
char data[1024];
} req;
struct rtattr *attr;


if(pthread_mutex_lock(&mutex))
err_sys("pthread_mutex_lock error");

split_arga = (struct split*) malloc(sizeof(struct split));
memcpy(split_arga, arg, sizeof(struct split));

if(pthread_mutex_unlock(&mutex))
err_sys("pthread_mutex_unlock error");

bzero(&mnaddr, sizeof(mnaddr));
mnaddr.sin6_family = AF_INET6;
mnaddr.sin6_addr = split_arga->split_MNaddress;

/*Open the Netlink Socket*/

nlsockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (nlsockfd < 0) {
sprintf(
errbuf, "Error Openning Netlink Socket: %.128s",
strerror(errno)
);
return errbuf;
}

/*Construct the mesage and copy the address i want to check to the message*/

memset(&req, 0, sizeof(req));
req.n.nlmsg_len =
NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r))) +
RTA_LENGTH(sizeof(mnaddr.sin6_addr));
req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_type = RTM_GETROUTE;
req.r.rtm_family = AF_INET6;
req.r.rtm_dst_len = 128;
attr = (void *) (
((char *) &req) + NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r)))
);
attr->rta_type = RTA_DST;
attr->rta_len = RTA_LENGTH(sizeof(mnaddr.sin6_addr));

memcpy(RTA_DATA(attr), &mnaddr.sin6_addr, sizeof(mnaddr.sin6_addr));
printf("MN Address Sent To Kernel is-> %s\n", inet_ntop(AF_INET6, &mnaddr.sin6_addr, temp, sizeof(temp)));


/*Send the message*/

if (send(nlsockfd, &req, req.n.nlmsg_len, 0) < 0) {
sprintf(
errbuf, "error sending netlink message: %.128s",
strerror(errno)
);
err:
close(nlsockfd);
return errbuf;
}

/*Receive the answer from the Kernel*/

len = recv(nlsockfd, &req, sizeof(req), 0);

if (len < 0) {
sprintf(
errbuf, "Error Receiving Netlink Message: %.128s",
strerror(errno)
);
goto err;
}
close(nlsockfd);
if (len < sizeof(struct nlmsghdr)) {
sprintf(errbuf, "Received Short Netlink Message: %d", len);
return errbuf;
}
if (len < req.n.nlmsg_len) {
sprintf(
errbuf, "Netlink Message Size Error: %d < %d",
len, req.n.nlmsg_len
);
return errbuf;
}
if (req.n.nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA(&req.n);
sprintf(
errbuf, "Netlink Error: %.128s",
strerror(-err->error)
);
return errbuf;
}

len -= NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r)));
while (len > sizeof(*attr) && len > attr->rta_len) {

/*Read the Reply and copy the address of the received Gateway*/

if (
attr->rta_type == RTA_GATEWAY &&
RTA_PAYLOAD(attr) == sizeof(addr.sin6_addr)
) {
memcpy(&addr.sin6_addr, RTA_DATA(attr), sizeof(attr));
printf("Gateway Received for MN form Kernel is -> %s\n", inet_ntop(AF_INET6, &addr.sin6_addr, temp, sizeof(temp)));
printf("Default Gateway is -> %s\n", inet_ntop(AF_INET6, &defrouter_ipaddr.s6_addr, temp, sizeof(temp)));


/*Compare the Gateway address with another one statically passed in the code*/

if(IN6_ARE_ADDR_EQUAL(addr.sin6_addr.s6_addr, defrouter_ipaddr.s6_addr)){
printf("Destination Gateway for MN is the Default Gateway\n");
printf(" Direct Route Not Found for MN\n" );
printf("-------------------------------------------------\n");
}
else{
printf("Destination Gateway for MN is NOT the Deafult Gateway\n");
printf(" Direct Route Found for MN\n");
printf(" \n");
/*if(pthread_create(&route_tid, NULL, &proc_split, (void*)split_arga))
err_sys("pthread_create error");*/
proc_split(split_arga);
}
return 0;
}
len -= attr->rta_len;
attr = (void *) (((char *) attr) + attr->rta_len);
}
strcpy(errbuf, "Netlink did not Return a Gateway Address");
return errbuf;
}

infamous41md 09-11-2004 12:37 PM

i haven't worked with netlink in a long time, but i wrote a tutorial about it when i did.
http://www.1nfamus.netfirms.com/netlink_tut.html

and also, iirc, messages could be split into multi parts. meaning you had to call read multiple times. here's an excerpt of my code:
Code:

//read a netlink reply in it's entirety
//responsibility of caller to make buf must at least NL_BUFSIZE
inline int
readnl(int sock, char *buf, int seq, pid_t pid)
{
    int nread = 0, ntread = 0;
    u_char  flag = 0;
    char    *tmp = buf;
    struct nlmsghdr *nlhdrp = NULL;

    //read the reply, check for multi-part reply
    //fill up buffer to NL_BUFSIZE bytes at most
    do{
            //we can't read more than NL_BUFSIZE bytes 
        if( (nread = read(sock, tmp, NL_BUFSIZE - ntread )) < 0)
            perr_quit("read");

        nlhdrp = (struct nlmsghdr *)tmp;

            //FIRST ALWAYS: check to make sure the message structure is ok
            //then check to make sure type isn't error type
        if( (NLMSG_OK(nlhdrp, nread) == 0) || (nlhdrp->nlmsg_type == NLMSG_ERROR) )
                    return -1;

        //if this is the last message then it contains no data
        //so we dont want to return it
        if(nlhdrp->nlmsg_type == NLMSG_DONE)
            flag = 1;
        else{
            tmp += nread;
            ntread += nread;
        }

        //in this case we never had a multipart message
        if( (nlhdrp->nlmsg_flags & NLM_F_MULTI) == 0 )
            flag = 1;

    }while(nlhdrp->nlmsg_seq != seq || nlhdrp->nlmsg_pid != pid || flag == 0);

    return ntread;
}


guam 11-29-2004 06:12 AM

Hello infamous41md,

I trying to do some experiments with netlink using NETLINK_USERSOCK. I am new to Kernel programming and netlink usage.

I saw your post and the information about the netlink tutorial. I could not reach to the web site you have mentioned in your post.

If possible can you provide the same tutorial again.

Thanks.

Devel.

gr33ndata 01-23-2005 06:17 PM

Hello Guam
I believe that Infamous has changed his home page
And here is his new address
http://www.infsec.net
http://www.infsec.net/netlink_tut.html


All times are GMT -5. The time now is 04:42 PM.