GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/switchctl/ofpclient.c Lines: 0 102 0.0 %
Date: 2017-11-13 Branches: 0 61 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ofpclient.c,v 1.6 2017/01/09 16:42:14 reyk Exp $	*/
2
3
/*
4
 * Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/queue.h>
20
#include <sys/types.h>
21
#include <sys/stat.h>
22
#include <sys/socket.h>
23
#include <sys/tree.h>
24
#include <sys/un.h>
25
26
#include <net/if.h>
27
#include <net/ofp.h>
28
#include <netinet/in.h>
29
#include <arpa/inet.h>
30
31
#include <stdlib.h>
32
#include <stdio.h>
33
#include <stddef.h>
34
#include <unistd.h>
35
#include <netdb.h>
36
#include <errno.h>
37
#include <event.h>
38
#include <fcntl.h>
39
#include <string.h>
40
#include <ctype.h>
41
#include <poll.h>
42
#include <err.h>
43
#include <pwd.h>
44
#include <vis.h>
45
46
#include "switchd.h"
47
#include "parser.h"
48
49
void	 ofpclient_read(struct switch_connection *, int);
50
int	 flowmod(struct switchd *, struct switch_connection *,
51
	    struct parse_result *);
52
int	 flowmod_test(struct switchd *, struct switch_connection *);
53
54
void
55
ofpclient(struct parse_result *res, struct passwd *pw)
56
{
57
	struct switch_connection con;
58
	struct switchd		 sc;
59
	int			 s, timeout;
60
61
	memset(&sc, 0, sizeof(sc));
62
	sc.sc_tap = -1;
63
64
	/* If no uri has been specified, try to connect to localhost */
65
	if (res->uri.swa_addr.ss_family == AF_UNSPEC) {
66
		res->uri.swa_type = SWITCH_CONN_TCP;
67
		if (parsehostport("127.0.0.1",
68
		    (struct sockaddr *)&res->uri.swa_addr,
69
		    sizeof(res->uri.swa_addr)) != 0)
70
			fatal("could not parse address");
71
	}
72
73
	memset(&con, 0, sizeof(con));
74
	memcpy(&con.con_peer, &res->uri.swa_addr, sizeof(res->uri.swa_addr));
75
	con.con_sc = &sc;
76
77
	/*
78
	 * Connect and send the request
79
	 */
80
	switch (res->uri.swa_type) {
81
	case SWITCH_CONN_TCP:
82
		if ((s = socket(res->uri.swa_addr.ss_family, SOCK_STREAM,
83
		    IPPROTO_TCP)) == -1)
84
			fatal("socket");
85
86
		/* Use the default port if no port has been specified */
87
		if (socket_getport(&con.con_peer) == 0)
88
			(void)socket_setport(&con.con_peer, SWITCHD_CTLR_PORT);
89
90
		if (connect(s, (struct sockaddr *)&con.con_peer,
91
		    con.con_peer.ss_len) == -1)
92
			fatal("connect");
93
94
		con.con_fd = s;
95
		break;
96
	default:
97
		fatalx("connect type not supported");
98
	}
99
100
	/* Drop privileges */
101
	if (pledge("stdio flock rpath cpath wpath", NULL) == -1)
102
		err(1, "pledge");
103
104
	/* Set a default read timeout */
105
	timeout = 3 * 1000;
106
107
	log_setverbose(res->verbose);
108
109
	ofp_send_hello(&sc, &con, OFP_V_1_3);
110
	ofpclient_read(&con, timeout);
111
112
	log_setverbose(res->quiet ? res->verbose : 2);
113
114
	switch (res->action) {
115
	case DUMP_DESC:
116
		ofp13_desc(&sc, &con);
117
		break;
118
	case DUMP_FEATURES:
119
		ofp_send_featuresrequest(&sc, &con);
120
		break;
121
	case DUMP_FLOWS:
122
		ofp13_flow_stats(&sc, &con, OFP_PORT_ANY, OFP_GROUP_ID_ANY,
123
		    res->table);
124
		break;
125
	case DUMP_TABLES:
126
		ofp13_table_features(&sc, &con, res->table);
127
		break;
128
	case FLOW_ADD:
129
	case FLOW_DELETE:
130
	case FLOW_MODIFY:
131
		timeout = 0;
132
		flowmod(&sc, &con, res);
133
		break;
134
	default:
135
		fatalx("unsupported action");
136
	}
137
138
	/* XXX */
139
	ofpclient_read(&con, timeout);
140
}
141
142
int
143
flowmod(struct switchd *sc, struct switch_connection *con,
144
    struct parse_result *res)
145
{
146
	struct ofp_header	*oh;
147
	struct ofp_flow_mod	*fm;
148
149
	if (oflowmod_iclose(&res->fctx) == -1)
150
		goto err;
151
	if (oflowmod_close(&res->fctx) == -1)
152
		goto err;
153
154
	fm = res->fctx.ctx_fm;
155
	fm->fm_table_id = res->table;
156
	oh = &fm->fm_oh;
157
158
	if (ofp_validate(sc, &con->con_local, &con->con_peer,
159
	    oh, res->fbuf, oh->oh_version) != 0)
160
		goto err;
161
162
	ofrelay_write(con, res->fbuf);
163
164
	return (0);
165
166
 err:
167
	(void)oflowmod_err(&res->fctx, __func__, __LINE__);
168
	log_warnx("invalid flow");
169
	return (-1);
170
}
171
172
void
173
ofpclient_read(struct switch_connection *con, int timeout)
174
{
175
	uint8_t			rbuf[0xffff];
176
	ssize_t			rlen;
177
	struct ofp_header	*oh;
178
	struct ibuf		*ibuf;
179
	struct pollfd		 pfd[1];
180
	int			 nfds;
181
182
	/* Wait for response */
183
	pfd[0].fd = con->con_fd;
184
	pfd[0].events = POLLIN;
185
	nfds = poll(pfd, 1, timeout);
186
	if (nfds == -1 || (pfd[0].revents & (POLLERR|POLLHUP|POLLNVAL)))
187
		fatal("poll error");
188
	if (nfds == 0) {
189
		if (timeout)
190
			fatal("time out");
191
		return;
192
	}
193
194
	if ((rlen = read(con->con_fd, rbuf, sizeof(rbuf))) == -1)
195
		fatal("read");
196
	if (rlen == 0)
197
		fatal("connection closed");
198
199
	if ((ibuf = ibuf_new(rbuf, rlen)) == NULL)
200
		fatal("ibuf_new");
201
202
	if ((oh = ibuf_seek(ibuf, 0, sizeof(*oh))) == NULL)
203
		fatal("short header");
204
205
	if (ofp_validate(con->con_sc,
206
	    &con->con_peer, &con->con_local, oh, ibuf, oh->oh_version) != 0)
207
		fatal("ofp_validate");
208
209
	ibuf_free(ibuf);
210
}
211
212
/*
213
 * stubs for ofp*.c
214
 */
215
216
void
217
ofrelay_write(struct switch_connection *con, struct ibuf *buf)
218
{
219
	struct msgbuf		msgbuf;
220
221
	msgbuf_init(&msgbuf);
222
	msgbuf.fd = con->con_fd;
223
224
	ibuf_close(&msgbuf, buf);
225
	ibuf_write(&msgbuf);
226
}
227
228
struct switch_control *
229
switch_add(struct switch_connection *con)
230
{
231
	static struct switch_control sw;
232
	con->con_switch = &sw;
233
	return (&sw);
234
}
235
236
struct macaddr *
237
switch_learn(struct switchd *sc, struct switch_control *sw,
238
    uint8_t *ea, uint32_t port)
239
{
240
	return (NULL);
241
}
242
243
struct macaddr *
244
switch_cached(struct switch_control *sw, uint8_t *ea)
245
{
246
	return (NULL);
247
}
248
249
int
250
ofp_nextstate(struct switchd *sc, struct switch_connection *con,
251
    enum ofp_state state)
252
{
253
	int		rv = 0;
254
255
	switch (con->con_state) {
256
	case OFP_STATE_CLOSED:
257
		if (state != OFP_STATE_HELLO_WAIT)
258
			return (-1);
259
		break;
260
261
	case OFP_STATE_HELLO_WAIT:
262
		if (state != OFP_STATE_FEATURE_WAIT)
263
			return (-1);
264
265
		rv = ofp_send_featuresrequest(sc, con);
266
		break;
267
268
	case OFP_STATE_FEATURE_WAIT:
269
		if (state != OFP_STATE_ESTABLISHED)
270
			return (-1);
271
		break;
272
273
	case OFP_STATE_ESTABLISHED:
274
		if (state != OFP_STATE_CLOSED)
275
			return (-1);
276
		break;
277
278
	default:
279
		return (-1);
280
	}
281
282
	/* Set the next state. */
283
	con->con_state = state;
284
285
	return (rv);
286
}