Compare commits
No commits in common. "395bb5c76422c8e8423730b2d17498aa330ce85d" and "d891ad5a488c842f951d80c5f8fce3aa42cf3226" have entirely different histories.
395bb5c764
...
d891ad5a48
3
Makefile
3
Makefile
@ -18,8 +18,7 @@ OBJS = \
|
|||||||
packet.o \
|
packet.o \
|
||||||
udp4.o \
|
udp4.o \
|
||||||
eth.o \
|
eth.o \
|
||||||
rtnetlink.o \
|
rtnetlink.o
|
||||||
interface.o
|
|
||||||
|
|
||||||
all: client test2
|
all: client test2
|
||||||
|
|
||||||
|
|||||||
253
client.cpp
253
client.cpp
@ -2,10 +2,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stddef.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
@ -19,8 +17,64 @@
|
|||||||
#include "udp4.h"
|
#include "udp4.h"
|
||||||
#include "dhcp4.h"
|
#include "dhcp4.h"
|
||||||
#include "eth.h"
|
#include "eth.h"
|
||||||
#include "packet.h"
|
|
||||||
#include "interface.h"
|
int make_packet(uint8_t * buf,
|
||||||
|
uint8_t const * eth_source_address,
|
||||||
|
uint8_t const * eth_destination_address,
|
||||||
|
uint32_t const ip4_source_address,
|
||||||
|
uint32_t const ip4_destination_address,
|
||||||
|
uint32_t const dhcp_transaction_id,
|
||||||
|
uint32_t const dhcp_message_type)
|
||||||
|
{
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// dhcp4
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int dhcp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header)) + (sizeof (udp4::header));
|
||||||
|
int dhcp4_length = dhcp4::make_message(reinterpret_cast<void *>(&buf[dhcp4_offset]),
|
||||||
|
dhcp4::op::bootrequest,
|
||||||
|
dhcp_transaction_id,
|
||||||
|
eth_source_address,
|
||||||
|
dhcp_message_type);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// eth
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int eth_offset = 0;
|
||||||
|
eth::header * eth_header = reinterpret_cast<eth::header *>(&buf[eth_offset]);
|
||||||
|
memcpy(eth_header->destination_address, eth_destination_address, 6);
|
||||||
|
memcpy(eth_header->source_address, eth_source_address, 6);
|
||||||
|
eth_header->ether_type = htons(0x0800);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// ip4
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int ip4_offset = (sizeof (eth::header));
|
||||||
|
int ip4_payload_length = dhcp4_length + (sizeof (udp4::header));
|
||||||
|
int ip4_identification = 55179;
|
||||||
|
ip4::make_header(reinterpret_cast<void *>(&buf[ip4_offset]),
|
||||||
|
ip4_payload_length,
|
||||||
|
ip4_identification,
|
||||||
|
ip4_source_address,
|
||||||
|
ip4_destination_address);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// udp4
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int udp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header));
|
||||||
|
udp4::make_header(reinterpret_cast<void *>(&buf[udp4_offset]),
|
||||||
|
htons(68),
|
||||||
|
htons(67),
|
||||||
|
ip4_source_address,
|
||||||
|
ip4_destination_address,
|
||||||
|
&buf[dhcp4_offset],
|
||||||
|
dhcp4_length);
|
||||||
|
|
||||||
|
return dhcp4_offset + dhcp4_length;
|
||||||
|
}
|
||||||
|
|
||||||
void interface_send(int sock,
|
void interface_send(int sock,
|
||||||
int interface_index,
|
int interface_index,
|
||||||
@ -107,8 +161,7 @@ int main()
|
|||||||
perror("ioctl(SIOCGIFINDEX)");
|
perror("ioctl(SIOCGIFINDEX)");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
int ifa_index = if_index.ifr_ifindex;
|
printf("interface index %d\n", if_index.ifr_ifindex);
|
||||||
printf("interface index %d\n", ifa_index);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// interface address
|
// interface address
|
||||||
@ -131,46 +184,21 @@ int main()
|
|||||||
// bind
|
// bind
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct sockaddr_ll bind_addr_ll = {
|
struct sockaddr_ll bind_addr = {
|
||||||
.sll_family = AF_PACKET,
|
.sll_family = AF_PACKET,
|
||||||
.sll_protocol = htons(ETH_P_IP),
|
.sll_protocol = htons(ETH_P_ALL),
|
||||||
.sll_ifindex = ifa_index,
|
.sll_ifindex = if_index.ifr_ifindex,
|
||||||
};
|
};
|
||||||
int bret_ll = bind(s, (struct sockaddr *)&bind_addr_ll, (sizeof (struct sockaddr_ll)));
|
int bret = bind(s, (struct sockaddr *)&bind_addr, (sizeof (struct sockaddr_ll)));
|
||||||
if (bret_ll < 0) {
|
if (bret < 0) {
|
||||||
perror("bind ll");
|
perror("bind");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
attach_dhcp_filter(s);
|
attach_dhcp_filter(s);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// fake socket
|
// send
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int sf;
|
|
||||||
{
|
|
||||||
sf = socket(AF_INET, SOCK_DGRAM, 0);
|
|
||||||
if (sf < 0) {
|
|
||||||
perror("socket");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this has the effect of inhibiting linux's generation of icmp
|
|
||||||
// "destination unreachable" packets
|
|
||||||
struct sockaddr_in bind_addr_in = {
|
|
||||||
.sin_family = AF_INET,
|
|
||||||
.sin_port = htons(68),
|
|
||||||
.sin_addr = { .s_addr = INADDR_ANY },
|
|
||||||
};
|
|
||||||
int bret_in = bind(sf, (struct sockaddr *)&bind_addr_in, (sizeof (struct sockaddr_in)));
|
|
||||||
if (bret_in < 0) {
|
|
||||||
perror("bind in");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// dhcp send discover
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
uint32_t dhcp_transaction_id = rand();
|
uint32_t dhcp_transaction_id = rand();
|
||||||
@ -182,143 +210,24 @@ int main()
|
|||||||
uint32_t ip4_source_address = 0x00000000;
|
uint32_t ip4_source_address = 0x00000000;
|
||||||
uint32_t ip4_destination_address = 0xffffffff;
|
uint32_t ip4_destination_address = 0xffffffff;
|
||||||
|
|
||||||
int length = packet::make(buf,
|
int length = make_packet(buf,
|
||||||
eth_source_address,
|
eth_source_address,
|
||||||
eth_destination_address,
|
eth_destination_address,
|
||||||
ip4_source_address,
|
ip4_source_address,
|
||||||
ip4_destination_address,
|
ip4_destination_address,
|
||||||
dhcp_transaction_id,
|
dhcp_transaction_id,
|
||||||
dhcp4::message_type::dhcpdiscover,
|
dhcp4::message_type::dhcpdiscover);
|
||||||
0);
|
|
||||||
|
|
||||||
interface_send(s, ifa_index, buf, length, eth_destination_address);
|
interface_send(s, if_index.ifr_ifindex, buf, length, eth_destination_address);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// dhcp recv offer
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
packet::packet p{};
|
|
||||||
dhcp4::options options{};
|
|
||||||
uint8_t recvbuf[65536];
|
uint8_t recvbuf[65536];
|
||||||
|
struct sockaddr_ll recv_address;
|
||||||
|
int flags = 0;
|
||||||
|
socklen_t socklen = (sizeof (struct sockaddr_ll));
|
||||||
|
ssize_t ret = recvfrom(s, recvbuf, 16384, flags,
|
||||||
|
(struct sockaddr *)&recv_address, &socklen);
|
||||||
|
printf("recv ret %ld\n", ret);
|
||||||
|
|
||||||
{
|
|
||||||
struct sockaddr_ll recv_address;
|
|
||||||
int flags = 0;
|
|
||||||
socklen_t socklen = (sizeof (struct sockaddr_ll));
|
|
||||||
ssize_t rret = recvfrom(s, recvbuf, (sizeof (recvbuf)), flags,
|
|
||||||
(struct sockaddr *)&recv_address, &socklen);
|
|
||||||
if (rret < 0) {
|
|
||||||
perror("recvfrom");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
packet::parse(recvbuf, rret, &p);
|
|
||||||
|
|
||||||
printf("dhcp4 op: %d\n", p.dhcp4->op);
|
|
||||||
printf("dhcp4 yiaddr: %s\n", ip4::tostr(p.dhcp4->yiaddr));
|
|
||||||
|
|
||||||
int dhcp4_options_length = rret - (packet::dhcp4_offset + (offsetof (dhcp4::message, options)));
|
|
||||||
dhcp4::parse_options(p.dhcp4, dhcp4_options_length, &options);
|
|
||||||
printf("message type: %s\n", dhcp4::message_type_tostr(options.message_type));
|
|
||||||
printf("subnet mask: %s\n", ip4::tostr(options.subnet_mask));
|
|
||||||
printf("router: %s\n", ip4::tostr(options.router));
|
|
||||||
printf("domain name server: %s\n", ip4::tostr(options.domain_name_server));
|
|
||||||
|
|
||||||
assert(p.dhcp4->op == dhcp4::op::bootreply);
|
|
||||||
assert(options.message_type == dhcp4::message_type::dhcpoffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// dhcp send request
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
{
|
|
||||||
int length = packet::make(buf,
|
|
||||||
eth_source_address,
|
|
||||||
eth_destination_address,
|
|
||||||
ip4_source_address,
|
|
||||||
ip4_destination_address,
|
|
||||||
dhcp_transaction_id,
|
|
||||||
dhcp4::message_type::dhcprequest,
|
|
||||||
p.dhcp4->yiaddr);
|
|
||||||
|
|
||||||
interface_send(s, ifa_index, buf, length, eth_destination_address);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// dhcp recv ack
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
{
|
|
||||||
struct sockaddr_ll recv_address;
|
|
||||||
int flags = 0;
|
|
||||||
socklen_t socklen = (sizeof (struct sockaddr_ll));
|
|
||||||
ssize_t rret = recvfrom(s, recvbuf, (sizeof (recvbuf)), flags,
|
|
||||||
(struct sockaddr *)&recv_address, &socklen);
|
|
||||||
if (rret < 0) {
|
|
||||||
perror("recvfrom");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
packet::parse(recvbuf, rret, &p);
|
|
||||||
|
|
||||||
printf("dhcp4 op: %d\n", p.dhcp4->op);
|
|
||||||
printf("dhcp4 yiaddr: %s\n", ip4::tostr(p.dhcp4->yiaddr));
|
|
||||||
|
|
||||||
int dhcp4_options_length = rret - (packet::dhcp4_offset + (offsetof (dhcp4::message, options)));
|
|
||||||
dhcp4::parse_options(p.dhcp4, dhcp4_options_length, &options);
|
|
||||||
printf("message type: %s\n", dhcp4::message_type_tostr(options.message_type));
|
|
||||||
printf("subnet mask: %s\n", ip4::tostr(options.subnet_mask));
|
|
||||||
printf("router: %s\n", ip4::tostr(options.router));
|
|
||||||
printf("domain name server: %s\n", ip4::tostr(options.domain_name_server));
|
|
||||||
|
|
||||||
assert(p.dhcp4->op == dhcp4::op::bootreply);
|
|
||||||
assert(options.message_type == dhcp4::message_type::dhcpack);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// interface configure
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
uint32_t mask = ntohl(options.subnet_mask);
|
|
||||||
uint8_t prefix_length = 32 - __builtin_ctz(mask);
|
|
||||||
printf("prefix_length %d\n", prefix_length);
|
|
||||||
|
|
||||||
interface::configure(ifa_index,
|
|
||||||
prefix_length,
|
|
||||||
p.dhcp4->yiaddr,
|
|
||||||
options.router);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// dns configure
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int dfd = open("/etc/resolv.conf", O_CREAT | O_WRONLY | O_TRUNC);
|
|
||||||
if (dfd < 0) {
|
|
||||||
perror("open");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
char dbuf[1024];
|
|
||||||
int dbuflen = snprintf(dbuf, (sizeof (dbuf)), "nameserver %s\n",
|
|
||||||
ip4::tostr(options.domain_name_server));
|
|
||||||
if (dbuflen < 0) {
|
|
||||||
perror("snprintf");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t dret = write(dfd, dbuf, dbuflen);
|
|
||||||
if (dret < 0) {
|
|
||||||
perror("write");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// exit
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
close(dfd);
|
|
||||||
close(s);
|
close(s);
|
||||||
close(sf);
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|||||||
13
dhcp4.cpp
13
dhcp4.cpp
@ -1,6 +1,5 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
@ -12,8 +11,7 @@ namespace dhcp4 {
|
|||||||
uint32_t bootp_message_type,
|
uint32_t bootp_message_type,
|
||||||
uint32_t transaction_id,
|
uint32_t transaction_id,
|
||||||
uint8_t const * chaddr,
|
uint8_t const * chaddr,
|
||||||
uint32_t dhcp_message_type,
|
uint32_t dhcp_message_type)
|
||||||
uint32_t requested_ip_address)
|
|
||||||
{
|
{
|
||||||
memset(buf, 0, (sizeof (message)));
|
memset(buf, 0, (sizeof (message)));
|
||||||
message * msg = reinterpret_cast<message *>(buf);
|
message * msg = reinterpret_cast<message *>(buf);
|
||||||
@ -50,15 +48,6 @@ namespace dhcp4 {
|
|||||||
prl[4] = option::domain_name_server;
|
prl[4] = option::domain_name_server;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requested_ip_address != 0) {
|
|
||||||
uint8_t * addr = &msg->options[index];
|
|
||||||
int length = 4;
|
|
||||||
index += 2 + length;
|
|
||||||
addr[0] = option::requested_ip_address;
|
|
||||||
addr[1] = length;
|
|
||||||
memcpy(&addr[2], &requested_ip_address, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t * end = &msg->options[index];
|
uint8_t * end = &msg->options[index];
|
||||||
index += 1;
|
index += 1;
|
||||||
end[0] = 255;
|
end[0] = 255;
|
||||||
|
|||||||
4
dhcp4.h
4
dhcp4.h
@ -51,7 +51,6 @@ namespace dhcp4 {
|
|||||||
router = 3,
|
router = 3,
|
||||||
domain_name_server = 6,
|
domain_name_server = 6,
|
||||||
broadcast_address = 28,
|
broadcast_address = 28,
|
||||||
requested_ip_address = 50,
|
|
||||||
ip_address_lease_time = 51,
|
ip_address_lease_time = 51,
|
||||||
option_overload = 52,
|
option_overload = 52,
|
||||||
message_type = 53,
|
message_type = 53,
|
||||||
@ -79,8 +78,7 @@ namespace dhcp4 {
|
|||||||
uint32_t bootp_message_type,
|
uint32_t bootp_message_type,
|
||||||
uint32_t transaction_id,
|
uint32_t transaction_id,
|
||||||
uint8_t const * chaddr,
|
uint8_t const * chaddr,
|
||||||
uint32_t dhcp_message_type,
|
uint32_t dhcp_message_type);
|
||||||
uint32_t requested_ip_address);
|
|
||||||
|
|
||||||
char const * message_type_tostr(int message_type);
|
char const * message_type_tostr(int message_type);
|
||||||
|
|
||||||
|
|||||||
114
interface.cpp
114
interface.cpp
@ -1,114 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
12
interface.h
12
interface.h
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace interface {
|
|
||||||
|
|
||||||
void configure(uint32_t ifa_index,
|
|
||||||
uint8_t ifa_prefixlen,
|
|
||||||
uint32_t address,
|
|
||||||
uint32_t gateway);
|
|
||||||
|
|
||||||
}
|
|
||||||
19
netlink.cpp
19
netlink.cpp
@ -10,7 +10,6 @@
|
|||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include "ip4.h"
|
#include "ip4.h"
|
||||||
#include "rtnetlink.h"
|
#include "rtnetlink.h"
|
||||||
@ -44,6 +43,7 @@ int main()
|
|||||||
// interface index
|
// interface index
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
char const * interface_name = "wlp174s0";
|
||||||
struct ifreq if_index = {};
|
struct ifreq if_index = {};
|
||||||
strncpy(if_index.ifr_name, interface_name, IFNAMSIZ - 1);
|
strncpy(if_index.ifr_name, interface_name, IFNAMSIZ - 1);
|
||||||
int iret = ioctl(fd, SIOCGIFINDEX, &if_index);
|
int iret = ioctl(fd, SIOCGIFINDEX, &if_index);
|
||||||
@ -103,22 +103,5 @@ 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
57
packet.cpp
57
packet.cpp
@ -1,5 +1,4 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
@ -60,60 +59,4 @@ namespace packet {
|
|||||||
p->udp4 = udp4_header;
|
p->udp4 = udp4_header;
|
||||||
p->dhcp4 = dhcp4_message;
|
p->dhcp4 = dhcp4_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
int make(uint8_t * buf,
|
|
||||||
uint8_t const * eth_source_address,
|
|
||||||
uint8_t const * eth_destination_address,
|
|
||||||
uint32_t const ip4_source_address,
|
|
||||||
uint32_t const ip4_destination_address,
|
|
||||||
uint32_t const dhcp_transaction_id,
|
|
||||||
uint32_t const dhcp_message_type,
|
|
||||||
uint32_t const requested_ip_address)
|
|
||||||
{
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// dhcp4
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int dhcp4_length = dhcp4::make_message(reinterpret_cast<void *>(&buf[dhcp4_offset]),
|
|
||||||
dhcp4::op::bootrequest,
|
|
||||||
dhcp_transaction_id,
|
|
||||||
eth_source_address,
|
|
||||||
dhcp_message_type,
|
|
||||||
requested_ip_address);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// eth
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
eth::header * eth_header = reinterpret_cast<eth::header *>(&buf[eth_offset]);
|
|
||||||
memcpy(eth_header->destination_address, eth_destination_address, 6);
|
|
||||||
memcpy(eth_header->source_address, eth_source_address, 6);
|
|
||||||
eth_header->ether_type = htons(0x0800);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// ip4
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int ip4_payload_length = dhcp4_length + (sizeof (udp4::header));
|
|
||||||
int ip4_identification = 55179;
|
|
||||||
ip4::make_header(reinterpret_cast<void *>(&buf[ip4_offset]),
|
|
||||||
ip4_payload_length,
|
|
||||||
ip4_identification,
|
|
||||||
ip4_source_address,
|
|
||||||
ip4_destination_address);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// udp4
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
udp4::make_header(reinterpret_cast<void *>(&buf[udp4_offset]),
|
|
||||||
htons(68),
|
|
||||||
htons(67),
|
|
||||||
ip4_source_address,
|
|
||||||
ip4_destination_address,
|
|
||||||
&buf[dhcp4_offset],
|
|
||||||
dhcp4_length);
|
|
||||||
|
|
||||||
return dhcp4_offset + dhcp4_length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
9
packet.h
9
packet.h
@ -19,13 +19,4 @@ namespace packet {
|
|||||||
const int ip4_offset = (sizeof (eth::header));
|
const int ip4_offset = (sizeof (eth::header));
|
||||||
const int udp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header));
|
const int udp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header));
|
||||||
const int dhcp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header)) + (sizeof (udp4::header));
|
const int dhcp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header)) + (sizeof (udp4::header));
|
||||||
|
|
||||||
int make(uint8_t * buf,
|
|
||||||
uint8_t const * eth_source_address,
|
|
||||||
uint8_t const * eth_destination_address,
|
|
||||||
uint32_t const ip4_source_address,
|
|
||||||
uint32_t const ip4_destination_address,
|
|
||||||
uint32_t const dhcp_transaction_id,
|
|
||||||
uint32_t const dhcp_message_type,
|
|
||||||
uint32_t const requested_ip_address);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,7 +18,7 @@ static inline int align4(int len)
|
|||||||
return (len + 3) & (~3);
|
return (len + 3) & (~3);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct getaddr_msg {
|
struct newaddr_msg {
|
||||||
struct nlmsghdr nl;
|
struct nlmsghdr nl;
|
||||||
struct ifaddrmsg ifaddr;
|
struct ifaddrmsg ifaddr;
|
||||||
};
|
};
|
||||||
@ -32,15 +32,6 @@ struct deladdr_msg {
|
|||||||
} attr[2];
|
} attr[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct newroute_msg {
|
|
||||||
struct nlmsghdr nl;
|
|
||||||
struct rtmsg rt;
|
|
||||||
struct {
|
|
||||||
struct rtattr rtattr;
|
|
||||||
uint32_t value;
|
|
||||||
} attr[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace rtnetlink {
|
namespace rtnetlink {
|
||||||
|
|
||||||
bool parse_newaddr(uint8_t const * buf, ssize_t length,
|
bool parse_newaddr(uint8_t const * buf, ssize_t length,
|
||||||
@ -136,9 +127,9 @@ namespace rtnetlink {
|
|||||||
|
|
||||||
int send_getaddr(int fd, uint32_t ifa_index)
|
int send_getaddr(int fd, uint32_t ifa_index)
|
||||||
{
|
{
|
||||||
const size_t message_length = (sizeof (struct getaddr_msg));
|
const size_t message_length = (sizeof (struct newaddr_msg));
|
||||||
|
|
||||||
struct getaddr_msg rtmmsg = {
|
struct newaddr_msg rtmmsg = {
|
||||||
.nl = {
|
.nl = {
|
||||||
.nlmsg_len = message_length,
|
.nlmsg_len = message_length,
|
||||||
.nlmsg_type = RTM_GETADDR,
|
.nlmsg_type = RTM_GETADDR,
|
||||||
@ -227,59 +218,6 @@ namespace rtnetlink {
|
|||||||
return 0;
|
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)
|
int handle_error(int fd)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
|
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
|
||||||
|
|||||||
@ -19,7 +19,5 @@ namespace rtnetlink {
|
|||||||
int send_getaddr(int fd, uint32_t ifa_index);
|
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_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);
|
int handle_error(int fd);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user