144 lines
3.2 KiB
C
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(ðer_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(ðer_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(ðer_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(ðer_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(ðer_devs); i++) {
|
|
card = ptr_vector_get(ðer_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(ðer_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);
|
|
}
|
|
}
|