sock.c: enhance socket ioctl parser
Decode as much data on entering syscall as possible. * sock.c: Update for RVAL_DECODED. (print_addr): Remove. (print_ifreq_addr, print_ifreq, print_ifc_len, decode_ifconf): New functions. (sock_ioctl) Use them. Use umove_or_printaddr.
This commit is contained in:
parent
a0beac1538
commit
b93c110079
436
sock.c
436
sock.c
@ -41,14 +41,19 @@
|
||||
#include "xlat/iffflags.h"
|
||||
|
||||
static void
|
||||
print_addr(struct tcb *tcp, long addr, struct ifreq *ifr)
|
||||
print_ifreq_addr(struct tcb *tcp, const struct ifreq *ifr, const long addr)
|
||||
{
|
||||
tprintf("{");
|
||||
printxval(addrfams, ifr->ifr_addr.sa_family, "AF_???");
|
||||
tprints(", ");
|
||||
if (ifr->ifr_addr.sa_family == AF_INET) {
|
||||
struct sockaddr_in *sinp;
|
||||
sinp = (struct sockaddr_in *) &ifr->ifr_addr;
|
||||
const struct sockaddr_in *sinp =
|
||||
(struct sockaddr_in *) &ifr->ifr_addr;
|
||||
tprintf("inet_addr(\"%s\")", inet_ntoa(sinp->sin_addr));
|
||||
} else
|
||||
printstr(tcp, addr, sizeof(ifr->ifr_addr.sa_data));
|
||||
printstr(tcp, addr + offsetof(struct ifreq, ifr_addr.sa_data),
|
||||
sizeof(ifr->ifr_addr.sa_data));
|
||||
tprints("}");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -57,59 +62,189 @@ print_ifname(const char *ifname)
|
||||
print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
|
||||
}
|
||||
|
||||
int
|
||||
sock_ioctl(struct tcb *tcp, const unsigned int code, long arg)
|
||||
static void
|
||||
print_ifreq(struct tcb *tcp, const unsigned int code, const long arg,
|
||||
const struct ifreq *ifr)
|
||||
{
|
||||
switch (code) {
|
||||
case SIOCSIFADDR:
|
||||
case SIOCGIFADDR:
|
||||
tprints("ifr_addr=");
|
||||
print_ifreq_addr(tcp, ifr, arg);
|
||||
break;
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCGIFDSTADDR:
|
||||
tprints("ifr_dstaddr=");
|
||||
print_ifreq_addr(tcp, ifr, arg);
|
||||
break;
|
||||
case SIOCSIFBRDADDR:
|
||||
case SIOCGIFBRDADDR:
|
||||
tprints("ifr_broadaddr=");
|
||||
print_ifreq_addr(tcp, ifr, arg);
|
||||
break;
|
||||
case SIOCSIFNETMASK:
|
||||
case SIOCGIFNETMASK:
|
||||
tprints("ifr_netmask=");
|
||||
print_ifreq_addr(tcp, ifr, arg);
|
||||
break;
|
||||
case SIOCSIFHWADDR:
|
||||
case SIOCGIFHWADDR: {
|
||||
/* XXX Are there other hardware addresses
|
||||
than 6-byte MACs? */
|
||||
const unsigned char *bytes =
|
||||
(unsigned char *) &ifr->ifr_hwaddr.sa_data;
|
||||
tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
bytes[0], bytes[1], bytes[2],
|
||||
bytes[3], bytes[4], bytes[5]);
|
||||
break;
|
||||
}
|
||||
case SIOCSIFFLAGS:
|
||||
case SIOCGIFFLAGS:
|
||||
tprints("ifr_flags=");
|
||||
printflags(iffflags, ifr->ifr_flags, "IFF_???");
|
||||
break;
|
||||
case SIOCSIFMETRIC:
|
||||
case SIOCGIFMETRIC:
|
||||
tprintf("ifr_metric=%d", ifr->ifr_metric);
|
||||
break;
|
||||
case SIOCSIFMTU:
|
||||
case SIOCGIFMTU:
|
||||
tprintf("ifr_mtu=%d", ifr->ifr_mtu);
|
||||
break;
|
||||
case SIOCSIFSLAVE:
|
||||
case SIOCGIFSLAVE:
|
||||
tprints("ifr_slave=");
|
||||
print_ifname(ifr->ifr_slave);
|
||||
break;
|
||||
case SIOCSIFTXQLEN:
|
||||
case SIOCGIFTXQLEN:
|
||||
tprintf("ifr_qlen=%d", ifr->ifr_qlen);
|
||||
break;
|
||||
case SIOCSIFMAP:
|
||||
case SIOCGIFMAP:
|
||||
tprintf("ifr_map={mem_start=%#lx, "
|
||||
"mem_end=%#lx, base_addr=%#x, "
|
||||
"irq=%u, dma=%u, port=%u}",
|
||||
ifr->ifr_map.mem_start,
|
||||
ifr->ifr_map.mem_end,
|
||||
(unsigned) ifr->ifr_map.base_addr,
|
||||
(unsigned) ifr->ifr_map.irq,
|
||||
(unsigned) ifr->ifr_map.dma,
|
||||
(unsigned) ifr->ifr_map.port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
print_ifc_len(int len)
|
||||
{
|
||||
const unsigned int n = (unsigned int) len / sizeof(struct ifreq);
|
||||
|
||||
if (len < 0 || n * sizeof(struct ifreq) != (unsigned int) len)
|
||||
tprintf("%d", len);
|
||||
else
|
||||
tprintf("%u * sizeof(struct ifreq)", n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_ifconf(struct tcb *tcp, const long addr)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
struct ifconf ifc;
|
||||
const char *str = NULL;
|
||||
unsigned char *bytes;
|
||||
|
||||
if (entering(tcp)) {
|
||||
switch (code) {
|
||||
case SIOCGIFCONF:
|
||||
if (umove(tcp, tcp->u_arg[2], &ifc) >= 0
|
||||
&& ifc.ifc_buf == NULL)
|
||||
tprintf(", {%d -> ", ifc.ifc_len);
|
||||
else
|
||||
tprints(", {");
|
||||
break;
|
||||
case SIOCSIFNAME:
|
||||
if (umove(tcp, tcp->u_arg[2], &ifr) < 0)
|
||||
tprintf(", %#lx", tcp->u_arg[2]);
|
||||
else {
|
||||
tprints(", {ifr_name=");
|
||||
print_ifname(ifr.ifr_name);
|
||||
tprints(", ifr_newname=");
|
||||
print_ifname(ifr.ifr_newname);
|
||||
tprints("}");
|
||||
}
|
||||
break;
|
||||
tprints(", ");
|
||||
if (umove_or_printaddr(tcp, addr, &ifc))
|
||||
return RVAL_DECODED | 1;
|
||||
if (ifc.ifc_buf) {
|
||||
tprints("{");
|
||||
print_ifc_len(ifc.ifc_len);
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (syserror(tcp) || umove(tcp, addr, &ifc) < 0) {
|
||||
if (ifc.ifc_buf)
|
||||
tprints("}");
|
||||
else
|
||||
printaddr(addr);
|
||||
return RVAL_DECODED | 1;
|
||||
}
|
||||
|
||||
if (!ifc.ifc_buf) {
|
||||
tprints("{");
|
||||
print_ifc_len(ifc.ifc_len);
|
||||
tprints(", NULL}");
|
||||
return RVAL_DECODED | 1;
|
||||
}
|
||||
|
||||
tprints(" => ");
|
||||
const unsigned int nifra = print_ifc_len(ifc.ifc_len);
|
||||
if (!nifra) {
|
||||
tprints("}");
|
||||
return RVAL_DECODED | 1;
|
||||
}
|
||||
|
||||
struct ifreq ifra[nifra > max_strlen ? max_strlen : nifra];
|
||||
tprints(", ");
|
||||
if (umove_or_printaddr(tcp, (unsigned long) ifc.ifc_buf, &ifra)) {
|
||||
tprints("}");
|
||||
return RVAL_DECODED | 1;
|
||||
}
|
||||
|
||||
tprints("[");
|
||||
unsigned int i;
|
||||
for (i = 0; i < ARRAY_SIZE(ifra); ++i) {
|
||||
if (i > 0)
|
||||
tprints(", ");
|
||||
tprints("{ifr_name=");
|
||||
print_ifname(ifra[i].ifr_name);
|
||||
tprints(", ");
|
||||
if (verbose(tcp)) {
|
||||
tprints("ifr_addr=");
|
||||
print_ifreq_addr(tcp, &ifra[i],
|
||||
addr + i * sizeof(ifra[0]));
|
||||
} else
|
||||
tprints("...");
|
||||
tprints("}");
|
||||
}
|
||||
if (i < nifra)
|
||||
tprints(", ...");
|
||||
tprints("]}");
|
||||
|
||||
return RVAL_DECODED | 1;
|
||||
}
|
||||
|
||||
int
|
||||
sock_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
switch (code) {
|
||||
#ifdef SIOCSHIWAT
|
||||
case SIOCSHIWAT:
|
||||
#endif
|
||||
#ifdef SIOCGHIWAT
|
||||
case SIOCGHIWAT:
|
||||
#endif
|
||||
#ifdef SIOCSLOWAT
|
||||
case SIOCSLOWAT:
|
||||
#endif
|
||||
#ifdef SIOCGLOWAT
|
||||
case SIOCGLOWAT:
|
||||
case SIOCGIFCONF:
|
||||
return decode_ifconf(tcp, arg);
|
||||
|
||||
#ifdef SIOCBRADDBR
|
||||
case SIOCBRADDBR:
|
||||
case SIOCBRDELBR:
|
||||
tprints(", ");
|
||||
printstr(tcp, arg, -1);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef FIOSETOWN
|
||||
case FIOSETOWN:
|
||||
#endif
|
||||
#ifdef FIOGETOWN
|
||||
case FIOGETOWN:
|
||||
#endif
|
||||
#ifdef SIOCSPGRP
|
||||
case SIOCSPGRP:
|
||||
#endif
|
||||
tprints(", ");
|
||||
printnum_int(tcp, arg, "%d");
|
||||
break;
|
||||
|
||||
#ifdef FIOGETOWN
|
||||
case FIOGETOWN:
|
||||
#endif
|
||||
#ifdef SIOCGPGRP
|
||||
case SIOCGPGRP:
|
||||
@ -117,178 +252,101 @@ sock_ioctl(struct tcb *tcp, const unsigned int code, long arg)
|
||||
#ifdef SIOCATMARK
|
||||
case SIOCATMARK:
|
||||
#endif
|
||||
printnum_int(tcp, arg, ", %d");
|
||||
if (entering(tcp))
|
||||
return 0;
|
||||
tprints(", ");
|
||||
printnum_int(tcp, arg, "%d");
|
||||
break;
|
||||
|
||||
#ifdef SIOCBRADDIF
|
||||
case SIOCBRADDIF:
|
||||
#endif
|
||||
#ifdef SIOCBRDELIF
|
||||
case SIOCBRDELIF:
|
||||
#endif
|
||||
/* no arguments */
|
||||
break;
|
||||
|
||||
case SIOCSIFNAME:
|
||||
return 1;
|
||||
case SIOCSIFADDR:
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCSIFBRDADDR:
|
||||
case SIOCSIFNETMASK:
|
||||
case SIOCSIFFLAGS:
|
||||
case SIOCSIFMETRIC:
|
||||
case SIOCSIFMTU:
|
||||
case SIOCSIFSLAVE:
|
||||
case SIOCSIFHWADDR:
|
||||
case SIOCSIFTXQLEN:
|
||||
case SIOCSIFMAP:
|
||||
tprints(", ");
|
||||
if (umove_or_printaddr(tcp, arg, &ifr))
|
||||
break;
|
||||
|
||||
tprints("{ifr_name=");
|
||||
print_ifname(ifr.ifr_name);
|
||||
tprints(", ");
|
||||
if (code == SIOCSIFNAME) {
|
||||
tprints("ifr_newname=");
|
||||
print_ifname(ifr.ifr_newname);
|
||||
} else {
|
||||
print_ifreq(tcp, code, arg, &ifr);
|
||||
}
|
||||
tprints("}");
|
||||
break;
|
||||
|
||||
case SIOCGIFNAME:
|
||||
case SIOCGIFINDEX:
|
||||
case SIOCGIFADDR:
|
||||
case SIOCSIFADDR:
|
||||
case SIOCGIFDSTADDR:
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCGIFBRDADDR:
|
||||
case SIOCSIFBRDADDR:
|
||||
case SIOCGIFNETMASK:
|
||||
case SIOCSIFNETMASK:
|
||||
case SIOCGIFFLAGS:
|
||||
case SIOCSIFFLAGS:
|
||||
case SIOCGIFMETRIC:
|
||||
case SIOCSIFMETRIC:
|
||||
case SIOCGIFMTU:
|
||||
case SIOCSIFMTU:
|
||||
case SIOCGIFSLAVE:
|
||||
case SIOCSIFSLAVE:
|
||||
case SIOCGIFHWADDR:
|
||||
case SIOCSIFHWADDR:
|
||||
case SIOCGIFTXQLEN:
|
||||
case SIOCSIFTXQLEN:
|
||||
case SIOCGIFMAP:
|
||||
case SIOCSIFMAP:
|
||||
if (umove(tcp, tcp->u_arg[2], &ifr) < 0)
|
||||
tprintf(", %#lx", tcp->u_arg[2]);
|
||||
else if (syserror(tcp)) {
|
||||
if (code == SIOCGIFNAME) {
|
||||
tprintf(", {ifr_index=%d, ifr_name=???}",
|
||||
ifr.ifr_ifindex);
|
||||
} else {
|
||||
tprints(", {ifr_name=");
|
||||
print_ifname(ifr.ifr_name);
|
||||
tprints(", ???}");
|
||||
}
|
||||
} else if (code == SIOCGIFNAME) {
|
||||
tprintf(", {ifr_index=%d, ifr_name=", ifr.ifr_ifindex);
|
||||
print_ifname(ifr.ifr_name);
|
||||
tprints("}");
|
||||
} else {
|
||||
tprints(", {ifr_name=");
|
||||
print_ifname(ifr.ifr_name);
|
||||
if (entering(tcp)) {
|
||||
tprints(", ");
|
||||
switch (code) {
|
||||
case SIOCGIFINDEX:
|
||||
tprintf("ifr_index=%d", ifr.ifr_ifindex);
|
||||
if (umove_or_printaddr(tcp, arg, &ifr))
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
case SIOCSIFADDR:
|
||||
str = "ifr_addr";
|
||||
case SIOCGIFDSTADDR:
|
||||
case SIOCSIFDSTADDR:
|
||||
if (!str)
|
||||
str = "ifr_dstaddr";
|
||||
case SIOCGIFBRDADDR:
|
||||
case SIOCSIFBRDADDR:
|
||||
if (!str)
|
||||
str = "ifr_broadaddr";
|
||||
case SIOCGIFNETMASK:
|
||||
case SIOCSIFNETMASK:
|
||||
if (!str)
|
||||
str = "ifr_netmask";
|
||||
tprintf("%s={", str);
|
||||
printxval(addrfams,
|
||||
ifr.ifr_addr.sa_family,
|
||||
"AF_???");
|
||||
tprints(", ");
|
||||
print_addr(tcp, ((long) tcp->u_arg[2]
|
||||
+ offsetof(struct ifreq,
|
||||
ifr_addr.sa_data)),
|
||||
&ifr);
|
||||
|
||||
if (SIOCGIFNAME == code) {
|
||||
tprintf("{ifr_index=%d", ifr.ifr_ifindex);
|
||||
} else {
|
||||
tprints("{ifr_name=");
|
||||
print_ifname(ifr.ifr_name);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
if (syserror(tcp)) {
|
||||
tprints("}");
|
||||
break;
|
||||
case SIOCGIFHWADDR:
|
||||
case SIOCSIFHWADDR:
|
||||
/* XXX Are there other hardware addresses
|
||||
than 6-byte MACs? */
|
||||
bytes = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
|
||||
tprintf("ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
bytes[0], bytes[1], bytes[2],
|
||||
bytes[3], bytes[4], bytes[5]);
|
||||
break;
|
||||
case SIOCGIFFLAGS:
|
||||
case SIOCSIFFLAGS:
|
||||
tprints("ifr_flags=");
|
||||
printflags(iffflags, ifr.ifr_flags, "IFF_???");
|
||||
break;
|
||||
case SIOCGIFMETRIC:
|
||||
case SIOCSIFMETRIC:
|
||||
tprintf("ifr_metric=%d", ifr.ifr_metric);
|
||||
break;
|
||||
case SIOCGIFMTU:
|
||||
case SIOCSIFMTU:
|
||||
tprintf("ifr_mtu=%d", ifr.ifr_mtu);
|
||||
break;
|
||||
case SIOCGIFSLAVE:
|
||||
case SIOCSIFSLAVE:
|
||||
tprints("ifr_slave=");
|
||||
print_ifname(ifr.ifr_slave);
|
||||
break;
|
||||
case SIOCGIFTXQLEN:
|
||||
case SIOCSIFTXQLEN:
|
||||
tprintf("ifr_qlen=%d", ifr.ifr_qlen);
|
||||
break;
|
||||
case SIOCGIFMAP:
|
||||
case SIOCSIFMAP:
|
||||
tprintf("ifr_map={mem_start=%#lx, "
|
||||
"mem_end=%#lx, base_addr=%#x, "
|
||||
"irq=%u, dma=%u, port=%u}",
|
||||
ifr.ifr_map.mem_start,
|
||||
ifr.ifr_map.mem_end,
|
||||
(unsigned) ifr.ifr_map.base_addr,
|
||||
(unsigned) ifr.ifr_map.irq,
|
||||
(unsigned) ifr.ifr_map.dma,
|
||||
(unsigned) ifr.ifr_map.port);
|
||||
break;
|
||||
}
|
||||
tprints("}");
|
||||
}
|
||||
return 1;
|
||||
case SIOCGIFCONF:
|
||||
if (umove(tcp, tcp->u_arg[2], &ifc) < 0) {
|
||||
tprints("???}");
|
||||
return 1;
|
||||
}
|
||||
tprintf("%d, ", ifc.ifc_len);
|
||||
if (syserror(tcp)) {
|
||||
tprintf("%lx", (unsigned long) ifc.ifc_buf);
|
||||
} else if (ifc.ifc_buf == NULL) {
|
||||
tprints("NULL");
|
||||
} else {
|
||||
unsigned int i;
|
||||
unsigned int nifra = ifc.ifc_len / sizeof(struct ifreq);
|
||||
struct ifreq ifra[nifra];
|
||||
|
||||
if (umoven(tcp, (unsigned long) ifc.ifc_buf,
|
||||
sizeof(ifra), ifra) < 0) {
|
||||
tprintf("%lx}", (unsigned long) ifc.ifc_buf);
|
||||
return 1;
|
||||
tprints(", ");
|
||||
if (umove(tcp, arg, &ifr) < 0) {
|
||||
tprints("???}");
|
||||
break;
|
||||
}
|
||||
tprints("{");
|
||||
for (i = 0; i < nifra; ++i ) {
|
||||
if (i > 0)
|
||||
tprints(", ");
|
||||
tprints("{");
|
||||
print_ifname(ifra[i].ifr_newname);
|
||||
tprints(", {");
|
||||
if (verbose(tcp)) {
|
||||
printxval(addrfams,
|
||||
ifra[i].ifr_addr.sa_family,
|
||||
"AF_???");
|
||||
tprints(", ");
|
||||
print_addr(tcp, ((long) tcp->u_arg[2]
|
||||
+ offsetof(struct ifreq,
|
||||
ifr_addr.sa_data)
|
||||
+ ((char *) &ifra[i]
|
||||
- (char *) &ifra[0])),
|
||||
&ifra[i]);
|
||||
} else
|
||||
tprints("...");
|
||||
tprints("}}");
|
||||
|
||||
if (SIOCGIFNAME == code) {
|
||||
tprints("ifr_name=");
|
||||
print_ifname(ifr.ifr_name);
|
||||
} else {
|
||||
print_ifreq(tcp, code, arg, &ifr);
|
||||
}
|
||||
tprints("}");
|
||||
break;
|
||||
}
|
||||
tprints("}");
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
return RVAL_DECODED;
|
||||
}
|
||||
|
||||
return RVAL_DECODED | 1;
|
||||
}
|
||||
|
||||
SYS_FUNC(socketcall)
|
||||
|
Loading…
x
Reference in New Issue
Block a user