diff --git a/netlink.cpp b/netlink.cpp index 3400ace..3fedaf1 100644 --- a/netlink.cpp +++ b/netlink.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "ip4.h" #include "rtnetlink.h" @@ -103,5 +104,22 @@ int main() } } + // newroute + { + printf("newroute\n"); + uint32_t gateway; + int ret = inet_pton(AF_INET, "192.168.1.1", (void *)&gateway); + assert(ret == 1); + + int dret = rtnetlink::send_newroute(fd, if_index.ifr_ifindex, gateway); + if (dret < 0) { + exit(EXIT_FAILURE); + } + int eret = rtnetlink::handle_error(fd); + if (eret < 0) { + exit(EXIT_FAILURE); + } + } + return 0; } diff --git a/rtnetlink.cpp b/rtnetlink.cpp index 7c19207..3a80fa5 100644 --- a/rtnetlink.cpp +++ b/rtnetlink.cpp @@ -18,7 +18,7 @@ static inline int align4(int len) return (len + 3) & (~3); } -struct newaddr_msg { +struct getaddr_msg { struct nlmsghdr nl; struct ifaddrmsg ifaddr; }; @@ -32,6 +32,15 @@ struct deladdr_msg { } attr[2]; }; +struct newroute_msg { + struct nlmsghdr nl; + struct rtmsg rt; + struct { + struct rtattr rtattr; + uint32_t value; + } attr[2]; +}; + namespace rtnetlink { bool parse_newaddr(uint8_t const * buf, ssize_t length, @@ -127,9 +136,9 @@ namespace rtnetlink { int send_getaddr(int fd, uint32_t ifa_index) { - const size_t message_length = (sizeof (struct newaddr_msg)); + const size_t message_length = (sizeof (struct getaddr_msg)); - struct newaddr_msg rtmmsg = { + struct getaddr_msg rtmmsg = { .nl = { .nlmsg_len = message_length, .nlmsg_type = RTM_GETADDR, @@ -218,6 +227,59 @@ namespace rtnetlink { return 0; } + int send_newroute(int fd, uint32_t ifa_index, uint32_t gateway) + { + const size_t message_length = (sizeof (struct newroute_msg)); + + struct newroute_msg rtmmsg = { + .nl = { + .nlmsg_len = message_length, + .nlmsg_type = RTM_NEWROUTE, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE, + .nlmsg_seq = 123456, + }, + .rt = { + .rtm_family = AF_INET, + .rtm_table = RT_TABLE_MAIN, + .rtm_protocol = RTPROT_BOOT, + .rtm_scope = RT_SCOPE_UNIVERSE, + .rtm_type = RTN_UNICAST, + }, + .attr = { + { + .rtattr = { .rta_len = 8, .rta_type = RTA_GATEWAY }, + .value = gateway, + }, + { + .rtattr = { .rta_len = 8, .rta_type = RTA_OIF }, + .value = ifa_index, + } + } + }; + + struct iovec iov[1] = { + { + .iov_base = &rtmmsg, + .iov_len = message_length, + } + }; + struct sockaddr_nl addr = { .nl_family = AF_NETLINK }; + struct msghdr msg = { + .msg_name = (void *)&addr, + .msg_namelen = (sizeof (sockaddr_nl)), + .msg_iov = iov, + .msg_iovlen = 1, + }; + + ssize_t sret = sendmsg(fd, &msg, 0); + if (sret < 0) { + perror("sendmsg"); + return -1; + } + + return 0; + } + int handle_error(int fd) { struct sockaddr_nl addr = { .nl_family = AF_NETLINK }; diff --git a/rtnetlink.h b/rtnetlink.h index 597eb92..beb28a5 100644 --- a/rtnetlink.h +++ b/rtnetlink.h @@ -19,5 +19,7 @@ namespace rtnetlink { int send_getaddr(int fd, uint32_t ifa_index); int send_typeaddr(int fd, uint16_t nlmsg_type, uint32_t ifa_index, uint8_t ifa_prefixlen, uint32_t local, uint32_t address); + int send_newroute(int fd, uint32_t ifa_index, uint32_t gateway); + int handle_error(int fd); }