linux-user: convert /proc/net/route when endianess differs
This patch allows to have IP addresses in correct order in the case of "netstat -nr" when the endianess of the guest differs from one of the host. For instance, an m68k guest on an x86_64 host: WITHOUT this patch: $ netstat -nr Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 1.3.0.10 0.0.0.0 UG 0 0 0 eth0 0.3.0.10 0.0.0.0 0.255.255.255 U 0 0 0 eth0 $ cat /proc/net/route Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT eth0 00000000 0103000A 0003 0 0 0 000000000 0 0 eth0 0003000A 00000000 0001 0 0 0 00FFFFFF0 0 0 WITH this patch: $ netstat -nr Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 10.0.3.1 0.0.0.0 UG 0 0 0 eth0 10.0.3.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 $ cat /proc/net/route Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT eth0 00000000 0a000301 0003 0 0 0 000000000 0 0 eth0 0a000300 00000000 0001 0 0 0 ffffff000 0 0 Signed-off-by: Laurent Vivier <laurent@vivier.eu> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
This commit is contained in:
parent
868e34d7bd
commit
de6b993377
@ -5071,22 +5071,70 @@ static int is_proc_myself(const char *filename, const char *entry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
static int is_proc(const char *filename, const char *entry)
|
||||
{
|
||||
return strcmp(filename, entry) == 0;
|
||||
}
|
||||
|
||||
static int open_net_route(void *cpu_env, int fd)
|
||||
{
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
fp = fopen("/proc/net/route", "r");
|
||||
if (fp == NULL) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/* read header */
|
||||
|
||||
read = getline(&line, &len, fp);
|
||||
dprintf(fd, "%s", line);
|
||||
|
||||
/* read routes */
|
||||
|
||||
while ((read = getline(&line, &len, fp)) != -1) {
|
||||
char iface[16];
|
||||
uint32_t dest, gw, mask;
|
||||
unsigned int flags, refcnt, use, metric, mtu, window, irtt;
|
||||
sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
|
||||
iface, &dest, &gw, &flags, &refcnt, &use, &metric,
|
||||
&mask, &mtu, &window, &irtt);
|
||||
dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
|
||||
iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
|
||||
metric, tswap32(mask), mtu, window, irtt);
|
||||
}
|
||||
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
struct fake_open {
|
||||
const char *filename;
|
||||
int (*fill)(void *cpu_env, int fd);
|
||||
int (*cmp)(const char *s1, const char *s2);
|
||||
};
|
||||
const struct fake_open *fake_open;
|
||||
static const struct fake_open fakes[] = {
|
||||
{ "maps", open_self_maps },
|
||||
{ "stat", open_self_stat },
|
||||
{ "auxv", open_self_auxv },
|
||||
{ NULL, NULL }
|
||||
{ "maps", open_self_maps, is_proc_myself },
|
||||
{ "stat", open_self_stat, is_proc_myself },
|
||||
{ "auxv", open_self_auxv, is_proc_myself },
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
{ "/proc/net/route", open_net_route, is_proc },
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
for (fake_open = fakes; fake_open->filename; fake_open++) {
|
||||
if (is_proc_myself(pathname, fake_open->filename)) {
|
||||
if (fake_open->cmp(pathname, fake_open->filename)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user