net: initial raw socket implementation
This commit is contained in:
parent
27229eefc4
commit
edc06e5f0c
@ -238,7 +238,6 @@ static void time_diff(struct timeval *start, struct timeval *end, time_t *sec_di
|
|||||||
extern char * _argv_0;
|
extern char * _argv_0;
|
||||||
|
|
||||||
static int configure_interface(const char * if_name) {
|
static int configure_interface(const char * if_name) {
|
||||||
#if 0
|
|
||||||
/* Open a raw socket. */
|
/* Open a raw socket. */
|
||||||
int sock = socket(AF_RAW, SOCK_RAW, 0);
|
int sock = socket(AF_RAW, SOCK_RAW, 0);
|
||||||
if (!sock) {
|
if (!sock) {
|
||||||
@ -253,7 +252,6 @@ static int configure_interface(const char * if_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Request the mac address */
|
/* Request the mac address */
|
||||||
#endif
|
|
||||||
char if_path[100];
|
char if_path[100];
|
||||||
snprintf(if_path, 100, "/dev/net/%s", if_name);
|
snprintf(if_path, 100, "/dev/net/%s", if_name);
|
||||||
int netdev = open(if_path, O_RDWR);
|
int netdev = open(if_path, O_RDWR);
|
||||||
@ -281,7 +279,7 @@ static int configure_interface(const char * if_name) {
|
|||||||
|
|
||||||
fill(&thething, 8);
|
fill(&thething, 8);
|
||||||
|
|
||||||
write(netdev, &thething, sizeof(struct payload));
|
send(sock, &thething, sizeof(struct payload), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t yiaddr;
|
uint32_t yiaddr;
|
||||||
@ -299,19 +297,23 @@ static int configure_interface(const char * if_name) {
|
|||||||
|
|
||||||
gettimeofday(&end, NULL);
|
gettimeofday(&end, NULL);
|
||||||
time_diff(&start,&end,&sec_diff,&usec_diff);
|
time_diff(&start,&end,&sec_diff,&usec_diff);
|
||||||
if (sec_diff > 3) {
|
if (sec_diff > 0 || usec_diff > 500000) {
|
||||||
close(netdev);
|
close(netdev);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pollfd fds[1];
|
struct pollfd fds[1];
|
||||||
fds[0].fd = netdev;
|
fds[0].fd = sock;
|
||||||
fds[0].events = POLLIN;
|
fds[0].events = POLLIN;
|
||||||
int ret = poll(fds,1,2000);
|
int ret = poll(fds,1,200);
|
||||||
if (ret <= 0) {
|
if (ret == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ssize_t rsize = read(netdev, &buf, 8092);
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "poll: failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ssize_t rsize = recv(sock, &buf, 8092, 0);
|
||||||
|
|
||||||
if (rsize <= 0) {
|
if (rsize <= 0) {
|
||||||
fprintf(stderr, "%s: %s: bad size? %zd\n", _argv_0, if_name, rsize);
|
fprintf(stderr, "%s: %s: bad size? %zd\n", _argv_0, if_name, rsize);
|
||||||
@ -347,7 +349,7 @@ static int configure_interface(const char * if_name) {
|
|||||||
55,2,3,6,255,0}
|
55,2,3,6,255,0}
|
||||||
};
|
};
|
||||||
fill(&thething, 14);
|
fill(&thething, 14);
|
||||||
write(netdev, &thething, sizeof(struct payload));
|
send(sock, &thething, sizeof(struct payload), 0);
|
||||||
stage = 2;
|
stage = 2;
|
||||||
} else if (stage == 2) {
|
} else if (stage == 2) {
|
||||||
yiaddr = response->dhcp_header.yiaddr;
|
yiaddr = response->dhcp_header.yiaddr;
|
||||||
@ -391,6 +393,7 @@ static int configure_interface(const char * if_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
close(netdev);
|
close(netdev);
|
||||||
|
close(sock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
|
22
base/usr/include/kernel/net/eth.h
Normal file
22
base/usr/include/kernel/net/eth.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/vfs.h>
|
||||||
|
#include <kernel/mod/net.h>
|
||||||
|
|
||||||
|
void net_eth_handle(struct ethernet_packet * frame, fs_node_t * nic);
|
||||||
|
|
||||||
|
struct EthernetDevice {
|
||||||
|
char if_name[32];
|
||||||
|
uint8_t mac[6];
|
||||||
|
|
||||||
|
size_t mtu;
|
||||||
|
|
||||||
|
/* XXX: just to get things going */
|
||||||
|
uint32_t ipv4_addr;
|
||||||
|
uint32_t ipv4_subnet;
|
||||||
|
|
||||||
|
uint8_t ipv6_addr[16];
|
||||||
|
/* TODO: Address lists? */
|
||||||
|
|
||||||
|
fs_node_t * device_node;
|
||||||
|
};
|
@ -1,5 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/vfs.h>
|
#include <kernel/vfs.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#define htonl(l) ( (((l) & 0xFF) << 24) | (((l) & 0xFF00) << 8) | (((l) & 0xFF0000) >> 8) | (((l) & 0xFF000000) >> 24))
|
||||||
|
#define htons(s) ( (((s) & 0xFF) << 8) | (((s) & 0xFF00) >> 8) )
|
||||||
|
#define ntohl(l) htonl((l))
|
||||||
|
#define ntohs(s) htons((s))
|
||||||
|
|
||||||
int net_add_interface(const char * name, fs_node_t * deviceNode);
|
int net_add_interface(const char * name, fs_node_t * deviceNode);
|
||||||
|
fs_node_t * net_if_lookup(const char * name);
|
||||||
|
|
||||||
|
typedef struct SockData {
|
||||||
|
fs_node_t _fnode;
|
||||||
|
spin_lock_t alert_lock;
|
||||||
|
spin_lock_t rx_lock;
|
||||||
|
list_t * alert_wait;
|
||||||
|
list_t * rx_wait;
|
||||||
|
list_t * rx_queue;
|
||||||
|
|
||||||
|
long (*sock_recv)(struct SockData * sock, struct msghdr * msg, int flags);
|
||||||
|
long (*sock_send)(struct SockData * sock, const struct msghdr *msg, int flags);
|
||||||
|
void (*sock_close)(struct SockData * sock);
|
||||||
|
} sock_t;
|
||||||
|
|
||||||
|
void net_sock_alert(sock_t * sock);
|
||||||
|
void net_sock_add(sock_t * sock, void * frame);
|
||||||
|
void * net_sock_get(sock_t * sock);
|
||||||
|
sock_t * net_sock_create(void);
|
||||||
|
@ -22,6 +22,8 @@ _Begin_C_Header
|
|||||||
#define SO_KEEPALIVE 1
|
#define SO_KEEPALIVE 1
|
||||||
#define SO_REUSEADDR 2
|
#define SO_REUSEADDR 2
|
||||||
|
|
||||||
|
#define SO_BINDTODEVICE 3
|
||||||
|
|
||||||
struct hostent {
|
struct hostent {
|
||||||
char *h_name; /* official name of host */
|
char *h_name; /* official name of host */
|
||||||
char **h_aliases; /* alias list */
|
char **h_aliases; /* alias list */
|
||||||
@ -30,8 +32,6 @@ struct hostent {
|
|||||||
char **h_addr_list; /* list of addresses */
|
char **h_addr_list; /* list of addresses */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct hostent * gethostbyname(const char * name);
|
|
||||||
|
|
||||||
typedef size_t socklen_t;
|
typedef size_t socklen_t;
|
||||||
|
|
||||||
struct sockaddr {
|
struct sockaddr {
|
||||||
@ -84,6 +84,9 @@ struct sockaddr_storage {
|
|||||||
typedef uint32_t in_addr_t;
|
typedef uint32_t in_addr_t;
|
||||||
typedef uint16_t in_port_t;
|
typedef uint16_t in_port_t;
|
||||||
|
|
||||||
|
#ifndef _KERNEL_
|
||||||
|
extern struct hostent * gethostbyname(const char * name);
|
||||||
|
|
||||||
extern ssize_t recv(int sockfd, void *buf, size_t len, int flags);
|
extern ssize_t recv(int sockfd, void *buf, size_t len, int flags);
|
||||||
extern ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
|
extern ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
|
||||||
extern ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
|
extern ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
|
||||||
@ -110,6 +113,7 @@ extern int setsockopt(int sockfd, int level, int optname, const void *optval, so
|
|||||||
|
|
||||||
extern int connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen);
|
extern int connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen);
|
||||||
extern int shutdown(int sockfd, int how);
|
extern int shutdown(int sockfd, int how);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IFF_UP 0x0001
|
#define IFF_UP 0x0001
|
||||||
#define IFF_BROADCAST 0x0002
|
#define IFF_BROADCAST 0x0002
|
||||||
|
@ -56,6 +56,7 @@ struct e1000_nic {
|
|||||||
|
|
||||||
spin_lock_t net_queue_lock;
|
spin_lock_t net_queue_lock;
|
||||||
spin_lock_t alert_lock;
|
spin_lock_t alert_lock;
|
||||||
|
spin_lock_t tx_lock;
|
||||||
list_t * net_queue;
|
list_t * net_queue;
|
||||||
list_t * rx_wait;
|
list_t * rx_wait;
|
||||||
list_t * alert_wait;
|
list_t * alert_wait;
|
||||||
@ -247,6 +248,7 @@ static int irq_handler(struct regs *r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void send_packet(struct e1000_nic * device, uint8_t* payload, size_t payload_size) {
|
static void send_packet(struct e1000_nic * device, uint8_t* payload, size_t payload_size) {
|
||||||
|
spin_lock(device->tx_lock);
|
||||||
device->tx_index = read_command(device, E1000_REG_TXDESCTAIL);
|
device->tx_index = read_command(device, E1000_REG_TXDESCTAIL);
|
||||||
|
|
||||||
memcpy(device->tx_virt[device->tx_index], payload, payload_size);
|
memcpy(device->tx_virt[device->tx_index], payload, payload_size);
|
||||||
@ -256,6 +258,7 @@ static void send_packet(struct e1000_nic * device, uint8_t* payload, size_t payl
|
|||||||
|
|
||||||
device->tx_index = (device->tx_index + 1) % E1000_NUM_TX_DESC;
|
device->tx_index = (device->tx_index + 1) % E1000_NUM_TX_DESC;
|
||||||
write_command(device, E1000_REG_TXDESCTAIL, device->tx_index);
|
write_command(device, E1000_REG_TXDESCTAIL, device->tx_index);
|
||||||
|
spin_unlock(device->tx_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_rx(struct e1000_nic * device) {
|
static void init_rx(struct e1000_nic * device) {
|
||||||
@ -354,6 +357,12 @@ static int ioctl_e1000(fs_node_t * node, unsigned long request, void * argp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void write_packet(fs_node_t * node, uint8_t * buffer, size_t len) {
|
||||||
|
struct e1000_nic * nic = node->device;
|
||||||
|
/* write packet */
|
||||||
|
send_packet(nic, buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t write_e1000(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) {
|
static ssize_t write_e1000(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) {
|
||||||
struct e1000_nic * nic = node->device;
|
struct e1000_nic * nic = node->device;
|
||||||
/* write packet */
|
/* write packet */
|
||||||
@ -520,7 +529,11 @@ static void e1000_init(void * data) {
|
|||||||
|
|
||||||
net_add_interface(nic->if_name, nic->device_node);
|
net_add_interface(nic->if_name, nic->device_node);
|
||||||
|
|
||||||
switch_task(0);
|
/* Now wait for packets */
|
||||||
|
while (1) {
|
||||||
|
struct ethernet_packet * packet = dequeue_packet(nic);
|
||||||
|
net_eth_handle(packet, nic->device_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void find_e1000(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * found) {
|
static void find_e1000(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * found) {
|
||||||
|
58
kernel/net/eth.c
Normal file
58
kernel/net/eth.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include <kernel/types.h>
|
||||||
|
#include <kernel/string.h>
|
||||||
|
#include <kernel/printf.h>
|
||||||
|
#include <kernel/process.h>
|
||||||
|
#include <kernel/pipe.h>
|
||||||
|
#include <kernel/list.h>
|
||||||
|
#include <kernel/spinlock.h>
|
||||||
|
#include <kernel/vfs.h>
|
||||||
|
#include <kernel/mod/net.h>
|
||||||
|
#include <kernel/net/netif.h>
|
||||||
|
#include <kernel/net/eth.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
struct ethernet_packet {
|
||||||
|
uint8_t destination[6];
|
||||||
|
uint8_t source[6];
|
||||||
|
uint16_t type;
|
||||||
|
uint8_t payload[];
|
||||||
|
} __attribute__((packed)) __attribute__((aligned(2)));
|
||||||
|
|
||||||
|
#define ETHERNET_TYPE_IPV4 0x0800
|
||||||
|
#define ETHERNET_TYPE_ARP 0x0806
|
||||||
|
#define BROADCAST_MAC {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
|
||||||
|
|
||||||
|
extern spin_lock_t net_raw_sockets_lock;
|
||||||
|
extern list_t * net_raw_sockets_list;
|
||||||
|
extern void net_sock_add(sock_t * sock, void * frame);
|
||||||
|
extern void net_ipv4_handle(void * packet, fs_node_t * nic);
|
||||||
|
|
||||||
|
void net_eth_handle(struct ethernet_packet * frame, fs_node_t * nic) {
|
||||||
|
spin_lock(net_raw_sockets_lock);
|
||||||
|
foreach(node, net_raw_sockets_list) {
|
||||||
|
sock_t * sock = node->value;
|
||||||
|
if (!sock->_fnode.device || sock->_fnode.device == nic) {
|
||||||
|
net_sock_add(sock, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock(net_raw_sockets_lock);
|
||||||
|
|
||||||
|
struct EthernetDevice * nic_eth = nic->device;
|
||||||
|
|
||||||
|
if (!memcmp(frame->destination, nic_eth->mac, 6) || !memcmp(frame->destination, (uint8_t[])BROADCAST_MAC, 6)) {
|
||||||
|
/* Now pass the frame to the appropriate handler... */
|
||||||
|
switch (ntohs(frame->type)) {
|
||||||
|
case ETHERNET_TYPE_ARP:
|
||||||
|
printf("net: eth: %s: rx arp packet\n", nic->name);
|
||||||
|
break;
|
||||||
|
case ETHERNET_TYPE_IPV4:
|
||||||
|
printf("net: eth: %s: rx ipv4 packet\n", nic->name);
|
||||||
|
net_ipv4_handle(&frame->payload, nic);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(frame);
|
||||||
|
}
|
@ -14,6 +14,34 @@
|
|||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
struct ipv4_packet {
|
||||||
|
uint8_t version_ihl;
|
||||||
|
uint8_t dscp_ecn;
|
||||||
|
uint16_t length;
|
||||||
|
uint16_t ident;
|
||||||
|
uint16_t flags_fragment;
|
||||||
|
uint8_t ttl;
|
||||||
|
uint8_t protocol;
|
||||||
|
uint16_t checksum;
|
||||||
|
uint32_t source;
|
||||||
|
uint32_t destination;
|
||||||
|
uint8_t payload[];
|
||||||
|
} __attribute__ ((packed)) __attribute__((aligned(2)));
|
||||||
|
|
||||||
|
#define IPV4_PROT_UDP 17
|
||||||
|
#define IPV4_PROT_TCP 6
|
||||||
|
|
||||||
|
void net_ipv4_handle(struct ipv4_packet * packet, fs_node_t * nic) {
|
||||||
|
switch (packet->protocol) {
|
||||||
|
case IPV4_PROT_UDP:
|
||||||
|
printf("net: ipv4: %s: udp packet\n", nic->name);
|
||||||
|
break;
|
||||||
|
case IPV4_PROT_TCP:
|
||||||
|
printf("net: ipv4: %s: tcp packet\n", nic->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
long net_ipv4_socket(int type, int protocol) {
|
long net_ipv4_socket(int type, int protocol) {
|
||||||
/* Ignore protocol, make socket for 'type' only... */
|
/* Ignore protocol, make socket for 'type' only... */
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
static hashmap_t * interfaces = NULL;
|
static hashmap_t * interfaces = NULL;
|
||||||
|
|
||||||
void net_install(void) {
|
void net_install(void) {
|
||||||
|
/* Set up virtual devices */
|
||||||
map_vfs_directory("/dev/net");
|
map_vfs_directory("/dev/net");
|
||||||
interfaces = hashmap_create(10);
|
interfaces = hashmap_create(10);
|
||||||
}
|
}
|
||||||
@ -36,3 +37,7 @@ int net_add_interface(const char * name, fs_node_t * deviceNode) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs_node_t * net_if_lookup(const char * name) {
|
||||||
|
return hashmap_get(interfaces, name);
|
||||||
|
}
|
||||||
|
@ -12,9 +12,12 @@
|
|||||||
#include <kernel/types.h>
|
#include <kernel/types.h>
|
||||||
#include <kernel/string.h>
|
#include <kernel/string.h>
|
||||||
#include <kernel/printf.h>
|
#include <kernel/printf.h>
|
||||||
|
#include <kernel/list.h>
|
||||||
#include <kernel/syscall.h>
|
#include <kernel/syscall.h>
|
||||||
#include <kernel/vfs.h>
|
#include <kernel/vfs.h>
|
||||||
|
|
||||||
|
#include <kernel/net/netif.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,6 +27,116 @@
|
|||||||
*/
|
*/
|
||||||
extern long net_ipv4_socket(int,int);
|
extern long net_ipv4_socket(int,int);
|
||||||
|
|
||||||
|
void net_sock_alert(sock_t * sock) {
|
||||||
|
spin_lock(sock->alert_lock);
|
||||||
|
while (sock->alert_wait->head) {
|
||||||
|
node_t * node = list_dequeue(sock->alert_wait);
|
||||||
|
process_t * p = node->value;
|
||||||
|
free(node);
|
||||||
|
spin_unlock(sock->alert_lock);
|
||||||
|
process_alert_node(p, (fs_node_t*)sock);
|
||||||
|
spin_lock(sock->alert_lock);
|
||||||
|
}
|
||||||
|
spin_unlock(sock->alert_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_sock_add(sock_t * sock, void * frame) {
|
||||||
|
spin_lock(sock->rx_lock);
|
||||||
|
char * bleh = malloc(8092);
|
||||||
|
memcpy(bleh, frame, 8092);
|
||||||
|
list_insert(sock->rx_queue, bleh);
|
||||||
|
wakeup_queue(sock->rx_wait);
|
||||||
|
net_sock_alert(sock);
|
||||||
|
spin_unlock(sock->rx_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void * net_sock_get(sock_t * sock) {
|
||||||
|
while (!sock->rx_queue->length) {
|
||||||
|
sleep_on(sock->rx_wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock(sock->rx_lock);
|
||||||
|
node_t * n = list_dequeue(sock->rx_queue);
|
||||||
|
void* value = n->value;
|
||||||
|
free(n);
|
||||||
|
spin_unlock(sock->rx_lock);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock_generic_check(fs_node_t *node) {
|
||||||
|
sock_t * sock = (sock_t*)node;
|
||||||
|
return sock->rx_queue->length ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock_generic_wait(fs_node_t *node, void * process) {
|
||||||
|
sock_t * sock = (sock_t*)node;
|
||||||
|
|
||||||
|
spin_lock(sock->alert_lock);
|
||||||
|
if (!list_find(sock->alert_wait, process)) {
|
||||||
|
list_insert(sock->alert_wait, process);
|
||||||
|
}
|
||||||
|
list_insert(((process_t *)process)->node_waits, sock);
|
||||||
|
spin_unlock(sock->alert_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sock_generic_close(fs_node_t *node) {
|
||||||
|
sock_t * sock = (sock_t*)node;
|
||||||
|
sock->sock_close(sock);
|
||||||
|
printf("net: socket closed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sock_t * net_sock_create(void) {
|
||||||
|
sock_t * sock = calloc(sizeof(struct SockData),1);
|
||||||
|
sock->_fnode.flags = FS_PIPE; /* uh, FS_SOCKET? */
|
||||||
|
sock->_fnode.mask = 0600;
|
||||||
|
sock->_fnode.device = NULL;
|
||||||
|
sock->_fnode.selectcheck = sock_generic_check;
|
||||||
|
sock->_fnode.selectwait = sock_generic_wait;
|
||||||
|
sock->_fnode.close = sock_generic_close;
|
||||||
|
sock->alert_wait = list_create("socket alert wait", sock);
|
||||||
|
sock->rx_wait = list_create("socket rx wait", sock);
|
||||||
|
sock->rx_queue = list_create("socket rx queue", sock);
|
||||||
|
open_fs((fs_node_t*)sock,0);
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_t net_raw_sockets_lock = {0};
|
||||||
|
list_t * net_raw_sockets_list = NULL;
|
||||||
|
|
||||||
|
static long sock_raw_recv(sock_t * sock, struct msghdr * msg, int flags) {
|
||||||
|
if (!sock->_fnode.device) return -EINVAL;
|
||||||
|
if (msg->msg_iovlen > 1) {
|
||||||
|
printf("net: todo: can't recv multiple iovs\n");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
if (msg->msg_iovlen == 0) return 0;
|
||||||
|
if (msg->msg_iov[0].iov_len != 8092) return -EINVAL;
|
||||||
|
void * data = net_sock_get(sock);
|
||||||
|
memcpy(msg->msg_iov[0].iov_base, data, 8092);
|
||||||
|
free(data);
|
||||||
|
return 8092;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long sock_raw_send(sock_t * sock, const struct msghdr *msg, int flags) {
|
||||||
|
if (!sock->_fnode.device) return -EINVAL;
|
||||||
|
if (msg->msg_iovlen > 1) {
|
||||||
|
printf("net: todo: can't send multiple iovs\n");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
if (msg->msg_iovlen == 0) return 0;
|
||||||
|
return write_fs(sock->_fnode.device, 0, msg->msg_iov[0].iov_len, msg->msg_iov[0].iov_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sock_raw_close(sock_t * sock) {
|
||||||
|
spin_lock(net_raw_sockets_lock);
|
||||||
|
list_delete(net_raw_sockets_list, list_find(net_raw_sockets_list, sock));
|
||||||
|
spin_unlock(net_raw_sockets_lock);
|
||||||
|
|
||||||
|
/* free stuff ? */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raw sockets
|
* Raw sockets
|
||||||
*/
|
*/
|
||||||
@ -31,13 +144,17 @@ long net_raw_socket(int type, int protocol) {
|
|||||||
if (type != SOCK_RAW) return -EINVAL;
|
if (type != SOCK_RAW) return -EINVAL;
|
||||||
|
|
||||||
/* Make a new raw socket? */
|
/* Make a new raw socket? */
|
||||||
fs_node_t * sock = calloc(sizeof(fs_node_t),1);
|
sock_t * sock = net_sock_create();
|
||||||
sock->flags = FS_PIPE; /* uh, FS_SOCKET? */
|
sock->sock_recv = sock_raw_recv;
|
||||||
sock->mask = 0600;
|
sock->sock_send = sock_raw_send;
|
||||||
//sock->read = sock_raw_read;
|
sock->sock_close = sock_raw_close;
|
||||||
//sock->write = sock_raw_write;
|
|
||||||
|
|
||||||
int fd = process_append_fd((process_t *)this_core->current_process, sock);
|
spin_lock(net_raw_sockets_lock);
|
||||||
|
if (!net_raw_sockets_list) net_raw_sockets_list = list_create("raw sockets", NULL);
|
||||||
|
list_insert(net_raw_sockets_list, sock);
|
||||||
|
spin_unlock(net_raw_sockets_lock);
|
||||||
|
|
||||||
|
int fd = process_append_fd((process_t *)this_core->current_process, (fs_node_t *)sock);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +169,30 @@ long net_socket(int domain, int type, int protocol) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long net_so_socket(struct SockData * sock, int optname, const void *optval, socklen_t optlen) {
|
||||||
|
switch (optname) {
|
||||||
|
case SO_BINDTODEVICE: {
|
||||||
|
if (optlen < 1 || optlen > 32 || ((const char*)optval)[optlen-1] != 0) return -EINVAL;
|
||||||
|
fs_node_t * netif = net_if_lookup((const char*)optval);
|
||||||
|
if (!netif) return -ENOENT;
|
||||||
|
sock->_fnode.device = netif;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return -ENOPROTOOPT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
long net_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
|
long net_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
|
||||||
|
if (!FD_CHECK(sockfd)) return -EBADF;
|
||||||
|
PTR_VALIDATE(optval);
|
||||||
|
sock_t * node = (sock_t*)FD_ENTRY(sockfd);
|
||||||
|
switch (level) {
|
||||||
|
case SOL_SOCKET:
|
||||||
|
return net_so_socket(node,optname,optval,optlen);
|
||||||
|
default:
|
||||||
|
return -ENOPROTOOPT;
|
||||||
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,11 +217,17 @@ long net_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
long net_recv(int sockfd, struct msghdr * msg, int flags) {
|
long net_recv(int sockfd, struct msghdr * msg, int flags) {
|
||||||
return -EINVAL;
|
if (!FD_CHECK(sockfd)) return -EBADF;
|
||||||
|
PTR_VALIDATE(msg);
|
||||||
|
sock_t * node = (sock_t*)FD_ENTRY(sockfd);
|
||||||
|
return node->sock_recv(node,msg,flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
long net_send(int sockfd, const struct msghdr * msg, int flags) {
|
long net_send(int sockfd, const struct msghdr * msg, int flags) {
|
||||||
return -EINVAL;
|
if (!FD_CHECK(sockfd)) return -EBADF;
|
||||||
|
PTR_VALIDATE(msg);
|
||||||
|
sock_t * node = (sock_t*)FD_ENTRY(sockfd);
|
||||||
|
return node->sock_send(node,msg,flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
long net_shutdown(int sockfd, int how) {
|
long net_shutdown(int sockfd, int how) {
|
||||||
|
Loading…
Reference in New Issue
Block a user