LQ Newbie
Registered: Sep 2004
Posts: 1
Rep:
|
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;
}
|