Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F174314143
D21460.id61438.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D21460.id61438.diff
View Options
Index: sys/net/debugnet.h
===================================================================
--- sys/net/debugnet.h
+++ sys/net/debugnet.h
@@ -177,6 +177,31 @@
*/
void debugnet_any_ifnet_update(struct ifnet *);
+/*
+ * DDB parsing helper for common debugnet options.
+ *
+ * -s <server> [-g <gateway] -c <localip> -i <interface>
+ *
+ * Order is not significant. Interface is an online interface that supports
+ * debugnet and can route to the debugnet server. The other parameters are all
+ * IP addresses. For now, all parameters are mandatory, except gateway.
+ *
+ * Provides basic '-h' using provided 'cmd' string.
+ *
+ * Caveat: 'line' is mutated during parsing.
+ *
+ * Returns zero on success, or errno.
+ */
+struct debugnet_ddb_config {
+ struct ifnet *dd_ifp; /* ref'd */
+ in_addr_t dd_client;
+ in_addr_t dd_server;
+ in_addr_t dd_gateway;
+ bool dd_has_gateway : 1;
+};
+int debugnet_parse_ddb_cmd(const char *cmd,
+ struct debugnet_ddb_config *result);
+
/* Expose sysctl variables for netdump(4) to alias. */
extern int debugnet_npolls;
extern int debugnet_nretries;
Index: sys/net/debugnet.c
===================================================================
--- sys/net/debugnet.c
+++ sys/net/debugnet.c
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_ddb.h"
#include "opt_inet.h"
#include <sys/param.h>
@@ -40,6 +41,11 @@
#include <sys/socket.h>
#include <sys/sysctl.h>
+#ifdef DDB
+#include <ddb/ddb.h>
+#include <ddb/db_lex.h>
+#endif
+
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -656,3 +662,222 @@
dn_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
}
SYSINIT(dn_evh_init, SI_SUB_EVENTHANDLER + 1, SI_ORDER_ANY, dn_evh_init, NULL);
+
+/*
+ * DDB parsing helpers for debugnet(4) consumers.
+ */
+#ifdef DDB
+struct my_inet_opt {
+ bool has_opt;
+ const char *printname;
+ in_addr_t *result;
+};
+
+static int
+dn_parse_optarg_ipv4(struct my_inet_opt *opt)
+{
+ in_addr_t tmp;
+ unsigned octet;
+ int t;
+
+ tmp = 0;
+ for (octet = 0; octet < 4; octet++) {
+ t = db_read_token();
+ if (t != tNUMBER) {
+ db_printf("%s:%s: octet %u expected number; found %d\n",
+ __func__, opt->printname, octet, t);
+ return (EINVAL);
+ }
+ /*
+ * db_lex lexes '-' distinctly from the number itself, but
+ * let's document that invariant.
+ */
+ MPASS(db_tok_number >= 0);
+
+ if (db_tok_number > UINT8_MAX) {
+ db_printf("%s:%s: octet %u out of range: %ld\n", __func__,
+ opt->printname, octet, db_tok_number);
+ return (EDOM);
+ }
+
+ /* Constructed host-endian and converted to network later. */
+ tmp = (tmp << 8) | db_tok_number;
+
+ if (octet < 3) {
+ t = db_read_token();
+ if (t != tDOT) {
+ db_printf("%s:%s: octet %u expected '.'; found"
+ " %d\n", __func__, opt->printname, octet,
+ t);
+ return (EINVAL);
+ }
+ }
+ }
+
+ *opt->result = htonl(tmp);
+ opt->has_opt = true;
+ return (0);
+}
+
+int
+debugnet_parse_ddb_cmd(const char *cmd, struct debugnet_ddb_config *result)
+{
+ struct ifnet *ifp;
+ int t, error;
+ bool want_ifp;
+ char ch;
+
+ /* Assume v4, dotted decimal encoding for now. */
+ db_cmd_radix = 10;
+
+ struct my_inet_opt opt_client = {
+ .printname = "client",
+ .result = &result->dd_client,
+ },
+ opt_server = {
+ .printname = "server",
+ .result = &result->dd_server,
+ },
+ opt_gateway = {
+ .printname = "gateway",
+ .result = &result->dd_gateway,
+ },
+ *cur_inet_opt;
+
+ ifp = NULL;
+ memset(result, 0, sizeof(*result));
+
+ /*
+ * command [space] [-] [opt] [[space] [optarg]] ...
+ *
+ * db_command has already lexed 'command' for us.
+ */
+ t = db_read_token();
+ if (t == tWSPACE)
+ t = db_read_token();
+
+ while (t != tEOL) {
+ if (t != tMINUS) {
+ db_printf("%s: Bad syntax; expected '-', got %d\n",
+ cmd, t);
+ goto usage;
+ }
+
+ t = db_read_token();
+ if (t != tIDENT) {
+ db_printf("%s: Bad syntax; expected tIDENT, got %d\n",
+ cmd, t);
+ goto usage;
+ }
+
+ if (strlen(db_tok_string) > 1) {
+ db_printf("%s: Bad syntax; expected single option "
+ "flag, got '%s'\n", cmd, db_tok_string);
+ goto usage;
+ }
+
+ want_ifp = false;
+ cur_inet_opt = NULL;
+ switch ((ch = db_tok_string[0])) {
+ default:
+ DNETDEBUG("Unexpected: '%c'\n", ch);
+ /* FALLTHROUGH */
+ case 'h':
+ goto usage;
+ case 'c':
+ cur_inet_opt = &opt_client;
+ break;
+ case 'g':
+ cur_inet_opt = &opt_gateway;
+ break;
+ case 's':
+ cur_inet_opt = &opt_server;
+ break;
+ case 'i':
+ want_ifp = true;
+ break;
+ }
+
+ t = db_read_token();
+ if (t != tWSPACE) {
+ db_printf("%s: Bad syntax; expected space after "
+ "flag %c, got %d\n", cmd, ch, t);
+ goto usage;
+ }
+
+ if (want_ifp) {
+ t = db_read_token();
+ if (t != tIDENT) {
+ db_printf("%s: Expected interface but got %d\n",
+ cmd, t);
+ goto usage;
+ }
+
+ CURVNET_SET(vnet0);
+ ifp = ifunit_ref(db_tok_string);
+ CURVNET_RESTORE();
+ if (ifp == NULL) {
+ db_printf("Could not locate interface %s\n",
+ db_tok_string);
+ goto cleanup;
+ }
+ } else {
+ MPASS(cur_inet_opt != NULL);
+ /* Assume IPv4 for now. */
+ error = dn_parse_optarg_ipv4(cur_inet_opt);
+ if (error != 0)
+ goto cleanup;
+ }
+
+ /* Skip (mandatory) whitespace after option, if not EOL. */
+ t = db_read_token();
+ if (t == tEOL)
+ break;
+ if (t != tWSPACE) {
+ db_printf("%s: Bad syntax; expected space after "
+ "flag %c option; got %d\n", cmd, ch, t);
+ goto usage;
+ }
+ t = db_read_token();
+ }
+
+ /* Currently, all three are required. */
+ if (!opt_client.has_opt || !opt_server.has_opt || ifp == NULL) {
+ db_printf("%s needs all of client, server, and interface "
+ "specified.\n", cmd);
+ goto usage;
+ }
+
+ result->dd_has_gateway = opt_gateway.has_opt;
+
+ /* Iface validation stolen from netdump_configure. */
+ if ((if_getflags(ifp) & IFF_UP) == 0) {
+ db_printf("%s: interface '%s' link is down\n", cmd,
+ if_name(ifp));
+ error = ENXIO;
+ goto cleanup;
+ }
+ if (!DEBUGNET_SUPPORTED_NIC(ifp)) {
+ db_printf("%s: interface '%s' does not support debugnet\n",
+ cmd, if_name(ifp));
+ error = ENODEV;
+ goto cleanup;
+ }
+
+ result->dd_ifp = ifp;
+
+ /* We parsed the full line to tEOL already, or bailed with an error. */
+ return (0);
+
+usage:
+ db_printf("Usage: %s -s <server> [-g <gateway>] -c <localip> "
+ "-i <interface>\n", cmd);
+ error = EINVAL;
+ /* FALLTHROUGH */
+cleanup:
+ if (ifp != NULL)
+ if_rele(ifp);
+ db_skip_to_eol();
+ return (error);
+}
+#endif /* DDB */
Index: sys/netinet/netdump/netdump_client.c
===================================================================
--- sys/netinet/netdump/netdump_client.c
+++ sys/netinet/netdump/netdump_client.c
@@ -34,6 +34,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_ddb.h"
+
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/disk.h>
@@ -52,6 +54,11 @@
#include <sys/syslog.h>
#include <sys/systm.h>
+#ifdef DDB
+#include <ddb/ddb.h>
+#include <ddb/db_lex.h>
+#endif
+
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -730,3 +737,73 @@
MODULE_VERSION(netdump, 1);
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.
+ */
+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);
+ if_rele(params.dd_ifp);
+ if (error != 0) {
+ db_printf("Error enabling netdump: %d\n", error);
+ return;
+ }
+
+ /* Fako the generic dump configuration list entry to avoid malloc. */
+ memset(&u.di_buf, 0, sizeof(u.di_buf));
+ 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);
+}
+#endif /* DDB */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 3, 7:32 AM (5 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40118249
Default Alt Text
D21460.id61438.diff (9 KB)
Attached To
Mode
D21460: Add ddb(4) 'netdump' command to netdump a core without preconfiguration
Attached
Detach File
Event Timeline
Log In to Comment