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