diff options
Diffstat (limited to 'watchlink/netlink_send.cc')
-rw-r--r-- | watchlink/netlink_send.cc | 174 |
1 files changed, 134 insertions, 40 deletions
diff --git a/watchlink/netlink_send.cc b/watchlink/netlink_send.cc index 656eb5d9..d48f2abb 100644 --- a/watchlink/netlink_send.cc +++ b/watchlink/netlink_send.cc @@ -30,6 +30,7 @@ #include <linux/types.h> #include <sys/types.h> #include <sys/socket.h> +#include <linux/netlink.h> #include <linux/rtnetlink.h> #include <syslog.h> @@ -37,12 +38,11 @@ #include <string> #include <iostream> +#include "netlink_utils.hh" #include "netlink_send.hh" using namespace std; -in_addr_t -ipv4_broadcast_addr (in_addr_t hostaddr, int masklen); /** * @@ -86,12 +86,16 @@ NetlinkSend::send_set(int sock, int ifindex, uint32_t local_addr, uint32_t addr, if (_debug) { struct in_addr in; in.s_addr = local_addr; - char *buf = inet_ntoa(in); - cout << "NetlinkSend::send_set(): " << type << ", " << buf << "/" << mask_len; + char *lbuf = inet_ntoa(in); in.s_addr = addr; - buf = inet_ntoa(in); - cout << ", to this address: " << buf << ", on interface: " << ifindex << endl; + char *buf = inet_ntoa(in); + + char sbuf[1024]; + sprintf(sbuf, "NetlinkSend::send_set(): %d, %s/%d, to this address: %s, on interface: %d",type,buf,mask_len,lbuf,ifindex); + cout << sbuf << endl; + + syslog(LOG_INFO,sbuf); } memset(&req, 0, sizeof(req)); @@ -106,10 +110,10 @@ NetlinkSend::send_set(int sock, int ifindex, uint32_t local_addr, uint32_t addr, req.ifa.ifa_prefixlen = mask_len; // addr = htonl( addr ); - addattr_l(&req.n, sizeof(req), IFA_LOCAL, &local_addr, sizeof(addr) ); + addattr_l(&req.n, sizeof(req), IFA_LOCAL, &local_addr, sizeof(local_addr) ); in_addr_t broadcast_addr = ipv4_broadcast_addr(local_addr,mask_len); - addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &broadcast_addr, sizeof(addr) ); + addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &broadcast_addr, sizeof(broadcast_addr) ); if (addr != -1 && local_addr != addr) { addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &addr, sizeof(addr) ); @@ -133,6 +137,108 @@ NetlinkSend::send_set(int sock, int ifindex, uint32_t local_addr, uint32_t addr, * **/ int +NetlinkSend::send_set_route(int sock, int ifindex, uint32_t local_addr, uint32_t dst_addr, int mask_len, int type, int table, int rtn_type, int rt_scope) +{ + int ret; + struct sockaddr_nl snl; + struct { + struct nlmsghdr n; + struct rtmsg rt_message; + char buf[8192]; + } req; + req.rt_message.rtm_table = 0; + req.rt_message.rtm_protocol = 0; + req.rt_message.rtm_scope = 0; + req.rt_message.rtm_type = 0; + req.rt_message.rtm_src_len = 0; + req.rt_message.rtm_dst_len = 0; + req.rt_message.rtm_tos = 0; + + memset(&snl, 0, sizeof(snl)); + snl.nl_family = AF_NETLINK; + + /* Check netlink socket. */ + if (sock < 0) { + syslog(LOG_ERR,"sock is not active, exiting"); + cerr << "sock is not active, exiting" << endl; + return -1; + } + + if (_debug) { + struct in_addr in; + in.s_addr = local_addr; + char *lbuf = inet_ntoa(in); + + in.s_addr = dst_addr; + char *buf = inet_ntoa(in); + + char sbuf[1024]; + sprintf(sbuf, "NetlinkSend::send_set_route(): %d, %s/%d, to this address: %s, on interface: %d, for this table: ",type,buf,mask_len,lbuf,ifindex,table); + cout << sbuf << endl; + + syslog(LOG_INFO,sbuf); + } + + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + if (type == RTM_NEWROUTE) { + req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; + } + else { + req.n.nlmsg_flags = NLM_F_REQUEST; + } + req.n.nlmsg_pid = getpid(); + req.n.nlmsg_type = type; + req.n.nlmsg_seq = time(NULL); + + req.rt_message.rtm_family = AF_INET; + req.rt_message.rtm_dst_len = mask_len; + req.rt_message.rtm_table = table; + if (type == RTM_NEWROUTE) { + req.rt_message.rtm_protocol = RTPROT_KERNEL; + if (rt_scope != -1) { + req.rt_message.rtm_scope = rt_scope;//RT_SCOPE_HOST; //will need to pass this in to get RT_SCOPE_HOST + } + if (rtn_type != -1) { + req.rt_message.rtm_type = rtn_type;//RTN_LOCAL; + } + } + else { + req.rt_message.rtm_scope = RT_SCOPE_NOWHERE; + req.rt_message.rtm_type = RTN_UNSPEC; + } + + addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &local_addr, sizeof(local_addr)); + addattr_l(&req.n, sizeof(req), RTA_DST, &dst_addr, sizeof(dst_addr)); + addattr32(&req.n, sizeof(req), RTA_OIF, ifindex); + + if (_debug) { + cout << "NetlinkSend::send_set_route():" << endl; + cout << " interface: " << ifindex << endl; + cout << " type: " << string(req.n.nlmsg_type == RTM_NEWROUTE ? string("RTM_NEWROUTE") : string("RTM_DELROUTE")) << endl; + cout << " flags: " << req.n.nlmsg_flags << endl; + cout << " protocol: " << int(req.rt_message.rtm_protocol) << endl; + cout << " scope: " << int(req.rt_message.rtm_scope) << endl; + cout << " addr(s): " << local_addr << ", " << dst_addr << ", " << mask_len << ", " << int(req.rt_message.rtm_dst_len) << endl; + cout << endl; + } + + ret = sendto (sock, (void*) &req, sizeof req, 0, + (struct sockaddr*) &snl, sizeof snl); + if (ret < 0) { + syslog(LOG_ERR,"netlink_send_route failed on send: %d, %d",ret,errno); + cerr << "netlink_send_route failed on send: " << ret << ", " << errno << endl; + return -1; + } + return 0; +} + +/** + * + * + **/ +int NetlinkSend::send_get(int sock, int type, int ifindex) { int ret; @@ -150,6 +256,13 @@ NetlinkSend::send_get(int sock, int type, int ifindex) return -1; } + if (_debug) { + char sbuf[1024]; + sprintf(sbuf,"NetlinkSend::send_get(): type: %d, ifindex: %d",type,ifindex); + cout << sbuf << endl; + syslog(LOG_INFO,sbuf); + } + memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); @@ -203,41 +316,22 @@ NetlinkSend::addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int return 0; } -/* Maskbit. */ -static u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, - 0xf8, 0xfc, 0xfe, 0xff}; - -/* Convert masklen into IP address's netmask. */ -void -masklen2ip (int masklen, struct in_addr *netmask) +int +NetlinkSend::addattr32(struct nlmsghdr *n, int maxlen, int type, int data) { - u_char *pnt; - int bit; - int offset; + int len; + struct rtattr *rta; - memset (netmask, 0, sizeof (struct in_addr)); - pnt = (unsigned char *) netmask; - - offset = masklen / 8; - bit = masklen % 8; - - while (offset--) - *pnt++ = 0xff; + len = RTA_LENGTH (4); - if (bit) - *pnt = maskbit[bit]; -} + if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen) + return -1; + rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len)); + rta->rta_type = type; + rta->rta_len = len; + memcpy (RTA_DATA (rta), &data, 4); + n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len; -in_addr_t -ipv4_broadcast_addr (in_addr_t hostaddr, int masklen) -{ - struct in_addr mask; - - masklen2ip (masklen, &mask); - return (masklen != 32-1) ? - /* normal case */ - (hostaddr | ~mask.s_addr) : - /* special case for /31 */ - (hostaddr ^ ~mask.s_addr); + return 0; } |