Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/netdump/netdump_client.c
Show All 28 Lines | |||||
* netdump_client.c | * netdump_client.c | ||||
* FreeBSD subsystem supporting netdump network dumps. | * FreeBSD subsystem supporting netdump network dumps. | ||||
* A dedicated server must be running to accept client dumps. | * A dedicated server must be running to accept client dumps. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_ddb.h" | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/disk.h> | #include <sys/disk.h> | ||||
#include <sys/endian.h> | #include <sys/endian.h> | ||||
#include <sys/eventhandler.h> | #include <sys/eventhandler.h> | ||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/kerneldump.h> | #include <sys/kerneldump.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/protosw.h> | #include <sys/protosw.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#ifdef DDB | |||||
#include <ddb/ddb.h> | |||||
#include <ddb/db_lex.h> | |||||
#endif | |||||
#include <net/ethernet.h> | #include <net/ethernet.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_arp.h> | #include <net/if_arp.h> | ||||
#include <net/if_dl.h> | #include <net/if_dl.h> | ||||
#include <net/if_types.h> | #include <net/if_types.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/debugnet.h> | #include <net/debugnet.h> | ||||
▲ Show 20 Lines • Show All 327 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
netdump_configure(struct diocskerneldump_arg *conf, struct thread *td) | netdump_configure(struct diocskerneldump_arg *conf, struct thread *td) | ||||
{ | { | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
NETDUMP_ASSERT_WLOCKED(); | NETDUMP_ASSERT_WLOCKED(); | ||||
CURVNET_SET(TD_TO_VNET(td)); | CURVNET_SET(TD_TO_VNET(td)); | ||||
if (!IS_DEFAULT_VNET(curvnet)) { | if (!IS_DEFAULT_VNET(curvnet)) { | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
cem: What's the best way of retaining this behavior for userspace configurers while using vtnet0 for… | |||||
Done Inline ActionsI think that's a reasonable way to check, yeah. Maybe at some point there will be another use for td and we will have to add a flag instead, but we can just handle that if and when it ever happens. markj: I think that's a reasonable way to check, yeah. Maybe at some point there will be another use… | |||||
ifp = ifunit_ref(conf->kda_iface); | ifp = ifunit_ref(conf->kda_iface); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
if (ifp == NULL) | if (ifp == NULL) | ||||
return (ENOENT); | return (ENOENT); | ||||
if ((if_getflags(ifp) & IFF_UP) == 0) { | if ((if_getflags(ifp) & IFF_UP) == 0) { | ||||
if_rele(ifp); | if_rele(ifp); | ||||
return (ENXIO); | return (ENXIO); | ||||
▲ Show 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | if (conf->kda_index == KDA_REMOVE || | ||||
conf->kda_index == KDA_REMOVE_ALL) { | conf->kda_index == KDA_REMOVE_ALL) { | ||||
if (netdump_enabled()) | if (netdump_enabled()) | ||||
netdump_unconfigure(); | netdump_unconfigure(); | ||||
if (conf->kda_index == KDA_REMOVE_ALL) | if (conf->kda_index == KDA_REMOVE_ALL) | ||||
error = dumper_remove(NULL, conf); | error = dumper_remove(NULL, conf); | ||||
break; | break; | ||||
} | } | ||||
error = netdump_configure(conf, td); | error = netdump_configure(conf, td); | ||||
Done Inline ActionsCalled from userspace here. cem: Called from userspace here. | |||||
if (error != 0) | if (error != 0) | ||||
break; | break; | ||||
if (conf->kda_encryption != KERNELDUMP_ENC_NONE) { | if (conf->kda_encryption != KERNELDUMP_ENC_NONE) { | ||||
if (conf->kda_encryptedkeysize <= 0 || | if (conf->kda_encryptedkeysize <= 0 || | ||||
conf->kda_encryptedkeysize > | conf->kda_encryptedkeysize > | ||||
KERNELDUMP_ENCKEY_MAX_SIZE) { | KERNELDUMP_ENCKEY_MAX_SIZE) { | ||||
error = EINVAL; | error = EINVAL; | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | if ((arg = kern_getenv("net.dump.iface")) != NULL) { | ||||
if ((arg = kern_getenv("net.dump.gateway")) != NULL) { | if ((arg = kern_getenv("net.dump.gateway")) != NULL) { | ||||
inet_aton(arg, &conf.kda_gateway.in4); | inet_aton(arg, &conf.kda_gateway.in4); | ||||
freeenv(arg); | freeenv(arg); | ||||
} | } | ||||
conf.kda_af = AF_INET; | conf.kda_af = AF_INET; | ||||
/* Ignore errors; we print a message to the console. */ | /* Ignore errors; we print a message to the console. */ | ||||
NETDUMP_WLOCK(); | NETDUMP_WLOCK(); | ||||
(void)netdump_configure(&conf, curthread); | (void)netdump_configure(&conf, curthread); | ||||
Done Inline ActionsAnd also kernel here. cem: And also kernel here. | |||||
NETDUMP_WUNLOCK(); | NETDUMP_WUNLOCK(); | ||||
} | } | ||||
break; | break; | ||||
case MOD_UNLOAD: | case MOD_UNLOAD: | ||||
NETDUMP_WLOCK(); | NETDUMP_WLOCK(); | ||||
if (netdump_enabled()) { | if (netdump_enabled()) { | ||||
printf("netdump: disabling dump device for unload\n"); | printf("netdump: disabling dump device for unload\n"); | ||||
netdump_unconfigure(); | netdump_unconfigure(); | ||||
Show All 13 Lines | |||||
static moduledata_t netdump_mod = { | static moduledata_t netdump_mod = { | ||||
"netdump", | "netdump", | ||||
netdump_modevent, | netdump_modevent, | ||||
NULL, | NULL, | ||||
}; | }; | ||||
MODULE_VERSION(netdump, 1); | MODULE_VERSION(netdump, 1); | ||||
DECLARE_MODULE(netdump, netdump_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); | DECLARE_MODULE(netdump, netdump_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); | ||||
#ifdef DDB | |||||
/* | |||||
* Usage: netdump -s <server> [-g <gateway] -c <localip> -i <interface> | |||||
* | |||||
* Order is not significant. | |||||
* | |||||
* Currently, this command does not support configuring encryption or | |||||
* compression. | |||||
Done Inline ActionsThis should be documented in ddb.4. markj: This should be documented in ddb.4. | |||||
Done Inline ActionsGood catch, thanks. Will fix. cem: Good catch, thanks. Will fix. | |||||
*/ | |||||
DB_FUNC(netdump, db_netdump_cmd, db_cmd_table, CS_OWN | CS_LEX_SPACE, NULL) | |||||
{ | |||||
static struct diocskerneldump_arg conf; | |||||
static char blockbuf[NETDUMP_DATASIZE]; | |||||
static union { | |||||
struct dumperinfo di; | |||||
/* For valid di_devname. */ | |||||
char di_buf[sizeof(struct dumperinfo) + 1]; | |||||
} u; | |||||
struct debugnet_ddb_config params; | |||||
int error; | |||||
error = debugnet_parse_ddb_cmd("netdump", ¶ms); | |||||
if (error != 0) { | |||||
db_printf("Error configuring netdump: %d\n", error); | |||||
return; | |||||
} | |||||
/* Translate to a netdump dumper config. */ | |||||
memset(&conf, 0, sizeof(conf)); | |||||
strlcpy(conf.kda_iface, if_name(params.dd_ifp), sizeof(conf.kda_iface)); | |||||
conf.kda_af = AF_INET; | |||||
conf.kda_server.in4 = (struct in_addr) { params.dd_server }; | |||||
conf.kda_client.in4 = (struct in_addr) { params.dd_client }; | |||||
if (params.dd_has_gateway) | |||||
conf.kda_gateway.in4 = (struct in_addr) { params.dd_gateway }; | |||||
else | |||||
conf.kda_gateway.in4 = (struct in_addr) { INADDR_ANY }; | |||||
/* Set the global netdump config to these options. */ | |||||
error = netdump_configure(&conf, curthread); | |||||
Done Inline ActionsInvoked from ddb here. cem: Invoked from ddb here. | |||||
if (error != 0) { | |||||
db_printf("Error enabling netdump: %d\n", error); | |||||
return; | |||||
} | |||||
/* Fake the generic dump configuration list entry to avoid malloc. */ | |||||
memset(&u.di_buf, 0, sizeof(u.di_buf)); | |||||
Done Inline ActionsTypo: "Fake". markj: Typo: "Fake". | |||||
Done Inline Actions'Fako' was actually how I intended to type it, but 'Fake' as a verb probably works as well or better. Will change. cem: 'Fako' was actually how I intended to type it, but 'Fake' as a verb probably works as well or… | |||||
u.di.dumper_start = netdump_start; | |||||
u.di.dumper_hdr = netdump_write_headers; | |||||
u.di.dumper = netdump_dumper; | |||||
u.di.priv = NULL; | |||||
u.di.blocksize = NETDUMP_DATASIZE; | |||||
u.di.maxiosize = MAXDUMPPGS * PAGE_SIZE; | |||||
u.di.mediaoffset = 0; | |||||
u.di.mediasize = 0; | |||||
u.di.blockbuf = blockbuf; | |||||
dumper_ddb_insert_static(&u.di); | |||||
error = doadump(false); | |||||
dumper_ddb_remove_static(&u.di); | |||||
if (error != 0) | |||||
db_printf("Cannot dump: %d", error); | |||||
markjUnsubmitted Done Inline ActionsMissing newline. markj: Missing newline. | |||||
cemAuthorUnsubmitted Done Inline ActionsGood catch, thanks. cem: Good catch, thanks. | |||||
} | |||||
#endif /* DDB */ |
What's the best way of retaining this behavior for userspace configurers while using vtnet0 for the ddb caller added in this revision?
We could pass td=NULL from DDB and conditionalize on that basis in this function?