/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2019 Isilon Systems, LLC.4* Copyright (c) 2005-2014 Sandvine Incorporated5* Copyright (c) 2000 Darrell Anderson <[email protected]>6* All rights reserved.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions10* are met:11* 1. Redistributions of source code must retain the above copyright12* notice, this list of conditions and the following disclaimer.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in the15* documentation and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*/2930/*31* Debugnet provides a reliable, bidirectional, UDP-encapsulated datagram32* transport while a machine is in a debug state. (N-1 CPUs stopped,33* interrupts disabled, may or may not be in a panic(9) state.) Only one34* stream may be active at a time. A dedicated server must be running to35* accept connections.36*/3738#pragma once3940#include <sys/types.h>41#include <netinet/in.h>4243/*44* Debugnet protocol details.45*/46#define DEBUGNET_HERALD 1 /* Connection handshake. */47#define DEBUGNET_FINISHED 2 /* Close the connection. */48#define DEBUGNET_DATA 3 /* Contains data. */4950struct debugnet_msg_hdr {51uint32_t mh_type; /* Debugnet message type. */52uint32_t mh_seqno; /* Match acks with msgs. */53uint64_t mh_offset; /* Offset in fragment. */54uint32_t mh_len; /* Attached data (bytes). */55uint32_t mh_aux2; /* Consumer-specific. */56} __packed;5758struct debugnet_ack {59uint32_t da_seqno; /* Match acks with msgs. */60} __packed;6162#define DEBUGNET_MAX_IN_FLIGHT 646364#ifdef _KERNEL65/*66* Hook API for network drivers.67*/68enum debugnet_ev {69DEBUGNET_START,70DEBUGNET_END,71};7273struct ifnet;74struct mbuf;75typedef void debugnet_init_t(struct ifnet *, int *nrxr, int *ncl, int *clsize);76typedef void debugnet_event_t(struct ifnet *, enum debugnet_ev);77typedef int debugnet_transmit_t(struct ifnet *, struct mbuf *);78typedef int debugnet_poll_t(struct ifnet *, int);7980struct debugnet_methods {81debugnet_init_t *dn_init;82debugnet_event_t *dn_event;83debugnet_transmit_t *dn_transmit;84debugnet_poll_t *dn_poll;85};8687#define DEBUGNET_SUPPORTED_NIC(ifp) \88((ifp)->if_debugnet_methods != NULL && (ifp)->if_type == IFT_ETHER)8990struct debugnet_pcb; /* opaque */9192/*93* Debugnet consumer API.94*/95struct debugnet_conn_params {96struct ifnet *dc_ifp;97in_addr_t dc_client;98in_addr_t dc_server;99in_addr_t dc_gateway;100101uint16_t dc_herald_port;102uint16_t dc_client_port;103104const void *dc_herald_data;105uint32_t dc_herald_datalen;106107/*108* Consistent with debugnet_send(), aux parameters to debugnet109* functions are provided host-endian (but converted to110* network endian on the wire).111*/112uint32_t dc_herald_aux2;113uint64_t dc_herald_offset;114115/*116* If NULL, debugnet is a unidirectional channel from panic machine to117* remote server (like netdump).118*119* If handler is non-NULL, packets received on the client port that are120* not just tx acks are forwarded to the provided handler.121*122* The mbuf chain will have all non-debugnet framing headers removed123* (ethernet, inet, udp). It will start with a debugnet_msg_hdr, of124* which the header is guaranteed to be contiguous. If m_pullup is125* used, the supplied in-out mbuf pointer should be updated126* appropriately.127*128* If the handler frees the mbuf chain, it should set the mbuf pointer129* to NULL. Otherwise, the debugnet input framework will free the130* chain.131*132* The handler should ACK receieved packets with debugnet_ack_output.133*/134int (*dc_rx_handler)(struct mbuf *);135136/* Cleanup signal for bidirectional protocols. */137void (*dc_finish_handler)(void);138};139140/*141* Open a stream to the specified server's herald port.142*143* If all goes well, the server will send ACK from a different port to our ack144* port. This allows servers to somewhat gracefully handle multiple debugnet145* clients. (Clients are limited to single connections.)146*147* Returns zero on success, or errno.148*/149int debugnet_connect(const struct debugnet_conn_params *,150struct debugnet_pcb **pcb_out);151152/*153* Free a debugnet stream that was previously successfully opened.154*155* No attempt is made to cleanly terminate communication with the remote156* server. Consumers should first send an empty DEBUGNET_FINISHED message, or157* otherwise let the remote know they are signing off.158*/159void debugnet_free(struct debugnet_pcb *);160161/*162* Send a message, with common debugnet_msg_hdr header, to the connected remote163* server.164*165* - mhtype translates directly to mh_type (e.g., DEBUGNET_DATA, or some other166* protocol-specific type).167* - Data and datalen describe the attached data; datalen may be zero.168* - If auxdata is NULL, mh_offset's initial value and mh_aux2 will be zero.169* Otherwise, mh_offset's initial value will be auxdata->dp_offset_start and170* mh_aux2 will have the value of auxdata->dp_aux2.171*172* Returns zero on success, or an errno on failure.173*/174struct debugnet_proto_aux {175uint64_t dp_offset_start;176uint32_t dp_aux2;177};178int debugnet_send(struct debugnet_pcb *, uint32_t mhtype, const void *data,179uint32_t datalen, const struct debugnet_proto_aux *auxdata);180181/*182* A simple wrapper around the above when no data or auxdata is needed.183*/184static inline int185debugnet_sendempty(struct debugnet_pcb *pcb, uint32_t mhtype)186{187return (debugnet_send(pcb, mhtype, NULL, 0, NULL));188}189190/*191* Full-duplex RX should ACK received messages.192*/193int debugnet_ack_output(struct debugnet_pcb *, uint32_t seqno /*net endian*/);194195/*196* Check and/or wait for further packets.197*/198void debugnet_network_poll(struct debugnet_pcb *);199200/*201* PCB accessors.202*/203204/*205* Get the 48-bit MAC address of the discovered next hop (gateway, or206* destination server if it is on the same segment.207*/208const unsigned char *debugnet_get_gw_mac(const struct debugnet_pcb *);209210/*211* Get the connected server address.212*/213const in_addr_t *debugnet_get_server_addr(const struct debugnet_pcb *);214215/*216* Get the connected server port.217*/218const uint16_t debugnet_get_server_port(const struct debugnet_pcb *);219220/*221* Callbacks from core mbuf code.222*/223void debugnet_any_ifnet_update(struct ifnet *);224225/*226* DDB parsing helper for common debugnet options.227*228* -s <server> [-g <gateway -c <localip> -i <interface>]229*230* Order is not significant. Interface is an online interface that supports231* debugnet and can route to the debugnet server. The other parameters are all232* IP addresses. Only the server parameter is required. The others are233* inferred automatically from the routing table, if not explicitly provided.234*235* Provides basic '-h' using provided 'cmd' string.236*237* Returns zero on success, or errno.238*/239struct debugnet_ddb_config {240struct ifnet *dd_ifp; /* not ref'd */241in_addr_t dd_client;242in_addr_t dd_server;243in_addr_t dd_gateway;244bool dd_has_client : 1;245bool dd_has_gateway : 1;246};247int debugnet_parse_ddb_cmd(const char *cmd,248struct debugnet_ddb_config *result);249250/* Expose sysctl variables for netdump(4) to alias. */251extern int debugnet_npolls;252extern int debugnet_nretries;253extern int debugnet_arp_nretries;254255/*256* Conditionally-defined macros for device drivers so we can avoid ifdef257* wrappers in every single implementation.258*/259#ifdef DEBUGNET260#define DEBUGNET_DEFINE(driver) \261static debugnet_init_t driver##_debugnet_init; \262static debugnet_event_t driver##_debugnet_event; \263static debugnet_transmit_t driver##_debugnet_transmit; \264static debugnet_poll_t driver##_debugnet_poll; \265\266static struct debugnet_methods driver##_debugnet_methods = { \267.dn_init = driver##_debugnet_init, \268.dn_event = driver##_debugnet_event, \269.dn_transmit = driver##_debugnet_transmit, \270.dn_poll = driver##_debugnet_poll, \271}272273#define DEBUGNET_NOTIFY_MTU(ifp) debugnet_any_ifnet_update(ifp)274275#define DEBUGNET_SET(ifp, driver) \276if_setdebugnet_methods((ifp), &driver##_debugnet_methods)277278#else /* !DEBUGNET || !INET */279280#define DEBUGNET_DEFINE(driver)281#define DEBUGNET_NOTIFY_MTU(ifp)282#define DEBUGNET_SET(ifp, driver)283284#endif /* DEBUGNET && INET */285#endif /* _KERNEL */286287288