]> git.ipfire.org Git - people/ms/rstp.git/blame - ctl_socket.c
Use new RSTP library.
[people/ms/rstp.git] / ctl_socket.c
CommitLineData
ad02a0eb
SH
1/*****************************************************************************
2 Copyright (c) 2006 EMC Corporation.
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2 of the License, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Authors: Srinivas Aji <Aji_Srinivas@emc.com>
22
23******************************************************************************/
24
25#include "ctl_socket.h"
26#include "ctl_socket_server.h"
27#include <sys/stat.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/un.h>
31#include <unistd.h>
32#include <stdio.h>
33#include <fcntl.h>
b600a2c3
SA
34#include <stdarg.h>
35#include <string.h>
ad02a0eb
SH
36
37#include "epoll_loop.h"
38#include "log.h"
39
ad02a0eb
SH
40int server_socket(void)
41{
11904a35
SH
42 struct sockaddr_un sa;
43 int s;
ad02a0eb 44
11904a35 45 TST(strlen(RSTP_SERVER_SOCK_NAME) < sizeof(sa.sun_path), -1);
ad02a0eb 46
11904a35
SH
47 s = socket(PF_UNIX, SOCK_DGRAM, 0);
48 if (s < 0) {
49 ERROR("Couldn't open unix socket: %m");
50 return -1;
51 }
52
53 set_socket_address(&sa, RSTP_SERVER_SOCK_NAME);
ad02a0eb 54
11904a35
SH
55 if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
56 ERROR("Couldn't bind socket: %m");
57 close(s);
58 return -1;
59 }
60
61 return s;
62}
ad02a0eb 63
b600a2c3 64int handle_message(int cmd, void *inbuf, int lin, void *outbuf, int lout)
ad02a0eb 65{
11904a35
SH
66 switch (cmd) {
67 SERVER_MESSAGE_CASE(enable_bridge_rstp);
b600a2c3 68 SERVER_MESSAGE_CASE(get_bridge_status);
11904a35 69 SERVER_MESSAGE_CASE(set_bridge_config);
b600a2c3 70 SERVER_MESSAGE_CASE(get_port_status);
11904a35 71 SERVER_MESSAGE_CASE(set_port_config);
b600a2c3 72 SERVER_MESSAGE_CASE(port_mcheck);
11904a35
SH
73 SERVER_MESSAGE_CASE(set_debug_level);
74
75 default:
76 ERROR("CTL: Unknown command %d", cmd);
77 return -1;
78 }
ad02a0eb
SH
79}
80
b600a2c3
SA
81int ctl_in_handler = 0;
82static unsigned char msg_logbuf[1024];
83static unsigned int msg_log_offset;
84void _ctl_err_log(char *fmt, ...)
85{
86 if (msg_log_offset >= sizeof(msg_logbuf) - 1)
87 return;
88 int r;
89 va_list ap;
90 va_start(ap, fmt);
91 r = vsnprintf((char *)msg_logbuf + msg_log_offset,
92 sizeof(msg_logbuf) - msg_log_offset,
93 fmt, ap);
94 va_end(ap);
95 msg_log_offset += r;
96 if (msg_log_offset == sizeof(msg_logbuf)) {
97 msg_log_offset = sizeof(msg_logbuf) - 1;
98 msg_logbuf[sizeof(msg_logbuf) - 1] = 0;
99 }
100}
101
102
ad02a0eb 103#define msg_buf_len 1024
b600a2c3
SA
104static unsigned char msg_inbuf[1024];
105static unsigned char msg_outbuf[1024];
ad02a0eb
SH
106
107void ctl_rcv_handler(uint32_t events, struct epoll_event_handler *p)
108{
11904a35
SH
109 struct ctl_msg_hdr mhdr;
110 struct msghdr msg;
111 struct sockaddr_un sa;
b600a2c3 112 struct iovec iov[3];
11904a35
SH
113 int l;
114
115 msg.msg_name = &sa;
116 msg.msg_namelen = sizeof(sa);
117 msg.msg_iov = iov;
b600a2c3 118 msg.msg_iovlen = 3;
11904a35
SH
119 msg.msg_control = NULL;
120 msg.msg_controllen = 0;
121 iov[0].iov_base = &mhdr;
122 iov[0].iov_len = sizeof(mhdr);
123 iov[1].iov_base = msg_inbuf;
124 iov[1].iov_len = msg_buf_len;
b600a2c3
SA
125 iov[2].iov_base = NULL;
126 iov[2].iov_len = 0;
11904a35
SH
127 l = recvmsg(p->fd, &msg, MSG_NOSIGNAL | MSG_DONTWAIT);
128 TST(l > 0,);
129 if (msg.msg_flags != 0 || l < sizeof(mhdr) ||
130 l != sizeof(mhdr) + mhdr.lin ||
131 mhdr.lout > msg_buf_len || mhdr.cmd < 0) {
132 ERROR("CTL: Unexpected message. Ignoring");
133 return;
134 }
135
b600a2c3
SA
136 msg_log_offset = 0;
137 ctl_in_handler = 1;
138
139 mhdr.res = handle_message(mhdr.cmd, msg_inbuf, mhdr.lin,
140 msg_outbuf, mhdr.lout);
11904a35 141
b600a2c3 142 ctl_in_handler = 0;
11904a35 143 if (mhdr.res < 0)
b600a2c3
SA
144 memset(msg_outbuf, 0, mhdr.lout);
145 if (msg_log_offset < mhdr.llog)
146 mhdr.llog = msg_log_offset;
147
11904a35
SH
148 iov[1].iov_base = msg_outbuf;
149 iov[1].iov_len = mhdr.lout;
b600a2c3
SA
150 iov[2].iov_base = msg_logbuf;
151 iov[2].iov_len = mhdr.llog;
11904a35
SH
152 l = sendmsg(p->fd, &msg, MSG_NOSIGNAL);
153 if (l < 0)
154 ERROR("CTL: Couldn't send response: %m");
155 else if (l != sizeof(mhdr) + mhdr.lout) {
156 ERROR
157 ("CTL: Couldn't send full response, sent %d bytes instead of %zd.",
158 l, sizeof(mhdr) + mhdr.lout);
159 }
ad02a0eb
SH
160}
161
162struct epoll_event_handler ctl_handler;
163
164int ctl_socket_init(void)
165{
11904a35
SH
166 int s = server_socket();
167 if (s < 0)
168 return -1;
ad02a0eb 169
11904a35
SH
170 ctl_handler.fd = s;
171 ctl_handler.handler = ctl_rcv_handler;
172
173 TST(add_epoll(&ctl_handler) == 0, -1);
174 return 0;
ad02a0eb
SH
175}
176
177void ctl_socket_cleanup(void)
178{
11904a35
SH
179 remove_epoll(&ctl_handler);
180 close(ctl_handler.fd);
ad02a0eb 181}