WIP more net stack
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
#include <kernel/mutex.h>
|
||||
#include <lk/trace.h>
|
||||
|
||||
#define LOCAL_TRACE 1
|
||||
#define LOCAL_TRACE 0
|
||||
typedef struct {
|
||||
struct list_node node;
|
||||
uint32_t addr;
|
||||
@@ -160,9 +160,15 @@ const uint8_t *arp_get_dest_mac(uint32_t host) {
|
||||
|
||||
dst_mac = arp_cache_lookup(host);
|
||||
if (dst_mac == NULL) {
|
||||
// TODO: lookup netif based on route
|
||||
netif_t *netif = netif_main;
|
||||
// look up route to set local address
|
||||
ipv4_route_t *route = ipv4_search_route(host);
|
||||
if (!route) {
|
||||
return NULL;
|
||||
}
|
||||
netif_t *netif = route->interface;
|
||||
|
||||
arp_send_request(netif, host);
|
||||
|
||||
memset(&arp_timeout_timer, 0, sizeof(arp_timeout_timer));
|
||||
net_timer_set(&arp_timeout_timer, handle_arp_timeout_cb, &arp_timeout, 100);
|
||||
while (!arp_timeout) {
|
||||
@@ -172,6 +178,7 @@ const uint8_t *arp_get_dest_mac(uint32_t host) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ipv4_dec_route_ref(route);
|
||||
}
|
||||
|
||||
return dst_mac;
|
||||
@@ -181,6 +188,8 @@ int handle_arp_pkt(netif_t *netif, pktbuf_t *p) {
|
||||
struct eth_hdr *eth;
|
||||
struct arp_pkt *arp;
|
||||
|
||||
LTRACEF("ARP packet, len %u\n", p->dlen);
|
||||
|
||||
eth = (void *) (p->data - sizeof(struct eth_hdr));
|
||||
|
||||
if ((arp = pktbuf_consume(p, sizeof(struct arp_pkt))) == NULL) {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "minip-internal.h"
|
||||
|
||||
/* XXX alternate implementation, merge */
|
||||
uint16_t ones_sum16(uint32_t sum, const void *_buf, int len) {
|
||||
const uint16_t *buf = _buf;
|
||||
|
||||
@@ -29,52 +28,3 @@ uint16_t ones_sum16(uint32_t sum, const void *_buf, int len) {
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
uint16_t rfc1701_chksum(const uint8_t *buf, size_t len) {
|
||||
uint32_t total = 0;
|
||||
uint16_t chksum = 0;
|
||||
const uint16_t *p = (const uint16_t *) buf;
|
||||
|
||||
// Length is in bytes
|
||||
for (size_t i = 0; i < len / 2; i++ ) {
|
||||
total += p[i];
|
||||
}
|
||||
|
||||
chksum = (total & 0xFFFF) + (total >> 16);
|
||||
chksum = ~chksum;
|
||||
|
||||
return chksum;
|
||||
}
|
||||
|
||||
#if MINIP_USE_UDP_CHECKSUM
|
||||
uint16_t rfc768_chksum(struct ipv4_hdr *ipv4, struct udp_hdr *udp) {
|
||||
uint32_t total = 0;
|
||||
uint16_t chksum = 0;
|
||||
size_t len = ntohs(udp->len);
|
||||
uint16_t *p;
|
||||
|
||||
p = (uint16_t *)ipv4->src_addr;
|
||||
total += htons(p[0]);
|
||||
total += htons(p[1]);
|
||||
|
||||
p = (uint16_t *)ipv4->dst_addr;
|
||||
total += htons(p[0]);
|
||||
total += htons(p[1]);
|
||||
|
||||
p = (const uint16_t *)udp->data;
|
||||
for (size_t i = 0; i < len / 2; i++ ) {
|
||||
total += p[i];
|
||||
}
|
||||
|
||||
total += IP_PROTO_UDP;
|
||||
total += udp->len;
|
||||
total += udp->src_port;
|
||||
total += udp->dst_port;
|
||||
total += ipv4->len;
|
||||
|
||||
chksum = (total & 0xFFFF) + (total >> 16);
|
||||
chksum = ~chksum;
|
||||
|
||||
return chksum;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define TRACE_DHCP 1
|
||||
#define TRACE_DHCP 0
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
dhcp() = default;
|
||||
~dhcp() = default;
|
||||
|
||||
status_t start();
|
||||
status_t start(netif_t *netif);
|
||||
|
||||
private:
|
||||
// must call the following two with the lock held
|
||||
@@ -232,7 +232,7 @@ void dhcp::udp_callback(void *data, size_t sz, uint32_t srcip, uint16_t srcport)
|
||||
|
||||
#if TRACE_DHCP
|
||||
printf("received DHCP op %d, len %zu, from p %d, ip=", msg->opcode, sz, srcport);
|
||||
printip(srcip);
|
||||
print_ipv4_address(srcip);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
@@ -241,10 +241,10 @@ void dhcp::udp_callback(void *data, size_t sz, uint32_t srcip, uint16_t srcport)
|
||||
return;
|
||||
}
|
||||
#if TRACE_DHCP
|
||||
printip_named("\tciaddr", msg->ciaddr);
|
||||
printip_named(" yiaddr", msg->yiaddr);
|
||||
printip_named(" siaddr", msg->siaddr);
|
||||
printip_named(" giaddr", msg->giaddr);
|
||||
print_ipv4_address_named("\tciaddr", msg->ciaddr);
|
||||
print_ipv4_address_named(" yiaddr", msg->yiaddr);
|
||||
print_ipv4_address_named(" siaddr", msg->siaddr);
|
||||
print_ipv4_address_named(" giaddr", msg->giaddr);
|
||||
printf(" chaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
msg->chaddr[0], msg->chaddr[1], msg->chaddr[2],
|
||||
msg->chaddr[3], msg->chaddr[4], msg->chaddr[5]);
|
||||
@@ -288,16 +288,16 @@ void dhcp::udp_callback(void *data, size_t sz, uint32_t srcip, uint16_t srcport)
|
||||
done:
|
||||
#if TRACE_DHCP
|
||||
printf("\n\t");
|
||||
if (server) printip_named("server", server);
|
||||
if (netmask) printip_named(" netmask", netmask);
|
||||
if (gateway) printip_named(" gateway", gateway);
|
||||
if (dns) printip_named(" dns", dns);
|
||||
if (server) print_ipv4_address_named("server", server);
|
||||
if (netmask) print_ipv4_address_named(" netmask", netmask);
|
||||
if (gateway) print_ipv4_address_named(" gateway", gateway);
|
||||
if (dns) print_ipv4_address_named(" dns", dns);
|
||||
printf("\n");
|
||||
#endif
|
||||
if (state_ == DISCOVER_SENT) {
|
||||
if (op == OP_DHCPOFFER) {
|
||||
#if TRACE_DHCP
|
||||
printip_named("dhcp: offer:", msg->yiaddr);
|
||||
print_ipv4_address_named("dhcp: offer:", msg->yiaddr);
|
||||
printf("\n");
|
||||
#endif
|
||||
if (server) {
|
||||
@@ -308,7 +308,7 @@ done:
|
||||
} else if (state_ == REQUEST_SENT) {
|
||||
if (op == OP_DHCPACK) {
|
||||
#if TRACE_DHCP
|
||||
printip_named("dhcp: ack:", msg->yiaddr);
|
||||
print_ipv4_address_named("dhcp: ack:", msg->yiaddr);
|
||||
printf("\n");
|
||||
#endif
|
||||
printf("DHCP configured\n");
|
||||
@@ -360,14 +360,13 @@ int dhcp::dhcp_thread(void *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t dhcp::start() {
|
||||
status_t dhcp::start(netif_t *netif) {
|
||||
AutoLock guard(lock_);
|
||||
|
||||
// for now just try to set up for the main netif
|
||||
netif_ = netif_main;
|
||||
netif_ = netif;
|
||||
|
||||
// TODO: bind udp socket to this interface
|
||||
int ret = udp_open(IPV4_BCAST, DHCP_CLIENT_PORT, DHCP_SERVER_PORT, &dhcp_udp_handle_);
|
||||
// open a udp socket bound to the interface we're dhcping
|
||||
int ret = udp_open_raw(IPV4_BCAST, DHCP_CLIENT_PORT, DHCP_SERVER_PORT, netif_, &dhcp_udp_handle_);
|
||||
if (ret != NO_ERROR) {
|
||||
printf("DHCP: error opening udp socket\n");
|
||||
return ret;
|
||||
@@ -383,7 +382,9 @@ status_t dhcp::start() {
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void minip_start_dhcp() {
|
||||
static dhcp d;
|
||||
d.start();
|
||||
void minip_start_dhcp(netif_t *netif) {
|
||||
DEBUG_ASSERT(netif);
|
||||
|
||||
auto *d = new dhcp();
|
||||
d->start(netif);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ __BEGIN_CDECLS
|
||||
|
||||
/* types */
|
||||
typedef uint32_t ipv4_addr_t;
|
||||
typedef struct netif netif_t;
|
||||
|
||||
typedef int (*tx_func_t)(void *arg, pktbuf_t *p);
|
||||
typedef void (*udp_callback_t)(void *data, size_t len,
|
||||
@@ -38,7 +39,7 @@ typedef void (*udp_callback_t)(void *data, size_t len,
|
||||
* note: may take a while to have an ip address assigned, check
|
||||
* for configuration with minip_is_configured()
|
||||
*/
|
||||
void minip_start_dhcp(void);
|
||||
void minip_start_dhcp(netif_t *);
|
||||
|
||||
/* ethernet driver install hook */
|
||||
void minip_set_eth(tx_func_t tx_handler, void *tx_arg, const uint8_t *macaddr);
|
||||
@@ -48,7 +49,6 @@ bool minip_is_configured(void);
|
||||
status_t minip_wait_for_configured(lk_time_t timeout);
|
||||
|
||||
/* packet rx hook to hand to ethernet driver */
|
||||
typedef struct netif netif_t;
|
||||
void minip_rx_driver_callback(netif_t *netif, pktbuf_t *p);
|
||||
|
||||
/* global configuration state */
|
||||
@@ -62,7 +62,8 @@ void minip_set_configured(void); // set by dhcp or static init to signal minip i
|
||||
typedef struct udp_socket udp_socket_t;
|
||||
|
||||
int udp_listen(uint16_t port, udp_callback_t cb, void *arg);
|
||||
status_t udp_open(uint32_t host, uint16_t sport, uint16_t dport, udp_socket_t **handle);
|
||||
status_t udp_open(ipv4_addr_t host, uint16_t sport, uint16_t dport, udp_socket_t **handle);
|
||||
status_t udp_open_raw(ipv4_addr_t host, uint16_t sport, uint16_t dport, netif_t *netif, udp_socket_t **handle);
|
||||
status_t udp_send(void *buf, size_t len, udp_socket_t *handle);
|
||||
status_t udp_send_iovec(const iovec_t *iov, uint iov_count, udp_socket_t *handle);
|
||||
status_t udp_close(udp_socket_t *handle);
|
||||
@@ -83,11 +84,9 @@ static inline status_t tcp_accept(tcp_socket_t *listen_socket, tcp_socket_t **ac
|
||||
|
||||
/* utilities */
|
||||
void gen_random_mac_address(uint8_t *mac_addr);
|
||||
uint32_t minip_parse_ipaddr(const char *addr, size_t len);
|
||||
|
||||
uint32_t minip_parse_ipaddr(const char *addr, size_t len);
|
||||
void printip(uint32_t x);
|
||||
void printip_named(const char *s, u32 x);
|
||||
ipv4_addr_t minip_parse_ipaddr(const char *addr, size_t len);
|
||||
void print_mac_address(const uint8_t *mac);
|
||||
void print_ipv4_address(ipv4_addr_t x);
|
||||
void print_ipv4_address_named(const char *s, ipv4_addr_t x);
|
||||
|
||||
__END_CDECLS
|
||||
|
||||
@@ -39,9 +39,10 @@ struct netif {
|
||||
typedef struct netif netif_t;
|
||||
#define NETIF_MAGIC 'NETI'
|
||||
|
||||
#define NETIF_FLAG_ETH_CONFIGURED (1U << 0) // mac address and tx func set
|
||||
#define NETIF_FLAG_REGISTERED (1U << 1) // added to the main list
|
||||
#define NETIF_FLAG_IPV4_CONFIGURED (1U << 2) // ipv4 address is set
|
||||
#define NETIF_FLAG_LOOPBACK (1U << 0) // loopback interface is a bit special
|
||||
#define NETIF_FLAG_ETH_CONFIGURED (1U << 1) // mac address and tx func set
|
||||
#define NETIF_FLAG_REGISTERED (1U << 2) // added to the main list
|
||||
#define NETIF_FLAG_IPV4_CONFIGURED (1U << 3) // ipv4 address is set
|
||||
|
||||
// Initialize a netif struct.
|
||||
// Allocates a new one if passed in pointer is null.
|
||||
|
||||
@@ -53,7 +53,7 @@ static int cmd_arp(int argc, const console_cmd_args *argv) {
|
||||
const char *addr_s = argv[2].str;
|
||||
uint32_t addr = str_ip_to_int(addr_s, strlen(addr_s));
|
||||
|
||||
arp_send_request(netif_main, addr);
|
||||
arp_get_dest_mac(addr);
|
||||
} else {
|
||||
arp_usage();
|
||||
}
|
||||
@@ -65,26 +65,27 @@ static int cmd_minip(int argc, const console_cmd_args *argv) {
|
||||
if (argc == 1) {
|
||||
minip_usage:
|
||||
printf("minip commands\n");
|
||||
printf("mi [a]rp dump arp table\n");
|
||||
printf("mi [i]interfaces dump interface list\n");
|
||||
printf("mi [r]outes dump routing table\n");
|
||||
printf("mi [s]tatus print ip status\n");
|
||||
printf("mi [t]est [dest] [port] [cnt] send <cnt> test packets to the dest:port\n");
|
||||
} else {
|
||||
switch (argv[1].str[0]) {
|
||||
|
||||
case 'a':
|
||||
arp_cache_dump();
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
netif_dump();
|
||||
break;
|
||||
case 's': {
|
||||
case 'r':
|
||||
dump_ipv4_route_table();
|
||||
break;
|
||||
case 's':
|
||||
printf("hostname: %s\n", minip_get_hostname());
|
||||
printf("gateway: %u.%u.%u.%u\n", IPV4_SPLIT(minip_get_gateway()));
|
||||
printf("interfaces:\n");
|
||||
netif_dump();
|
||||
}
|
||||
break;
|
||||
printf("ipv4 routing table:\n");
|
||||
dump_ipv4_route_table();
|
||||
break;
|
||||
case 't': {
|
||||
uint32_t count = 1;
|
||||
uint32_t host = 0x0100000A; // 10.0.0.1
|
||||
@@ -140,7 +141,7 @@ minip_usage:
|
||||
udp_close(handle);
|
||||
#undef BUFSIZE
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
goto minip_usage;
|
||||
}
|
||||
@@ -149,7 +150,10 @@ minip_usage:
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int cmd_tcp(int argc, const console_cmd_args *argv);
|
||||
|
||||
STATIC_COMMAND_START
|
||||
STATIC_COMMAND("arp", "arp commands", &cmd_arp)
|
||||
STATIC_COMMAND("mi", "minip commands", &cmd_minip)
|
||||
STATIC_COMMAND("tcp", "tcp commands", &cmd_tcp)
|
||||
STATIC_COMMAND_END(minip);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <lib/minip/netif.h>
|
||||
|
||||
/* Lib configuration */
|
||||
#define MINIP_USE_UDP_CHECKSUM 0
|
||||
#define MINIP_USE_UDP_CHECKSUM 1
|
||||
#define MINIP_MTU_SIZE 1536
|
||||
#define MINIP_USE_ARP 1
|
||||
|
||||
@@ -103,28 +103,54 @@ int arp_send_request(netif_t *, ipv4_addr_t addr);
|
||||
const uint8_t *arp_get_dest_mac(uint32_t host);
|
||||
int handle_arp_pkt(netif_t *netif, pktbuf_t *p);
|
||||
|
||||
uint16_t rfc1701_chksum(const uint8_t *buf, size_t len);
|
||||
uint16_t rfc768_chksum(struct ipv4_hdr *ipv4, udp_hdr_t *udp);
|
||||
// checksums
|
||||
uint16_t ones_sum16(uint32_t sum, const void *_buf, int len);
|
||||
|
||||
typedef struct ipv4_pseudo_header {
|
||||
ipv4_addr_t source_addr;
|
||||
ipv4_addr_t dest_addr;
|
||||
uint8_t zero;
|
||||
uint8_t protocol;
|
||||
uint16_t tcp_length;
|
||||
} __PACKED ipv4_pseudo_header_t;
|
||||
|
||||
static inline uint16_t cksum_pheader(const ipv4_pseudo_header_t *pheader, const void *buf, size_t len) {
|
||||
uint16_t checksum = ones_sum16(0, pheader, sizeof(*pheader));
|
||||
return ~ones_sum16(checksum, buf, len);
|
||||
}
|
||||
|
||||
// ipv4 routing
|
||||
typedef struct ipv4_route {
|
||||
uint32_t flags;
|
||||
int ref;
|
||||
ipv4_addr_t dest;
|
||||
ipv4_addr_t mask;
|
||||
netif_t *interface;
|
||||
} ipv4_route_t;
|
||||
|
||||
#define IPV4_ROUTE_UP (1<<0)
|
||||
#define IPV4_ROUTE_DEFAULT (1<<1)
|
||||
|
||||
ipv4_route_t *ipv4_search_route(ipv4_addr_t dest);
|
||||
void ipv4_dec_route_ref(ipv4_route_t *r);
|
||||
status_t ipv4_add_route(ipv4_addr_t dest, ipv4_addr_t mask, netif_t *n);
|
||||
status_t ipv4_add_default_route(ipv4_addr_t dest, netif_t *n);
|
||||
|
||||
void dump_ipv4_route_table(void);
|
||||
|
||||
// Helper methods for building headers
|
||||
void minip_build_mac_hdr(netif_t *netif, struct eth_hdr *pkt, const uint8_t *dst, uint16_t type);
|
||||
void minip_build_ipv4_hdr(netif_t *netif, struct ipv4_hdr *ipv4, ipv4_addr_t dst, uint8_t proto, uint16_t len);
|
||||
|
||||
status_t minip_ipv4_send(pktbuf_t *p, ipv4_addr_t dest_addr, uint8_t proto);
|
||||
status_t minip_ipv4_send_raw(pktbuf_t *p, ipv4_addr_t dest_addr, uint8_t proto, const uint8_t *dest_mac, netif_t *netif);
|
||||
|
||||
void tcp_input(netif_t *netif, pktbuf_t *p, uint32_t src_ip, uint32_t dst_ip);
|
||||
void udp_input(netif_t *netif, pktbuf_t *p, uint32_t src_ip);
|
||||
|
||||
const uint8_t *get_dest_mac(uint32_t host);
|
||||
|
||||
// interface list
|
||||
void netif_init(void);
|
||||
void netif_dump(void);
|
||||
|
||||
extern netif_t *netif_loopback;
|
||||
extern netif_t *netif_main;
|
||||
|
||||
// timers
|
||||
typedef void (*net_timer_callback_t)(void *);
|
||||
|
||||
|
||||
@@ -20,47 +20,45 @@
|
||||
#include <string.h>
|
||||
#include <lk/trace.h>
|
||||
#include <malloc.h>
|
||||
#include <arch/atomic.h>
|
||||
#include <lk/list.h>
|
||||
#include <lk/init.h>
|
||||
#include <kernel/event.h>
|
||||
#include <kernel/mutex.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
// TODO
|
||||
// 1. Tear endian code out into something that flips words before/after tx/rx calls
|
||||
|
||||
#define LOCAL_TRACE 1
|
||||
//static ipv4_addr_t minip_ip = IPV4_NONE;
|
||||
//static ipv4_addr_t minip_netmask = IPV4_NONE;
|
||||
//static ipv4_addr_t minip_broadcast = IPV4_BCAST;
|
||||
#define LOCAL_TRACE 0
|
||||
static ipv4_addr_t minip_gateway = IPV4_NONE;
|
||||
|
||||
static const uint8_t broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
//static uint8_t minip_mac[6] = {0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC};
|
||||
|
||||
static char minip_hostname[32] = "";
|
||||
|
||||
static volatile bool minip_configured = false;
|
||||
static event_t minip_configured_event = EVENT_INITIAL_VALUE(minip_configured_event, false, 0);
|
||||
|
||||
/* This function is called by minip to send packets */
|
||||
//tx_func_t minip_tx_handler;
|
||||
//void *minip_tx_arg;
|
||||
|
||||
static void dump_ipv4_addr(uint32_t addr);
|
||||
/* routing table */
|
||||
static mutex_t route_lock = MUTEX_INITIAL_VALUE(route_lock);
|
||||
static ipv4_route_t route_table[16];
|
||||
|
||||
/* if all the important configuration bits are set, signal that we're configured */
|
||||
static void check_and_set_configured(void) {
|
||||
if (netif_main == NULL) return;
|
||||
if (netif_main->ipv4_addr == IPV4_NONE) return;
|
||||
if (netif_get_netmask_ipv4(netif_main) == IPV4_NONE) return;
|
||||
if (netif_get_broadcast_ipv4(netif_main) == IPV4_BCAST) return;
|
||||
// minip_gateway doesn't have to be set
|
||||
if (netif_main->mac_address[0] == 0 &&
|
||||
netif_main->mac_address[1] == 0 &&
|
||||
netif_main->mac_address[2] == 0 &&
|
||||
netif_main->mac_address[3] == 0 &&
|
||||
netif_main->mac_address[4] == 0 &&
|
||||
netif_main->mac_address[5] == 0) return;
|
||||
// search for an ip route other than loopback to signal configured
|
||||
mutex_acquire(&route_lock);
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < countof(route_table); i++) {
|
||||
if (route_table[i].flags & IPV4_ROUTE_UP) {
|
||||
if ((route_table[i].interface->flags & NETIF_FLAG_LOOPBACK) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_release(&route_lock);
|
||||
if (!found) return;
|
||||
|
||||
// we're configured
|
||||
printf("MINIP: setting configured state\n");
|
||||
@@ -76,47 +74,20 @@ const char *minip_get_hostname(void) {
|
||||
return minip_hostname;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void compute_broadcast_address(void) {
|
||||
minip_broadcast = (minip_ip & minip_netmask) | (IPV4_BCAST & ~minip_netmask);
|
||||
}
|
||||
|
||||
void minip_get_macaddr(uint8_t *addr) {
|
||||
mac_addr_copy(addr, minip_mac);
|
||||
}
|
||||
|
||||
uint32_t minip_get_ipaddr(void) {
|
||||
return minip_ip;
|
||||
}
|
||||
|
||||
void minip_set_ipaddr(const ipv4_addr_t addr) {
|
||||
minip_ip = addr;
|
||||
compute_broadcast_address();
|
||||
check_and_set_configured();
|
||||
}
|
||||
|
||||
uint32_t minip_get_broadcast(void) {
|
||||
return minip_broadcast;
|
||||
}
|
||||
|
||||
uint32_t minip_get_netmask(void) {
|
||||
return minip_netmask;
|
||||
}
|
||||
|
||||
void minip_set_netmask(const ipv4_addr_t netmask) {
|
||||
minip_netmask = netmask;
|
||||
compute_broadcast_address();
|
||||
check_and_set_configured();
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t minip_get_gateway(void) {
|
||||
return minip_gateway;
|
||||
}
|
||||
|
||||
void minip_set_gateway(const ipv4_addr_t addr) {
|
||||
minip_gateway = addr;
|
||||
// TODO: check that it is reacheable on local network
|
||||
|
||||
// look up the route to this and set a default route
|
||||
ipv4_route_t *route = ipv4_search_route(addr);
|
||||
if (route) {
|
||||
ipv4_add_default_route(addr, route->interface);
|
||||
ipv4_dec_route_ref(route);
|
||||
}
|
||||
|
||||
check_and_set_configured();
|
||||
}
|
||||
|
||||
@@ -147,22 +118,138 @@ void minip_start_static(uint32_t ip, uint32_t mask, uint32_t gateway) {
|
||||
minip_set_gateway(gateway);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void minip_set_eth(tx_func_t tx_handler, void *tx_arg, const uint8_t *macaddr) {
|
||||
LTRACEF("handler %p, arg %p, macaddr %p\n", tx_handler, tx_arg, macaddr);
|
||||
// search for an ipv4 route given the destination
|
||||
// bumps the ref of the route upon return
|
||||
ipv4_route_t *ipv4_search_route(ipv4_addr_t dest) {
|
||||
ipv4_route_t *r = NULL;
|
||||
ipv4_route_t *def_route = NULL;
|
||||
|
||||
DEBUG_ASSERT(minip_tx_handler == NULL);
|
||||
DEBUG_ASSERT(minip_tx_arg == NULL);
|
||||
// TODO: assert mac address is not already set
|
||||
mutex_acquire(&route_lock);
|
||||
|
||||
// set up the low level driver handler
|
||||
minip_tx_handler = tx_handler;
|
||||
minip_tx_arg = tx_arg;
|
||||
for (size_t i = 0; i < countof(route_table); i++) {
|
||||
ipv4_route_t *rtemp = &route_table[i];
|
||||
if (rtemp->flags & IPV4_ROUTE_UP) {
|
||||
if (rtemp->flags & IPV4_ROUTE_DEFAULT) {
|
||||
def_route = rtemp;
|
||||
} else {
|
||||
// does this route satisfy our destination
|
||||
if ((dest & rtemp->mask) == rtemp->dest) {
|
||||
r = rtemp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mac_addr_copy(minip_mac, macaddr);
|
||||
if (!r && def_route) {
|
||||
r = def_route;
|
||||
}
|
||||
if (r) {
|
||||
// inc ref on the route and pass it back
|
||||
r->ref++;
|
||||
}
|
||||
|
||||
mutex_release(&route_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ipv4_dec_route_ref(ipv4_route_t *r) {
|
||||
DEBUG_ASSERT(r);
|
||||
|
||||
mutex_acquire(&route_lock);
|
||||
|
||||
DEBUG_ASSERT(r->ref >= 1);
|
||||
r->ref--;
|
||||
|
||||
mutex_release(&route_lock);
|
||||
}
|
||||
|
||||
status_t ipv4_add_route(ipv4_addr_t dest, ipv4_addr_t mask, netif_t *n) {
|
||||
LTRACE_ENTRY;
|
||||
DEBUG_ASSERT(n);
|
||||
|
||||
mutex_acquire(&route_lock);
|
||||
|
||||
// find an unused slot
|
||||
status_t err;
|
||||
for (size_t i = 0; i < countof(route_table); i++) {
|
||||
ipv4_route_t *r = &route_table[i];
|
||||
|
||||
if (r->ref == 0 && r->flags == 0) {
|
||||
// unused route, use this slot
|
||||
r->dest = dest;
|
||||
r->mask = mask;
|
||||
r->interface = n;
|
||||
r->ref = 0;
|
||||
r->flags |= IPV4_ROUTE_UP;
|
||||
err = NO_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
err = ERR_NO_MEMORY;
|
||||
|
||||
done:
|
||||
mutex_release(&route_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t ipv4_add_default_route(ipv4_addr_t dest, netif_t *n) {
|
||||
LTRACE_ENTRY;
|
||||
DEBUG_ASSERT(n);
|
||||
|
||||
mutex_acquire(&route_lock);
|
||||
|
||||
// find an unused slot
|
||||
status_t err;
|
||||
for (size_t i = 0; i < countof(route_table); i++) {
|
||||
ipv4_route_t *r = &route_table[i];
|
||||
|
||||
if (r->ref == 0 && r->flags == 0) {
|
||||
// unused route, use this slot
|
||||
r->dest = dest;
|
||||
r->mask = 0;
|
||||
r->interface = n;
|
||||
r->ref = 0;
|
||||
r->flags |= IPV4_ROUTE_UP;
|
||||
r->flags |= IPV4_ROUTE_DEFAULT;
|
||||
err = NO_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
err = ERR_NO_MEMORY;
|
||||
|
||||
done:
|
||||
mutex_release(&route_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void dump_ipv4_route_table(void) {
|
||||
mutex_acquire(&route_lock);
|
||||
|
||||
for (size_t i = 0; i < countof(route_table); i++) {
|
||||
ipv4_route_t *r = &route_table[i];
|
||||
if (r->ref > 0 || r->flags != 0) {
|
||||
printf("route dest ");
|
||||
print_ipv4_address(r->dest);
|
||||
printf(" mask ");
|
||||
print_ipv4_address(r->mask);
|
||||
printf(" flags %c%c ref %d interface %s\n",
|
||||
r->flags & IPV4_ROUTE_UP ? 'U' : ' ',
|
||||
r->flags & IPV4_ROUTE_DEFAULT ? 'D' : ' ',
|
||||
r->ref,
|
||||
r->interface->name);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_release(&route_lock);
|
||||
}
|
||||
|
||||
// ipv4 send/receive logic
|
||||
static uint16_t ipv4_payload_len(struct ipv4_hdr *pkt) {
|
||||
return (pkt->len - ((pkt->ver_ihl >> 4) * 5));
|
||||
}
|
||||
@@ -173,7 +260,7 @@ void minip_build_mac_hdr(netif_t *netif, struct eth_hdr *pkt, const uint8_t *dst
|
||||
pkt->type = htons(type);
|
||||
}
|
||||
|
||||
void minip_build_ipv4_hdr(netif_t *netif, struct ipv4_hdr *ipv4, ipv4_addr_t dst, uint8_t proto, uint16_t len) {
|
||||
static void minip_build_ipv4_hdr(netif_t *netif, struct ipv4_hdr *ipv4, ipv4_addr_t dst, uint8_t proto, uint16_t len) {
|
||||
ipv4->ver_ihl = 0x45;
|
||||
ipv4->dscp_ecn = 0;
|
||||
ipv4->len = htons(20 + len); // 5 * 4 from ihl, plus payload length
|
||||
@@ -186,27 +273,44 @@ void minip_build_ipv4_hdr(netif_t *netif, struct ipv4_hdr *ipv4, ipv4_addr_t dst
|
||||
|
||||
/* This may be unnecessary if the controller supports checksum offloading */
|
||||
ipv4->chksum = 0;
|
||||
ipv4->chksum = rfc1701_chksum((uint8_t *) ipv4, sizeof(struct ipv4_hdr));
|
||||
ipv4->chksum = ~ones_sum16(0, (uint8_t *) ipv4, sizeof(struct ipv4_hdr));
|
||||
}
|
||||
|
||||
status_t minip_ipv4_send(pktbuf_t *p, ipv4_addr_t dest_addr, uint8_t proto) {
|
||||
status_t ret = 0;
|
||||
status_t minip_ipv4_send_raw(pktbuf_t *p, ipv4_addr_t dest_addr, uint8_t proto, const uint8_t *dest_mac, netif_t *netif) {
|
||||
DEBUG_ASSERT(p);
|
||||
DEBUG_ASSERT(netif);
|
||||
|
||||
size_t data_len = p->dlen;
|
||||
const uint8_t *dst_mac;
|
||||
|
||||
struct ipv4_hdr *ip = pktbuf_prepend(p, sizeof(struct ipv4_hdr));
|
||||
struct eth_hdr *eth = pktbuf_prepend(p, sizeof(struct eth_hdr));
|
||||
|
||||
// TODO: consult routing table here
|
||||
netif_t *netif = netif_main;
|
||||
if (!netif) {
|
||||
if (LOCAL_TRACE) {
|
||||
printf("sending ipv4\n");
|
||||
}
|
||||
|
||||
minip_build_mac_hdr(netif, eth, dest_mac, ETH_TYPE_IPV4);
|
||||
minip_build_ipv4_hdr(netif, ip, dest_addr, proto, data_len);
|
||||
|
||||
return netif->tx_func(netif->tx_func_arg, p);
|
||||
}
|
||||
|
||||
status_t minip_ipv4_send(pktbuf_t *p, ipv4_addr_t dest_addr, uint8_t proto) {
|
||||
status_t ret = 0;
|
||||
|
||||
// TODO: cache route at socket creation
|
||||
ipv4_route_t *route = ipv4_search_route(dest_addr);
|
||||
if (!route) {
|
||||
ret = -EHOSTUNREACH;
|
||||
goto err;
|
||||
}
|
||||
DEBUG_ASSERT(route->interface);
|
||||
netif_t *netif = route->interface;
|
||||
|
||||
// are we sending a broadcast packet?
|
||||
const uint8_t *dest_mac;
|
||||
if (dest_addr == IPV4_BCAST || dest_addr == netif_get_broadcast_ipv4(netif)) {
|
||||
dst_mac = bcast_mac;
|
||||
dest_mac = bcast_mac;
|
||||
goto ready;
|
||||
}
|
||||
|
||||
@@ -216,30 +320,27 @@ status_t minip_ipv4_send(pktbuf_t *p, ipv4_addr_t dest_addr, uint8_t proto) {
|
||||
if ((dest_addr & netmask) != (netif->ipv4_addr & netmask)) {
|
||||
// need to use the gateway
|
||||
if (minip_gateway == IPV4_NONE) {
|
||||
return ERR_NOT_FOUND; // TODO: better error code
|
||||
ret = ERR_NOT_FOUND; // TODO: better error code
|
||||
goto err;
|
||||
}
|
||||
|
||||
target_addr = minip_gateway;
|
||||
}
|
||||
|
||||
dst_mac = arp_get_dest_mac(target_addr);
|
||||
if (!dst_mac) {
|
||||
dest_mac = arp_get_dest_mac(target_addr);
|
||||
if (!dest_mac) {
|
||||
pktbuf_free(p, true);
|
||||
ret = -EHOSTUNREACH;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ready:
|
||||
if (LOCAL_TRACE) {
|
||||
printf("sending ipv4\n");
|
||||
}
|
||||
|
||||
minip_build_mac_hdr(netif, eth, dst_mac, ETH_TYPE_IPV4);
|
||||
minip_build_ipv4_hdr(netif, ip, dest_addr, proto, data_len);
|
||||
|
||||
netif->tx_func(netif->tx_func_arg, p);
|
||||
ret = minip_ipv4_send_raw(p, dest_addr, proto, dest_mac, netif);
|
||||
|
||||
err:
|
||||
if (route) {
|
||||
ipv4_dec_route_ref(route);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -272,22 +373,16 @@ static void send_ping_reply(netif_t *netif, uint32_t ipaddr, struct icmp_pkt *re
|
||||
icmp->code = 0;
|
||||
memcpy(icmp->hdr_data, req->hdr_data, sizeof(icmp->hdr_data));
|
||||
icmp->chksum = 0;
|
||||
icmp->chksum = rfc1701_chksum((uint8_t *) icmp, len);
|
||||
icmp->chksum = ~ones_sum16(0, (uint8_t *) icmp, len);
|
||||
|
||||
netif->tx_func(netif->tx_func_arg, p);
|
||||
}
|
||||
|
||||
static void dump_ipv4_addr(uint32_t addr) {
|
||||
const uint8_t *a = (void *)&addr;
|
||||
|
||||
printf("%hhu.%hhu.%hhu.%hhu", a[0], a[1], a[2], a[3]);
|
||||
}
|
||||
|
||||
static void dump_ipv4_packet(const struct ipv4_hdr *ip) {
|
||||
__NO_INLINE static void dump_ipv4_packet(const struct ipv4_hdr *ip) {
|
||||
printf("IP ");
|
||||
dump_ipv4_addr(ip->src_addr);
|
||||
print_ipv4_address(ip->src_addr);
|
||||
printf(" -> ");
|
||||
dump_ipv4_addr(ip->dst_addr);
|
||||
print_ipv4_address(ip->dst_addr);
|
||||
printf(" hlen 0x%x, prot 0x%x, cksum 0x%x, len 0x%x, ident 0x%x, frag offset 0x%x\n",
|
||||
(ip->ver_ihl & 0xf) * 4, ip->proto, ntohs(ip->chksum), ntohs(ip->len), ntohs(ip->id), ntohs(ip->flags_frags) & 0x1fff);
|
||||
}
|
||||
@@ -296,8 +391,10 @@ __NO_INLINE static void handle_ipv4_packet(netif_t *netif, pktbuf_t *p, const ui
|
||||
struct ipv4_hdr *ip;
|
||||
|
||||
ip = (struct ipv4_hdr *)p->data;
|
||||
if (p->dlen < sizeof(struct ipv4_hdr))
|
||||
if (p->dlen < sizeof(struct ipv4_hdr)) {
|
||||
LTRACEF("REJECT: packet too short to hold header\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* print packets for us */
|
||||
if (LOCAL_TRACE) {
|
||||
@@ -319,7 +416,7 @@ __NO_INLINE static void handle_ipv4_packet(netif_t *netif, pktbuf_t *p, const ui
|
||||
}
|
||||
|
||||
/* compute checksum */
|
||||
if (rfc1701_chksum((void *)ip, header_len) != 0) {
|
||||
if (ones_sum16(0, (void *)ip, header_len) == 0) {
|
||||
/* bad checksum */
|
||||
LTRACEF("REJECT: bad checksum\n");
|
||||
return;
|
||||
@@ -397,29 +494,26 @@ void minip_rx_driver_callback(netif_t *netif, pktbuf_t *p) {
|
||||
}
|
||||
|
||||
if (memcmp(eth->dst_mac, netif->mac_address, 6) != 0 &&
|
||||
memcmp(eth->dst_mac, broadcast_mac, 6) != 0) {
|
||||
memcmp(eth->dst_mac, bcast_mac, 6) != 0) {
|
||||
/* not for us */
|
||||
return;
|
||||
}
|
||||
|
||||
switch (htons(eth->type)) {
|
||||
case ETH_TYPE_IPV4:
|
||||
LTRACEF("ipv4 pkt\n");
|
||||
handle_ipv4_packet(netif, p, eth->src_mac);
|
||||
break;
|
||||
|
||||
case ETH_TYPE_ARP:
|
||||
LTRACEF("arp pkt\n");
|
||||
handle_arp_pkt(netif, p);
|
||||
break;
|
||||
default:
|
||||
LTRACEF("unhandled pkt type %#hx\n", htons(eth->type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void print_mac_address(const uint8_t *mac) {
|
||||
printf("%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
|
||||
// utility routines
|
||||
uint32_t minip_parse_ipaddr(const char *ipaddr_str, size_t len) {
|
||||
uint8_t ip[4] = { 0, 0, 0, 0 };
|
||||
uint8_t pos = 0, i = 0;
|
||||
@@ -440,19 +534,23 @@ uint32_t minip_parse_ipaddr(const char *ipaddr_str, size_t len) {
|
||||
return IPV4_PACK(ip);
|
||||
}
|
||||
|
||||
// printf the ip address passed in
|
||||
void printip(uint32_t x) {
|
||||
void print_mac_address(const uint8_t *mac) {
|
||||
printf("%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
|
||||
void print_ipv4_address(ipv4_addr_t x) {
|
||||
union {
|
||||
u32 u;
|
||||
u8 b[4];
|
||||
uint32_t u;
|
||||
uint8_t b[4];
|
||||
} ip;
|
||||
ip.u = x;
|
||||
printf("%d.%d.%d.%d", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
|
||||
}
|
||||
|
||||
void printip_named(const char *s, uint32_t x) {
|
||||
void print_ipv4_address_named(const char *s, ipv4_addr_t x) {
|
||||
printf("%s ", s);
|
||||
printip(x);
|
||||
print_ipv4_address(x);
|
||||
}
|
||||
|
||||
// run static initialization
|
||||
@@ -462,5 +560,4 @@ static void minip_init(uint level) {
|
||||
netif_init();
|
||||
}
|
||||
|
||||
|
||||
LK_INIT_HOOK(minip, minip_init, LK_INIT_LEVEL_THREADING);
|
||||
|
||||
@@ -25,12 +25,6 @@ static struct list_node netif_list = LIST_INITIAL_VALUE(netif_list);
|
||||
static mutex_t lock = MUTEX_INITIAL_VALUE(lock);
|
||||
static netif_t loopback;
|
||||
|
||||
// Used by the ip layer to directly get a handle to the loopback and first
|
||||
// registered interface (main).
|
||||
// TODO: remove once proper routing is in place
|
||||
netif_t *netif_loopback = NULL;
|
||||
netif_t *netif_main = NULL;
|
||||
|
||||
static int loopback_tx_func(void *arg, pktbuf_t *p) {
|
||||
LTRACEF("arg %p, pkt %p\n", arg, p);
|
||||
return 0;
|
||||
@@ -41,12 +35,10 @@ void netif_init(void) {
|
||||
|
||||
// loopback device
|
||||
netif_create(&loopback, "loopback");
|
||||
loopback.flags |= NETIF_FLAG_LOOPBACK;
|
||||
netif_set_eth(&loopback, loopback_tx_func, NULL, bcast_mac);
|
||||
netif_set_ipv4_addr(&loopback, IPV4(128, 0, 0, 1), 8);
|
||||
netif_set_ipv4_addr(&loopback, IPV4(127, 0, 0, 1), 8);
|
||||
netif_register(&loopback);
|
||||
|
||||
// publish for the main stack to find
|
||||
netif_loopback = &loopback;
|
||||
}
|
||||
|
||||
netif_t *netif_create(netif_t *n, const char *name) {
|
||||
@@ -56,7 +48,7 @@ netif_t *netif_create(netif_t *n, const char *name) {
|
||||
n = malloc(sizeof(netif_t));
|
||||
}
|
||||
if (!n) {
|
||||
return n;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(n, 0, sizeof(*n));
|
||||
@@ -67,6 +59,15 @@ netif_t *netif_create(netif_t *n, const char *name) {
|
||||
return n;
|
||||
}
|
||||
|
||||
// generic logic to decide what to do when a netif comes up
|
||||
// TODO: make this overridable
|
||||
void netif_registration_callback(netif_t *n) {
|
||||
// if the interface isn't already configured, kick off a dhcp thread
|
||||
if ((n->flags & NETIF_FLAG_IPV4_CONFIGURED) == 0) {
|
||||
minip_start_dhcp(n);
|
||||
}
|
||||
}
|
||||
|
||||
status_t netif_register(netif_t *n) {
|
||||
LTRACEF("n %p\n", n);
|
||||
|
||||
@@ -81,14 +82,11 @@ status_t netif_register(netif_t *n) {
|
||||
list_add_head(&netif_list, &n->node);
|
||||
n->flags |= NETIF_FLAG_REGISTERED;
|
||||
|
||||
// TODO: replace with mechanism to set up ip routing (probably in DHCP)
|
||||
if (netif_main == NULL && n != &loopback) {
|
||||
// register this as the 'main' interface
|
||||
netif_main = n;
|
||||
}
|
||||
|
||||
mutex_release(&lock);
|
||||
|
||||
// let overridable external logic deal with this
|
||||
netif_registration_callback(n);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -123,6 +121,9 @@ status_t netif_set_ipv4_addr(netif_t *n, ipv4_addr_t addr, uint8_t subnet_width)
|
||||
|
||||
mutex_release(&lock);
|
||||
|
||||
// set an ipv4 route for this
|
||||
ipv4_add_route(netif_get_network_ipv4(n), netif_get_netmask_ipv4(n), n);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -134,12 +135,12 @@ void netif_dump(void) {
|
||||
printf("net interface @%p: name '%s' mac ", n, n->name);
|
||||
print_mac_address(n->mac_address);
|
||||
printf(" addr ");
|
||||
printip(n->ipv4_addr);
|
||||
print_ipv4_address(n->ipv4_addr);
|
||||
printf("/%u", n->ipv4_subnet_width);
|
||||
printf(" netmask ");
|
||||
printip(netif_get_netmask_ipv4(n));
|
||||
print_ipv4_address(netif_get_netmask_ipv4(n));
|
||||
printf(" bcast ");
|
||||
printip(netif_get_broadcast_ipv4(n));
|
||||
print_ipv4_address(netif_get_broadcast_ipv4(n));
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -36,14 +36,6 @@ typedef struct tcp_header {
|
||||
uint16_t urg_pointer;
|
||||
} __PACKED tcp_header_t;
|
||||
|
||||
typedef struct tcp_pseudo_header {
|
||||
ipv4_addr_t source_addr;
|
||||
ipv4_addr_t dest_addr;
|
||||
uint8_t zero;
|
||||
uint8_t protocol;
|
||||
uint16_t tcp_length;
|
||||
} __PACKED tcp_pseudo_header_t;
|
||||
|
||||
typedef struct tcp_mss_option {
|
||||
uint8_t kind; /* 0x2 */
|
||||
uint8_t len; /* 0x4 */
|
||||
@@ -84,6 +76,7 @@ typedef struct tcp_socket {
|
||||
ipv4_addr_t remote_ip;
|
||||
uint16_t local_port;
|
||||
uint16_t remote_port;
|
||||
ipv4_route_t *route;
|
||||
|
||||
uint32_t mss;
|
||||
|
||||
@@ -121,7 +114,7 @@ typedef struct tcp_socket {
|
||||
#define DEFAULT_RX_WINDOW_SIZE (8192)
|
||||
#define DEFAULT_TX_BUFFER_SIZE (8192)
|
||||
|
||||
#define RETRANSMIT_TIMEOUT (50)
|
||||
#define RETRANSMIT_TIMEOUT (250)
|
||||
#define DELAYED_ACK_TIMEOUT (50)
|
||||
#define TIME_WAIT_TIMEOUT (60000) // 1 minute
|
||||
|
||||
@@ -156,11 +149,6 @@ static void tcp_wakeup_waiters(tcp_socket_t *s);
|
||||
static void inc_socket_ref(tcp_socket_t *s);
|
||||
static bool dec_socket_ref(tcp_socket_t *s);
|
||||
|
||||
static uint16_t cksum_pheader(const tcp_pseudo_header_t *pheader, const void *buf, size_t len) {
|
||||
uint16_t checksum = ones_sum16(0, pheader, sizeof(*pheader));
|
||||
return ~ones_sum16(checksum, buf, len);
|
||||
}
|
||||
|
||||
__NO_INLINE static void dump_tcp_header(const tcp_header_t *header) {
|
||||
printf("TCP: src_port %u, dest_port %u, seq %u, ack %u, win %u, flags %c%c%c%c%c%c\n",
|
||||
ntohs(header->source_port), ntohs(header->dest_port), ntohl(header->seq_num), ntohl(header->ack_num),
|
||||
@@ -299,6 +287,10 @@ static bool dec_socket_ref(tcp_socket_t *s) {
|
||||
|
||||
if (oldval == 1) {
|
||||
LTRACEF("destroying socket\n");
|
||||
if (s->route) {
|
||||
ipv4_dec_route_ref(s->route);
|
||||
s->route = NULL;
|
||||
}
|
||||
event_destroy(&s->tx_event);
|
||||
event_destroy(&s->rx_event);
|
||||
event_destroy(&s->connect_event);
|
||||
@@ -351,7 +343,7 @@ void tcp_input(netif_t *netif, pktbuf_t *p, uint32_t src_ip, uint32_t dst_ip) {
|
||||
|
||||
/* checksum */
|
||||
if (FORCE_TCP_CHECKSUM || (p->flags & PKTBUF_FLAG_CKSUM_TCP_GOOD) == 0) {
|
||||
tcp_pseudo_header_t pheader;
|
||||
ipv4_pseudo_header_t pheader;
|
||||
|
||||
// set up the pseudo header for checksum purposes
|
||||
pheader.source_addr = src_ip;
|
||||
@@ -433,6 +425,13 @@ void tcp_input(netif_t *netif, pktbuf_t *p, uint32_t src_ip, uint32_t dst_ip) {
|
||||
accept_socket->remote_port = header->source_port;
|
||||
accept_socket->state = STATE_SYN_RCVD;
|
||||
|
||||
/* look up and cache the route for the accepted socket */
|
||||
ipv4_route_t *route = ipv4_search_route(src_ip);
|
||||
if (!route) {
|
||||
goto done;
|
||||
}
|
||||
accept_socket->route = route;
|
||||
|
||||
mutex_acquire(&accept_socket->lock);
|
||||
|
||||
add_socket_to_list(accept_socket);
|
||||
@@ -751,7 +750,7 @@ static status_t tcp_send(ipv4_addr_t dest_ip, uint16_t dest_port, ipv4_addr_t sr
|
||||
/* compute the checksum */
|
||||
/* XXX get the tx ckecksum capability from the nic */
|
||||
if (FORCE_TCP_CHECKSUM || true) {
|
||||
tcp_pseudo_header_t pheader;
|
||||
ipv4_pseudo_header_t pheader;
|
||||
pheader.source_addr = src_ip;
|
||||
pheader.dest_addr = dest_ip;
|
||||
pheader.zero = 0;
|
||||
@@ -994,14 +993,15 @@ status_t tcp_connect(tcp_socket_t **handle, uint32_t addr, uint16_t port) {
|
||||
|
||||
// XXX add some entropy to try to better randomize things
|
||||
lk_bigtime_t t = current_time_hires();
|
||||
printf("%lld\n", t);
|
||||
rand_add_entropy(&t, sizeof(t));
|
||||
|
||||
// TODO: look up route to set local address
|
||||
netif_t *netif = netif_main;
|
||||
if (!netif) {
|
||||
// look up route to set local address
|
||||
ipv4_route_t *route = ipv4_search_route(addr);
|
||||
if (!route) {
|
||||
return ERR_NO_ROUTE;
|
||||
}
|
||||
netif_t *netif = route->interface;
|
||||
s->route = route;
|
||||
|
||||
// set up the socket for outgoing connections
|
||||
s->local_ip = netif->ipv4_addr;
|
||||
@@ -1034,6 +1034,7 @@ status_t tcp_connect(tcp_socket_t **handle, uint32_t addr, uint16_t port) {
|
||||
|
||||
// block to wait for a successful connection
|
||||
if (event_wait(&s->connect_event) == ERR_TIMED_OUT) {
|
||||
ipv4_dec_route_ref(s->route);
|
||||
return ERR_TIMED_OUT;
|
||||
}
|
||||
|
||||
@@ -1283,7 +1284,7 @@ out:
|
||||
}
|
||||
|
||||
/* debug stuff */
|
||||
static int cmd_tcp(int argc, const console_cmd_args *argv) {
|
||||
int cmd_tcp(int argc, const console_cmd_args *argv) {
|
||||
if (argc < 2) {
|
||||
notenoughargs:
|
||||
printf("ERROR not enough arguments\n");
|
||||
@@ -1366,7 +1367,3 @@ usage:
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
STATIC_COMMAND_START
|
||||
STATIC_COMMAND("tcp", "tcp commands", &cmd_tcp)
|
||||
STATIC_COMMAND_END(tcp);
|
||||
|
||||
|
||||
100
lib/minip/udp.c
100
lib/minip/udp.c
@@ -30,10 +30,13 @@ struct udp_listener {
|
||||
};
|
||||
|
||||
typedef struct udp_socket {
|
||||
uint32_t host;
|
||||
ipv4_addr_t local_ip;
|
||||
ipv4_addr_t remote_ip;
|
||||
uint16_t sport;
|
||||
uint16_t dport;
|
||||
const uint8_t *mac;
|
||||
ipv4_route_t *route;
|
||||
|
||||
// only set if bound to a particular network interface
|
||||
netif_t *netif;
|
||||
} udp_socket_t;
|
||||
|
||||
@@ -44,7 +47,6 @@ typedef struct udp_hdr {
|
||||
uint16_t chksum;
|
||||
} __PACKED udp_hdr_t;
|
||||
|
||||
|
||||
int udp_listen(uint16_t port, udp_callback_t cb, void *arg) {
|
||||
struct udp_listener *entry, *temp;
|
||||
|
||||
@@ -71,33 +73,61 @@ int udp_listen(uint16_t port, udp_callback_t cb, void *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t udp_open(uint32_t host, uint16_t sport, uint16_t dport, udp_socket_t **handle) {
|
||||
status_t udp_open(ipv4_addr_t host, uint16_t sport, uint16_t dport, udp_socket_t **handle) {
|
||||
LTRACEF("host %u.%u.%u.%u sport %u dport %u handle %p\n",
|
||||
IPV4_SPLIT(host), sport, dport, handle);
|
||||
udp_socket_t *socket;
|
||||
const uint8_t *dst_mac;
|
||||
|
||||
if (handle == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
socket = (udp_socket_t *) malloc(sizeof(udp_socket_t));
|
||||
socket = (udp_socket_t *) calloc(1, sizeof(udp_socket_t));
|
||||
if (!socket) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dst_mac = arp_get_dest_mac(host);
|
||||
if (dst_mac == NULL) {
|
||||
free(socket);
|
||||
return -EHOSTUNREACH;
|
||||
// look up route to set local address
|
||||
ipv4_route_t *route = ipv4_search_route(host);
|
||||
if (!route) {
|
||||
return ERR_NO_ROUTE;
|
||||
}
|
||||
|
||||
socket->host = host;
|
||||
netif_t *netif = route->interface;
|
||||
|
||||
socket->local_ip = netif->ipv4_addr;
|
||||
socket->remote_ip = host;
|
||||
socket->sport = sport;
|
||||
socket->dport = dport;
|
||||
socket->mac = dst_mac;
|
||||
// TODO: replace with route lookup
|
||||
socket->netif = netif_main;
|
||||
socket->route = route;
|
||||
|
||||
*handle = socket;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t udp_open_raw(ipv4_addr_t host, uint16_t sport, uint16_t dport, netif_t *netif, udp_socket_t **handle) {
|
||||
LTRACEF("host %u.%u.%u.%u sport %u dport %u netif '%s' handle %p\n",
|
||||
IPV4_SPLIT(host), sport, dport, netif->name, handle);
|
||||
udp_socket_t *socket;
|
||||
|
||||
if (handle == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (netif == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
socket = (udp_socket_t *) calloc(1, sizeof(udp_socket_t));
|
||||
if (!socket) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
socket->local_ip = netif->ipv4_addr;
|
||||
socket->remote_ip = host;
|
||||
socket->sport = sport;
|
||||
socket->dport = dport;
|
||||
socket->netif = netif;
|
||||
|
||||
*handle = socket;
|
||||
|
||||
@@ -109,16 +139,17 @@ status_t udp_close(udp_socket_t *handle) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (handle->route) {
|
||||
ipv4_dec_route_ref(handle->route);
|
||||
}
|
||||
|
||||
free(handle);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t udp_send_iovec(const iovec_t *iov, uint iov_count, udp_socket_t *handle) {
|
||||
pktbuf_t *p;
|
||||
struct eth_hdr *eth;
|
||||
struct ipv4_hdr *ip;
|
||||
udp_hdr_t *udp;
|
||||
status_t ret = NO_ERROR;
|
||||
void *buf;
|
||||
ssize_t len;
|
||||
|
||||
@@ -130,37 +161,42 @@ status_t udp_send_iovec(const iovec_t *iov, uint iov_count, udp_socket_t *handle
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (handle->netif == NULL) {
|
||||
LTRACEF("aborting send due to lack of netif\n");
|
||||
return -EHOSTUNREACH;
|
||||
}
|
||||
|
||||
len = iovec_size(iov, iov_count);
|
||||
|
||||
buf = pktbuf_append(p, len);
|
||||
udp = pktbuf_prepend(p, sizeof(udp_hdr_t));
|
||||
ip = pktbuf_prepend(p, sizeof(struct ipv4_hdr));
|
||||
eth = pktbuf_prepend(p, sizeof(struct eth_hdr));
|
||||
|
||||
iovec_to_membuf(buf, len, iov, iov_count, 0);
|
||||
|
||||
udp = pktbuf_prepend(p, sizeof(udp_hdr_t));
|
||||
udp->src_port = htons(handle->sport);
|
||||
udp->dst_port = htons(handle->dport);
|
||||
udp->len = htons(sizeof(udp_hdr_t) + len);
|
||||
udp->chksum = 0;
|
||||
|
||||
minip_build_mac_hdr(handle->netif, eth, handle->mac, ETH_TYPE_IPV4);
|
||||
minip_build_ipv4_hdr(handle->netif, ip, handle->host, IP_PROTO_UDP, len + sizeof(udp_hdr_t));
|
||||
#if MINIP_USE_UDP_CHECKSUM
|
||||
{
|
||||
ipv4_pseudo_header_t pheader;
|
||||
pheader.source_addr = handle->local_ip;
|
||||
pheader.dest_addr = handle->remote_ip;
|
||||
pheader.zero = 0;
|
||||
pheader.protocol = IP_PROTO_UDP;
|
||||
pheader.tcp_length = htons(p->dlen);
|
||||
|
||||
#if (MINIP_USE_UDP_CHECKSUM != 0)
|
||||
udp->chksum = rfc768_chksum(ip, udp);
|
||||
udp->chksum = cksum_pheader(&pheader, p->data, p->dlen);
|
||||
}
|
||||
#endif
|
||||
|
||||
LTRACEF("packet paylod len %ld\n", len);
|
||||
LTRACEF("sending udp packet, len %u\n", p->dlen);
|
||||
|
||||
handle->netif->tx_func(handle->netif->tx_func_arg, p);
|
||||
status_t err;
|
||||
if (handle->netif) {
|
||||
// XXX: does this always use the broadcast mac?
|
||||
err = minip_ipv4_send_raw(p, handle->remote_ip, IP_PROTO_UDP, bcast_mac, handle->netif);
|
||||
} else {
|
||||
err = minip_ipv4_send(p, handle->remote_ip, IP_PROTO_UDP);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t udp_send(void *buf, size_t len, udp_socket_t *handle) {
|
||||
|
||||
@@ -222,8 +222,6 @@ void platform_init(void) {
|
||||
TRACEF("found virtio networking interface\n");
|
||||
|
||||
virtio_net_start();
|
||||
|
||||
minip_start_dhcp();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user