summaryrefslogtreecommitdiff
path: root/usr.sbin/switchd
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2016-10-12 19:07:43 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2016-10-12 19:07:43 +0000
commit2c8b4a5d06668df9dd4ca308364599ed7bd90ce6 (patch)
tree1957e11b32cbb7f59e980e7bed52f779522b2dc9 /usr.sbin/switchd
parent9a8144695bfe9da05620d6691336173b6178623c (diff)
Start reworking the "device" support in switchd: Once connected, a
device is just an fd that is connected to a switch, either via TCP or via /dev/switch. Change the switchctl from "device add" to "connect" etc. This change is an intermediate step towards other changes, including the configuration grammar, so a few things will be left undocumented for now. switchctl(8) examples, switchctl connect /dev/switch0 switchctl connect /dev/switch0 forward-to 10.1.1.1 switchctl connect 127.0.0.1 switchctl connect 127.0.0.1 forward-to 10.1.1.1 switchctl disconnect /dev/switch0 Discussed with rzalamena@
Diffstat (limited to 'usr.sbin/switchd')
-rw-r--r--usr.sbin/switchd/control.c6
-rw-r--r--usr.sbin/switchd/ofcconn.c42
-rw-r--r--usr.sbin/switchd/ofp.c33
-rw-r--r--usr.sbin/switchd/ofrelay.c4
-rw-r--r--usr.sbin/switchd/parse.y77
-rw-r--r--usr.sbin/switchd/switchd.c246
-rw-r--r--usr.sbin/switchd/switchd.h28
-rw-r--r--usr.sbin/switchd/types.h9
8 files changed, 278 insertions, 167 deletions
diff --git a/usr.sbin/switchd/control.c b/usr.sbin/switchd/control.c
index 291e060bce6..b1b23d3ca48 100644
--- a/usr.sbin/switchd/control.c
+++ b/usr.sbin/switchd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.4 2016/09/14 13:46:51 rzalamena Exp $ */
+/* $OpenBSD: control.c,v 1.5 2016/10/12 19:07:42 reyk Exp $ */
/*
* Copyright (c) 2010-2016 Reyk Floeter <reyk@openbsd.org>
@@ -340,8 +340,8 @@ control_dispatch_imsg(int fd, short event, void *arg)
proc_compose(&env->sc_ps, PROC_OFP,
imsg.hdr.type, &fd, sizeof(fd));
break;
- case IMSG_CTL_DEVICE_CONNECT:
- case IMSG_CTL_DEVICE_DISCONNECT:
+ case IMSG_CTL_CONNECT:
+ case IMSG_CTL_DISCONNECT:
proc_compose(&env->sc_ps, PROC_PARENT,
imsg.hdr.type, imsg.data, IMSG_DATA_SIZE(&imsg));
break;
diff --git a/usr.sbin/switchd/ofcconn.c b/usr.sbin/switchd/ofcconn.c
index a26159b47dd..059f2f4fdd9 100644
--- a/usr.sbin/switchd/ofcconn.c
+++ b/usr.sbin/switchd/ofcconn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofcconn.c,v 1.11 2016/09/30 12:48:27 reyk Exp $ */
+/* $OpenBSD: ofcconn.c,v 1.12 2016/10/12 19:07:42 reyk Exp $ */
/*
* Copyright (c) 2016 YASUOKA Masahiko <yasuoka@openbsd.org>
@@ -20,6 +20,7 @@
#include <sys/queue.h>
#include <sys/uio.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <net/ofp.h>
@@ -78,7 +79,7 @@ void ofsw_on_io(int, short, void *);
int ofsw_write(struct ofsw *, struct ofcconn *);
int ofsw_ofc_write_ready(struct ofsw *);
void ofsw_reset_event_handlers(struct ofsw *);
-int ofsw_new_ofcconn(struct ofsw *, struct switch_controller *);
+int ofsw_new_ofcconn(struct ofsw *, struct switch_address *);
int ofcconn_connect(struct ofcconn *);
void ofcconn_on_sockio(int, short, void *);
void ofcconn_connect_again(struct ofcconn *);
@@ -126,30 +127,33 @@ int
ofcconn_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
struct ofsw *os;
- struct switch_device *sdv;
- struct switch_controller *swc;
+ struct switch_client swc;
+ struct sockaddr_un *un;
switch (imsg->hdr.type) {
- case IMSG_CTL_DEVICE_CONNECT:
- if (IMSG_DATA_SIZE(imsg) < sizeof(*sdv)) {
- log_warnx("%s: IMSG_CTL_DEVICE_CONNECT: "
+ case IMSG_CTL_CONNECT:
+ if (IMSG_DATA_SIZE(imsg) < sizeof(swc)) {
+ log_warnx("%s: IMSG_CTL_CONNECT: "
"invalid message size", __func__);
return (0);
}
- sdv = imsg->data;
- swc = &sdv->sdv_swc;
- if ((os = ofsw_create(sdv->sdv_device, imsg->fd)) != NULL)
- ofsw_new_ofcconn(os, swc);
+ memcpy(&swc, imsg->data, sizeof(swc));
+ un = (struct sockaddr_un *)&swc.swc_addr.swa_addr;
+
+ if ((os = ofsw_create(un->sun_path, imsg->fd)) != NULL)
+ ofsw_new_ofcconn(os, &swc.swc_target);
return (0);
- case IMSG_CTL_DEVICE_DISCONNECT:
- if (IMSG_DATA_SIZE(imsg) < sizeof(*sdv)) {
+ case IMSG_CTL_DISCONNECT:
+ if (IMSG_DATA_SIZE(imsg) < sizeof(swc)) {
log_warnx("%s: IMSG_CTL_DEVICE_DISCONNECT: "
"invalid message size", __func__);
return (0);
}
- sdv = imsg->data;
+ memcpy(&swc, imsg->data, sizeof(swc));
+ un = (struct sockaddr_un *)&swc.swc_addr.swa_addr;
+
TAILQ_FOREACH(os, &ofsw_list, os_next) {
- if (!strcmp(os->os_name, sdv->sdv_device))
+ if (!strcmp(os->os_name, un->sun_path))
break;
}
if (os) {
@@ -375,7 +379,7 @@ ofsw_reset_event_handlers(struct ofsw *os)
}
int
-ofsw_new_ofcconn(struct ofsw *os, struct switch_controller *swc)
+ofsw_new_ofcconn(struct ofsw *os, struct switch_address *swa)
{
struct ofcconn *oc = NULL;
char buf[128];
@@ -386,7 +390,7 @@ ofsw_new_ofcconn(struct ofsw *os, struct switch_controller *swc)
}
if (asprintf(&oc->oc_name, "tcp:%s",
- print_host(&swc->swc_addr, buf, sizeof(buf))) == -1) {
+ print_host(&swa->swa_addr, buf, sizeof(buf))) == -1) {
log_warn("%s: strdup failed", __func__);
goto fail;
}
@@ -396,7 +400,7 @@ ofsw_new_ofcconn(struct ofsw *os, struct switch_controller *swc)
}
oc->oc_sw = os;
oc->oc_sock = -1;
- memcpy(&oc->oc_peer, &swc->swc_addr, sizeof(oc->oc_peer));
+ memcpy(&oc->oc_peer, &swa->swa_addr, sizeof(oc->oc_peer));
if (ntohs(((struct sockaddr_in *)&oc->oc_peer)->sin_port) == 0)
((struct sockaddr_in *)&oc->oc_peer)->sin_port =
@@ -444,7 +448,7 @@ ofcconn_connect(struct ofcconn *oc)
ofcconn_on_sockio, oc);
event_add(&oc->oc_evsock, NULL);
- tv.tv_sec = SWITCHD_OFCCONN_TIMEOUT;
+ tv.tv_sec = SWITCHD_CONNECT_TIMEOUT;
tv.tv_usec = 0;
event_add(&oc->oc_evtimer, &tv);
diff --git a/usr.sbin/switchd/ofp.c b/usr.sbin/switchd/ofp.c
index 76585a72a87..5c77deeef9f 100644
--- a/usr.sbin/switchd/ofp.c
+++ b/usr.sbin/switchd/ofp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofp.c,v 1.13 2016/10/05 16:40:55 reyk Exp $ */
+/* $OpenBSD: ofp.c,v 1.14 2016/10/12 19:07:42 reyk Exp $ */
/*
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -93,8 +93,7 @@ ofp_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
{
struct privsep *ps = p->p_ps;
struct switchd *sc = ps->ps_env;
- struct sockaddr_un un;
- struct switch_device *sdv;
+ struct switch_client swc;
struct switch_connection *con;
switch (imsg->hdr.type) {
@@ -103,24 +102,16 @@ ofp_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
close(sc->sc_tap);
sc->sc_tap = imsg->fd;
return (0);
- case IMSG_CTL_DEVICE_CONNECT:
- case IMSG_CTL_DEVICE_DISCONNECT:
- IMSG_SIZE_CHECK(imsg, sdv);
- sdv = imsg->data;
-
- if (strlcpy(un.sun_path, sdv->sdv_device,
- sizeof(un.sun_path)) >= sizeof(un.sun_path)) {
- log_warnx("invalid device: %s", sdv->sdv_device);
- return (0);
- }
- un.sun_family = AF_UNIX;
- un.sun_len = sizeof(un);
-
- if (imsg->hdr.type == IMSG_CTL_DEVICE_CONNECT)
- ofrelay_attach(&sc->sc_server,
- imsg->fd, (struct sockaddr *)&un);
- else if ((con =
- switchd_connbyaddr(sc, (struct sockaddr *)&un)) != NULL)
+ case IMSG_CTL_CONNECT:
+ case IMSG_CTL_DISCONNECT:
+ IMSG_SIZE_CHECK(imsg, &swc);
+ memcpy(&swc, imsg->data, sizeof(swc));
+
+ if (imsg->hdr.type == IMSG_CTL_CONNECT)
+ ofrelay_attach(&sc->sc_server, imsg->fd,
+ (struct sockaddr *)&swc.swc_addr.swa_addr);
+ else if ((con = switchd_connbyaddr(sc,
+ (struct sockaddr *)&swc.swc_addr.swa_addr)) != NULL)
ofp_close(con);
return (0);
default:
diff --git a/usr.sbin/switchd/ofrelay.c b/usr.sbin/switchd/ofrelay.c
index 381b3c648aa..0a29941f40b 100644
--- a/usr.sbin/switchd/ofrelay.c
+++ b/usr.sbin/switchd/ofrelay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofrelay.c,v 1.5 2016/10/07 08:31:08 rzalamena Exp $ */
+/* $OpenBSD: ofrelay.c,v 1.6 2016/10/12 19:07:42 reyk Exp $ */
/*
* Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
@@ -76,7 +76,7 @@ ofrelay_run(struct privsep *ps, struct privsep_proc *p, void *arg)
struct switch_server *srv = &sc->sc_server;
TAILQ_INIT(&sc->sc_conns);
- TAILQ_INIT(&sc->sc_devs);
+ TAILQ_INIT(&sc->sc_clients);
srv->srv_sc = sc;
event_set(&srv->srv_ev, srv->srv_fd, EV_READ, ofrelay_accept, srv);
diff --git a/usr.sbin/switchd/parse.y b/usr.sbin/switchd/parse.y
index a1c338f2c1c..8f051d7a8bb 100644
--- a/usr.sbin/switchd/parse.y
+++ b/usr.sbin/switchd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.2 2016/09/30 11:57:57 reyk Exp $ */
+/* $OpenBSD: parse.y,v 1.3 2016/10/12 19:07:42 reyk Exp $ */
/*
* Copyright (c) 2007-2016 Reyk Floeter <reyk@openbsd.org>
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <ctype.h>
#include <err.h>
@@ -79,7 +80,7 @@ typedef struct {
int64_t number;
char *string;
in_port_t port;
- struct switch_device
+ struct switch_client
*conn;
} v;
int lineno;
@@ -157,51 +158,73 @@ opttls : /* empty */ { $$ = 0; }
;
device : DEVICE STRING optofcconn {
- struct switch_device *c;
+ struct switch_client *c;
+ struct switch_address s;
+ struct sockaddr_un *un;
- TAILQ_FOREACH(c, &conf->sc_devs, sdv_next) {
- if (strcmp(c->sdv_device, $2) == 0)
+ memset(&s, 0, sizeof(s));
+ un = (struct sockaddr_un *)&s.swa_addr;
+
+ if (*$2 != '/') {
+ yyerror("not an absolute path: %s", $2);
+ free($2);
+ YYERROR;
+ }
+
+ un->sun_family = AF_LOCAL;
+ un->sun_len = sizeof(*un);
+ if (strlcpy(un->sun_path, $2,
+ sizeof(un->sun_path)) >= sizeof(un->sun_path)) {
+ yyerror("device name is too long: %s", $2);
+ free($2);
+ YYERROR;
+ }
+ free($2);
+
+ TAILQ_FOREACH(c, &conf->sc_clients, swc_next) {
+ if (sockaddr_cmp((struct sockaddr *)
+ &c->swc_addr.swa_addr,
+ (struct sockaddr *)&s.swa_addr, -1) == 0)
break;
}
if (c != NULL) {
yyerror("device name is duplicated");
YYERROR;
}
- if (strlcpy($3->sdv_device, $2, sizeof($3->sdv_device))
- >= sizeof($3->sdv_device)) {
- yyerror("device name is too long");
- YYERROR;
- }
- free($2);
- TAILQ_INSERT_TAIL(&conf->sc_devs, $3, sdv_next);
+
+ memcpy(&$3->swc_addr, &s, sizeof(s));
+
+ TAILQ_INSERT_TAIL(&conf->sc_clients, $3, swc_next);
}
;
optofcconn : /* empty */ {
if (($$ = calloc(1,
- sizeof(struct switch_device))) == NULL)
+ sizeof(struct switch_client))) == NULL)
fatal("calloc");
- $$->sdv_swc.swc_type = SWITCH_CONN_LOCAL;
+ $$->swc_addr.swa_type = $$->swc_target.swa_type =
+ SWITCH_CONN_LOCAL;
}
| FORWARD TO STRING {
+ size_t len;
+
if (($$ = calloc(1,
- sizeof(struct switch_device))) == NULL)
+ sizeof(struct switch_client))) == NULL)
fatal("calloc");
- if (strncmp($3, "tcp:", 4) == 0)
- $$->sdv_swc.swc_type = SWITCH_CONN_TCP;
- else if (strncmp($3, "tls:", 4) == 0)
- $$->sdv_swc.swc_type = SWITCH_CONN_TLS;
+ len = 4;
+ if (strncmp($3, "tcp:", len) == 0)
+ $$->swc_target.swa_type = SWITCH_CONN_TCP;
+ else if (strncmp($3, "tls:", len) == 0)
+ $$->swc_target.swa_type = SWITCH_CONN_TLS;
else {
- yyerror("foward to proto is not supported");
- free($$);
- free($3);
- YYERROR;
+ len = 0;
+ $$->swc_target.swa_type = SWITCH_CONN_TCP;
}
- if (parsehostport($3 + 4,
- (struct sockaddr *)&$$->sdv_swc.swc_addr,
- sizeof($$->sdv_swc.swc_addr)) == -1) {
+ if (parsehostport($3 + len,
+ (struct sockaddr *)&$$->swc_target.swa_addr,
+ sizeof($$->swc_target.swa_addr)) == -1) {
yyerror("could not parse host and port part "
- "of connect-to");
+ "of forward target");
free($$);
free($3);
YYERROR;
diff --git a/usr.sbin/switchd/switchd.c b/usr.sbin/switchd/switchd.c
index 72e62fb35da..64b26fbf452 100644
--- a/usr.sbin/switchd/switchd.c
+++ b/usr.sbin/switchd/switchd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: switchd.c,v 1.13 2016/09/30 12:32:31 reyk Exp $ */
+/* $OpenBSD: switchd.c,v 1.14 2016/10/12 19:07:42 reyk Exp $ */
/*
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#include <sys/un.h>
#include <sys/queue.h>
#include <arpa/inet.h>
@@ -45,8 +46,9 @@ int parent_dispatch_ofp(int, struct privsep_proc *, struct imsg *);
int parent_dispatch_control(int, struct privsep_proc *, struct imsg *);
int parent_configure(struct switchd *);
int parent_reload(struct switchd *);
-void parent_device_connect(struct privsep *, struct switch_device *);
-int switch_device_cmp(struct switch_device *, struct switch_device *);
+void parent_connect(struct privsep *, struct switch_client *);
+void parent_connected(int, short, void *);
+void parent_disconnect(struct privsep *, struct switch_client *);
__dead void usage(void);
@@ -152,7 +154,7 @@ main(int argc, char *argv[])
ps = &sc->sc_ps;
ps->ps_env = sc;
TAILQ_INIT(&ps->ps_rcsocks);
- TAILQ_INIT(&sc->sc_devs);
+ TAILQ_INIT(&sc->sc_clients);
if (parse_config(sc->sc_conffile, sc) == -1) {
proc_kill(&sc->sc_ps);
@@ -362,7 +364,7 @@ parent_sig_handler(int sig, short event, void *arg)
int
parent_configure(struct switchd *sc)
{
- struct switch_device *c;
+ struct switch_client *swc, *swcn;
int fd;
if ((fd = switchd_tap()) == -1)
@@ -370,8 +372,8 @@ parent_configure(struct switchd *sc)
proc_compose_imsg(&sc->sc_ps, PROC_OFP, -1,
IMSG_TAPFD, -1, fd, NULL, 0);
- TAILQ_FOREACH(c, &sc->sc_devs, sdv_next) {
- parent_device_connect(&sc->sc_ps, c);
+ TAILQ_FOREACH_SAFE(swc, &sc->sc_clients, swc_next, swcn) {
+ parent_connect(&sc->sc_ps, swc);
}
return (0);
@@ -381,43 +383,39 @@ int
parent_reload(struct switchd *sc)
{
struct switchd newconf;
- struct switch_device *sdv, *osdv, *sdvn;
- enum privsep_procid procid;
+ struct switch_client *swc, *oswc, *swcn;
memset(&newconf, 0, sizeof(newconf));
- TAILQ_INIT(&newconf.sc_devs);
+ TAILQ_INIT(&newconf.sc_clients);
TAILQ_INIT(&newconf.sc_conns);
if (parse_config(sc->sc_conffile, &newconf) != -1) {
- TAILQ_FOREACH_SAFE(sdv, &sc->sc_devs, sdv_next, sdvn) {
- TAILQ_FOREACH(osdv, &newconf.sc_devs, sdv_next) {
- if (switch_device_cmp(osdv, sdv) == 0) {
- TAILQ_REMOVE(&newconf.sc_devs,
- osdv, sdv_next);
+ TAILQ_FOREACH_SAFE(swc, &sc->sc_clients, swc_next, swcn) {
+ TAILQ_FOREACH(oswc, &newconf.sc_clients, swc_next) {
+ if (sockaddr_cmp((struct sockaddr *)
+ &oswc->swc_addr.swa_addr,
+ (struct sockaddr *)
+ &swc->swc_addr.swa_addr, -1) == 0) {
+ TAILQ_REMOVE(&newconf.sc_clients,
+ oswc, swc_next);
break;
}
}
- if (osdv == NULL) {
+ if (oswc == NULL) {
/* Removed */
- TAILQ_REMOVE(&sc->sc_devs, sdv, sdv_next);
- procid = (sdv->sdv_swc.swc_type ==
- SWITCH_CONN_LOCAL)
- ? PROC_OFP : PROC_OFCCONN;
- proc_compose_imsg(&sc->sc_ps, procid, -1,
- IMSG_CTL_DEVICE_DISCONNECT,
- -1, -1, sdv, sizeof(*sdv));
+ parent_disconnect(&sc->sc_ps, swc);
} else {
/* Keep the existing one */
- TAILQ_REMOVE(&newconf.sc_devs, osdv, sdv_next);
- free(osdv);
+ TAILQ_REMOVE(&newconf.sc_clients,
+ oswc, swc_next);
+ free(oswc);
}
}
- TAILQ_FOREACH(sdv, &newconf.sc_devs, sdv_next) {
- procid =
- (sdv->sdv_swc.swc_type == SWITCH_CONN_LOCAL)
- ? PROC_OFP : PROC_OFCCONN;
- TAILQ_INSERT_TAIL(&sc->sc_devs, sdv, sdv_next);
- parent_device_connect(&sc->sc_ps, sdv);
+ TAILQ_FOREACH_SAFE(swc, &newconf.sc_clients, swc_next, swcn) {
+ TAILQ_REMOVE(&newconf.sc_clients, swc, swc_next);
+ TAILQ_INSERT_TAIL(&sc->sc_clients, swc, swc_next);
+
+ parent_connect(&sc->sc_ps, swc);
}
}
@@ -427,26 +425,41 @@ parent_reload(struct switchd *sc)
int
parent_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg)
{
+ struct switch_client *swc, *oswc;
+ struct privsep *ps = p->p_ps;
+ struct switchd *sc = ps->ps_env;
+
switch (imsg->hdr.type) {
- case IMSG_CTL_DEVICE_CONNECT:
- case IMSG_CTL_DEVICE_DISCONNECT:
- if (IMSG_DATA_SIZE(imsg) <
- sizeof(struct switch_device)) {
- log_warnx("%s: IMSG_CTL_DEVICE_CONNECT: "
- "message size is wrong", __func__);
+ case IMSG_CTL_CONNECT:
+ case IMSG_CTL_DISCONNECT:
+ IMSG_SIZE_CHECK(imsg, swc);
+
+ /* Need to allocate it in case it is reused */
+ if ((swc = calloc(1, sizeof(*swc))) == NULL) {
+ log_warnx("%s: calloc", __func__);
return (0);
}
- if (imsg->hdr.type == IMSG_CTL_DEVICE_CONNECT)
- parent_device_connect(p->p_ps, imsg->data);
- else {
- /*
- * Since we don't know which the device was attached
- * to, we send the message to the both.
- */
- proc_compose(p->p_ps, PROC_OFP,
- imsg->hdr.type, imsg->data, IMSG_DATA_SIZE(imsg));
- proc_compose(p->p_ps, PROC_OFCCONN,
- imsg->hdr.type, imsg->data, IMSG_DATA_SIZE(imsg));
+ memcpy(swc, imsg->data, sizeof(*swc));
+ memset(&swc->swc_ev, 0, sizeof(swc->swc_ev));
+
+ if (imsg->hdr.type == IMSG_CTL_CONNECT) {
+ TAILQ_INSERT_TAIL(&sc->sc_clients, swc, swc_next);
+ parent_connect(p->p_ps, swc);
+ } else {
+ TAILQ_FOREACH(oswc, &sc->sc_clients, swc_next) {
+ if (sockaddr_cmp((struct sockaddr *)
+ &oswc->swc_addr.swa_addr,
+ (struct sockaddr *)
+ &swc->swc_addr.swa_addr, -1) == 0) {
+ parent_disconnect(ps, oswc);
+ break;
+ }
+ }
+ if (oswc == NULL)
+ log_warnx("client %s is not connected",
+ print_host(&swc->swc_addr.swa_addr,
+ NULL, 0));
+ free(swc);
}
return (0);
default:
@@ -468,52 +481,131 @@ parent_shutdown(struct switchd *sc)
}
void
-parent_device_connect(struct privsep *ps, struct switch_device *sdv)
+parent_connect(struct privsep *ps, struct switch_client *swc)
{
- int fd;
+ struct switchd *sc = ps->ps_env;
+ struct sockaddr_storage *ss;
+ struct sockaddr_un *un;
+ struct sockaddr_in *sin4;
+ struct sockaddr_in6 *sin6;
+ int fd = -1;
+ struct timeval tv;
+
+ ss = &swc->swc_addr.swa_addr;
+
+ if (ss->ss_len == 0) {
+ log_warnx("%s: invalid address", __func__);
+ goto fail;
+ }
+ swc->swc_arg = ps;
+ memset(&swc->swc_ev, 0, sizeof(swc->swc_ev));
+
+ switch (ss->ss_family) {
+ case AF_LOCAL:
+ un = (struct sockaddr_un *)ss;
+
+ /* restrict the opening path to /dev/switch* */
+ if (strncmp(un->sun_path, "/dev/switch",
+ strlen("/dev/switch")) != 0) {
+ log_warnx("%s: device path is wrong: %s", __func__,
+ un->sun_path);
+ goto fail;
+ }
- /* restrict the opening path to /dev/switch* */
- if (strncmp(sdv->sdv_device, "/dev/switch", 11) != 0) {
- log_warnx("%s: device path is wrong: %s", __func__,
- sdv->sdv_device);
- goto on_error;
+ if ((fd = open(un->sun_path, O_RDWR | O_NONBLOCK)) == -1) {
+ log_warn("%s: failed to open %s",
+ __func__, un->sun_path);
+ goto fail;
+ }
+ break;
+ case AF_INET:
+ case AF_INET6:
+ if (ss->ss_family == AF_INET) {
+ sin4 = (struct sockaddr_in *)ss;
+ if (sin4->sin_port == 0)
+ sin4->sin_port = htons(SWITCHD_CTLR_PORT);
+ } else if (ss->ss_family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)ss;
+ if (sin6->sin6_port == 0)
+ sin6->sin6_port = htons(SWITCHD_CTLR_PORT);
+ }
+
+ if ((fd = switchd_socket((struct sockaddr *)ss, 0)) == -1) {
+ log_debug("%s: failed to get socket for %s", __func__,
+ print_host(ss, NULL, 0));
+ goto fail;
+ }
+
+ retry:
+ if (connect(fd, (struct sockaddr *)ss, ss->ss_len) == -1) {
+ if (errno == EINTR)
+ goto retry;
+ if (errno == EINPROGRESS) {
+ tv.tv_sec = SWITCHD_CONNECT_TIMEOUT;
+ tv.tv_usec = 0;
+ event_set(&swc->swc_ev, fd, EV_WRITE|EV_TIMEOUT,
+ parent_connected, swc);
+ event_add(&swc->swc_ev, &tv);
+ return;
+ }
+
+ log_warn("%s: failed to connect to %s, fd %d", __func__,
+ print_host(ss, NULL, 0), fd);
+ goto fail;
+ }
+
+ break;
}
- if ((fd = open(sdv->sdv_device, O_RDWR | O_NONBLOCK)) == -1) {
- log_warn("%s: open(%s) failed", __func__, sdv->sdv_device);
- goto on_error;
+ parent_connected(fd, 0, swc);
+ return;
+
+ fail:
+ TAILQ_REMOVE(&sc->sc_clients, swc, swc_next);
+ free(swc);
+}
+
+void
+parent_connected(int fd, short event, void *arg)
+{
+ struct switch_client *swc = arg;
+ struct privsep *ps = swc->swc_arg;
+ struct switchd *sc = ps->ps_env;
+
+ if (event & EV_TIMEOUT) {
+ log_debug("%s: failed to connect to %s", __func__,
+ print_host(&swc->swc_addr.swa_addr, NULL, 0));
+ TAILQ_REMOVE(&sc->sc_clients, swc, swc_next);
+ free(swc);
+ return;
}
- switch (sdv->sdv_swc.swc_type) {
+ switch (swc->swc_target.swa_type) {
case SWITCH_CONN_LOCAL:
- proc_compose_imsg(ps, PROC_OFP, -1, IMSG_CTL_DEVICE_CONNECT,
- -1, fd, sdv, sizeof(*sdv));
+ proc_compose_imsg(ps, PROC_OFP, -1, IMSG_CTL_CONNECT,
+ -1, fd, swc, sizeof(*swc));
break;
case SWITCH_CONN_TLS:
case SWITCH_CONN_TCP:
- proc_compose_imsg(ps, PROC_OFCCONN, -1, IMSG_CTL_DEVICE_CONNECT,
- -1, fd, sdv, sizeof(struct switch_device));
+ proc_compose_imsg(ps, PROC_OFCCONN, -1, IMSG_CTL_CONNECT,
+ -1, fd, swc, sizeof(*swc));
break;
default:
fatalx("not implemented");
}
-on_error:
- return;
}
-int
-switch_device_cmp(struct switch_device *a,
- struct switch_device *b)
+void
+parent_disconnect(struct privsep *ps, struct switch_client *swc)
{
- struct switch_controller *ca = &a->sdv_swc;
- struct switch_controller *cb = &b->sdv_swc;
- int c;
+ struct switchd *sc = ps->ps_env;
+ enum privsep_procid target;
+
+ TAILQ_REMOVE(&sc->sc_clients, swc, swc_next);
- if ((c = strcmp(a->sdv_device, b->sdv_device)) != 0)
- return (c);
- if ((c = cb->swc_type - ca->swc_type) != 0)
- return (c);
+ target = swc->swc_target.swa_type == SWITCH_CONN_LOCAL ?
+ PROC_OFP : PROC_OFCCONN;
+ proc_compose(ps, target, IMSG_CTL_DISCONNECT, swc, sizeof(*swc));
- return (sockaddr_cmp((struct sockaddr *)&ca->swc_addr,
- (struct sockaddr *)&cb->swc_addr, -1));
+ free(swc);
}
diff --git a/usr.sbin/switchd/switchd.h b/usr.sbin/switchd/switchd.h
index 92a7533a4ad..ad94ee56306 100644
--- a/usr.sbin/switchd/switchd.h
+++ b/usr.sbin/switchd/switchd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: switchd.h,v 1.15 2016/10/07 08:49:53 reyk Exp $ */
+/* $OpenBSD: switchd.h,v 1.16 2016/10/12 19:07:42 reyk Exp $ */
/*
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -76,6 +76,11 @@ struct multipart_message {
};
SLIST_HEAD(multipart_list, multipart_message);
+struct switch_address {
+ enum switch_conn_type swa_type;
+ struct sockaddr_storage swa_addr;
+};
+
struct switch_connection {
unsigned int con_id;
unsigned int con_instance;
@@ -113,18 +118,15 @@ struct switch_server {
struct switchd *srv_sc;
};
-struct switch_controller {
- enum switch_conn_type swc_type;
- struct sockaddr_storage swc_addr;
-};
-
-struct switch_device {
- char sdv_device[PATH_MAX];
- struct switch_controller sdv_swc;
- TAILQ_ENTRY(switch_device)
- sdv_next;
+struct switch_client {
+ struct switch_address swc_addr;
+ struct switch_address swc_target;
+ struct event swc_ev;
+ void *swc_arg;
+ TAILQ_ENTRY(switch_client)
+ swc_next;
};
-TAILQ_HEAD(switch_devices, switch_device);
+TAILQ_HEAD(switch_clients, switch_client);
struct switchd {
struct privsep sc_ps;
@@ -136,7 +138,7 @@ struct switchd {
unsigned int sc_cache_timeout;
char sc_conffile[PATH_MAX];
uint8_t sc_opts;
- struct switch_devices sc_devs;
+ struct switch_clients sc_clients;
struct switch_connections
sc_conns;
};
diff --git a/usr.sbin/switchd/types.h b/usr.sbin/switchd/types.h
index a8300b92bcf..b9d8b81c95b 100644
--- a/usr.sbin/switchd/types.h
+++ b/usr.sbin/switchd/types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: types.h,v 1.6 2016/10/06 20:27:44 reyk Exp $ */
+/* $OpenBSD: types.h,v 1.7 2016/10/12 19:07:42 reyk Exp $ */
/*
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -43,8 +43,7 @@
#define SWITCHD_CACHE_MAX 4096 /* Default MAC address cache limit */
#define SWITCHD_CACHE_TIMEOUT 240 /* t/o in seconds for learned MACs */
-#define SWITCHD_OFCCONN_TIMEOUT 20 /* connect timeout for OpenFlow ch. */
-
+#define SWITCHD_CONNECT_TIMEOUT 5
#ifndef ETHER_ADDR_LEN
#define ETHER_ADDR_LEN 6
@@ -69,8 +68,8 @@ enum imsg_type {
IMSG_CTL_SWITCH,
IMSG_CTL_MAC,
IMSG_CTL_SHOW_SUM,
- IMSG_CTL_DEVICE_CONNECT,
- IMSG_CTL_DEVICE_DISCONNECT,
+ IMSG_CTL_CONNECT,
+ IMSG_CTL_DISCONNECT,
IMSG_TAPFD
};