115 lines
3.0 KiB
C++
115 lines
3.0 KiB
C++
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <linux/rtnetlink.h>
|
|
|
|
#include "ip4.h"
|
|
#include "rtnetlink.h"
|
|
#include "interface.h"
|
|
|
|
namespace interface {
|
|
static void newaddr(int fd,
|
|
uint32_t ifa_index, uint8_t ifa_prefixlen, uint32_t local, uint32_t address)
|
|
{
|
|
int dret = rtnetlink::send_typeaddr(fd, RTM_NEWADDR, ifa_index,
|
|
ifa_prefixlen, local, address);
|
|
if (dret < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
int eret = rtnetlink::handle_error(fd);
|
|
if (eret < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
static void deladdr(int fd,
|
|
uint32_t ifa_index, uint8_t ifa_prefixlen, uint32_t local, uint32_t address)
|
|
{
|
|
int dret = rtnetlink::send_typeaddr(fd, RTM_DELADDR, ifa_index,
|
|
ifa_prefixlen, local, address);
|
|
if (dret < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
int eret = rtnetlink::handle_error(fd);
|
|
if (eret < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
static void newroute(int fd,
|
|
uint32_t ifa_index, uint32_t gateway)
|
|
{
|
|
int dret = rtnetlink::send_newroute(fd, ifa_index, gateway);
|
|
if (dret < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
int eret = rtnetlink::handle_error(fd);
|
|
if (eret < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
static void flush_addresses(int fd,
|
|
uint32_t ifa_index)
|
|
{
|
|
int grets = rtnetlink::send_getaddr(fd, ifa_index);
|
|
if (grets < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
const int out_length = 64;
|
|
rtnetlink::newaddr out[out_length];
|
|
int greth = rtnetlink::handle_getaddr(fd, ifa_index, out, out_length);
|
|
if (greth < 0) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
for (int i = 0; i < greth; i++) {
|
|
printf("deladdr[%d]:\n", i);
|
|
printf(" prefixlen %d\n", out[i].ifa_prefixlen);
|
|
printf(" local %s\n", ip4::tostr(out[i].local));
|
|
printf(" address %s\n", ip4::tostr(out[i].address));
|
|
|
|
deladdr(fd, ifa_index, out[i].ifa_prefixlen, out[i].local, out[i].address);
|
|
}
|
|
}
|
|
|
|
void configure(uint32_t ifa_index,
|
|
uint8_t ifa_prefixlen,
|
|
uint32_t address,
|
|
uint32_t gateway)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////
|
|
// netlink socket
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
|
if (fd < 0) {
|
|
perror("socket");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
struct sockaddr_nl bsa = { .nl_family = AF_NETLINK };
|
|
int ret = bind(fd, (struct sockaddr *)&bsa, (sizeof (sockaddr_nl)));
|
|
if (ret < 0) {
|
|
perror("bind");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
flush_addresses(fd, ifa_index);
|
|
|
|
newaddr(fd,
|
|
ifa_index, ifa_prefixlen, address, address);
|
|
|
|
newroute(fd,
|
|
ifa_index, gateway);
|
|
}
|
|
}
|