quinn-os/ether.c
2022-07-03 17:59:27 +10:00

144 lines
3.2 KiB
C

#include "pvec.h"
#include "arp.h"
#include "ether.h"
#include "ipv4.h"
#include "i825xx.h"
#include "memory.h"
#include "virtio.h"
struct ipv4_header_t {
unsigned char vhl;
unsigned char tos;
unsigned short len;
unsigned short ipid;
unsigned short ipoffset;
unsigned char ttl;
unsigned char protocol;
unsigned short chksum;
unsigned int src_addr;
unsigned int dest_addr;
unsigned char payload[];
} __attribute__((packed));
struct ptr_vector ether_devs;
static int add_ether(struct ether_t *card) {
ptr_vector_append(&ether_devs, card);
return 1;
}
int ether_send(struct ether_t *card, char *packet, int len) {
int sr;
if (card->type == 1) {
sr = i825xx_send((struct i825xx_device_t *)card->data, packet, len);
return sr;
}
if (card->type == 2) {
sr = virtnet_send((struct virtio_device_info *)card->data, packet, len);
return sr;
}
return -1;
}
int ether_receive(struct ether_t *ether, unsigned char *packet, int len) {
struct ether_packet_t *p = (struct ether_packet_t *)packet;
if (htons(p->ethertype) == 0x806) {
if (!(len - 14 < sizeof(struct arp_packet_t))) {
arp_process_packet(ether, (struct arp_packet_t *)(p->payload));
}
} else if (htons(p->ethertype) == 0x800) {
arp_update_ipv4(ether, p->sourcemac, htonl(((struct ipv4_header_t *)(p->payload))->src_addr));
ipv4_process_packet(ether, (char *)(p->payload), len - sizeof(struct ether_packet_t));
} else {
// kprintf("OTHER %x\n", htons(p->ethertype));
}
return 0;
}
int ether_get_mac(int ether, unsigned char *dest) {
struct ether_t *card = ptr_vector_get(&ether_devs, ether);
if (card == NULL) {
return -1;
}
dest[0] = card->mac[0];
dest[1] = card->mac[1];
dest[2] = card->mac[2];
dest[3] = card->mac[3];
dest[4] = card->mac[4];
dest[5] = card->mac[5];
return 0;
}
int ether_enable(int ether, unsigned int ipv4, unsigned int mask) {
struct ether_t *card = ptr_vector_get(&ether_devs, ether);
if (card == NULL) {
return -1;
}
card->ipv4 = ipv4;
card->mask = mask;
if (card->arp_initialized == 0) {
init_arp(card);
}
if (card->state == 0) {
if (card->type == 1) {
i825xx_enable(card);
}
if (card->type == 2) {
virtnet_enable(card);
}
}
return card->state;
}
int ether_add_default_gw(int ether, unsigned int ipv4) {
struct ether_t *card = ptr_vector_get(&ether_devs, ether);
if (card == NULL) {
return -1;
}
card->default_gw = ipv4;
return 0;
}
struct ether_t *ether_find_from_ipv4(unsigned int ipv4) {
int i;
struct ether_t *card;
for (i = 0; i < ptr_vector_len(&ether_devs); i++) {
card = ptr_vector_get(&ether_devs, i);
if (card->ipv4 == 0) continue;
if ((ipv4 & card->mask) == (card->ipv4 & card->mask) || card->default_gw != 0) {
return card;
}
}
return NULL;
}
void init_ether() {
struct ether_t *ether;
int count;
init_ptr_vector(&ether_devs);
count = 0;
ether = init_i825xx(count);
while (ether != (void *)0) {
add_ether(ether);
count++;
ether = init_i825xx(count);
}
count = 0;
ether = init_virtnet(count);
while (ether != (void *)0) {
add_ether(ether);
count++;
ether = init_virtnet(count);
}
}