diff --git a/kernel-src/fs/sockfs.c b/kernel-src/fs/sockfs.c index c18f797b..63c31b57 100644 --- a/kernel-src/fs/sockfs.c +++ b/kernel-src/fs/sockfs.c @@ -100,46 +100,51 @@ int sockfs_setattr(vnode_t *node, vattr_t *attr, int which, cred_t *cred) { return 0; } +static int handle_ifreq(unsigned long request, ifreq_t *uifreq, cred_t *cred) { + ifreq_t ifreq; + int e = USERCOPY_POSSIBLY_FROM_USER(&ifreq, uifreq, sizeof(ifreq_t)); + if (e) + return e; + + netdev_t *netdev = netdev_getdev(ifreq.name); + if (!netdev) + return ENODEV; + + switch (request) { + case SIOCSIFADDR: + e = auth_network_check(cred, AUTH_ACTIONS_NETWORK_CONFIGURE, NULL, netdev); + if (e) + return e; + + sockaddr_t sockaddr; + e = sock_convertaddress(&sockaddr, &ifreq.addr); + if (e) + return e; + netdev->ip = sockaddr.ipv4addr.addr; + break; + case SIOCGIFHWADDR: + return USERCOPY_POSSIBLY_TO_USER(uifreq->addr.addr, netdev->mac.address, sizeof(mac_t)); + case SIOCGIFMTU: { + int mtu = netdev->mtu; + return USERCOPY_POSSIBLY_TO_USER(&uifreq->mtu, &mtu, sizeof(mtu)); + } + case SIOCGIFFLAGS: { + short flags = netdev->flags; + return USERCOPY_POSSIBLY_TO_USER(&uifreq->flags, &flags, sizeof(flags)); + } + } + + return 0; +} + // arg can be in userspace int sockfs_ioctl(vnode_t *node, unsigned long request, void *arg, int *result, cred_t *cred) { switch (request) { - case SIOCSIFADDR: { - ifreq_t ifreq; - int e = USERCOPY_POSSIBLY_FROM_USER(&ifreq, arg, sizeof(ifreq_t)); - if (e) - return e; - - netdev_t *netdev = netdev_getdev(ifreq.name); - if (netdev) { - e = auth_network_check(cred, AUTH_ACTIONS_NETWORK_CONFIGURE, NULL, netdev); - if (e) - return e; - - sockaddr_t sockaddr; - e = sock_convertaddress(&sockaddr, &ifreq.addr); - if (e) - return e; - netdev->ip = sockaddr.ipv4addr.addr; - } else { - return ENODEV; - } - break; - } - case SIOCGIFHWADDR: { - ifreq_t *ifreq = arg; - ifreq_t kifreq; - int e = USERCOPY_POSSIBLY_FROM_USER(&kifreq, arg, sizeof(ifreq_t)); - if (e) - return e; - - netdev_t *netdev = netdev_getdev(kifreq.name); - if (netdev) { - return USERCOPY_POSSIBLY_TO_USER(ifreq->addr.addr, netdev->mac.address, sizeof(mac_t)); - } else { - return ENODEV; - } - break; - } + case SIOCSIFADDR: + case SIOCGIFHWADDR: + case SIOCGIFMTU: + case SIOCGIFFLAGS: + return handle_ifreq(request, arg, cred); case SIOCADDRT: { abirtentry_t abirtentry; int e = USERCOPY_POSSIBLY_FROM_USER(&abirtentry, arg, sizeof(abirtentry_t)); @@ -199,6 +204,7 @@ int sockfs_ioctl(vnode_t *node, unsigned long request, void *arg, int *result, c return USERCOPY_POSSIBLY_TO_USER(arg, &count, sizeof(int)); } default: + printf("got unknown socket ioctl %lu\n", request); return ENOTTY; } return 0; diff --git a/kernel-src/include/kernel/abi.h b/kernel-src/include/kernel/abi.h index b3d0a813..777a7fd8 100644 --- a/kernel-src/include/kernel/abi.h +++ b/kernel-src/include/kernel/abi.h @@ -135,15 +135,20 @@ typedef struct { } msghdr_t; #define IFNAMSIZ 16 + +#define SIOCGIFFLAGS 0x8913 +#define SIOCSIFADDR 0x8916 +#define SIOCGIFMTU 0x8921 #define SIOCGIFHWADDR 0x8927 #define SIOCADDRT 0x890b -#define SIOCSIFADDR 0x8916 #define FIONREAD 0x541B typedef struct { char name[IFNAMSIZ]; union { abisockaddr_t addr; + int mtu; + short flags; }; } ifreq_t;