I have been trying to code a short program (see below) to set the
default route on the big stack using routing sockets but to no avail. It
fails on the write to the socket but I can’t see why. Please could someone
point me to what I am doing wrong.
I am logged in as root and the program is chmodded to a+s with root
owner and group in case there is any confusion as to whether it is being run
as superuser or not.
Thanks in advance
Poseidon
#include <stdio.h>
#include <sys/ioctl.h>
#include <net/if_dl.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <net/route.h>
#include <net/if.h>
struct {
struct rt_msghdr m_rtm;
char m_space[512]; // leave enough space for the sockaddr’s
} m_rtmsg;
#define rtm m_rtmsg.m_rtm
int rtm_seq = 0;
int len;
int main(int argc, char *argv[])
{
int rtsk;
struct sockaddr_in *rtdst;
struct sockaddr_in *rtgat;
struct sockaddr_in *rtnet;
register unsigned char *cp = m_rtmsg.m_space;
int result;
memset(&m_rtmsg,0x00, sizeof(m_rtmsg)); // zero message area
rtm.rtm_version = RTM_VERSION;
rtm.rtm_type = RTM_CHANGE; // RTM_ADD also fails write
rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
rtm.rtm_pid = getpid();
rtm.rtm_seq = ++rtm_seq;
/* set up sockaddrs in order of addr flags from lsb up, that means DST,
followed by GATEWAY followed by NETMASK
*/
rtdst = (struct sockaddr_in *)cp; // rtdst points to start of m_space
rtdst->sin_len = sizeof(*rtdst); // it’s address is 0.0.0.0 since
rtdst->sin_family = AF_INET; // m_space has been zeroed
cp += sizeof(*rtdst); // point cp to after dst
sockaddr
rtgat = (struct sockaddr_in *)cp; // rtgat is next in m_space
rtgat->sin_len = sizeof(*rtgat);
rtgat->sin_family = AF_INET; // address is from command line
if (inet_aton(argv[1],&(rtgat->sin_addr))==0) { // 0 if error occurs
printf(“failure\n”);
return -1;
}
cp += sizeof(*rtgat); // advance cp to after gateway
rtnet = (struct sockaddr_in *)cp; // rtnet is next in m_space
rtnet->sin_len = sizeof(*rtnet); // address is 0.0.0.0 as m_space
rtnet->sin_family = AF_INET; // has been cleared
cp += sizeof(*rtnet); // advance cp to after netmask
rtm.rtm_msglen = len = cp - (unsigned char*)&m_rtmsg;
if ((rtsk = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
printf(“no route socket\n”);
return -1;
}
// result always returns -1 here.
if ((result = write(rtsk, (char *)&m_rtmsg, len)) < len) {
printf(“no write to route socket, result: %d\n”,result);
return -1;
}
}