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 (buytenh@gnu.org)
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