debugnet.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  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. * $FreeBSD$
  31. */
  32. /*
  33. * Debugnet provides a reliable, bidirectional, UDP-encapsulated datagram
  34. * transport while a machine is in a debug state. (N-1 CPUs stopped,
  35. * interrupts disabled, may or may not be in a panic(9) state.) Only one
  36. * stream may be active at a time. A dedicated server must be running to
  37. * accept connections.
  38. */
  39. #pragma once
  40. #include <sys/types.h>
  41. #include <netinet/in.h>
  42. /*
  43. * Debugnet protocol details.
  44. */
  45. #define DEBUGNET_HERALD 1 /* Connection handshake. */
  46. #define DEBUGNET_FINISHED 2 /* Close the connection. */
  47. #define DEBUGNET_DATA 3 /* Contains data. */
  48. struct debugnet_msg_hdr {
  49. uint32_t mh_type; /* Debugnet message type. */
  50. uint32_t mh_seqno; /* Match acks with msgs. */
  51. uint64_t mh_offset; /* Offset in fragment. */
  52. uint32_t mh_len; /* Attached data (bytes). */
  53. uint32_t mh_aux2; /* Consumer-specific. */
  54. } __packed;
  55. struct debugnet_ack {
  56. uint32_t da_seqno; /* Match acks with msgs. */
  57. } __packed;
  58. #define DEBUGNET_MAX_IN_FLIGHT 64
  59. #ifdef _KERNEL
  60. /*
  61. * Hook API for network drivers.
  62. */
  63. enum debugnet_ev {
  64. DEBUGNET_START,
  65. DEBUGNET_END,
  66. };
  67. struct ifnet;
  68. struct mbuf;
  69. typedef void debugnet_init_t(struct ifnet *, int *nrxr, int *ncl, int *clsize);
  70. typedef void debugnet_event_t(struct ifnet *, enum debugnet_ev);
  71. typedef int debugnet_transmit_t(struct ifnet *, struct mbuf *);
  72. typedef int debugnet_poll_t(struct ifnet *, int);
  73. struct debugnet_methods {
  74. debugnet_init_t *dn_init;
  75. debugnet_event_t *dn_event;
  76. debugnet_transmit_t *dn_transmit;
  77. debugnet_poll_t *dn_poll;
  78. };
  79. #define DEBUGNET_SUPPORTED_NIC(ifp) \
  80. ((ifp)->if_debugnet_methods != NULL && (ifp)->if_type == IFT_ETHER)
  81. struct debugnet_pcb; /* opaque */
  82. /*
  83. * Debugnet consumer API.
  84. */
  85. struct debugnet_conn_params {
  86. struct ifnet *dc_ifp;
  87. in_addr_t dc_client;
  88. in_addr_t dc_server;
  89. in_addr_t dc_gateway;
  90. uint16_t dc_herald_port;
  91. uint16_t dc_client_port;
  92. const void *dc_herald_data;
  93. uint32_t dc_herald_datalen;
  94. /*
  95. * Consistent with debugnet_send(), aux paramaters to debugnet
  96. * functions are provided host-endian (but converted to
  97. * network endian on the wire).
  98. */
  99. uint32_t dc_herald_aux2;
  100. uint64_t dc_herald_offset;
  101. /*
  102. * If NULL, debugnet is a unidirectional channel from panic machine to
  103. * remote server (like netdump).
  104. *
  105. * If handler is non-NULL, packets received on the client port that are
  106. * not just tx acks are forwarded to the provided handler.
  107. *
  108. * The mbuf chain will have all non-debugnet framing headers removed
  109. * (ethernet, inet, udp). It will start with a debugnet_msg_hdr, of
  110. * which the header is guaranteed to be contiguous. If m_pullup is
  111. * used, the supplied in-out mbuf pointer should be updated
  112. * appropriately.
  113. *
  114. * If the handler frees the mbuf chain, it should set the mbuf pointer
  115. * to NULL. Otherwise, the debugnet input framework will free the
  116. * chain.
  117. *
  118. * The handler should ACK receieved packets with debugnet_ack_output.
  119. */
  120. void (*dc_rx_handler)(struct debugnet_pcb *, struct mbuf **);
  121. };
  122. /*
  123. * Open a stream to the specified server's herald port.
  124. *
  125. * If all goes well, the server will send ACK from a different port to our ack
  126. * port. This allows servers to somewhat gracefully handle multiple debugnet
  127. * clients. (Clients are limited to single connections.)
  128. *
  129. * Returns zero on success, or errno.
  130. */
  131. int debugnet_connect(const struct debugnet_conn_params *,
  132. struct debugnet_pcb **pcb_out);
  133. /*
  134. * Free a debugnet stream that was previously successfully opened.
  135. *
  136. * No attempt is made to cleanly terminate communication with the remote
  137. * server. Consumers should first send an empty DEBUGNET_FINISHED message, or
  138. * otherwise let the remote know they are signing off.
  139. */
  140. void debugnet_free(struct debugnet_pcb *);
  141. /*
  142. * Send a message, with common debugnet_msg_hdr header, to the connected remote
  143. * server.
  144. *
  145. * - mhtype translates directly to mh_type (e.g., DEBUGNET_DATA, or some other
  146. * protocol-specific type).
  147. * - Data and datalen describe the attached data; datalen may be zero.
  148. * - If auxdata is NULL, mh_offset's initial value and mh_aux2 will be zero.
  149. * Otherwise, mh_offset's initial value will be auxdata->dp_offset_start and
  150. * mh_aux2 will have the value of auxdata->dp_aux2.
  151. *
  152. * Returns zero on success, or an errno on failure.
  153. */
  154. struct debugnet_proto_aux {
  155. uint64_t dp_offset_start;
  156. uint32_t dp_aux2;
  157. };
  158. int debugnet_send(struct debugnet_pcb *, uint32_t mhtype, const void *data,
  159. uint32_t datalen, const struct debugnet_proto_aux *auxdata);
  160. /*
  161. * A simple wrapper around the above when no data or auxdata is needed.
  162. */
  163. static inline int
  164. debugnet_sendempty(struct debugnet_pcb *pcb, uint32_t mhtype)
  165. {
  166. return (debugnet_send(pcb, mhtype, NULL, 0, NULL));
  167. }
  168. /*
  169. * Full-duplex RX should ACK received messages.
  170. */
  171. int debugnet_ack_output(struct debugnet_pcb *, uint32_t seqno /*net endian*/);
  172. /*
  173. * Check and/or wait for further packets.
  174. */
  175. void debugnet_network_poll(struct debugnet_pcb *);
  176. /*
  177. * PCB accessors.
  178. */
  179. /*
  180. * Get the 48-bit MAC address of the discovered next hop (gateway, or
  181. * destination server if it is on the same segment.
  182. */
  183. const unsigned char *debugnet_get_gw_mac(const struct debugnet_pcb *);
  184. /*
  185. * Callbacks from core mbuf code.
  186. */
  187. void debugnet_any_ifnet_update(struct ifnet *);
  188. /*
  189. * DDB parsing helper for common debugnet options.
  190. *
  191. * -s <server> [-g <gateway -c <localip> -i <interface>]
  192. *
  193. * Order is not significant. Interface is an online interface that supports
  194. * debugnet and can route to the debugnet server. The other parameters are all
  195. * IP addresses. Only the server parameter is required. The others are
  196. * inferred automatically from the routing table, if not explicitly provided.
  197. *
  198. * Provides basic '-h' using provided 'cmd' string.
  199. *
  200. * Returns zero on success, or errno.
  201. */
  202. struct debugnet_ddb_config {
  203. struct ifnet *dd_ifp; /* not ref'd */
  204. in_addr_t dd_client;
  205. in_addr_t dd_server;
  206. in_addr_t dd_gateway;
  207. bool dd_has_client : 1;
  208. bool dd_has_gateway : 1;
  209. };
  210. int debugnet_parse_ddb_cmd(const char *cmd,
  211. struct debugnet_ddb_config *result);
  212. /* Expose sysctl variables for netdump(4) to alias. */
  213. extern int debugnet_npolls;
  214. extern int debugnet_nretries;
  215. extern int debugnet_arp_nretries;
  216. /*
  217. * Conditionally-defined macros for device drivers so we can avoid ifdef
  218. * wrappers in every single implementation.
  219. */
  220. #ifdef DEBUGNET
  221. #define DEBUGNET_DEFINE(driver) \
  222. static debugnet_init_t driver##_debugnet_init; \
  223. static debugnet_event_t driver##_debugnet_event; \
  224. static debugnet_transmit_t driver##_debugnet_transmit; \
  225. static debugnet_poll_t driver##_debugnet_poll; \
  226. \
  227. static struct debugnet_methods driver##_debugnet_methods = { \
  228. .dn_init = driver##_debugnet_init, \
  229. .dn_event = driver##_debugnet_event, \
  230. .dn_transmit = driver##_debugnet_transmit, \
  231. .dn_poll = driver##_debugnet_poll, \
  232. }
  233. #define DEBUGNET_NOTIFY_MTU(ifp) debugnet_any_ifnet_update(ifp)
  234. #define DEBUGNET_SET(ifp, driver) \
  235. (ifp)->if_debugnet_methods = &driver##_debugnet_methods
  236. #else /* !DEBUGNET || !INET */
  237. #define DEBUGNET_DEFINE(driver)
  238. #define DEBUGNET_NOTIFY_MTU(ifp)
  239. #define DEBUGNET_SET(ifp, driver)
  240. #endif /* DEBUGNET && INET */
  241. #endif /* _KERNEL */