Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
um
drivers
mconsole_user.c
Go to the documentation of this file.
1
/*
2
* Copyright (C) 2001 Lennert Buytenhek (
[email protected]
)
3
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4
* Licensed under the GPL
5
*/
6
7
#include <errno.h>
8
#include <string.h>
9
#include <unistd.h>
10
#include <sys/socket.h>
11
#include <sys/uio.h>
12
#include <sys/un.h>
13
#include "
mconsole.h
"
14
15
static
struct
mconsole_command
commands
[] = {
16
/*
17
* With uts namespaces, uts information becomes process-specific, so
18
* we need a process context. If we try handling this in interrupt
19
* context, we may hit an exiting process without a valid uts
20
* namespace.
21
*/
22
{
"version"
,
mconsole_version
,
MCONSOLE_PROC
},
23
{
"halt"
,
mconsole_halt
,
MCONSOLE_PROC
},
24
{
"reboot"
,
mconsole_reboot
,
MCONSOLE_PROC
},
25
{
"config"
,
mconsole_config
,
MCONSOLE_PROC
},
26
{
"remove"
,
mconsole_remove
,
MCONSOLE_PROC
},
27
{
"sysrq"
,
mconsole_sysrq
,
MCONSOLE_INTR
},
28
{
"help"
,
mconsole_help
,
MCONSOLE_INTR
},
29
{
"cad"
,
mconsole_cad
,
MCONSOLE_INTR
},
30
{
"stop"
,
mconsole_stop
,
MCONSOLE_PROC
},
31
{
"go"
,
mconsole_go
,
MCONSOLE_INTR
},
32
{
"log"
,
mconsole_log
,
MCONSOLE_INTR
},
33
{
"proc"
,
mconsole_proc
,
MCONSOLE_PROC
},
34
{
"stack"
,
mconsole_stack
,
MCONSOLE_INTR
},
35
};
36
37
/* Initialized in mconsole_init, which is an initcall */
38
char
mconsole_socket_name
[256];
39
40
static
int
mconsole_reply_v0(
struct
mc_request
*
req
,
char
*reply)
41
{
42
struct
iovec
iov;
43
struct
msghdr
msg;
44
45
iov.
iov_base
= reply;
46
iov.
iov_len
=
strlen
(reply);
47
48
msg.
msg_name
= &(req->
origin
);
49
msg.
msg_namelen
= req->
originlen
;
50
msg.
msg_iov
= &iov;
51
msg.
msg_iovlen
= 1;
52
msg.
msg_control
=
NULL
;
53
msg.
msg_controllen
= 0;
54
msg.
msg_flags
= 0;
55
56
return
sendmsg(req->
originating_fd
, &msg, 0);
57
}
58
59
static
struct
mconsole_command
*mconsole_parse(
struct
mc_request
*
req
)
60
{
61
struct
mconsole_command
*
cmd
;
62
int
i
;
63
64
for
(i = 0; i <
ARRAY_SIZE
(commands); i++) {
65
cmd = &commands[
i
];
66
if
(!
strncmp
(req->
request
.data, cmd->
command
,
67
strlen
(cmd->
command
))) {
68
return
cmd
;
69
}
70
}
71
return
NULL
;
72
}
73
74
#define MIN(a,b) ((a)<(b) ? (a):(b))
75
76
#define STRINGX(x) #x
77
#define STRING(x) STRINGX(x)
78
79
int
mconsole_get_request
(
int
fd
,
struct
mc_request
*req)
80
{
81
int
len
;
82
83
req->
originlen
=
sizeof
(req->
origin
);
84
req->
len
= recvfrom(fd, &req->
request
,
sizeof
(req->
request
), 0,
85
(
struct
sockaddr
*) req->
origin
, &req->
originlen
);
86
if
(req->
len
< 0)
87
return
0;
88
89
req->
originating_fd
=
fd
;
90
91
if
(req->
request
.magic !=
MCONSOLE_MAGIC
) {
92
/* Unversioned request */
93
len =
MIN
(
sizeof
(req->
request
.data) - 1,
94
strlen
((
char
*) &req->
request
));
95
memmove
(req->
request
.data, &req->
request
, len);
96
req->
request
.data[len] =
'\0'
;
97
98
req->
request
.magic =
MCONSOLE_MAGIC
;
99
req->
request
.version = 0;
100
req->
request
.len = len;
101
102
mconsole_reply_v0(req,
"ERR Version 0 mconsole clients are "
103
"not supported by this driver"
);
104
return
0;
105
}
106
107
if
(req->
request
.len >=
MCONSOLE_MAX_DATA
) {
108
mconsole_reply
(req,
"Request too large"
, 1, 0);
109
return
0;
110
}
111
if
(req->
request
.version !=
MCONSOLE_VERSION
) {
112
mconsole_reply
(req,
"This driver only supports version "
113
STRING
(
MCONSOLE_VERSION
)
" clients"
, 1, 0);
114
}
115
116
req->
request
.data[req->
request
.len] =
'\0'
;
117
req->
cmd
= mconsole_parse(req);
118
if
(req->
cmd
==
NULL
) {
119
mconsole_reply
(req,
"Unknown command"
, 1, 0);
120
return
0;
121
}
122
123
return
1;
124
}
125
126
int
mconsole_reply_len
(
struct
mc_request
*req,
const
char
*
str
,
int
total,
127
int
err
,
int
more)
128
{
129
/*
130
* XXX This is a stack consumption problem. It'd be nice to
131
* make it global and serialize access to it, but there are a
132
* ton of callers to this function.
133
*/
134
struct
mconsole_reply
reply;
135
int
len
,
n
;
136
137
do
{
138
reply.
err
=
err
;
139
140
/* err can only be true on the first packet */
141
err = 0;
142
143
len =
MIN
(total,
MCONSOLE_MAX_DATA
- 1);
144
145
if
(len == total) reply.
more
=
more
;
146
else
reply.
more
= 1;
147
148
memcpy
(reply.
data
, str, len);
149
reply.
data
[
len
] =
'\0'
;
150
total -=
len
;
151
str +=
len
;
152
reply.
len
= len + 1;
153
154
len =
sizeof
(reply) + reply.
len
-
sizeof
(reply.
data
);
155
156
n = sendto(req->
originating_fd
, &reply, len, 0,
157
(
struct
sockaddr
*) req->
origin
, req->
originlen
);
158
159
if
(n < 0)
160
return
-
errno
;
161
}
while
(total > 0);
162
return
0;
163
}
164
165
int
mconsole_reply
(
struct
mc_request
*req,
const
char
*
str
,
int
err
,
int
more
)
166
{
167
return
mconsole_reply_len
(req, str,
strlen
(str), err, more);
168
}
169
170
171
int
mconsole_unlink_socket
(
void
)
172
{
173
unlink(
mconsole_socket_name
);
174
return
0;
175
}
176
177
static
int
notify_sock = -1;
178
179
int
mconsole_notify
(
char
*sock_name,
int
type
,
const
void
*
data
,
int
len
)
180
{
181
struct
sockaddr_un
target;
182
struct
mconsole_notify
packet;
183
int
n
,
err
= 0;
184
185
lock_notify
();
186
if
(notify_sock < 0) {
187
notify_sock =
socket
(
PF_UNIX
,
SOCK_DGRAM
, 0);
188
if
(notify_sock < 0) {
189
err = -
errno
;
190
printk
(
UM_KERN_ERR
"mconsole_notify - socket failed, "
191
"errno = %d\n"
,
errno
);
192
}
193
}
194
unlock_notify
();
195
196
if
(err)
197
return
err
;
198
199
target.
sun_family
=
AF_UNIX
;
200
strcpy
(target.
sun_path
, sock_name);
201
202
packet.
magic
=
MCONSOLE_MAGIC
;
203
packet.
version
=
MCONSOLE_VERSION
;
204
packet.
type
=
type
;
205
len = (len >
sizeof
(packet.
data
)) ?
sizeof
(packet.
data
) : len;
206
packet.
len
=
len
;
207
memcpy
(packet.
data
, data, len);
208
209
err = 0;
210
len =
sizeof
(packet) + packet.
len
-
sizeof
(packet.
data
);
211
n = sendto(notify_sock, &packet, len, 0, (
struct
sockaddr
*) &target,
212
sizeof
(target));
213
if
(n < 0) {
214
err = -
errno
;
215
printk
(
UM_KERN_ERR
"mconsole_notify - sendto failed, "
216
"errno = %d\n"
,
errno
);
217
}
218
return
err
;
219
}
Generated on Thu Jan 10 2013 13:19:19 for Linux Kernel by
1.8.2