Skip to content

Commit caa39eb

Browse files
committed
sysdeps/zinnia: Implement getifaddrs and InetConfigured
1 parent 652f6e0 commit caa39eb

6 files changed

Lines changed: 284 additions & 3 deletions

File tree

abis/zinnia/ioctls.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,20 @@
9696
#define TIOCSER_TEMT 0x01
9797

9898
#define SIOCPROTOPRIVATE 0x89E0
99+
#define SIOCADDRT 0x890B
100+
#define SIOCDELRT 0x890C
99101
#define SIOCGIFNAME 0x8910
100102
#define SIOCGIFCONF 0x8912
101103
#define SIOCGIFFLAGS 0x8913
102104
#define SIOCSIFFLAGS 0x8914
105+
#define SIOCGIFADDR 0x8915
106+
#define SIOCSIFADDR 0x8916
107+
#define SIOCGIFNETMASK 0x891B
108+
#define SIOCSIFNETMASK 0x891C
109+
#define SIOCGIFBRDADDR 0x8919
110+
#define SIOCSIFBRDADDR 0x891A
111+
#define SIOCGIFMTU 0x8921
112+
#define SIOCSIFMTU 0x8922
103113
#define SIOCGIFINDEX 0x8933
104114
#define SIOCATMARK 0x8905
105115
#define SIOCGIFHWADDR 0x8927

sysdeps/zinnia/generic/ifaddrs.cpp

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,142 @@
1+
#include <errno.h>
12
#include <ifaddrs.h>
3+
#include <net/if.h>
4+
#include <net/if_arp.h>
5+
#include <netinet/in.h>
6+
#include <netpacket/packet.h>
27
#include <stdlib.h>
8+
#include <string.h>
9+
#include <sys/ioctl.h>
10+
#include <sys/socket.h>
11+
#include <unistd.h>
312

4-
// TODO
13+
namespace {
14+
15+
struct ifaddrs *alloc_node(const char *name, size_t addrspace) {
16+
size_t sz = sizeof(struct ifaddrs) + IF_NAMESIZE + addrspace;
17+
char *block = (char *)malloc(sz);
18+
if (!block)
19+
return nullptr;
20+
memset(block, 0, sz);
21+
struct ifaddrs *ifa = (struct ifaddrs *)block;
22+
char *namep = block + sizeof(struct ifaddrs);
23+
strlcpy(namep, name, IF_NAMESIZE);
24+
ifa->ifa_name = namep;
25+
return ifa;
26+
}
27+
28+
void *node_addr(struct ifaddrs *ifa) {
29+
return (char *)ifa + sizeof(struct ifaddrs) + IF_NAMESIZE;
30+
}
31+
32+
void append(struct ifaddrs **head, struct ifaddrs **tail, struct ifaddrs *ifa) {
33+
if (*tail)
34+
(*tail)->ifa_next = ifa;
35+
else
36+
*head = ifa;
37+
*tail = ifa;
38+
}
39+
40+
}
541

642
int getifaddrs(struct ifaddrs **ifap) {
743
*ifap = nullptr;
44+
45+
int fd = socket(AF_INET, SOCK_DGRAM, 0);
46+
if (fd < 0)
47+
return -1;
48+
49+
struct ifconf ifc;
50+
memset(&ifc, 0, sizeof(ifc));
51+
if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
52+
close(fd);
53+
return -1;
54+
}
55+
56+
char *buf = nullptr;
57+
if (ifc.ifc_len > 0) {
58+
buf = (char *)malloc((size_t)ifc.ifc_len);
59+
if (!buf) {
60+
close(fd);
61+
errno = ENOMEM;
62+
return -1;
63+
}
64+
ifc.ifc_buf = buf;
65+
if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
66+
free(buf);
67+
close(fd);
68+
return -1;
69+
}
70+
}
71+
72+
size_t count = (size_t)ifc.ifc_len / sizeof(struct ifreq);
73+
struct ifaddrs *head = nullptr, *tail = nullptr;
74+
75+
for (size_t i = 0; i < count; i++) {
76+
struct ifreq *src = ((struct ifreq *)buf) + i;
77+
char name[IF_NAMESIZE];
78+
strlcpy(name, src->ifr_name, IF_NAMESIZE);
79+
80+
struct ifreq req;
81+
short flags = 0;
82+
memset(&req, 0, sizeof(req));
83+
strlcpy(req.ifr_name, name, IF_NAMESIZE);
84+
if (ioctl(fd, SIOCGIFFLAGS, &req) == 0)
85+
flags = req.ifr_flags;
86+
87+
struct ifaddrs *ll = alloc_node(name, sizeof(struct sockaddr_ll));
88+
if (ll) {
89+
struct sockaddr_ll *sll = (struct sockaddr_ll *)node_addr(ll);
90+
sll->sll_family = AF_PACKET;
91+
sll->sll_hatype = ARPHRD_ETHER;
92+
sll->sll_halen = 6;
93+
94+
memset(&req, 0, sizeof(req));
95+
strlcpy(req.ifr_name, name, IF_NAMESIZE);
96+
if (ioctl(fd, SIOCGIFINDEX, &req) == 0)
97+
sll->sll_ifindex = req.ifr_ifindex;
98+
99+
memset(&req, 0, sizeof(req));
100+
strlcpy(req.ifr_name, name, IF_NAMESIZE);
101+
if (ioctl(fd, SIOCGIFHWADDR, &req) == 0)
102+
memcpy(sll->sll_addr, req.ifr_hwaddr.sa_data, 6);
103+
104+
ll->ifa_addr = (struct sockaddr *)sll;
105+
ll->ifa_flags = (unsigned int)flags;
106+
append(&head, &tail, ll);
107+
}
108+
109+
struct sockaddr_in *cfg = (struct sockaddr_in *)(void *)&src->ifr_addr;
110+
if (cfg->sin_family == AF_INET && cfg->sin_addr.s_addr != 0) {
111+
struct ifaddrs *in =
112+
alloc_node(name, 2 * sizeof(struct sockaddr_in));
113+
if (in) {
114+
struct sockaddr_in *addr =
115+
(struct sockaddr_in *)node_addr(in);
116+
struct sockaddr_in *netmask = addr + 1;
117+
118+
memcpy(addr, cfg, sizeof(struct sockaddr_in));
119+
addr->sin_family = AF_INET;
120+
in->ifa_addr = (struct sockaddr *)addr;
121+
122+
memset(&req, 0, sizeof(req));
123+
strlcpy(req.ifr_name, name, IF_NAMESIZE);
124+
if (ioctl(fd, SIOCGIFNETMASK, &req) == 0) {
125+
memcpy(netmask, &req.ifr_netmask,
126+
sizeof(struct sockaddr_in));
127+
netmask->sin_family = AF_INET;
128+
in->ifa_netmask = (struct sockaddr *)netmask;
129+
}
130+
131+
in->ifa_flags = (unsigned int)flags;
132+
append(&head, &tail, in);
133+
}
134+
}
135+
}
136+
137+
free(buf);
138+
close(fd);
139+
*ifap = head;
8140
return 0;
9141
}
10142

sysdeps/zinnia/generic/posix.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
#include <mlibc/all-sysdeps.hpp>
66
#include <mlibc/debug.hpp>
77
#include <mlibc/tcb.hpp>
8+
#include <ifaddrs.h>
89
#include <net/if.h>
10+
#include <netinet/in.h>
911
#include <stdio.h>
1012
#include <stdlib.h>
1113
#include <string.h>
@@ -873,11 +875,32 @@ int Sysdeps<IfNametoindex>::operator()(const char *name, unsigned int *ret) {
873875
}
874876

875877
int Sysdeps<InetConfigured>::operator()(bool *ipv4, bool *ipv6) {
876-
// TODO
877878
if (ipv4)
878-
*ipv4 = true;
879+
*ipv4 = false;
879880
if (ipv6)
880881
*ipv6 = false;
882+
#
883+
struct ifaddrs *ifaddr = nullptr;
884+
if (getifaddrs(&ifaddr) != 0)
885+
return 0;
886+
887+
for (struct ifaddrs *ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
888+
if (!ifa->ifa_addr || !ifa->ifa_name)
889+
continue;
890+
if (!strncmp(ifa->ifa_name, "lo", IF_NAMESIZE))
891+
continue;
892+
893+
if (ifa->ifa_addr->sa_family == AF_INET) {
894+
auto *in = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr);
895+
if (in->sin_addr.s_addr != 0 && ipv4)
896+
*ipv4 = true;
897+
} else if (ifa->ifa_addr->sa_family == AF_INET6) {
898+
if (ipv6)
899+
*ipv6 = true;
900+
}
901+
}
902+
903+
freeifaddrs(ifaddr);
881904
return 0;
882905
}
883906

sysdeps/zinnia/include/net/bpf.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#ifndef _NET_BPF_H
2+
#define _NET_BPF_H
3+
4+
#include <stdint.h>
5+
6+
struct bpf_insn {
7+
uint16_t code;
8+
uint8_t jt;
9+
uint8_t jf;
10+
uint32_t k;
11+
};
12+
13+
struct bpf_program {
14+
unsigned int bf_len;
15+
struct bpf_insn *bf_insns;
16+
};
17+
18+
#define BPF_STMT(code, k) { (uint16_t)(code), 0, 0, k }
19+
#define BPF_JUMP(code, k, jt, jf) { (uint16_t)(code), jt, jf, k }
20+
21+
#define BPF_CLASS(code) ((code) & 0x07)
22+
#define BPF_LD 0x00
23+
#define BPF_LDX 0x01
24+
#define BPF_ST 0x02
25+
#define BPF_STX 0x03
26+
#define BPF_ALU 0x04
27+
#define BPF_JMP 0x05
28+
#define BPF_RET 0x06
29+
#define BPF_MISC 0x07
30+
31+
#define BPF_SIZE(code) ((code) & 0x18)
32+
#define BPF_W 0x00
33+
#define BPF_H 0x08
34+
#define BPF_B 0x10
35+
#define BPF_MODE(code) ((code) & 0xe0)
36+
#define BPF_IMM 0x00
37+
#define BPF_ABS 0x20
38+
#define BPF_IND 0x40
39+
#define BPF_MEM 0x60
40+
#define BPF_LEN 0x80
41+
#define BPF_MSH 0xa0
42+
43+
#define BPF_OP(code) ((code) & 0xf0)
44+
#define BPF_ADD 0x00
45+
#define BPF_SUB 0x10
46+
#define BPF_MUL 0x20
47+
#define BPF_DIV 0x30
48+
#define BPF_OR 0x40
49+
#define BPF_AND 0x50
50+
#define BPF_LSH 0x60
51+
#define BPF_RSH 0x70
52+
#define BPF_NEG 0x80
53+
#define BPF_MOD 0x90
54+
#define BPF_XOR 0xa0
55+
56+
#define BPF_JA 0x00
57+
#define BPF_JEQ 0x10
58+
#define BPF_JGT 0x20
59+
#define BPF_JGE 0x30
60+
#define BPF_JSET 0x40
61+
#define BPF_SRC(code) ((code) & 0x08)
62+
#define BPF_K 0x00
63+
#define BPF_X 0x08
64+
65+
#define BPF_RVAL(code) ((code) & 0x18)
66+
#define BPF_A 0x10
67+
68+
#define BPF_MISCOP(code) ((code) & 0xf8)
69+
#define BPF_TAX 0x00
70+
#define BPF_TXA 0x80
71+
72+
#ifndef BPF_MAXINSNS
73+
#define BPF_MAXINSNS 4096
74+
#endif
75+
76+
#endif
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef _NETPACKET_PACKET_H
2+
#define _NETPACKET_PACKET_H
3+
4+
#define PACKET_HOST 0
5+
#define PACKET_BROADCAST 1
6+
#define PACKET_MULTICAST 2
7+
#define PACKET_OTHERHOST 3
8+
#define PACKET_OUTGOING 4
9+
#define PACKET_LOOPBACK 5
10+
#define PACKET_FASTROUTE 6
11+
12+
struct sockaddr_ll {
13+
unsigned short int sll_family;
14+
unsigned short int sll_protocol;
15+
int sll_ifindex;
16+
unsigned short int sll_hatype;
17+
unsigned char sll_pkttype;
18+
unsigned char sll_halen;
19+
unsigned char sll_addr[8];
20+
};
21+
22+
struct packet_mreq {
23+
int mr_ifindex;
24+
unsigned short int mr_type;
25+
unsigned short int mr_alen;
26+
unsigned char mr_address[8];
27+
};
28+
29+
#define PACKET_ADD_MEMBERSHIP 1
30+
#define PACKET_DROP_MEMBERSHIP 2
31+
32+
#define PACKET_MR_MULTICAST 0
33+
#define PACKET_MR_PROMISC 1
34+
#define PACKET_MR_ALLMULTI 2
35+
#define PACKET_MR_UNICAST 3
36+
37+
#endif

sysdeps/zinnia/meson.build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ if not no_headers
107107

108108
install_headers('include/mntent.h')
109109
install_headers('include/ifaddrs.h')
110+
111+
install_headers('include/netpacket/packet.h', subdir: 'netpacket')
112+
install_headers('include/net/bpf.h', subdir: 'net')
110113
endif
111114

112115
if not headers_only

0 commit comments

Comments
 (0)