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
createSocket()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
debugger_puts(const char * message,int32 length)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
std_ops(int32 op,...)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