]> git.ipfire.org Git - people/ms/mstpd.git/blame - ctl_socket_client.c
driver hooks for creating/deleting new MSTI
[people/ms/mstpd.git] / ctl_socket_client.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#include <sys/poll.h>
30
31#include "ctl_functions.h"
32#define NO_DAEMON
33#include "log.h"
34
35static int fd = -1;
36
37int ctl_client_init(void)
38{
39 struct sockaddr_un sa_svr;
40 int s;
41 TST(strlen(MSTP_SERVER_SOCK_NAME) < sizeof(sa_svr.sun_path), -1);
42
43 if(0 > (s = socket(PF_UNIX, SOCK_DGRAM, 0)))
44 {
45 ERROR("Couldn't open unix socket: %m");
46 return -1;
47 }
48
49 set_socket_address(&sa_svr, MSTP_SERVER_SOCK_NAME);
50
51 struct sockaddr_un sa;
52 char tmpname[64];
53 sprintf(tmpname, "MSTPCTL_%d", getpid());
54 set_socket_address(&sa, tmpname);
55 /* We need this bind. The autobind on connect isn't working properly.
56 * The server doesn't get a proper sockaddr in recvmsg if we don't do this.
57 */
58 if(0 != bind(s, (struct sockaddr *)&sa, sizeof(sa)))
59 {
60 ERROR("Couldn't bind socket: %m");
61 close(s);
62 return -1;
63 }
64
65 if(0 != connect(s, (struct sockaddr *)&sa_svr, sizeof(sa_svr)))
66 {
67 ERROR("Couldn't connect to server");
68 close(s);
69 return -1;
70 }
71 fd = s;
72
73 return 0;
74}
75
76void ctl_client_cleanup(void)
77{
78 if(fd >= 0)
79 {
80 close(fd);
81 fd = -1;
82 }
83}
84
85int send_ctl_message(int cmd, void *inbuf, int lin, void *outbuf, int lout,
86 LogString *log, int *res)
87{
88 struct ctl_msg_hdr mhdr;
89 struct msghdr msg;
90 struct iovec iov[3];
91 int l;
92
93 msg.msg_name = NULL;
94 msg.msg_namelen = 0;
95 msg.msg_iov = iov;
96 msg.msg_iovlen = 3;
97 msg.msg_control = NULL;
98 msg.msg_controllen = 0;
99
100 mhdr.cmd = cmd;
101 mhdr.lin = lin;
102 mhdr.lout = lout;
103 mhdr.llog = sizeof(log->buf) - 1;
104 iov[0].iov_base = &mhdr;
105 iov[0].iov_len = sizeof(mhdr);
106 iov[1].iov_base = (void *)inbuf;
107 iov[1].iov_len = lin;
108 iov[2].iov_base = log->buf;
109 iov[2].iov_len = 0;
110
111 l = sendmsg(fd, &msg, 0);
112 if(0 > l)
113 {
114 ERROR("Error sending message to server: %m");
115 return -1;
116 }
117 if(l != sizeof(mhdr) + lin)
118 {
119 ERROR("Error sending message to server: Partial write");
120 return -1;
121 }
122
123 iov[1].iov_base = outbuf;
124 iov[1].iov_len = lout;
125 iov[2].iov_base = log->buf;
126 iov[2].iov_len = sizeof(log->buf);
127
128 struct pollfd pfd;
129 int timeout = 5000; /* 5 s */
130 int r;
131
132 pfd.fd = fd;
133 pfd.events = POLLIN;
134 do
135 {
136 if(0 == (r = poll(&pfd, 1, timeout)))
137 {
138 ERROR("Error getting message from server: Timeout");
139 return -1;
140 }
141 if(0 > r)
142 {
143 ERROR("Error getting message from server: poll error: %m");
144 return -1;
145 }
146 }while(0 == (pfd.revents & (POLLERR | POLLHUP | POLLNVAL | POLLIN)));
147
148 l = recvmsg(fd, &msg, 0);
149 if(0 > l)
150 {
151 ERROR("Error getting message from server: %m");
152 return -1;
153 }
154 if((sizeof(mhdr) > l)
155 || (l != sizeof(mhdr) + mhdr.lout + mhdr.llog)
156 || (mhdr.cmd != cmd)
157 )
158 {
159 ERROR("Error getting message from server: Bad format");
160 return -1;
161 }
162 if(mhdr.lout != lout)
163 {
164 ERROR("Error, unexpected result length %d, expected %d\n",
165 mhdr.lout, lout);
166 return -1;
167 }
168 if(sizeof(log->buf) <= mhdr.llog)
169 {
170 ERROR("Invalid log message length %d", mhdr.llog);
171 return -1;
172 }
173 if(res)
174 *res = mhdr.res;
175 log->buf[mhdr.llog] = 0;
176 return 0;
177}