Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linsysfs/linsysfs.c
Context not available. | |||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | * SPDX-License-Identifier: BSD-2-Clause-FreeBSD | ||||
* | * | ||||
* Copyright (c) 2006 IronPort Systems | * Copyright (c) 2006 IronPort Systems | ||||
* Copyright (c) 2017 Carlos Neira cneirabustos@gmail.com | |||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
Context not available. | |||||
#include <dev/pci/pcivar.h> | #include <dev/pci/pcivar.h> | ||||
#include <dev/pci/pcireg.h> | #include <dev/pci/pcireg.h> | ||||
#include <sys/ctype.h> | |||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_types.h> | |||||
#include <net/if_var.h> | |||||
#include <net/if_dl.h> | |||||
#include <net/vnet.h> | |||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
Context not available. | |||||
#include <compat/linux/linux_mib.h> | #include <compat/linux/linux_mib.h> | ||||
#include <compat/linux/linux_util.h> | #include <compat/linux/linux_util.h> | ||||
#include <fs/pseudofs/pseudofs.h> | #include <fs/pseudofs/pseudofs.h> | ||||
#include <sys/jail.h> | |||||
#define LINUX_IFNAMSIZ 16 | |||||
struct scsi_host_queue { | struct scsi_host_queue { | ||||
TAILQ_ENTRY(scsi_host_queue) scsi_host_next; | TAILQ_ENTRY(scsi_host_queue) scsi_host_next; | ||||
Context not available. | |||||
return (int)strtol(str, (char **)NULL, 10); | return (int)strtol(str, (char **)NULL, 10); | ||||
} | } | ||||
/* | |||||
* Filler function for sys/class/net/<iface> | |||||
* Only 2 interfaces are created eth0 and lo and they expose the following files | |||||
* address, addr_len, flags, ifindex, mty, tx_queue_len and type. | |||||
*/ | |||||
#define ETHERADDRL 6 | |||||
#define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER) | |||||
static struct ifnet * | |||||
ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) | |||||
{ | |||||
struct ifnet *ifp; | |||||
int len, unit; | |||||
char *ep; | |||||
int is_eth, index; | |||||
for (len = 0; len < LINUX_IFNAMSIZ; ++len) | |||||
if (!isalpha(lxname[len])) | |||||
break; | |||||
if (len == 0 || len == LINUX_IFNAMSIZ) | |||||
return (NULL); | |||||
unit = (int)strtoul(lxname + len, &ep, 10); | |||||
if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) | |||||
return (NULL); | |||||
index = 0; | |||||
is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0; | |||||
CURVNET_SET(TD_TO_VNET(td)); | |||||
IFNET_RLOCK(); | |||||
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { | |||||
/* | |||||
dchagin: tab until }? | |||||
* Allow Linux programs to use FreeBSD names. Don't presume | |||||
* we never have an interface named "eth", so don't make | |||||
* the test optional based on is_eth. | |||||
*/ | |||||
if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0) | |||||
break; | |||||
if (is_eth && IFP_IS_ETH(ifp) && unit == index++) | |||||
break; | |||||
} | |||||
IFNET_RUNLOCK(); | |||||
CURVNET_RESTORE(); | |||||
if (ifp != NULL) | |||||
strlcpy(bsdname, ifp->if_xname, IFNAMSIZ); | |||||
return (ifp); | |||||
} | |||||
static int | |||||
dchaginUnsubmitted Done Inline Actionsextra line dchagin: extra line | |||||
linsysfs_ifnet_addr (PFS_FILL_ARGS) { | |||||
struct ifnet* ifp; | |||||
char bsdname[IFNAMSIZ+1]; | |||||
uint8_t* address; | |||||
if (!memcmp((const char*)pn->pn_parent->pn_name,"lo",2)) { | |||||
sbuf_printf (sb, "00:00:00:00:00:00\n"); | |||||
return (0); | |||||
} else { | |||||
ifp = ifname_linux_to_bsd(curthread,(const char*)pn->pn_parent->pn_name,bsdname); | |||||
if (!ifp) { | |||||
sbuf_printf (sb, "00:00:00:00:00:00\n"); | |||||
return (0); | |||||
} | |||||
address = IF_LLADDR(ifp); | |||||
sbuf_printf (sb,"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", | |||||
address[0], address[1], address[2], | |||||
address[3], address[4], address[5]); | |||||
return (0); | |||||
} | |||||
} | |||||
dchaginUnsubmitted Done Inline Actionsremove '\n' dchagin: remove '\n' | |||||
static int | |||||
linsysfs_ifnet_addrlen (PFS_FILL_ARGS) { | |||||
dchaginUnsubmitted Done Inline Actionswhitespace dchagin: whitespace | |||||
sbuf_printf(sb,"6\n"); | |||||
return (0); | |||||
} | |||||
static int | |||||
dchaginUnsubmitted Done Inline Actionsadd '\n' dchagin: add '\n' | |||||
linsysfs_ifnet_flags (PFS_FILL_ARGS) { | |||||
int buf; | |||||
struct ifnet* ifp; | |||||
char bsdname[IFNAMSIZ+1]; | |||||
if (!memcmp((const char*)pn->pn_parent->pn_name,"eth",3)) { | |||||
ifp = ifname_linux_to_bsd(curthread, | |||||
(const char*)pn->pn_parent->pn_name,bsdname); | |||||
buf = ifp->if_flags & (IFF_UP | IFF_BROADCAST | IFF_DEBUG | | |||||
IFF_LOOPBACK | IFF_POINTOPOINT | | |||||
IFF_DRV_RUNNING | IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI); | |||||
buf |= 0x1000; | |||||
sbuf_printf(sb,"0x%x\n",buf); | |||||
} else { | |||||
sbuf_printf(sb,"0x9\n"); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
dchaginUnsubmitted Done Inline Actionssame dchagin: same | |||||
linsysfs_ifnet_ifindex (PFS_FILL_ARGS) { | |||||
struct ifnet* ifp; | |||||
char bsdname[IFNAMSIZ+1]; | |||||
if (!memcmp((const char*)pn->pn_parent->pn_name,"eth",3)) { | |||||
ifp = ifname_linux_to_bsd(curthread, | |||||
(const char*)pn->pn_parent->pn_name,bsdname); | |||||
sbuf_printf(sb,"%u\n",ifp->if_index); | |||||
} else { | |||||
sbuf_printf(sb,"1\n"); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
dchaginUnsubmitted Done Inline Actionssame dchagin: same | |||||
linsysfs_ifnet_mtu (PFS_FILL_ARGS) { | |||||
struct ifnet* ifp; | |||||
char bsdname[IFNAMSIZ+1]; | |||||
if (!memcmp((const char*)pn->pn_parent->pn_name,"lo",2)) { | |||||
sbuf_printf(sb,"65536\n"); | |||||
} else { | |||||
ifp = ifname_linux_to_bsd(curthread, | |||||
(const char*)pn->pn_parent->pn_name,bsdname); | |||||
sbuf_printf(sb,"%u\n",ifp->if_mtu); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
linsysfs_ifnet_tx_queue_len (PFS_FILL_ARGS) { | |||||
sbuf_printf(sb,"1000\n"); | |||||
return (0); | |||||
} | |||||
static int | |||||
linsysfs_ifnet_type (PFS_FILL_ARGS) { | |||||
if (!memcmp((const char*)pn->pn_parent->pn_name,"lo",2)) | |||||
sbuf_printf(sb,"772\n"); | |||||
else | |||||
sbuf_printf(sb,"2\n"); | |||||
return (0); | |||||
} | |||||
static void | |||||
linsysfs_listnics (struct pfs_node *dir) | |||||
{ | |||||
struct pfs_node *nic; | |||||
struct pfs_node *lo; | |||||
nic = pfs_create_dir (dir, "eth0", NULL, NULL, NULL, 0); | |||||
dchaginUnsubmitted Done Inline Actionswhitespace in function, below too dchagin: whitespace in function, below too | |||||
pfs_create_file (nic, "address", &linsysfs_ifnet_addr, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (nic, "addr_len", &linsysfs_ifnet_addrlen, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (nic, "flags", &linsysfs_ifnet_flags, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (nic, "ifindex", &linsysfs_ifnet_ifindex, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (nic, "mtu", &linsysfs_ifnet_mtu, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (nic, "tx_queue_len", &linsysfs_ifnet_tx_queue_len, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (nic, "type", &linsysfs_ifnet_type, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
lo = pfs_create_dir (dir, "lo", NULL, NULL, NULL, 0); | |||||
pfs_create_file (lo, "address", &linsysfs_ifnet_addr, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (lo, "addr_len", &linsysfs_ifnet_addrlen, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (lo, "flags", &linsysfs_ifnet_flags, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
Done Inline Actionsbtw, why lo instead of lo0? dchagin: btw, why lo instead of lo0? | |||||
Done Inline ActionsIt's Linux's name for the loopback interface (not lo0). cem: It's Linux's name for the loopback interface (not lo0). | |||||
Done Inline ActionsThat's correct. cneirabustos_gmail.com: That's correct. | |||||
Done Inline ActionsAs @cem explained, the loopback device is named lo in Linux. cneirabustos_gmail.com: As @cem explained, the loopback device is named lo in Linux. | |||||
pfs_create_file (lo, "ifindex", &linsysfs_ifnet_ifindex, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (lo, "mtu", &linsysfs_ifnet_mtu, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (lo, "tx_queue_len", &linsysfs_ifnet_tx_queue_len, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
pfs_create_file (lo, "type", &linsysfs_ifnet_type, | |||||
NULL, NULL, NULL, PFS_RD); | |||||
} | |||||
/* | /* | ||||
* Filler function for proc_name | * Filler function for proc_name | ||||
*/ | */ | ||||
Context not available. | |||||
struct pfs_node *drm; | struct pfs_node *drm; | ||||
struct pfs_node *pci; | struct pfs_node *pci; | ||||
struct pfs_node *scsi; | struct pfs_node *scsi; | ||||
struct pfs_node *net; | |||||
struct pfs_node *devdir, *chardev; | struct pfs_node *devdir, *chardev; | ||||
devclass_t devclass; | devclass_t devclass; | ||||
device_t dev; | device_t dev; | ||||
Context not available. | |||||
scsi = pfs_create_dir(class, "scsi_host", NULL, NULL, NULL, 0); | scsi = pfs_create_dir(class, "scsi_host", NULL, NULL, NULL, 0); | ||||
drm = pfs_create_dir(class, "drm", NULL, NULL, NULL, 0); | drm = pfs_create_dir(class, "drm", NULL, NULL, NULL, 0); | ||||
/* /sys/class/net/.. */ | |||||
net = pfs_create_dir(class, "net", NULL, NULL, NULL, 0); | |||||
/* /sys/dev/... */ | /* /sys/dev/... */ | ||||
devdir = pfs_create_dir(root, "dev", NULL, NULL, NULL, 0); | devdir = pfs_create_dir(root, "dev", NULL, NULL, NULL, 0); | ||||
chardev = pfs_create_dir(devdir, "char", NULL, NULL, NULL, 0); | chardev = pfs_create_dir(devdir, "char", NULL, NULL, NULL, 0); | ||||
Context not available. | |||||
NULL, NULL, NULL, PFS_RD); | NULL, NULL, NULL, PFS_RD); | ||||
linsysfs_listcpus(cpu); | linsysfs_listcpus(cpu); | ||||
linsysfs_listnics(net); | |||||
return (0); | return (0); | ||||
} | } | ||||
Context not available. |
tab until }?