Page MenuHomeFreeBSD

D21460.id61438.diff
No OneTemporary

D21460.id61438.diff

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", &params);
+ 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

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)

Event Timeline