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