Compare commits
No commits in common. "d891ad5a488c842f951d80c5f8fce3aa42cf3226" and "4024bcf42fac1e5c2fad4058f281a72c88b872ae" have entirely different histories.
d891ad5a48
...
4024bcf42f
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,7 +1,3 @@
|
|||||||
*
|
|
||||||
!*.*
|
|
||||||
!*/
|
|
||||||
|
|
||||||
*.o
|
*.o
|
||||||
*.out
|
*.out
|
||||||
.gdb_history
|
.gdb_history
|
||||||
40
Makefile
40
Makefile
@ -1,40 +0,0 @@
|
|||||||
OPT = -O0 -fno-stack-protector
|
|
||||||
|
|
||||||
CFLAGS = -g -gdwarf-4 -Wall -Wextra -Wno-error -Wfatal-errors
|
|
||||||
#CFLAGS += -Wno-error=unused-parameter
|
|
||||||
#CFLAGS += -Wno-error=unused-variable
|
|
||||||
#CFLAGS += -Wno-error=unused-but-set-variable
|
|
||||||
CFLAGS += -Wno-missing-field-initializers
|
|
||||||
CFLAGS += -I../../include
|
|
||||||
CFLAGS += $(OPT)
|
|
||||||
|
|
||||||
LDFLAGS += $(OPT)
|
|
||||||
|
|
||||||
CXXFLAGS = -std=c++23
|
|
||||||
|
|
||||||
OBJS = \
|
|
||||||
dhcp4.o \
|
|
||||||
ip4.o \
|
|
||||||
packet.o \
|
|
||||||
udp4.o \
|
|
||||||
eth.o \
|
|
||||||
rtnetlink.o
|
|
||||||
|
|
||||||
all: client test2
|
|
||||||
|
|
||||||
%.o: %.cpp
|
|
||||||
$(CXX) $(CFLAGS) $(CXXFLAGS) $(FREETYPE_CFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
%: %.o $(OBJS)
|
|
||||||
$(CXX) $(LDFLAGS) $^ -o $@
|
|
||||||
|
|
||||||
.SUFFIXES:
|
|
||||||
.INTERMEDIATE:
|
|
||||||
.SECONDARY:
|
|
||||||
.PHONY: all clean phony
|
|
||||||
|
|
||||||
%: RCS/%,v
|
|
||||||
%: RCS/%
|
|
||||||
%: %,v
|
|
||||||
%: s.%
|
|
||||||
%: SCCS/s.%
|
|
||||||
40
client.cpp
40
client.cpp
@ -13,7 +13,7 @@
|
|||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
|
|
||||||
#include "ip4.h"
|
#include "ipv4.h"
|
||||||
#include "udp4.h"
|
#include "udp4.h"
|
||||||
#include "dhcp4.h"
|
#include "dhcp4.h"
|
||||||
#include "eth.h"
|
#include "eth.h"
|
||||||
@ -21,8 +21,8 @@
|
|||||||
int make_packet(uint8_t * buf,
|
int make_packet(uint8_t * buf,
|
||||||
uint8_t const * eth_source_address,
|
uint8_t const * eth_source_address,
|
||||||
uint8_t const * eth_destination_address,
|
uint8_t const * eth_destination_address,
|
||||||
uint32_t const ip4_source_address,
|
uint32_t const ipv4_source_address,
|
||||||
uint32_t const ip4_destination_address,
|
uint32_t const ipv4_destination_address,
|
||||||
uint32_t const dhcp_transaction_id,
|
uint32_t const dhcp_transaction_id,
|
||||||
uint32_t const dhcp_message_type)
|
uint32_t const dhcp_message_type)
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ int make_packet(uint8_t * buf,
|
|||||||
// dhcp4
|
// dhcp4
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int dhcp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header)) + (sizeof (udp4::header));
|
int dhcp4_offset = (sizeof (eth::header)) + (sizeof (ipv4::header)) + (sizeof (udp4::header));
|
||||||
int dhcp4_length = dhcp4::make_message(reinterpret_cast<void *>(&buf[dhcp4_offset]),
|
int dhcp4_length = dhcp4::make_message(reinterpret_cast<void *>(&buf[dhcp4_offset]),
|
||||||
dhcp4::op::bootrequest,
|
dhcp4::op::bootrequest,
|
||||||
dhcp_transaction_id,
|
dhcp_transaction_id,
|
||||||
@ -48,28 +48,28 @@ int make_packet(uint8_t * buf,
|
|||||||
eth_header->ether_type = htons(0x0800);
|
eth_header->ether_type = htons(0x0800);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// ip4
|
// ipv4
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int ip4_offset = (sizeof (eth::header));
|
int ipv4_offset = (sizeof (eth::header));
|
||||||
int ip4_payload_length = dhcp4_length + (sizeof (udp4::header));
|
int ipv4_payload_length = dhcp4_length + (sizeof (udp4::header));
|
||||||
int ip4_identification = 55179;
|
int ipv4_identification = 55179;
|
||||||
ip4::make_header(reinterpret_cast<void *>(&buf[ip4_offset]),
|
ipv4::make_header(reinterpret_cast<void *>(&buf[ipv4_offset]),
|
||||||
ip4_payload_length,
|
ipv4_payload_length,
|
||||||
ip4_identification,
|
ipv4_identification,
|
||||||
ip4_source_address,
|
ipv4_source_address,
|
||||||
ip4_destination_address);
|
ipv4_destination_address);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// udp4
|
// udp4
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int udp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header));
|
int udp4_offset = (sizeof (eth::header)) + (sizeof (ipv4::header));
|
||||||
udp4::make_header(reinterpret_cast<void *>(&buf[udp4_offset]),
|
udp4::make_header(reinterpret_cast<void *>(&buf[udp4_offset]),
|
||||||
htons(68),
|
htons(68),
|
||||||
htons(67),
|
htons(67),
|
||||||
ip4_source_address,
|
ipv4_source_address,
|
||||||
ip4_destination_address,
|
ipv4_destination_address,
|
||||||
&buf[dhcp4_offset],
|
&buf[dhcp4_offset],
|
||||||
dhcp4_length);
|
dhcp4_length);
|
||||||
|
|
||||||
@ -207,14 +207,14 @@ int main()
|
|||||||
memcpy(eth_source_address, if_hwaddr.ifr_hwaddr.sa_data, 6);
|
memcpy(eth_source_address, if_hwaddr.ifr_hwaddr.sa_data, 6);
|
||||||
uint8_t eth_destination_address[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
uint8_t eth_destination_address[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
uint32_t ip4_source_address = 0x00000000;
|
uint32_t ipv4_source_address = 0x00000000;
|
||||||
uint32_t ip4_destination_address = 0xffffffff;
|
uint32_t ipv4_destination_address = 0xffffffff;
|
||||||
|
|
||||||
int length = make_packet(buf,
|
int length = make_packet(buf,
|
||||||
eth_source_address,
|
eth_source_address,
|
||||||
eth_destination_address,
|
eth_destination_address,
|
||||||
ip4_source_address,
|
ipv4_source_address,
|
||||||
ip4_destination_address,
|
ipv4_destination_address,
|
||||||
dhcp_transaction_id,
|
dhcp_transaction_id,
|
||||||
dhcp4::message_type::dhcpdiscover);
|
dhcp4::message_type::dhcpdiscover);
|
||||||
|
|
||||||
|
|||||||
70
dhcp4.cpp
70
dhcp4.cpp
@ -1,5 +1,4 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
@ -39,13 +38,24 @@ namespace dhcp4 {
|
|||||||
|
|
||||||
{
|
{
|
||||||
uint8_t * prl = &msg->options[index];
|
uint8_t * prl = &msg->options[index];
|
||||||
int length = 3;
|
int length = 4;
|
||||||
index += 2 + length;
|
index += 2 + length;
|
||||||
prl[0] = option::parameter_request_list;
|
prl[0] = option::parameter_request_list;
|
||||||
prl[1] = length;
|
prl[1] = length;
|
||||||
prl[2] = option::subnet_mask;
|
prl[2] = 1; // subnet mask
|
||||||
prl[3] = option::router;
|
prl[3] = 3; // router
|
||||||
prl[4] = option::domain_name_server;
|
prl[4] = 6; // domain name server
|
||||||
|
prl[5] = 28; // broadcast address
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
uint8_t * message_size = &msg->options[index];
|
||||||
|
int length = 2;
|
||||||
|
index += 2 + length;
|
||||||
|
message_size[0] = option::maximum_message_size;
|
||||||
|
message_size[1] = length;
|
||||||
|
message_size[2] = 0x05;
|
||||||
|
message_size[3] = 0xc0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * end = &msg->options[index];
|
uint8_t * end = &msg->options[index];
|
||||||
@ -54,54 +64,4 @@ namespace dhcp4 {
|
|||||||
|
|
||||||
return (sizeof (message)) + index;
|
return (sizeof (message)) + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const * message_type_tostr(int message_type)
|
|
||||||
{
|
|
||||||
switch (message_type) {
|
|
||||||
case message_type::dhcpdiscover: return "dhcpdiscover";
|
|
||||||
case message_type::dhcpoffer: return "dhcpoffer";
|
|
||||||
case message_type::dhcprequest: return "dhcprequest";
|
|
||||||
case message_type::dhcpdecline: return "dhcpdecline";
|
|
||||||
case message_type::dhcpack: return "dhcpack";
|
|
||||||
case message_type::dhcpnak: return "dhcpnak";
|
|
||||||
case message_type::dhcprelease: return "dhcprelease";
|
|
||||||
case message_type::dhcpinform: return "dhcpinform";
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void parse_options(message const * m, int options_length, options * o)
|
|
||||||
{
|
|
||||||
uint8_t const * options = m->options;
|
|
||||||
|
|
||||||
int index = 4;
|
|
||||||
while (index + 2 <= options_length) {
|
|
||||||
int option = options[index + 0];
|
|
||||||
int option_length = options[index + 1];
|
|
||||||
|
|
||||||
//printf("option %d length %d\n", option, option_length);
|
|
||||||
|
|
||||||
switch (option) {
|
|
||||||
case option::message_type:
|
|
||||||
o->message_type = options[index + 2];
|
|
||||||
break;
|
|
||||||
case option::subnet_mask:
|
|
||||||
o->subnet_mask = *reinterpret_cast<uint32_t const *>(&options[index + 2]);
|
|
||||||
break;
|
|
||||||
case option::router:
|
|
||||||
o->router = *reinterpret_cast<uint32_t const *>(&options[index + 2]);
|
|
||||||
break;
|
|
||||||
case option::domain_name_server:
|
|
||||||
o->domain_name_server = *reinterpret_cast<uint32_t const *>(&options[index + 2]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
index += 2 + option_length;
|
|
||||||
}
|
|
||||||
assert(options[index] == 255);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
15
dhcp4.h
15
dhcp4.h
@ -23,13 +23,6 @@ namespace dhcp4 {
|
|||||||
uint8_t options[];
|
uint8_t options[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct options {
|
|
||||||
int message_type; // 53
|
|
||||||
uint32_t subnet_mask; // 1
|
|
||||||
uint32_t router; // 3
|
|
||||||
uint32_t domain_name_server; // 6
|
|
||||||
};
|
|
||||||
|
|
||||||
struct op {
|
struct op {
|
||||||
enum {
|
enum {
|
||||||
bootrequest = 1,
|
bootrequest = 1,
|
||||||
@ -47,10 +40,6 @@ namespace dhcp4 {
|
|||||||
|
|
||||||
struct option {
|
struct option {
|
||||||
enum {
|
enum {
|
||||||
subnet_mask = 1,
|
|
||||||
router = 3,
|
|
||||||
domain_name_server = 6,
|
|
||||||
broadcast_address = 28,
|
|
||||||
ip_address_lease_time = 51,
|
ip_address_lease_time = 51,
|
||||||
option_overload = 52,
|
option_overload = 52,
|
||||||
message_type = 53,
|
message_type = 53,
|
||||||
@ -79,8 +68,4 @@ namespace dhcp4 {
|
|||||||
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);
|
||||||
|
|
||||||
char const * message_type_tostr(int message_type);
|
|
||||||
|
|
||||||
void parse_options(message const * m, int options_length, options * o);
|
|
||||||
}
|
}
|
||||||
|
|||||||
15
eth.cpp
15
eth.cpp
@ -1,15 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "eth.h"
|
|
||||||
|
|
||||||
namespace eth {
|
|
||||||
char const * tostr(uint8_t const * buf)
|
|
||||||
{
|
|
||||||
static char tmp[18];
|
|
||||||
int ret = snprintf(tmp, 18,
|
|
||||||
"%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
|
|
||||||
assert(ret > 0);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
eth.h
2
eth.h
@ -8,6 +8,4 @@ namespace eth {
|
|||||||
uint8_t source_address[6];
|
uint8_t source_address[6];
|
||||||
uint16_t ether_type;
|
uint16_t ether_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
char const * tostr(uint8_t const * buf);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,15 +4,9 @@
|
|||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "ip4.h"
|
#include "ipv4.h"
|
||||||
|
|
||||||
namespace ip4 {
|
namespace ipv4 {
|
||||||
|
|
||||||
char const * tostr(uint32_t a)
|
|
||||||
{
|
|
||||||
static char tmp[16];
|
|
||||||
return inet_ntop(AF_INET, reinterpret_cast<void const *>(&a), tmp, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t checksum_partial(uint32_t sum, void const * src, int length)
|
uint32_t checksum_partial(uint32_t sum, void const * src, int length)
|
||||||
{
|
{
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace ip4 {
|
namespace ipv4 {
|
||||||
|
|
||||||
struct header {
|
struct header {
|
||||||
uint8_t version_ihl;
|
uint8_t version_ihl;
|
||||||
@ -19,8 +19,6 @@ namespace ip4 {
|
|||||||
|
|
||||||
static_assert((sizeof (header)) == 20);
|
static_assert((sizeof (header)) == 20);
|
||||||
|
|
||||||
char const * tostr(uint32_t a);
|
|
||||||
|
|
||||||
uint32_t checksum_partial(uint32_t sum, void const * src, int length);
|
uint32_t checksum_partial(uint32_t sum, void const * src, int length);
|
||||||
uint32_t checksum_finish(uint32_t sum);
|
uint32_t checksum_finish(uint32_t sum);
|
||||||
uint32_t checksum(void const * src, int length);
|
uint32_t checksum(void const * src, int length);
|
||||||
107
netlink.cpp
107
netlink.cpp
@ -1,107 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <linux/netlink.h>
|
|
||||||
#include <linux/rtnetlink.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include "ip4.h"
|
|
||||||
#include "rtnetlink.h"
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
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 };
|
|
||||||
ret = bind(fd, (struct sockaddr *)&bsa, (sizeof (sockaddr_nl)));
|
|
||||||
if (ret < 0) {
|
|
||||||
perror("bind");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_nl gsa;
|
|
||||||
socklen_t addrlen = (sizeof (sockaddr_nl));
|
|
||||||
ret = getsockname(fd, (struct sockaddr *)&gsa, &addrlen);
|
|
||||||
if (ret < 0) {
|
|
||||||
perror("getsockname");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// interface index
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
char const * interface_name = "wlp174s0";
|
|
||||||
struct ifreq if_index = {};
|
|
||||||
strncpy(if_index.ifr_name, interface_name, IFNAMSIZ - 1);
|
|
||||||
int iret = ioctl(fd, SIOCGIFINDEX, &if_index);
|
|
||||||
if (iret < 0) {
|
|
||||||
perror("ioctl(SIOCGIFINDEX)");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
printf("ifa_index %d\n", if_index.ifr_ifindex);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// message
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int rtrets = rtnetlink::send_getaddr(fd, if_index.ifr_ifindex);
|
|
||||||
if (rtrets < 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int out_length = 64;
|
|
||||||
rtnetlink::newaddr out[out_length];
|
|
||||||
int rtreth = rtnetlink::handle_getaddr(fd, if_index.ifr_ifindex, out, out_length);
|
|
||||||
if (rtreth < 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < rtreth; i++) {
|
|
||||||
printf("out[%d] prefixlen %d\n", i, out[i].ifa_prefixlen);
|
|
||||||
printf("out[%d] local %s\n", i, ip4::tostr(out[i].local));
|
|
||||||
printf("out[%d] address %s\n", i, ip4::tostr(out[i].address));
|
|
||||||
|
|
||||||
// del
|
|
||||||
{
|
|
||||||
printf("del\n");
|
|
||||||
int dret = rtnetlink::send_typeaddr(fd, RTM_DELADDR, if_index.ifr_ifindex,
|
|
||||||
out[i].ifa_prefixlen, out[i].local, out[i].address);
|
|
||||||
if (dret < 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
int eret = rtnetlink::handle_error(fd);
|
|
||||||
if (eret < 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// new
|
|
||||||
{
|
|
||||||
printf("new\n");
|
|
||||||
int dret = rtnetlink::send_typeaddr(fd, RTM_NEWADDR, if_index.ifr_ifindex,
|
|
||||||
out[i].ifa_prefixlen, out[i].local, out[i].address);
|
|
||||||
if (dret < 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
int eret = rtnetlink::handle_error(fd);
|
|
||||||
if (eret < 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
62
packet.cpp
62
packet.cpp
@ -1,62 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include "packet.h"
|
|
||||||
|
|
||||||
namespace packet {
|
|
||||||
|
|
||||||
void parse(uint8_t const * buf, int length, packet * p)
|
|
||||||
{
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// eth
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
eth::header const * eth_header = reinterpret_cast<eth::header const *>(&buf[eth_offset]);
|
|
||||||
|
|
||||||
//printf("eth source address ");
|
|
||||||
//print_eth_address(eth_header->source_address);
|
|
||||||
//printf("eth destination address ");
|
|
||||||
//print_eth_address(eth_header->destination_address);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// ip4
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ip4::header const * ip4_header = reinterpret_cast<ip4::header const *>(&buf[ip4_offset]);
|
|
||||||
//printf("ip4 total length: %d\n", ntohs(ip4_header->total_length));
|
|
||||||
assert(ip4_offset + ntohs(ip4_header->total_length) == length);
|
|
||||||
|
|
||||||
printf("ip4 source address: %s\n", ip4::tostr(ip4_header->source_address));
|
|
||||||
printf("ip4 destination address: %s\n", ip4::tostr(ip4_header->destination_address));
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// udp4
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
udp4::header const * udp4_header = reinterpret_cast<udp4::header const *>(&buf[udp4_offset]);
|
|
||||||
//printf("udp4 length: %d\n", ntohs(udp4_header->length));
|
|
||||||
assert(udp4_offset + ntohs(udp4_header->length) == length);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// dhcp4
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
dhcp4::message const * dhcp4_message = reinterpret_cast<dhcp4::message const *>(&buf[dhcp4_offset]);
|
|
||||||
uint8_t const * dhcp4_options = dhcp4_message->options;
|
|
||||||
//printf("dhcp4 cookie %02x %02x %02x %02x\n", dhcp4_options[0], dhcp4_options[1], dhcp4_options[2], dhcp4_options[3]);
|
|
||||||
assert(dhcp4_options[0] == 0x63 &&
|
|
||||||
dhcp4_options[1] == 0x82 &&
|
|
||||||
dhcp4_options[2] == 0x53 &&
|
|
||||||
dhcp4_options[3] == 0x63);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// packet
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
p->eth = eth_header;
|
|
||||||
p->ip4 = ip4_header;
|
|
||||||
p->udp4 = udp4_header;
|
|
||||||
p->dhcp4 = dhcp4_message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
22
packet.h
22
packet.h
@ -1,22 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "eth.h"
|
|
||||||
#include "ip4.h"
|
|
||||||
#include "udp4.h"
|
|
||||||
#include "dhcp4.h"
|
|
||||||
|
|
||||||
namespace packet {
|
|
||||||
struct packet {
|
|
||||||
eth::header const * eth;
|
|
||||||
ip4::header const * ip4;
|
|
||||||
udp4::header const * udp4;
|
|
||||||
dhcp4::message const * dhcp4;
|
|
||||||
};
|
|
||||||
|
|
||||||
void parse(uint8_t const * buf, int length, packet * p);
|
|
||||||
|
|
||||||
const int eth_offset = 0;
|
|
||||||
const int ip4_offset = (sizeof (eth::header));
|
|
||||||
const int udp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header));
|
|
||||||
const int dhcp4_offset = (sizeof (eth::header)) + (sizeof (ip4::header)) + (sizeof (udp4::header));
|
|
||||||
};
|
|
||||||
263
rtnetlink.cpp
263
rtnetlink.cpp
@ -1,263 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <linux/netlink.h>
|
|
||||||
#include <linux/rtnetlink.h>
|
|
||||||
|
|
||||||
#include "rtnetlink.h"
|
|
||||||
|
|
||||||
static inline int align4(int len)
|
|
||||||
{
|
|
||||||
return (len + 3) & (~3);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct newaddr_msg {
|
|
||||||
struct nlmsghdr nl;
|
|
||||||
struct ifaddrmsg ifaddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct deladdr_msg {
|
|
||||||
struct nlmsghdr nl;
|
|
||||||
struct ifaddrmsg ifaddr;
|
|
||||||
struct {
|
|
||||||
struct rtattr rtattr;
|
|
||||||
uint32_t value;
|
|
||||||
} attr[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace rtnetlink {
|
|
||||||
|
|
||||||
bool parse_newaddr(uint8_t const * buf, ssize_t length,
|
|
||||||
uint32_t ifa_index,
|
|
||||||
newaddr * out, int out_length,
|
|
||||||
int & index)
|
|
||||||
{
|
|
||||||
uint8_t const * bufi = buf;
|
|
||||||
|
|
||||||
while (index < out_length) {
|
|
||||||
struct nlmsghdr * nl = (struct nlmsghdr *)&bufi[0];
|
|
||||||
struct ifaddrmsg * ifaddr = (struct ifaddrmsg *)&bufi[(sizeof (struct nlmsghdr))];
|
|
||||||
size_t rtattr_offset = (sizeof (struct nlmsghdr)) + (sizeof (struct ifaddrmsg));
|
|
||||||
|
|
||||||
assert((nl->nlmsg_flags & NLM_F_MULTI) == NLM_F_MULTI);
|
|
||||||
|
|
||||||
if (nl->nlmsg_type == NLMSG_DONE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(nl->nlmsg_type == RTM_NEWADDR);
|
|
||||||
|
|
||||||
out[index].ifa_prefixlen = ifaddr->ifa_prefixlen;
|
|
||||||
|
|
||||||
while (rtattr_offset < nl->nlmsg_len) {
|
|
||||||
struct rtattr * rtattr = (struct rtattr *)&bufi[rtattr_offset];
|
|
||||||
rtattr_offset += align4(rtattr->rta_len);
|
|
||||||
|
|
||||||
void * value = (void *)(((ptrdiff_t)rtattr) + (sizeof (struct rtattr)));
|
|
||||||
|
|
||||||
switch (rtattr->rta_type) {
|
|
||||||
case IFA_ADDRESS:
|
|
||||||
out[index].address = *((uint32_t *)value);
|
|
||||||
break;
|
|
||||||
case IFA_LOCAL:
|
|
||||||
out[index].local = *((uint32_t *)value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifaddr->ifa_index == ifa_index) {
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bufi = &bufi[nl->nlmsg_len];
|
|
||||||
if (bufi - buf == length) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int handle_getaddr(int fd, uint32_t ifa_index, newaddr * out, int out_length)
|
|
||||||
{
|
|
||||||
bool done = false;
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
while (!done) {
|
|
||||||
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
|
|
||||||
struct iovec iov[1] = {};
|
|
||||||
struct msghdr msg = {
|
|
||||||
.msg_name = (void *)&addr,
|
|
||||||
.msg_namelen = (sizeof (sockaddr_nl)),
|
|
||||||
.msg_iov = iov,
|
|
||||||
.msg_iovlen = 1,
|
|
||||||
.msg_flags = MSG_TRUNC,
|
|
||||||
};
|
|
||||||
ssize_t peek_length = recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC);
|
|
||||||
if (peek_length < 0) {
|
|
||||||
perror("recvmsg(MSG_PEEK|MSG_TRUNC)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t * buf = (uint8_t *)malloc(peek_length);
|
|
||||||
|
|
||||||
iov[0].iov_base = buf;
|
|
||||||
iov[0].iov_len = peek_length;
|
|
||||||
msg.msg_flags = 0;
|
|
||||||
ssize_t length = recvmsg(fd, &msg, 0);
|
|
||||||
if (length < 0) {
|
|
||||||
perror("recvmsg");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
assert(peek_length == length);
|
|
||||||
|
|
||||||
done = parse_newaddr(buf, length, ifa_index, out, out_length, index);
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
int send_getaddr(int fd, uint32_t ifa_index)
|
|
||||||
{
|
|
||||||
const size_t message_length = (sizeof (struct newaddr_msg));
|
|
||||||
|
|
||||||
struct newaddr_msg rtmmsg = {
|
|
||||||
.nl = {
|
|
||||||
.nlmsg_len = message_length,
|
|
||||||
.nlmsg_type = RTM_GETADDR,
|
|
||||||
.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
|
|
||||||
.nlmsg_seq = 1234,
|
|
||||||
},
|
|
||||||
.ifaddr = {
|
|
||||||
.ifa_family = AF_INET,
|
|
||||||
.ifa_scope = RT_SCOPE_UNIVERSE,
|
|
||||||
.ifa_index = 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 send_typeaddr(int fd, uint16_t nlmsg_type, uint32_t ifa_index, uint8_t ifa_prefixlen, uint32_t local, uint32_t address)
|
|
||||||
{
|
|
||||||
const size_t message_length = (sizeof (struct deladdr_msg));
|
|
||||||
|
|
||||||
struct deladdr_msg rtmmsg = {
|
|
||||||
.nl = {
|
|
||||||
.nlmsg_len = message_length,
|
|
||||||
.nlmsg_type = nlmsg_type,
|
|
||||||
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
|
|
||||||
.nlmsg_seq = 12345,
|
|
||||||
},
|
|
||||||
.ifaddr = {
|
|
||||||
.ifa_family = AF_INET,
|
|
||||||
.ifa_prefixlen = ifa_prefixlen,
|
|
||||||
.ifa_scope = RT_SCOPE_UNIVERSE,
|
|
||||||
.ifa_index = ifa_index,
|
|
||||||
},
|
|
||||||
.attr = {
|
|
||||||
{
|
|
||||||
.rtattr = { .rta_len = 8, .rta_type = IFA_LOCAL },
|
|
||||||
.value = local,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rtattr = { .rta_len = 8, .rta_type = IFA_ADDRESS },
|
|
||||||
.value = address,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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 };
|
|
||||||
struct iovec iov[1] = {};
|
|
||||||
struct msghdr msg = {
|
|
||||||
.msg_name = (void *)&addr,
|
|
||||||
.msg_namelen = (sizeof (sockaddr_nl)),
|
|
||||||
.msg_iov = iov,
|
|
||||||
.msg_iovlen = 1,
|
|
||||||
.msg_flags = MSG_TRUNC,
|
|
||||||
};
|
|
||||||
ssize_t peek_length = recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC);
|
|
||||||
if (peek_length < 0) {
|
|
||||||
perror("recvmsg(MSG_PEEK|MSG_TRUNC)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t * buf = (uint8_t *)malloc(peek_length);
|
|
||||||
|
|
||||||
iov[0].iov_base = buf;
|
|
||||||
iov[0].iov_len = peek_length;
|
|
||||||
msg.msg_flags = 0;
|
|
||||||
ssize_t length = recvmsg(fd, &msg, 0);
|
|
||||||
if (length < 0) {
|
|
||||||
perror("recvmsg");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
assert(peek_length == length);
|
|
||||||
|
|
||||||
struct nlmsghdr * nl = (struct nlmsghdr *)&buf[0];
|
|
||||||
struct nlmsgerr * msgerr = (struct nlmsgerr *)&buf[(sizeof (struct nlmsghdr))];
|
|
||||||
|
|
||||||
assert(nl->nlmsg_type == NLMSG_ERROR);
|
|
||||||
if (msgerr->error < 0) {
|
|
||||||
printf("msgerr %d %s\n", msgerr->error, strerror(-msgerr->error));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
23
rtnetlink.h
23
rtnetlink.h
@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace rtnetlink {
|
|
||||||
|
|
||||||
struct newaddr {
|
|
||||||
uint32_t address;
|
|
||||||
uint32_t local;
|
|
||||||
uint32_t ifa_prefixlen;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool parse_newaddr(uint8_t const * buf, ssize_t length,
|
|
||||||
uint32_t ifa_index,
|
|
||||||
newaddr * out, int out_length,
|
|
||||||
int & index);
|
|
||||||
|
|
||||||
int handle_getaddr(int fd, uint32_t ifa_index, newaddr * out, int out_length);
|
|
||||||
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 handle_error(int fd);
|
|
||||||
}
|
|
||||||
16
test.cpp
16
test.cpp
@ -5,7 +5,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "udp4.h"
|
#include "udp4.h"
|
||||||
#include "ip4.h"
|
#include "ipv4.h"
|
||||||
#include "dhcp4.h"
|
#include "dhcp4.h"
|
||||||
|
|
||||||
void dump_hex(void const * src, int length)
|
void dump_hex(void const * src, int length)
|
||||||
@ -32,16 +32,16 @@ int main()
|
|||||||
inet_aton("192.168.1.1", &srcA);
|
inet_aton("192.168.1.1", &srcA);
|
||||||
inet_aton("192.168.1.240", &dstA);
|
inet_aton("192.168.1.240", &dstA);
|
||||||
|
|
||||||
int ip4_payload_length = (sizeof (payload)) + (sizeof (udp4::header));
|
int ipv4_payload_length = (sizeof (payload)) + (sizeof (udp4::header));
|
||||||
int ip4_identification = 55179;
|
int ipv4_identification = 55179;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
ip4::header * ip4_header = ip4::make_header(reinterpret_cast<void *>(&buf[offset]),
|
ipv4::header * ipv4_header = ipv4::make_header(reinterpret_cast<void *>(&buf[offset]),
|
||||||
ip4_payload_length,
|
ipv4_payload_length,
|
||||||
ip4_identification,
|
ipv4_identification,
|
||||||
srcA.s_addr,
|
srcA.s_addr,
|
||||||
dstA.s_addr);
|
dstA.s_addr);
|
||||||
offset += (sizeof (ip4::header));
|
offset += (sizeof (ipv4::header));
|
||||||
dump_hex(ip4_header, (sizeof (ip4::header)));
|
dump_hex(ipv4_header, (sizeof (ipv4::header)));
|
||||||
|
|
||||||
udp4::header * udp4_header = udp4::make_header(reinterpret_cast<void *>(&buf[offset]),
|
udp4::header * udp4_header = udp4::make_header(reinterpret_cast<void *>(&buf[offset]),
|
||||||
htons(67),
|
htons(67),
|
||||||
|
|||||||
31
test2.cpp
31
test2.cpp
@ -1,31 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include "packet.h"
|
|
||||||
|
|
||||||
unsigned char bytes[] = {0xf4, 0x7b, 0x9, 0x99, 0x3e, 0x28, 0x0, 0xbc, 0x2f, 0x8c, 0x58, 0x20, 0x8, 0x0, 0x45, 0xb8, 0x1, 0x6f, 0x48, 0x9d, 0x0, 0x0, 0x40, 0x11, 0xab, 0xe7, 0xc0, 0xa8, 0x1, 0x1, 0xc0, 0xa8, 0x1, 0xf0, 0x0, 0x43, 0x0, 0x44, 0x1, 0x5b, 0xe6, 0xe6, 0x2, 0x1, 0x6, 0x0, 0x99, 0x87, 0x50, 0x1a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0xa8, 0x1, 0xf0, 0xc0, 0xa8, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0xf4, 0x7b, 0x9, 0x99, 0x3e, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x63, 0x82, 0x53, 0x63, 0x35, 0x1, 0x2, 0x36, 0x4, 0xc0, 0xa8, 0x1, 0x1, 0x33, 0x4, 0x0, 0x1, 0x51, 0x80, 0x3a, 0x4, 0x0, 0x0, 0xa8, 0xc0, 0x3b, 0x4, 0x0, 0x1, 0x27, 0x50, 0x1c, 0x4, 0xc0, 0xa8, 0x1, 0xff, 0x3, 0x4, 0xc0, 0xa8, 0x1, 0x1, 0xf, 0x3, 0x6c, 0x61, 0x6e, 0x1, 0x4, 0xff, 0xff, 0xff, 0x0, 0x6, 0x4, 0xc0, 0xa8, 0x1, 0x1, 0x7d, 0x28, 0x0, 0x0, 0xd, 0xe9, 0x23, 0x6, 0x8, 0x47, 0x52, 0x42, 0x45, 0x33, 0x33, 0x31, 0x43, 0x5, 0xf, 0x52, 0x30, 0x31, 0x43, 0x31, 0x4d, 0x32, 0x35, 0x34, 0x36, 0x30, 0x30, 0x32, 0x48, 0x45, 0x4, 0x6, 0x30, 0x30, 0x30, 0x46, 0x42, 0x33, 0xff};
|
|
||||||
|
|
||||||
void parse_packet(uint8_t const * buf, int length)
|
|
||||||
{
|
|
||||||
packet::packet p;
|
|
||||||
packet::parse(buf, length, &p);
|
|
||||||
|
|
||||||
printf("dhcp4 op: %d\n", p.dhcp4->op);
|
|
||||||
printf("dhcp4 yiaddr: %s\n", ip4::tostr(p.dhcp4->yiaddr));
|
|
||||||
|
|
||||||
int dhcp4_options_length = length - (packet::dhcp4_offset + (offsetof (dhcp4::message, options)));
|
|
||||||
dhcp4::options 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
parse_packet(bytes, (sizeof (bytes)));
|
|
||||||
}
|
|
||||||
14
udp4.cpp
14
udp4.cpp
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "ip4.h"
|
#include "ipv4.h"
|
||||||
#include "udp4.h"
|
#include "udp4.h"
|
||||||
|
|
||||||
namespace udp4 {
|
namespace udp4 {
|
||||||
@ -22,19 +22,19 @@ namespace udp4 {
|
|||||||
hdr->destination_port = destination_port;
|
hdr->destination_port = destination_port;
|
||||||
hdr->length = htons(payload_length + (sizeof (header)));
|
hdr->length = htons(payload_length + (sizeof (header)));
|
||||||
|
|
||||||
ip4_psuedo_header phdr;
|
ipv4_psuedo_header phdr;
|
||||||
phdr.source_address = source_address;
|
phdr.source_address = source_address;
|
||||||
phdr.destination_address = destination_address;
|
phdr.destination_address = destination_address;
|
||||||
phdr.zeros = 0;
|
phdr.zeros = 0;
|
||||||
phdr.protocol = ip4::protocol::udp;
|
phdr.protocol = ipv4::protocol::udp;
|
||||||
phdr.udp_length = hdr->length; // already big endian
|
phdr.udp_length = hdr->length; // already big endian
|
||||||
|
|
||||||
uint32_t sum = 0;
|
uint32_t sum = 0;
|
||||||
sum = ip4::checksum_partial(sum, reinterpret_cast<void const *>(&phdr), (sizeof (ip4_psuedo_header)));
|
sum = ipv4::checksum_partial(sum, reinterpret_cast<void const *>(&phdr), (sizeof (ipv4_psuedo_header)));
|
||||||
sum = ip4::checksum_partial(sum, reinterpret_cast<void const *>(hdr), (sizeof (header)));
|
sum = ipv4::checksum_partial(sum, reinterpret_cast<void const *>(hdr), (sizeof (header)));
|
||||||
sum = ip4::checksum_partial(sum, reinterpret_cast<void const *>(payload), payload_length);
|
sum = ipv4::checksum_partial(sum, reinterpret_cast<void const *>(payload), payload_length);
|
||||||
|
|
||||||
hdr->checksum = htons(ip4::checksum_finish(sum));
|
hdr->checksum = htons(ipv4::checksum_finish(sum));
|
||||||
|
|
||||||
return hdr;
|
return hdr;
|
||||||
}
|
}
|
||||||
|
|||||||
4
udp4.h
4
udp4.h
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "ip4.h"
|
#include "ipv4.h"
|
||||||
|
|
||||||
namespace udp4 {
|
namespace udp4 {
|
||||||
struct header {
|
struct header {
|
||||||
@ -14,7 +14,7 @@ namespace udp4 {
|
|||||||
|
|
||||||
static_assert((sizeof (header)) == 8);
|
static_assert((sizeof (header)) == 8);
|
||||||
|
|
||||||
struct ip4_psuedo_header {
|
struct ipv4_psuedo_header {
|
||||||
uint32_t source_address;
|
uint32_t source_address;
|
||||||
uint32_t destination_address;
|
uint32_t destination_address;
|
||||||
uint8_t zeros;
|
uint8_t zeros;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user