Skip to content
This repository has been archived by the owner on May 31, 2021. It is now read-only.

Commit

Permalink
Hook this temporary interface up for polling
Browse files Browse the repository at this point in the history
  • Loading branch information
klange committed May 30, 2021
1 parent ec86339 commit bb61177
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 62 deletions.
165 changes: 103 additions & 62 deletions apps/dhcp_bitbanger.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

Expand All @@ -10,7 +12,7 @@ struct ethernet_packet {
uint8_t source[6];
uint16_t type;
uint8_t payload[];
} __attribute__((packed));
} __attribute__((packed)) __attribute__((aligned(2)));

struct ipv4_packet {
uint8_t version_ihl;
Expand All @@ -24,15 +26,15 @@ struct ipv4_packet {
uint32_t source;
uint32_t destination;
uint8_t payload[];
} __attribute__ ((packed));
} __attribute__ ((packed)) __attribute__((aligned(2)));

struct udp_packet {
uint16_t source_port;
uint16_t destination_port;
uint16_t length;
uint16_t checksum;
uint8_t payload[];
} __attribute__ ((packed));
} __attribute__ ((packed)) __attribute__((aligned(2)));

struct dhcp_packet {
uint8_t op;
Expand All @@ -58,7 +60,7 @@ struct dhcp_packet {
uint32_t magic;

uint8_t options[];
} __attribute__ ((packed));
} __attribute__ ((packed)) __attribute__((aligned(2)));

struct dns_packet {
uint16_t qid;
Expand All @@ -68,7 +70,7 @@ struct dns_packet {
uint16_t authorities;
uint16_t additional;
uint8_t data[];
} __attribute__ ((packed));
} __attribute__ ((packed)) __attribute__((aligned(2)));

struct tcp_header {
uint16_t source_port;
Expand All @@ -83,7 +85,7 @@ struct tcp_header {
uint16_t urgent;

uint8_t payload[];
} __attribute__((packed));
} __attribute__((packed)) __attribute__((aligned(2)));

struct tcp_check_header {
uint32_t source;
Expand Down Expand Up @@ -135,6 +137,60 @@ struct payload {
uint8_t payload[32];
};

static void eth_ntoa(const uint8_t addr[6], char * out) {
/* XX:XX:XX:XX:XX:XX */
snprintf(out, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5]);
}

static void ip_ntoa(const uint32_t src_addr, char * out) {
snprintf(out, 16, "%d.%d.%d.%d",
(src_addr & 0xFF000000) >> 24,
(src_addr & 0xFF0000) >> 16,
(src_addr & 0xFF00) >> 8,
(src_addr & 0xFF));
}

static const char * eth_type_str(uint16_t type) {
switch(type) {
case ETHERNET_TYPE_IPV4: return "IPv4";
case ETHERNET_TYPE_ARP: return "ARP";
default: return "unknown";
}
}

static void print_ipv4_header(struct ipv4_packet * packet) {
/* get addresses, type... */
char dest_addr[16];
char src_addr[16];
ip_ntoa(ntohl(packet->destination), dest_addr);
ip_ntoa(ntohl(packet->source), src_addr);
fprintf(stderr, "%s -> %s %d (%s) ",
src_addr, dest_addr, packet->protocol,
packet->protocol == IPV4_PROT_UDP ? "udp" :
packet->protocol == IPV4_PROT_TCP ? "tcp" : "?");
}

void print_header(const struct payload * header) {
/* Assume it's at least an Ethernet frame */
char dest_addr[18];
char src_addr[18];
eth_ntoa(header->eth_header.destination, dest_addr);
eth_ntoa(header->eth_header.source, src_addr);
fprintf(stderr, "%s -> %s %d (%s) ",
src_addr, dest_addr, ntohs(header->eth_header.type), eth_type_str(ntohs(header->eth_header.type)));
switch (ntohs(header->eth_header.type)) {
case ETHERNET_TYPE_IPV4:
print_ipv4_header((void*)&header->eth_header.payload);
break;
case ETHERNET_TYPE_ARP:
//print_arp_header(&header->eth_header.payload);
break;
}
fprintf(stderr, "\n");
}

uint16_t calculate_ipv4_checksum(struct ipv4_packet * p) {
uint32_t sum = 0;
uint16_t * s = (uint16_t *)p;
Expand All @@ -151,14 +207,6 @@ uint16_t calculate_ipv4_checksum(struct ipv4_packet * p) {
return ~(sum & 0xFFFF) & 0xFFFF;
}

void ip_ntoa(uint32_t src_addr, char * out) {
sprintf(out, "%d.%d.%d.%d",
(src_addr & 0xFF000000) >> 24,
(src_addr & 0xFF0000) >> 16,
(src_addr & 0xFF00) >> 8,
(src_addr & 0xFF));
}

uint8_t mac_addr[6];

void fill(struct payload *it, size_t payload_size) {
Expand Down Expand Up @@ -221,12 +269,14 @@ void fill(struct payload *it, size_t payload_size) {

int main(int argc, char * argv[]) {

#if 0
/* Let's make a socket. */
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
//if (sockfd < 0) { perror("socket"); return 1; }
if (sockfd < 0) { perror("socket"); return 1; }

/* Bind the socket to the requested device. */
//if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
#endif

char * if_name = "enp0s4";
char if_path[100];
Expand Down Expand Up @@ -262,50 +312,19 @@ int main(int argc, char * argv[]) {
}

uint32_t yiaddr;
int stage = 1;

do {
char buf[8092] = {0};
ssize_t rsize = read(netdev, &buf, 8092);

if (rsize <= 0) {
printf("bad size? %zd\n", rsize);
struct pollfd fds[1];
fds[0].fd = netdev;
fds[0].events = POLLIN;
int ret = poll(fds,1,2000);
if (ret <= 0) {
printf("...\n");
continue;
}

struct payload * response = (void*)buf;

if (ntohs(response->udp_header.destination_port) != 68) {
printf("not what I was expecting\n");
continue;
}

yiaddr = response->dhcp_header.yiaddr;
char yiaddr_ip[16];
ip_ntoa(ntohl(yiaddr), yiaddr_ip);

printf("Response from DHCP Discover: %s\n", yiaddr_ip);

break;
} while (1);

{
printf("Writing request\n");
struct payload thething = {
.payload = {53,1,3,50,4,
(yiaddr) & 0xFF,
(yiaddr >> 8) & 0xFF,
(yiaddr >> 16) & 0xFF,
(yiaddr >> 24) & 0xFF,
55,2,3,6,255,0}
};

fill(&thething, 14);

write(netdev, &thething, sizeof(struct payload));
}

do {
char buf[8092] = {0};
ssize_t rsize = read(netdev, &buf, 8092);

if (rsize <= 0) {
Expand All @@ -315,19 +334,41 @@ int main(int argc, char * argv[]) {

struct payload * response = (void*)buf;

print_header(response);

if (ntohs(response->udp_header.destination_port) != 68) {
printf("not what I was expecting\n");
continue;
}

yiaddr = response->dhcp_header.yiaddr;
char yiaddr_ip[16];
ip_ntoa(ntohl(yiaddr), yiaddr_ip);

printf("ACK returns: %s\n", yiaddr_ip);

break;
if (stage == 1) {
yiaddr = response->dhcp_header.yiaddr;
char yiaddr_ip[16];
ip_ntoa(ntohl(yiaddr), yiaddr_ip);

printf("Response from DHCP Discover: %s\n", yiaddr_ip);
struct payload thething = {
.payload = {53,1,3,50,4,
(yiaddr) & 0xFF,
(yiaddr >> 8) & 0xFF,
(yiaddr >> 16) & 0xFF,
(yiaddr >> 24) & 0xFF,
55,2,3,6,255,0}
};

fill(&thething, 14);
write(netdev, &thething, sizeof(struct payload));

stage = 2;
} else if (stage == 2) {
yiaddr = response->dhcp_header.yiaddr;
char yiaddr_ip[16];
ip_ntoa(ntohl(yiaddr), yiaddr_ip);

printf("ACK returns: %s\n", yiaddr_ip);
printf("Address is configured, continuing trace mode.\n");

stage = 3;
}
} while (1);

return 0;
}
35 changes: 35 additions & 0 deletions kernel/net/e1000.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ struct e1000_nic {
int link_status;

spin_lock_t net_queue_lock;
spin_lock_t alert_lock;
list_t * net_queue;
list_t * rx_wait;
list_t * alert_wait;

uint8_t * rx_virt[E1000_NUM_RX_DESC];
uint8_t * tx_virt[E1000_NUM_TX_DESC];
Expand Down Expand Up @@ -157,6 +159,19 @@ static void read_mac(struct e1000_nic * device) {
}
}

static void e1000_alert_waiters(struct e1000_nic * nic) {
spin_lock(nic->alert_lock);
while (nic->alert_wait->head) {
node_t * node = list_dequeue(nic->alert_wait);
process_t * p = node->value;
free(node);
spin_unlock(nic->alert_lock);
process_alert_node(p, nic->device_node);
spin_lock(nic->alert_lock);
}
spin_unlock(nic->alert_lock);
}

static void e1000_handle(struct e1000_nic * nic, uint32_t status) {
if (status & ICR_LSC) {
/* TODO: Change interface link status. */
Expand Down Expand Up @@ -194,6 +209,7 @@ static void e1000_handle(struct e1000_nic * nic, uint32_t status) {
}
} while (1);
wakeup_queue(nic->rx_wait);
e1000_alert_waiters(nic);
}
}

Expand Down Expand Up @@ -296,6 +312,22 @@ static uint64_t read_e1000(fs_node_t *node, uint64_t offset, uint64_t size, uint
return 8092;
}

static int check_e1000(fs_node_t *node) {
struct e1000_nic * nic = node->device;
return nic->net_queue->head ? 0 : 1;
}

static int wait_e1000(fs_node_t *node, void * process) {
struct e1000_nic * nic = node->device;
spin_lock(nic->alert_lock);
if (!list_find(nic->alert_wait, process)) {
list_insert(nic->alert_wait, process);
}
list_insert(((process_t *)process)->node_waits, nic->device_node);
spin_unlock(nic->alert_lock);
return 0;
}

static void e1000_init(void * data) {
struct e1000_nic * nic = data;
uint32_t e1000_device_pci = nic->pci_device;
Expand Down Expand Up @@ -388,6 +420,7 @@ static void e1000_init(void * data) {

nic->net_queue = list_create("e1000 net queue", nic);
nic->rx_wait = list_create("e1000 rx sem", nic);
nic->alert_wait = list_create("e1000 select waiters", nic);

nic->irq_number = pci_get_interrupt(e1000_device_pci);

Expand Down Expand Up @@ -419,6 +452,8 @@ static void e1000_init(void * data) {
nic->device_node->ioctl = ioctl_e1000;
nic->device_node->write = write_e1000;
nic->device_node->read = read_e1000;
nic->device_node->selectcheck = check_e1000;
nic->device_node->selectwait = wait_e1000;
nic->device_node->device = nic;

char tmp[100];
Expand Down

0 comments on commit bb61177

Please sign in to comment.