net: add methods to configure addresses

This commit is contained in:
K Lange 2021-06-06 18:34:24 +09:00
parent 5eaeced119
commit 5106daf9f6
4 changed files with 161 additions and 99 deletions

View File

@ -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;
}

View File

@ -5,7 +5,89 @@
* Manipulates and enumerates network interfaces.
*/
#include <stdio.h>
#include <stdint.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
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;
}

View File

@ -18,12 +18,14 @@
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <dirent.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/fswait.h>
#include <sys/socket.h>
#include <toaru/yutani.h>
#include <toaru/graphics.h>
@ -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);

View File

@ -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;