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;
|
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)
|
static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
struct fake_open {
|
struct fake_open {
|
||||||
const char *filename;
|
const char *filename;
|
||||||
int (*fill)(void *cpu_env, int fd);
|
int (*fill)(void *cpu_env, int fd);
|
||||||
|
int (*cmp)(const char *s1, const char *s2);
|
||||||
};
|
};
|
||||||
const struct fake_open *fake_open;
|
const struct fake_open *fake_open;
|
||||||
static const struct fake_open fakes[] = {
|
static const struct fake_open fakes[] = {
|
||||||
{ "maps", open_self_maps },
|
{ "maps", open_self_maps, is_proc_myself },
|
||||||
{ "stat", open_self_stat },
|
{ "stat", open_self_stat, is_proc_myself },
|
||||||
{ "auxv", open_self_auxv },
|
{ "auxv", open_self_auxv, is_proc_myself },
|
||||||
{ NULL, NULL }
|
#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++) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user