]> git.ipfire.org Git - people/ms/rstp.git/blob - ctl_socket_client.c
Revised packet SOCK_RAW code
[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;
93 msg.msg_namelen = 0;
94 msg.msg_iov = iov;
95 msg.msg_iovlen = 2;
96 msg.msg_control = NULL;
97 msg.msg_controllen = 0;
98
99 mhdr.cmd = cmd;
100 mhdr.lin = lin;
101 mhdr.lout = lout != NULL ? *lout : 0;
102 iov[0].iov_base = &mhdr;
103 iov[0].iov_len = sizeof(mhdr);
104 iov[1].iov_base = (void *)inbuf;
105 iov[1].iov_len = lin;
106
107 l = sendmsg(fd, &msg, 0);
108 if (l < 0) {
109 ERROR("Error sending message to server: %m");
110 return -1;
111 }
112 if (l != sizeof(mhdr) + lin) {
113 ERROR("Error sending message to server: Partial write");
114 return -1;
115 }
116
117 iov[1].iov_base = outbuf;
118 iov[1].iov_len = lout != NULL ? *lout : 0;
119
120 {
121 struct pollfd pfd;
122 int timeout = 5000; /* 5 s */
123 int r;
124
125 pfd.fd = fd;
126 pfd.events = POLLIN;
127 do {
128 r = poll(&pfd, 1, timeout);
129 if (r == 0) {
130 ERROR
131 ("Error getting message from server: Timeout");
132 return -1;
133 }
134 if (r < 0) {
135 ERROR
136 ("Error getting message from server: poll error: %m");
137 return -1;
138 }
139 } while ((pfd.
140 revents & (POLLERR | POLLHUP | POLLNVAL | POLLIN)) ==
141 0);
142
143 l = recvmsg(fd, &msg, 0);
144 if (l < 0) {
145 ERROR("Error getting message from server: %m");
146 return -1;
147 }
148 if (l < sizeof(mhdr) || l != sizeof(mhdr) + mhdr.lout
149 || mhdr.cmd != cmd) {
150 ERROR("Error getting message from server: Bad format");
151 return -1;
152 }
153 }
154 if (lout)
155 *lout = mhdr.lout;
156 if (res)
157 *res = mhdr.res;
158
159 return 0;
160 }