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
19static int gSocket;
20
21
22static int
23createSocket()
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.
54static int
55debugger_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
76static status_t
77std_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
106static 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
118module_info* modules[] = {
119	(module_info*)&sModuleInfo,
120	NULL
121};
122
123