xref: /haiku/src/add-ons/kernel/debugger/netconsole/netconsole.cpp (revision 02cb3dd4406b923be4ad52f24ade747516ca99a9)
1b4aed463SAdrien Destugues /*
2b4aed463SAdrien Destugues  * Copyright 2008-2016, Haiku, Inc. All Rights Reserved.
3b4aed463SAdrien Destugues  * Distributed under the terms of the MIT License.
4b4aed463SAdrien Destugues  *
5b4aed463SAdrien Destugues  * Authors:
6b4aed463SAdrien Destugues  *		Adrien Destugues, pulkomandy@pulkomandy.tk
7b4aed463SAdrien Destugues  */
8b4aed463SAdrien Destugues 
9b4aed463SAdrien Destugues 
10b4aed463SAdrien Destugues #include <debug.h>
11b4aed463SAdrien Destugues #include <driver_settings.h>
12b4aed463SAdrien Destugues #include <netinet/in.h>
13b4aed463SAdrien Destugues #include <sys/socket.h>
14b4aed463SAdrien Destugues 
15b4aed463SAdrien Destugues 
16b4aed463SAdrien Destugues #define NETCONSOLE_PORT 6666
17b4aed463SAdrien Destugues 
18b4aed463SAdrien Destugues 
19b4aed463SAdrien Destugues static int gSocket;
20b4aed463SAdrien Destugues 
21b4aed463SAdrien Destugues 
22b4aed463SAdrien Destugues static int
createSocket()23b4aed463SAdrien Destugues createSocket()
24b4aed463SAdrien Destugues {
25b4aed463SAdrien Destugues 	gSocket = socket(AF_INET, SOCK_DGRAM, 0);
26*02cb3dd4SAdrien Destugues 	if (gSocket < 0)
27b4aed463SAdrien Destugues 		return B_ERROR;
28b4aed463SAdrien Destugues 
29b4aed463SAdrien Destugues 	// bind socket
30b4aed463SAdrien Destugues 	sockaddr_in fSocketAddress;
31b4aed463SAdrien Destugues 	fSocketAddress.sin_family = AF_INET;
32b4aed463SAdrien Destugues 	fSocketAddress.sin_port = 0;
33b4aed463SAdrien Destugues 	fSocketAddress.sin_addr.s_addr = INADDR_ANY;
34b4aed463SAdrien Destugues 	fSocketAddress.sin_len = sizeof(sockaddr_in);
35b4aed463SAdrien Destugues 	if (bind(gSocket, (sockaddr*)&fSocketAddress, sizeof(fSocketAddress)) < 0) {
36b4aed463SAdrien Destugues 		return B_ERROR;
37b4aed463SAdrien Destugues 	}
38b4aed463SAdrien Destugues 
39b4aed463SAdrien Destugues 	// set SO_BROADCAST on socket
40b4aed463SAdrien Destugues 	int soBroadcastValue = 1;
41b4aed463SAdrien Destugues 	if (setsockopt(gSocket, SOL_SOCKET, SO_BROADCAST, &soBroadcastValue,
42b4aed463SAdrien Destugues 			sizeof(soBroadcastValue)) < 0) {
43b4aed463SAdrien Destugues 		return B_ERROR;
44b4aed463SAdrien Destugues 	}
45b4aed463SAdrien Destugues 
46b4aed463SAdrien Destugues 	return B_OK;
47b4aed463SAdrien Destugues }
48b4aed463SAdrien Destugues 
49b4aed463SAdrien Destugues 
50*02cb3dd4SAdrien Destugues // FIXME this can't work this way, because debugger_puts is called with
51*02cb3dd4SAdrien Destugues // interrupts disabled and can't send to the network directly. Must be reworked
52*02cb3dd4SAdrien Destugues // to use a buffer, and do the network access from another thread. A similar
53*02cb3dd4SAdrien Destugues // solution is implemented to get syslog data to the syslog_daemon.
54b4aed463SAdrien Destugues static int
debugger_puts(const char * message,int32 length)55*02cb3dd4SAdrien Destugues debugger_puts(const char* message, int32 length)
56b4aed463SAdrien Destugues {
57b4aed463SAdrien Destugues 	if (gSocket < 0)
58b4aed463SAdrien Destugues 		createSocket();
59b4aed463SAdrien Destugues 
60b4aed463SAdrien Destugues 	if (gSocket >= 0) {
61b4aed463SAdrien Destugues 		// init server address to broadcast
62b4aed463SAdrien Destugues 		sockaddr_in fServerAddress;
63b4aed463SAdrien Destugues 		fServerAddress.sin_family = AF_INET;
64b4aed463SAdrien Destugues 		fServerAddress.sin_port = htons(NETCONSOLE_PORT);
65b4aed463SAdrien Destugues 		fServerAddress.sin_addr.s_addr = htonl(INADDR_BROADCAST);
66b4aed463SAdrien Destugues 		fServerAddress.sin_len = sizeof(sockaddr_in);
67b4aed463SAdrien Destugues 
68*02cb3dd4SAdrien Destugues 		return sendto(gSocket, message, length, 0,
69b4aed463SAdrien Destugues 			(sockaddr*)&fServerAddress, sizeof(fServerAddress));
70b4aed463SAdrien Destugues 	}
71b4aed463SAdrien Destugues 
72b4aed463SAdrien Destugues 	return 0;
73b4aed463SAdrien Destugues }
74b4aed463SAdrien Destugues 
75b4aed463SAdrien Destugues 
76b4aed463SAdrien Destugues static status_t
std_ops(int32 op,...)77b4aed463SAdrien Destugues std_ops(int32 op, ...)
78b4aed463SAdrien Destugues {
79b4aed463SAdrien Destugues 	void* handle;
80b4aed463SAdrien Destugues 	bool load = false;
81b4aed463SAdrien Destugues 
82b4aed463SAdrien Destugues 	switch (op) {
83b4aed463SAdrien Destugues 		case B_MODULE_INIT:
84b4aed463SAdrien Destugues 			gSocket = -1;
85b4aed463SAdrien Destugues 			return B_OK;
86b4aed463SAdrien Destugues #if 0
87b4aed463SAdrien Destugues 			handle = load_driver_settings("kernel");
88b4aed463SAdrien Destugues 			if (handle) {
89b4aed463SAdrien Destugues 				load = get_driver_boolean_parameter(handle,
90b4aed463SAdrien Destugues 					"netconsole_debug_output", load, true);
91b4aed463SAdrien Destugues 				unload_driver_settings(handle);
92b4aed463SAdrien Destugues 			}
93*02cb3dd4SAdrien Destugues 			if (load)
94b4aed463SAdrien Destugues 				gSocket = -1;
95b4aed463SAdrien Destugues 			return load ? B_OK : B_ERROR;
96b4aed463SAdrien Destugues #endif
97b4aed463SAdrien Destugues 		case B_MODULE_UNINIT:
98b4aed463SAdrien Destugues 			if (gSocket >= 0)
99b4aed463SAdrien Destugues 				close(gSocket);
100b4aed463SAdrien Destugues 			return B_OK;
101b4aed463SAdrien Destugues 	}
102b4aed463SAdrien Destugues 	return B_BAD_VALUE;
103b4aed463SAdrien Destugues }
104b4aed463SAdrien Destugues 
105b4aed463SAdrien Destugues 
106b4aed463SAdrien Destugues static struct debugger_module_info sModuleInfo = {
107b4aed463SAdrien Destugues 	{
108b4aed463SAdrien Destugues 		"debugger/netconsole/v1",
109b4aed463SAdrien Destugues 		0,
110b4aed463SAdrien Destugues 		&std_ops
111b4aed463SAdrien Destugues 	},
112b4aed463SAdrien Destugues 	NULL,
113b4aed463SAdrien Destugues 	NULL,
114b4aed463SAdrien Destugues 	debugger_puts,
115b4aed463SAdrien Destugues 	NULL
116b4aed463SAdrien Destugues };
117b4aed463SAdrien Destugues 
118b4aed463SAdrien Destugues module_info* modules[] = {
119b4aed463SAdrien Destugues 	(module_info*)&sModuleInfo,
120b4aed463SAdrien Destugues 	NULL
121b4aed463SAdrien Destugues };
122b4aed463SAdrien Destugues 
123