Results 1 to 2 of 2
I wrote a function to use netlink sockets to create secondary IP addresses on existing interfaces. The data appears correct and the sendmsg routine reports the correct amount of sent ...
- 01-20-2009 #1Just Joined!
- Join Date
- Jan 2009
- Posts
- 1
netlink socket add secondary interface question
I wrote a function to use netlink sockets to create secondary IP addresses on existing interfaces. The data appears correct and the sendmsg routine reports the correct amount of sent data but no secondary IP addresses is added. The function I wrote is:
#include <asm/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#define MYPROTO NETLINK_ROUTE
typedef struct req {
struct nlmsghdr nlh;
struct ifaddrmsg ifmsg;
char buffer[8192];
} req;
int send_netlink_msg()
{
int sock = socket(AF_NETLINK,SOCK_RAW,MYPROTO);
struct sockaddr_nl addr;
struct msghdr msg;
struct iovec iov;
char ifname[10]={0};
char ip[8]={0};
int size = 0,cnt=1;
req rq;
struct rtattr *rtap = (struct rtattr *)rq.buffer;
ulong inaddr;
if_indextoname(cnt,&ifname);
while (strcmp(ifname,"eth0")) {
cnt++;
if_indextoname(cnt,&ifname);
}
printf("ETH0 index: %d\n",cnt);
bzero(&rq,sizeof(rq));
memset((void *)&addr, 0, sizeof(addr));
if (sock<0)
return sock;
addr.nl_family = AF_NETLINK;
addr.nl_pid = 0;
addr.nl_groups = 0;
if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0)
return -1;
rq.ifmsg.ifa_family = AF_UNSPEC;
rq.ifmsg.ifa_flags = IFA_F_SECONDARY;
rq.ifmsg.ifa_scope = RT_SCOPE_HOST;
rq.ifmsg.ifa_index = cnt;
size = sizeof(struct ifaddrmsg);
rtap = (struct rtattr *)rq.buffer;
rtap->rta_len = sizeof(struct rtattr)+sizeof(ulong);
rtap->rta_type = IFA_LOCAL;
strcpy(ip,"1.2.3.10");
if ((inet_pton(AF_INET,ip,((char *)rtap)+sizeof(struct rtattr)))<0) {
printf("Error with inet_pton\n");
return(-1);
}
{
char *ptr=RTA_DATA(rtap);
printf("%x\n",ptr[0]);
printf("%x\n",ptr[1]);
printf("%x\n",ptr[2]);
printf("%x\n",ptr[3]);
printf("payload size: %d\n",RTA_PAYLOAD(rtap));
printf("ok: %d\n",RTA_OK(rtap,8 ));
}
size+=rtap->rta_len;
rq.nlh.nlmsg_len = NLMSG_LENGTH(size);
rq.nlh.nlmsg_type = RTM_NEWADDR;
rq.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
rq.nlh.nlmsg_seq = 0;
rq.nlh.nlmsg_pid = getpid();
bzero(&msg,sizeof(msg));
msg.msg_name = (void *)&(addr);
msg.msg_namelen = sizeof(addr);
iov.iov_base = (void *)&rq;
iov.iov_len = sizeof(struct nlmsghdr)+size;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Msg length: %d\n",rq.nlh.nlmsg_len);
printf("Data sent : %d\n\n",sendmsg(sock,&msg,0));
system("ifconfig eth0");
return sock;
}
int main(int argc, char *argv[])
{
int nls = send_netlink_msg();
return 0;
}
any help on this would be greatly appreciated.
Scott
- 11-23-2011 #2Just Joined!
- Join Date
- Nov 2011
- Posts
- 1
#include <bits/sockaddr.h>
#include <asm/types.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#include <string.h>
// buffer to hold the RTNETLINK request
struct {
struct nlmsghdr nl;
struct ifaddrmsg rt;
char buf[8192];
} req;
// variables used for
// socket communications
int fd;
struct sockaddr_nl la;
struct sockaddr_nl pa;
struct msghdr msg;
struct iovec iov;
int rtn;
// buffer to hold the RTNETLINK reply(ies)
char buf[8192];
// RTNETLINK message pointers & lengths
// used when processing messages
struct nlmsghdr *nlp;
int nll;
struct rtmsg *rtp;
int ifal;
struct rtattr *rtap;
int main(int argc, char *argv[])
{
// open socket
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
// setup local address & bind using
// this address
bzero(&la, sizeof(la));
la.nl_family = AF_NETLINK;
la.nl_pid = getpid();
bind(fd, (struct sockaddr*) &la, sizeof(la));
// sub functions to create RTNETLINK message,
// send over socket, reveive reply & process
// message
/*TODO*/
char dsts[24] = "192.168.1.3";
// initalize RTNETLINK request buffer
bzero(&req, sizeof(req));
// compute the initial length of the
// service request
ifal = sizeof(struct ifaddrmsg);
// add first attrib:
// set IP addr
// RTNETLINK buffer size
rtap = (struct rtattr *) req.buf;
rtap->rta_type = IFA_ADDRESS;
rtap->rta_len = sizeof(struct rtattr) + 4;
inet_pton(AF_INET, dsts,
((char *)rtap) + sizeof(struct rtattr));
ifal += rtap->rta_len;
// add second attrib:
// set ifc index and increment the size
rtap = (struct rtattr *) (((char *)rtap)
+ rtap->rta_len);
rtap->rta_type = IFA_LOCAL;
rtap->rta_len = sizeof(struct rtattr) + 4;
inet_pton(AF_INET, dsts,
((char *)rtap) + sizeof(struct rtattr));
ifal += rtap->rta_len;
// setup the NETLINK header
req.nl.nlmsg_len = NLMSG_LENGTH(ifal);
/* TODO: test with NLM_F_APPEND */
req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_APPEND;
req.nl.nlmsg_type = RTM_NEWADDR;
// setup the service header (struct rtmsg)
req.rt.ifa_family = AF_INET;
req.rt.ifa_prefixlen = 32; /*hardcoded*/
req.rt.ifa_flags = IFA_F_PERMANENT;
req.rt.ifa_scope = RT_SCOPE_HOST;
/*TODO: think how can you find out the ifa_index */
req.rt.ifa_index = 3;
// create the remote address
// to communicate
bzero(&pa, sizeof(pa));
pa.nl_family = AF_NETLINK;
// initialize & create the struct msghdr supplied
// to the sendmsg() function
bzero(&msg, sizeof(msg));
msg.msg_name = (void *) &pa;
msg.msg_namelen = sizeof(pa);
// place the pointer & size of the RTNETLINK
// message in the struct msghdr
iov.iov_base = (void *) &req.nl;
iov.iov_len = req.nl.nlmsg_len;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
// send the RTNETLINK message to kernel
rtn = sendmsg(fd, &msg, 0);
// close socket
close(fd);
}
I am posting here so late, because it might help someone in the future. The above code worked for me. I did not have time to play with all the flags, but this is a start point for you.


