zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

debugnet.h (9015B) - Raw


      1 /*-
      2  * SPDX-License-Identifier: BSD-2-Clause
      3  *
      4  * Copyright (c) 2019 Isilon Systems, LLC.
      5  * Copyright (c) 2005-2014 Sandvine Incorporated
      6  * Copyright (c) 2000 Darrell Anderson <anderson@cs.duke.edu>
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  * SUCH DAMAGE.
     29  */
     30 
     31 /*
     32  * Debugnet provides a reliable, bidirectional, UDP-encapsulated datagram
     33  * transport while a machine is in a debug state.  (N-1 CPUs stopped,
     34  * interrupts disabled, may or may not be in a panic(9) state.)  Only one
     35  * stream may be active at a time.  A dedicated server must be running to
     36  * accept connections.
     37  */
     38 
     39 #pragma once
     40 
     41 #include <sys/types.h>
     42 #include <netinet/in.h>
     43 
     44 /*
     45  * Debugnet protocol details.
     46  */
     47 #define	DEBUGNET_HERALD		1	/* Connection handshake. */
     48 #define	DEBUGNET_FINISHED	2	/* Close the connection. */
     49 #define	DEBUGNET_DATA		3	/* Contains data. */
     50 
     51 struct debugnet_msg_hdr {
     52 	uint32_t	mh_type;	/* Debugnet message type. */
     53 	uint32_t	mh_seqno;	/* Match acks with msgs. */
     54 	uint64_t	mh_offset;	/* Offset in fragment. */
     55 	uint32_t	mh_len;		/* Attached data (bytes). */
     56 	uint32_t	mh_aux2;	/* Consumer-specific. */
     57 } __packed;
     58 
     59 struct debugnet_ack {
     60 	uint32_t	da_seqno;	/* Match acks with msgs. */
     61 } __packed;
     62 
     63 #define	DEBUGNET_MAX_IN_FLIGHT	64
     64 
     65 #ifdef _KERNEL
     66 /*
     67  * Hook API for network drivers.
     68  */
     69 enum debugnet_ev {
     70 	DEBUGNET_START,
     71 	DEBUGNET_END,
     72 };
     73 
     74 struct ifnet;
     75 struct mbuf;
     76 typedef void debugnet_init_t(struct ifnet *, int *nrxr, int *ncl, int *clsize);
     77 typedef void debugnet_event_t(struct ifnet *, enum debugnet_ev);
     78 typedef int debugnet_transmit_t(struct ifnet *, struct mbuf *);
     79 typedef int debugnet_poll_t(struct ifnet *, int);
     80 
     81 struct debugnet_methods {
     82 	debugnet_init_t		*dn_init;
     83 	debugnet_event_t	*dn_event;
     84 	debugnet_transmit_t	*dn_transmit;
     85 	debugnet_poll_t		*dn_poll;
     86 };
     87 
     88 #define	DEBUGNET_SUPPORTED_NIC(ifp)				\
     89 	((ifp)->if_debugnet_methods != NULL && (ifp)->if_type == IFT_ETHER)
     90 
     91 struct debugnet_pcb; /* opaque */
     92 
     93 /*
     94  * Debugnet consumer API.
     95  */
     96 struct debugnet_conn_params {
     97 	struct ifnet	*dc_ifp;
     98 	in_addr_t	dc_client;
     99 	in_addr_t	dc_server;
    100 	in_addr_t	dc_gateway;
    101 
    102 	uint16_t	dc_herald_port;
    103 	uint16_t	dc_client_port;
    104 
    105 	const void	*dc_herald_data;
    106 	uint32_t	dc_herald_datalen;
    107 
    108 	/*
    109 	 * Consistent with debugnet_send(), aux parameters to debugnet
    110 	 * functions are provided host-endian (but converted to
    111 	 * network endian on the wire).
    112 	 */
    113 	uint32_t	dc_herald_aux2;
    114 	uint64_t	dc_herald_offset;
    115 
    116 	/*
    117 	 * If NULL, debugnet is a unidirectional channel from panic machine to
    118 	 * remote server (like netdump).
    119 	 *
    120 	 * If handler is non-NULL, packets received on the client port that are
    121 	 * not just tx acks are forwarded to the provided handler.
    122 	 *
    123 	 * The mbuf chain will have all non-debugnet framing headers removed
    124 	 * (ethernet, inet, udp).  It will start with a debugnet_msg_hdr, of
    125 	 * which the header is guaranteed to be contiguous.  If m_pullup is
    126 	 * used, the supplied in-out mbuf pointer should be updated
    127 	 * appropriately.
    128 	 *
    129 	 * If the handler frees the mbuf chain, it should set the mbuf pointer
    130 	 * to NULL.  Otherwise, the debugnet input framework will free the
    131 	 * chain.
    132 	 *
    133 	 * The handler should ACK receieved packets with debugnet_ack_output.
    134 	 */
    135 	int			(*dc_rx_handler)(struct mbuf *);
    136 
    137 	/* Cleanup signal for bidirectional protocols. */
    138 	void		(*dc_finish_handler)(void);
    139 };
    140 
    141 /*
    142  * Open a stream to the specified server's herald port.
    143  *
    144  * If all goes well, the server will send ACK from a different port to our ack
    145  * port.  This allows servers to somewhat gracefully handle multiple debugnet
    146  * clients.  (Clients are limited to single connections.)
    147  *
    148  * Returns zero on success, or errno.
    149  */
    150 int debugnet_connect(const struct debugnet_conn_params *,
    151     struct debugnet_pcb **pcb_out);
    152 
    153 /*
    154  * Free a debugnet stream that was previously successfully opened.
    155  *
    156  * No attempt is made to cleanly terminate communication with the remote
    157  * server.  Consumers should first send an empty DEBUGNET_FINISHED message, or
    158  * otherwise let the remote know they are signing off.
    159  */
    160 void debugnet_free(struct debugnet_pcb *);
    161 
    162 /*
    163  * Send a message, with common debugnet_msg_hdr header, to the connected remote
    164  * server.
    165  *
    166  * - mhtype translates directly to mh_type (e.g., DEBUGNET_DATA, or some other
    167  *   protocol-specific type).
    168  * - Data and datalen describe the attached data; datalen may be zero.
    169  * - If auxdata is NULL, mh_offset's initial value and mh_aux2 will be zero.
    170  *   Otherwise, mh_offset's initial value will be auxdata->dp_offset_start and
    171  *   mh_aux2 will have the value of auxdata->dp_aux2.
    172  *
    173  * Returns zero on success, or an errno on failure.
    174  */
    175 struct debugnet_proto_aux {
    176 	uint64_t dp_offset_start;
    177 	uint32_t dp_aux2;
    178 };
    179 int debugnet_send(struct debugnet_pcb *, uint32_t mhtype, const void *data,
    180     uint32_t datalen, const struct debugnet_proto_aux *auxdata);
    181 
    182 /*
    183  * A simple wrapper around the above when no data or auxdata is needed.
    184  */
    185 static inline int
    186 debugnet_sendempty(struct debugnet_pcb *pcb, uint32_t mhtype)
    187 {
    188 	return (debugnet_send(pcb, mhtype, NULL, 0, NULL));
    189 }
    190 
    191 /*
    192  * Full-duplex RX should ACK received messages.
    193  */
    194 int debugnet_ack_output(struct debugnet_pcb *, uint32_t seqno /*net endian*/);
    195 
    196 /*
    197  * Check and/or wait for further packets.
    198  */
    199 void debugnet_network_poll(struct debugnet_pcb *);
    200 
    201 /*
    202  * PCB accessors.
    203  */
    204 
    205 /*
    206  * Get the 48-bit MAC address of the discovered next hop (gateway, or
    207  * destination server if it is on the same segment.
    208  */
    209 const unsigned char *debugnet_get_gw_mac(const struct debugnet_pcb *);
    210 
    211 /*
    212  * Get the connected server address.
    213  */
    214 const in_addr_t *debugnet_get_server_addr(const struct debugnet_pcb *);
    215 
    216 /*
    217  * Get the connected server port.
    218  */
    219 const uint16_t debugnet_get_server_port(const struct debugnet_pcb *);
    220 
    221 /*
    222  * Callbacks from core mbuf code.
    223  */
    224 void debugnet_any_ifnet_update(struct ifnet *);
    225 
    226 /*
    227  * DDB parsing helper for common debugnet options.
    228  *
    229  * -s <server> [-g <gateway -c <localip> -i <interface>]
    230  *
    231  * Order is not significant.  Interface is an online interface that supports
    232  * debugnet and can route to the debugnet server.  The other parameters are all
    233  * IP addresses.  Only the server parameter is required.  The others are
    234  * inferred automatically from the routing table, if not explicitly provided.
    235  *
    236  * Provides basic '-h' using provided 'cmd' string.
    237  *
    238  * Returns zero on success, or errno.
    239  */
    240 struct debugnet_ddb_config {
    241 	struct ifnet	*dd_ifp;	/* not ref'd */
    242 	in_addr_t	dd_client;
    243 	in_addr_t	dd_server;
    244 	in_addr_t	dd_gateway;
    245 	bool		dd_has_client : 1;
    246 	bool		dd_has_gateway : 1;
    247 };
    248 int debugnet_parse_ddb_cmd(const char *cmd,
    249     struct debugnet_ddb_config *result);
    250 
    251 /* Expose sysctl variables for netdump(4) to alias. */
    252 extern int debugnet_npolls;
    253 extern int debugnet_nretries;
    254 extern int debugnet_arp_nretries;
    255 
    256 /*
    257  * Conditionally-defined macros for device drivers so we can avoid ifdef
    258  * wrappers in every single implementation.
    259  */
    260 #ifdef DEBUGNET
    261 #define	DEBUGNET_DEFINE(driver)					\
    262 	static debugnet_init_t driver##_debugnet_init;		\
    263 	static debugnet_event_t driver##_debugnet_event;	\
    264 	static debugnet_transmit_t driver##_debugnet_transmit;	\
    265 	static debugnet_poll_t driver##_debugnet_poll;		\
    266 								\
    267 	static struct debugnet_methods driver##_debugnet_methods = { \
    268 		.dn_init = driver##_debugnet_init,		\
    269 		.dn_event = driver##_debugnet_event,		\
    270 		.dn_transmit = driver##_debugnet_transmit,	\
    271 		.dn_poll = driver##_debugnet_poll,		\
    272 	}
    273 
    274 #define	DEBUGNET_NOTIFY_MTU(ifp)	debugnet_any_ifnet_update(ifp)
    275 
    276 #define	DEBUGNET_SET(ifp, driver)				\
    277 	if_setdebugnet_methods((ifp), &driver##_debugnet_methods)
    278 
    279 #else /* !DEBUGNET || !INET */
    280 
    281 #define	DEBUGNET_DEFINE(driver)
    282 #define	DEBUGNET_NOTIFY_MTU(ifp)
    283 #define	DEBUGNET_SET(ifp, driver)
    284 
    285 #endif /* DEBUGNET && INET */
    286 #endif /* _KERNEL */