From 5106daf9f6c6812ffa46010dca181a0af5db5fbe Mon Sep 17 00:00:00 2001 From: K Lange Date: Sun, 6 Jun 2021 18:34:24 +0900 Subject: [PATCH] net: add methods to configure addresses --- apps/dhclient.c | 6 +- apps/ifconfig.c | 84 ++++++++++++++++++++++++- apps/panel.c | 153 +++++++++++++++++---------------------------- kernel/net/e1000.c | 17 ++++- 4 files changed, 161 insertions(+), 99 deletions(-) diff --git a/apps/dhclient.c b/apps/dhclient.c index 68634e4d..40ad4d33 100644 --- a/apps/dhclient.c +++ b/apps/dhclient.c @@ -332,7 +332,11 @@ static int configure_interface(const char * if_name) { yiaddr = response->dhcp_header.yiaddr; char yiaddr_ip[16]; ip_ntoa(ntohl(yiaddr), yiaddr_ip); - printf("%s: %s: configured for %s\n", _argv_0, if_name, yiaddr_ip); + if (!ioctl(netdev, 0x12340012, &yiaddr)) { + printf("%s: %s: configured for %s\n", _argv_0, if_name, yiaddr_ip); + } else { + perror(_argv_0); + } close(netdev); return 0; } diff --git a/apps/ifconfig.c b/apps/ifconfig.c index 9ddbc00e..76dec128 100644 --- a/apps/ifconfig.c +++ b/apps/ifconfig.c @@ -5,7 +5,89 @@ * Manipulates and enumerates network interfaces. */ #include +#include +#include +#include +#include +#include +#include +#include + +extern char * _argv_0; + +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 int configure_interface(const char * if_name) { + char if_path[100]; + snprintf(if_path, 100, "/dev/net/%s", if_name); + int netdev = open(if_path, O_RDWR); + + if (netdev < 0) { + perror(_argv_0); + return 1; + } + + fprintf(stdout,"%s:\n", if_name); /* + flags? */ + + /* Get IPv4 address */ + uint32_t ip_addr; + if (!ioctl(netdev, 0x12340002, &ip_addr)) { + char ip_str[16]; + ip_ntoa(ntohl(ip_addr), ip_str); + fprintf(stdout," inet %s\n", ip_str); + } + + uint8_t ip6_addr[16]; + if (!ioctl(netdev, 0x12340003, &ip6_addr)) { + /* TODO inet6 address to nice string */ + fprintf(stdout," inet6 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + ip6_addr[0], ip6_addr[1], ip6_addr[2], ip6_addr[3], + ip6_addr[4], ip6_addr[5], ip6_addr[6], ip6_addr[7], + ip6_addr[8], ip6_addr[9], ip6_addr[10], ip6_addr[11], + ip6_addr[12], ip6_addr[13], ip6_addr[14], ip6_addr[15]); + } + + /* Get ethernet address */ + uint8_t mac_addr[6]; + if (!ioctl(netdev, 0x12340001, &mac_addr)) { + fprintf(stdout," ether %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + } + + return 0; +} int main(int argc, char * argv[]) { - /* I have no idea how this works on Linux or BSD, but based on some manpages... */ + int retval = 0; + + if (argc > 1) { + return configure_interface(argv[1]); + } else { + /* Read /dev/net for interfaces */ + DIR * d = opendir("/dev/net"); + if (!d) { + fprintf(stderr, "%s: no network?\n", _argv_0); + return 1; + } + + struct dirent * ent; + while ((ent = readdir(d))) { + if (ent->d_name[0] == '.') continue; + if (configure_interface(ent->d_name)) { + retval = 1; + } + } + + closedir(d); + } + + return retval; } diff --git a/apps/panel.c b/apps/panel.c index 8b42600f..e35a3f01 100644 --- a/apps/panel.c +++ b/apps/panel.c @@ -18,12 +18,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -388,86 +390,56 @@ static void update_weather_status(void) { } static int netstat_left = 0; +static int netstat_count = 0; +static char netstat_data[32][1024]; -static struct MenuEntry_Normal * netstat_ip_entry; -static char * netstat_ip = NULL; -static struct MenuEntry_Normal * netstat_device_entry; -static char * netstat_device = NULL; -static struct MenuEntry_Normal * netstat_gateway_entry; -static char * netstat_gateway = NULL; -static struct MenuEntry_Normal * netstat_dns_entry; -static char * netstat_dns = NULL; -static struct MenuEntry_Normal * netstat_mac_entry; -static char * netstat_mac = NULL; +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 void check_network(const char * if_name) { + if (netstat_count >= 32) return; + + char if_path[512]; + snprintf(if_path, 511, "/dev/net/%s", if_name); + int netdev = open(if_path, O_RDWR); + + if (netdev < 0) return; + + /* Get IPv4 address */ + uint32_t ip_addr; + if (!ioctl(netdev, 0x12340002, &ip_addr)) { + char ip_str[16]; + ip_ntoa(ntohl(ip_addr), ip_str); + snprintf(netstat_data[netstat_count], 1023, "%s: %s", if_name, ip_str); + network_status |= 2; + } else { + snprintf(netstat_data[netstat_count], 1023, "%s: disconnected", if_name); + network_status |= 1; + } + + close(netdev); + netstat_count++; +} static void update_network_status(void) { - FILE * net = fopen("/proc/netif","r"); + network_status = 0; + netstat_count = 0; - if (!net) return; + DIR * d = opendir("/dev/net"); + if (!d) return; - char line[256]; + struct dirent * ent; + while ((ent = readdir(d))) { + if (ent->d_name[0] == '.') continue; + check_network(ent->d_name); + } - do { - memset(line, 0, 256); - fgets(line, 256, net); - if (!*line) break; - if (strstr(line,"no network") != NULL) { - network_status = 0; - break; - } else if (strstr(line,"ip:") != NULL) { - network_status = 1; - if (netstat_ip) { - free(netstat_ip); - } - char tmp[512]; - sprintf(tmp, "IP: %s", &line[strlen("ip: ")]); - char * lf = strstr(tmp,"\n"); - if (lf) *lf = '\0'; - netstat_ip = strdup(tmp); - } else if (strstr(line,"device:") != NULL) { - network_status = 1; - if (netstat_device) { - free(netstat_device); - } - char tmp[512]; - sprintf(tmp, "Device: %s", &line[strlen("device: ")]); - char * lf = strstr(tmp,"\n"); - if (lf) *lf = '\0'; - netstat_device = strdup(tmp); - } else if (strstr(line,"gateway:") != NULL) { - network_status = 1; - if (netstat_gateway) { - free(netstat_gateway); - } - char tmp[512]; - sprintf(tmp, "Gateway: %s", &line[strlen("gateway: ")]); - char * lf = strstr(tmp,"\n"); - if (lf) *lf = '\0'; - netstat_gateway = strdup(tmp); - } else if (strstr(line,"dns:") != NULL) { - network_status = 1; - if (netstat_dns) { - free(netstat_dns); - } - char tmp[512]; - sprintf(tmp, "Primary DNS: %s", &line[strlen("dns: ")]); - char * lf = strstr(tmp,"\n"); - if (lf) *lf = '\0'; - netstat_dns = strdup(tmp); - } else if (strstr(line,"mac:") != NULL) { - network_status = 1; - if (netstat_mac) { - free(netstat_mac); - } - char tmp[512]; - sprintf(tmp, "MAC: %s", &line[strlen("mac: ")]); - char * lf = strstr(tmp,"\n"); - if (lf) *lf = '\0'; - netstat_mac = strdup(tmp); - } - } while (1); - - fclose(net); + closedir(d); } static void show_logout_menu(void) { @@ -561,29 +533,18 @@ static void show_network_status(void) { netstat = menu_create(); menu_insert(netstat, menu_create_normal(NULL, NULL, "Network Status", NULL)); menu_insert(netstat, menu_create_separator()); - netstat_ip_entry = (struct MenuEntry_Normal *)menu_create_normal(NULL, NULL, "", NULL); - menu_insert(netstat, netstat_ip_entry); - netstat_dns_entry = (struct MenuEntry_Normal *)menu_create_normal(NULL, NULL, "", NULL); - menu_insert(netstat, netstat_dns_entry); - netstat_gateway_entry = (struct MenuEntry_Normal *)menu_create_normal(NULL, NULL, "", NULL); - menu_insert(netstat, netstat_gateway_entry); - netstat_mac_entry = (struct MenuEntry_Normal *)menu_create_normal(NULL, NULL, "", NULL); - menu_insert(netstat, netstat_mac_entry); - netstat_device_entry = (struct MenuEntry_Normal *)menu_create_normal(NULL, NULL, "", NULL); - menu_insert(netstat, netstat_device_entry); } - if (network_status) { - menu_update_title(netstat_ip_entry, netstat_ip); - menu_update_title(netstat_device_entry, netstat_device ? netstat_device : "(?)"); - menu_update_title(netstat_dns_entry, netstat_dns ? netstat_dns : "(?)"); - menu_update_title(netstat_gateway_entry, netstat_gateway ? netstat_gateway : "(?)"); - menu_update_title(netstat_mac_entry, netstat_mac ? netstat_mac : "(?)"); + while (netstat->entries->length > 2) { + node_t * node = list_pop(netstat->entries); + menu_free_entry((struct MenuEntry *)node->value); + free(node); + } + if (!network_status) { + menu_insert(netstat, menu_create_normal(NULL, NULL, "No network.", NULL)); } else { - menu_update_title(netstat_ip_entry, "No network."); - menu_update_title(netstat_device_entry, ""); - menu_update_title(netstat_dns_entry, ""); - menu_update_title(netstat_gateway_entry, ""); - menu_update_title(netstat_mac_entry, ""); + for (int i = 0; i < netstat_count; ++i) { + menu_insert(netstat, menu_create_normal(NULL, NULL, netstat_data[i], NULL)); + } } if (!netstat->window) { menu_show(netstat, yctx); @@ -1027,7 +988,7 @@ static void redraw(void) { /* - Network */ if (widgets_network_enabled) { uint32_t color = (netstat && netstat->window) ? HILIGHT_COLOR : ICON_COLOR; - if (network_status == 1) { + if (network_status & 2) { draw_sprite_alpha_paint(ctx, sprite_net_active, WIDGET_POSITION(widget), 0, 1.0, color); } else { draw_sprite_alpha_paint(ctx, sprite_net_disabled, WIDGET_POSITION(widget), 0, 1.0, color); diff --git a/kernel/net/e1000.c b/kernel/net/e1000.c index 0b0ff9e2..77da4646 100644 --- a/kernel/net/e1000.c +++ b/kernel/net/e1000.c @@ -32,6 +32,9 @@ struct e1000_nic { /* This should be generic netif struct stuff... */ char if_name[32]; uint8_t mac[6]; + /* XXX: just to get things going */ + uint32_t ipv4_addr; + uint8_t ipv6_addr[16]; /* TODO: Address lists? */ fs_node_t * device_node; @@ -290,6 +293,18 @@ static int ioctl_e1000(fs_node_t * node, int request, void * argp) { /* fill argp with mac */ memcpy(argp, nic->mac, 6); return 0; + case 0x12340002: + if (nic->ipv4_addr == 0) return -ENOENT; + memcpy(argp, &nic->ipv4_addr, sizeof(nic->ipv4_addr)); + return 0; + case 0x12340012: + memcpy(&nic->ipv4_addr, argp, sizeof(nic->ipv4_addr)); + return 0; + case 0x12340003: + return -ENOENT; + case 0x12340013: + memcpy(&nic->ipv6_addr, argp, sizeof(nic->ipv6_addr)); + return 0; default: return -EINVAL; } @@ -449,7 +464,7 @@ static void e1000_init(void * data) { nic->device_node = calloc(sizeof(fs_node_t),1); snprintf(nic->device_node->name, 100, "%s", nic->if_name); nic->device_node->flags = FS_BLOCKDEVICE; /* NETDEVICE? */ - nic->device_node->mask = 0600; /* Only root can access network devices directly */ + nic->device_node->mask = 0666; /* temporary; shouldn't be doing this with these device files */ nic->device_node->ioctl = ioctl_e1000; nic->device_node->write = write_e1000; nic->device_node->read = read_e1000;