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