]> git.ipfire.org Git - people/ms/rstp.git/blob - ctl_socket.c
Revised packet SOCK_RAW code
[people/ms/rstp.git] / ctl_socket.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 "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>
34
35 #include "epoll_loop.h"
36 #include "log.h"
37
38 int server_socket(void)
39 {
40 struct sockaddr_un sa;
41 int s;
42
43 TST(strlen(RSTP_SERVER_SOCK_NAME) < sizeof(sa.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, RSTP_SERVER_SOCK_NAME);
52
53 if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
54 ERROR("Couldn't bind socket: %m");
55 close(s);
56 return -1;
57 }
58
59 return s;
60 }
61
62 int handle_message(int cmd, void *inbuf, int lin, void *outbuf, int *lout)
63 {
64 switch (cmd) {
65 SERVER_MESSAGE_CASE(enable_bridge_rstp);
66 SERVER_MESSAGE_CASE(get_bridge_state);
67 SERVER_MESSAGE_CASE(set_bridge_config);
68 SERVER_MESSAGE_CASE(get_port_state);
69 SERVER_MESSAGE_CASE(set_port_config);
70 SERVER_MESSAGE_CASE(set_debug_level);
71
72 default:
73 ERROR("CTL: Unknown command %d", cmd);
74 return -1;
75 }
76 }
77
78 #define msg_buf_len 1024
79 unsigned char msg_inbuf[1024];
80 unsigned char msg_outbuf[1024];
81
82 void ctl_rcv_handler(uint32_t events, struct epoll_event_handler *p)
83 {
84 struct ctl_msg_hdr mhdr;
85 struct msghdr msg;
86 struct sockaddr_un sa;
87 struct iovec iov[2];
88 int l;
89
90 msg.msg_name = &sa;
91 msg.msg_namelen = sizeof(sa);
92 msg.msg_iov = iov;
93 msg.msg_iovlen = 2;
94 msg.msg_control = NULL;
95 msg.msg_controllen = 0;
96 iov[0].iov_base = &mhdr;
97 iov[0].iov_len = sizeof(mhdr);
98 iov[1].iov_base = msg_inbuf;
99 iov[1].iov_len = msg_buf_len;
100 l = recvmsg(p->fd, &msg, MSG_NOSIGNAL | MSG_DONTWAIT);
101 TST(l > 0,);
102 if (msg.msg_flags != 0 || l < sizeof(mhdr) ||
103 l != sizeof(mhdr) + mhdr.lin ||
104 mhdr.lout > msg_buf_len || mhdr.cmd < 0) {
105 ERROR("CTL: Unexpected message. Ignoring");
106 return;
107 }
108
109 if (mhdr.lout)
110 mhdr.res = handle_message(mhdr.cmd, msg_inbuf, mhdr.lin,
111 msg_outbuf, &mhdr.lout);
112 else
113 mhdr.res = handle_message(mhdr.cmd, msg_inbuf, mhdr.lin,
114 NULL, NULL);
115
116 if (mhdr.res < 0)
117 mhdr.lout = 0;
118 iov[1].iov_base = msg_outbuf;
119 iov[1].iov_len = mhdr.lout;
120 l = sendmsg(p->fd, &msg, MSG_NOSIGNAL);
121 if (l < 0)
122 ERROR("CTL: Couldn't send response: %m");
123 else if (l != sizeof(mhdr) + mhdr.lout) {
124 ERROR
125 ("CTL: Couldn't send full response, sent %d bytes instead of %zd.",
126 l, sizeof(mhdr) + mhdr.lout);
127 }
128 }
129
130 struct epoll_event_handler ctl_handler;
131
132 int ctl_socket_init(void)
133 {
134 int s = server_socket();
135 if (s < 0)
136 return -1;
137
138 ctl_handler.fd = s;
139 ctl_handler.handler = ctl_rcv_handler;
140
141 TST(add_epoll(&ctl_handler) == 0, -1);
142 return 0;
143 }
144
145 void ctl_socket_cleanup(void)
146 {
147 remove_epoll(&ctl_handler);
148 close(ctl_handler.fd);
149 }