extern "C" { #include #include #include #include #include #include #include #include #include #include } #define BUFSIZE 8192 #include #include #include #include #include std::expected Router::AddRoute(std::string address, uint64_t prefix, std::string gateway) { struct sockaddr_in sa; if (inet_pton(AF_INET, address.data(), &(sa.sin_addr)) == 1) { } else { return std::unexpected(std::format("Incorrect address {}", address)); } struct rtentry rt; memset(&rt, 0, sizeof(rt)); struct sockaddr_in *sin; sin = (struct sockaddr_in*)&rt.rt_dst; sin->sin_family = AF_INET; if (inet_pton(AF_INET, address.data(), &sin->sin_addr) != 1){ int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Incorrect address {}, error: {}", address, error)); }; sin = (struct sockaddr_in*) &rt.rt_gateway; sin->sin_family = AF_INET; if (inet_pton(AF_INET, gateway.data(), &sin->sin_addr) != 1) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Incorrect address {}, error: {}", gateway, error)); }; char buffer[INET_ADDRSTRLEN]; uint32_t mask = (prefix == 0) ? 0 : htonl(~((1U << (32 - prefix)) - 1)); //uint32_t mask = (prefix == 0) ? 0 : (~0U << (32 - prefix)); struct in_addr addr; addr.s_addr = mask; const char *dottedmask; if ((dottedmask = inet_ntop(AF_INET, &addr, buffer, INET_ADDRSTRLEN)) == NULL) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Incorrect prefix {}, error: {}", prefix, error)); }; sin = (struct sockaddr_in*) &rt.rt_genmask; sin->sin_family = AF_INET; if (inet_pton(AF_INET, dottedmask, &sin->sin_addr) != 1) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Incorrect address {}, error: {}", gateway, error)); }; rt.rt_flags = RTF_UP | RTF_GATEWAY; //rt.rt_dev = std::string("eth0").data(); int sockfd = 0; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Error: {}", error)); } if (ioctl(sockfd, SIOCADDRT, &rt) < 0) { close(sockfd); int errnoCopy = errno; std::string error = std::strerror(errnoCopy); return std::unexpected(std::format("Cannot set route, error: {}", error)); } close(sockfd); return {}; } std::expected Router::List(void) { std::vector routes; struct { struct nlmsghdr n; struct rtmsg r; } req; std::string buffer(1024 * 10, 0); struct nlmsghdr *nlh; int sock, len; if ((sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) { return std::unexpected("Create netlink socket error"); } memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; req.n.nlmsg_type = RTM_GETROUTE; req.r.rtm_family = AF_INET; send(sock, &req, req.n.nlmsg_len, 0); while ((len = recv(sock, buffer.data(), buffer.size(), 0)) > 0) { nlh = (struct nlmsghdr *)buffer.data(); while (NLMSG_OK(nlh, len)) { if (nlh->nlmsg_type == NLMSG_DONE) { return {}; }; struct rtmsg *route = (struct rtmsg *)NLMSG_DATA(nlh); struct rtattr *rta = (struct rtattr *)RTM_RTA(route); int len = RTM_PAYLOAD(nlh); char dest_ip[INET_ADDRSTRLEN] = "0.0.0.0"; char gw_ip[INET_ADDRSTRLEN] = "0.0.0.0"; for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { switch (rta->rta_type) { case RTA_DST: inet_ntop(AF_INET, RTA_DATA(rta), dest_ip, sizeof(dest_ip)); break; case RTA_GATEWAY: inet_ntop(AF_INET, RTA_DATA(rta), gw_ip, sizeof(gw_ip)); break; case RTA_OIF: int if_idx = *(int *)RTA_DATA(rta); printf("Interface Index: %d ", if_idx); break; } } printf("Found route: dest %s / %d, gw %s\n", dest_ip, route->rtm_dst_len, gw_ip); nlh = NLMSG_NEXT(nlh, len); } } close(sock); return routes; }