diff options
-rw-r--r-- | lib/rconn.c | 29 | ||||
-rw-r--r-- | lib/rconn.h | 5 | ||||
-rw-r--r-- | lib/vconn-provider.h | 10 | ||||
-rw-r--r-- | lib/vconn-ssl.c | 20 | ||||
-rw-r--r-- | lib/vconn-stream.c | 20 | ||||
-rw-r--r-- | lib/vconn-stream.h | 6 | ||||
-rw-r--r-- | lib/vconn-tcp.c | 23 | ||||
-rw-r--r-- | lib/vconn-unix.c | 4 | ||||
-rw-r--r-- | lib/vconn.c | 49 | ||||
-rw-r--r-- | lib/vconn.h | 5 | ||||
-rw-r--r-- | secchan/in-band.c | 4 |
11 files changed, 151 insertions, 24 deletions
diff --git a/lib/rconn.c b/lib/rconn.c index b18a2e59..1301f25c 100644 --- a/lib/rconn.c +++ b/lib/rconn.c @@ -638,9 +638,34 @@ rconn_failure_duration(const struct rconn *rconn) /* Returns the IP address of the peer, or 0 if the peer is not connected over * an IP-based protocol or if its IP address is not known. */ uint32_t -rconn_get_ip(const struct rconn *rconn) +rconn_get_remote_ip(const struct rconn *rconn) { - return rconn->vconn ? vconn_get_ip(rconn->vconn) : 0; + return rconn->vconn ? vconn_get_remote_ip(rconn->vconn) : 0; +} + +/* Returns the transport port of the peer, or 0 if the peer does not + * contain a port or if the port is not known. */ +uint16_t +rconn_get_remote_port(const struct rconn *rconn) +{ + return rconn->vconn ? vconn_get_remote_port(rconn->vconn) : 0; +} + +/* Returns the IP address used to connect to the peer, or 0 if the + * connection is not an IP-based protocol or if its IP address is not + * known. */ +uint32_t +rconn_get_local_ip(const struct rconn *rconn) +{ + return rconn->vconn ? vconn_get_local_ip(rconn->vconn) : 0; +} + +/* Returns the transport port used to connect to the peer, or 0 if the + * connection does not contain a port or if the port is not known. */ +uint16_t +rconn_get_local_port(const struct rconn *rconn) +{ + return rconn->vconn ? vconn_get_local_port(rconn->vconn) : 0; } /* If 'rconn' can't connect to the peer, it could be for any number of reasons. diff --git a/lib/rconn.h b/lib/rconn.h index 1249b844..ed0780a3 100644 --- a/lib/rconn.h +++ b/lib/rconn.h @@ -72,7 +72,10 @@ bool rconn_is_connected(const struct rconn *); int rconn_failure_duration(const struct rconn *); bool rconn_is_connectivity_questionable(struct rconn *); -uint32_t rconn_get_ip(const struct rconn *); +uint32_t rconn_get_remote_ip(const struct rconn *); +uint16_t rconn_get_remote_port(const struct rconn *); +uint32_t rconn_get_local_ip(const struct rconn *); +uint16_t rconn_get_local_port(const struct rconn *); const char *rconn_get_state(const struct rconn *); unsigned int rconn_get_attempted_connections(const struct rconn *); diff --git a/lib/vconn-provider.h b/lib/vconn-provider.h index ada61368..0b25dee8 100644 --- a/lib/vconn-provider.h +++ b/lib/vconn-provider.h @@ -34,13 +34,19 @@ struct vconn { int error; int min_version; int version; - uint32_t ip; + uint32_t remote_ip; + uint16_t remote_port; + uint32_t local_ip; + uint16_t local_port; char *name; bool reconnectable; }; void vconn_init(struct vconn *, struct vconn_class *, int connect_status, - uint32_t ip, const char *name, bool reconnectable); + uint32_t remote_ip, uint16_t remote_port, + const char *name, bool reconnectable); +void vconn_set_local_ip(struct vconn *, uint32_t local_ip); +void vconn_set_local_port(struct vconn *, uint16_t local_port); static inline void vconn_assert_class(const struct vconn *vconn, const struct vconn_class *class) { diff --git a/lib/vconn-ssl.c b/lib/vconn-ssl.c index 905996fb..d4dbc9f7 100644 --- a/lib/vconn-ssl.c +++ b/lib/vconn-ssl.c @@ -238,8 +238,8 @@ new_ssl_vconn(const char *name, int fd, enum session_type type, /* Create and return the ssl_vconn. */ sslv = xmalloc(sizeof *sslv); - vconn_init(&sslv->vconn, &ssl_vconn_class, EAGAIN, sin->sin_addr.s_addr, - name, true); + vconn_init(&sslv->vconn, &ssl_vconn_class, EAGAIN, + sin->sin_addr.s_addr, sin->sin_port, name, true); sslv->state = state; sslv->type = type; sslv->fd = fd; @@ -426,7 +426,19 @@ ssl_connect(struct vconn *vconn) sslv->state = STATE_SSL_CONNECTING; /* Fall through. */ - case STATE_SSL_CONNECTING: + case STATE_SSL_CONNECTING: { + struct sockaddr_in local_addr; + socklen_t addrlen = sizeof(local_addr); + + /* Get the local IP and port information */ + retval = getsockname(sslv->fd, (struct sockaddr *)&local_addr, + &addrlen); + if (retval) { + memset(&local_addr, 0, sizeof local_addr); + } + vconn_set_local_ip(vconn, local_addr.sin_addr.s_addr); + vconn_set_local_port(vconn, local_addr.sin_port); + retval = (sslv->type == CLIENT ? SSL_connect(sslv->ssl) : SSL_accept(sslv->ssl)); if (retval != 1) { @@ -458,6 +470,8 @@ ssl_connect(struct vconn *vconn) } else { return 0; } + + } } NOT_REACHED(); diff --git a/lib/vconn-stream.c b/lib/vconn-stream.c index a9fcd98d..46279e57 100644 --- a/lib/vconn-stream.c +++ b/lib/vconn-stream.c @@ -41,6 +41,7 @@ struct stream_vconn { struct vconn vconn; int fd; + void (*connect_success_cb)(struct vconn *, int); struct ofpbuf *rxbuf; struct ofpbuf *txbuf; struct poll_waiter *tx_waiter; @@ -54,17 +55,21 @@ static void stream_clear_txbuf(struct stream_vconn *); int new_stream_vconn(const char *name, int fd, int connect_status, - uint32_t ip, bool reconnectable, struct vconn **vconnp) + uint32_t remote_ip, uint16_t remote_port, + bool reconnectable, + connect_success_cb_func *connect_success_cb, + struct vconn **vconnp) { struct stream_vconn *s; s = xmalloc(sizeof *s); - vconn_init(&s->vconn, &stream_vconn_class, connect_status, ip, name, - reconnectable); + vconn_init(&s->vconn, &stream_vconn_class, connect_status, remote_ip, + remote_port, name, reconnectable); s->fd = fd; s->txbuf = NULL; s->tx_waiter = NULL; s->rxbuf = NULL; + s->connect_success_cb = connect_success_cb; *vconnp = &s->vconn; return 0; } @@ -91,7 +96,14 @@ static int stream_connect(struct vconn *vconn) { struct stream_vconn *s = stream_vconn_cast(vconn); - return check_connection_completion(s->fd); + int retval = check_connection_completion(s->fd); + if (retval) { + return retval; + } + if (s->connect_success_cb) { + s->connect_success_cb(vconn, s->fd); + } + return 0; } static int diff --git a/lib/vconn-stream.h b/lib/vconn-stream.h index 10e30bed..efebdd84 100644 --- a/lib/vconn-stream.h +++ b/lib/vconn-stream.h @@ -25,8 +25,12 @@ struct vconn; struct pvconn; struct sockaddr; +typedef void connect_success_cb_func(struct vconn *, int); + int new_stream_vconn(const char *name, int fd, int connect_status, - uint32_t ip, bool reconnectable, struct vconn **vconnp); + uint32_t remote_ip, uint16_t remote_port, + bool reconnectable, connect_success_cb_func *, + struct vconn **vconnp); int new_pstream_pvconn(const char *name, int fd, int (*accept_cb)(int fd, const struct sockaddr *, size_t sa_len, struct vconn **), diff --git a/lib/vconn-tcp.c b/lib/vconn-tcp.c index 911fe6d8..50367806 100644 --- a/lib/vconn-tcp.c +++ b/lib/vconn-tcp.c @@ -36,6 +36,8 @@ /* Active TCP. */ +void tcp_connect_success_cb(struct vconn *vconn, int fd); + static int new_tcp_vconn(const char *name, int fd, int connect_status, const struct sockaddr_in *sin, struct vconn **vconnp) @@ -50,8 +52,9 @@ new_tcp_vconn(const char *name, int fd, int connect_status, return errno; } - return new_stream_vconn(name, fd, connect_status, sin->sin_addr.s_addr, - true, vconnp); + return new_stream_vconn(name, fd, connect_status, + sin->sin_addr.s_addr, sin->sin_port, + true, tcp_connect_success_cb, vconnp); } static int @@ -105,6 +108,22 @@ tcp_open(const char *name, char *suffix, struct vconn **vconnp) } } +void +tcp_connect_success_cb(struct vconn *vconn, int fd) +{ + int retval; + struct sockaddr_in local_addr; + socklen_t addrlen = sizeof(local_addr); + + /* Get the local IP and port information */ + retval = getsockname(fd, (struct sockaddr *)&local_addr, &addrlen); + if (retval) { + memset(&local_addr, 0, sizeof local_addr); + } + vconn_set_local_ip(vconn, local_addr.sin_addr.s_addr); + vconn_set_local_port(vconn, local_addr.sin_port); +} + struct vconn_class tcp_vconn_class = { "tcp", /* name */ tcp_open, /* open */ diff --git a/lib/vconn-unix.c b/lib/vconn-unix.c index aec2e31d..fddf6e85 100644 --- a/lib/vconn-unix.c +++ b/lib/vconn-unix.c @@ -60,7 +60,7 @@ unix_open(const char *name, char *suffix, struct vconn **vconnp) } return new_stream_vconn(name, fd, check_connection_completion(fd), - 0, true, vconnp); + 0, 0, true, NULL, vconnp); } struct vconn_class unix_vconn_class = { @@ -105,7 +105,7 @@ punix_accept(int fd, const struct sockaddr *sa, size_t sa_len, } else { strcpy(name, "unix"); } - return new_stream_vconn(name, fd, 0, 0, true, vconnp); + return new_stream_vconn(name, fd, 0, 0, 0, true, NULL, vconnp); } struct pvconn_class punix_pvconn_class = { diff --git a/lib/vconn.c b/lib/vconn.c index a006efbe..2940c114 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -251,9 +251,34 @@ vconn_get_name(const struct vconn *vconn) /* Returns the IP address of the peer, or 0 if the peer is not connected over * an IP-based protocol or if its IP address is not yet known. */ uint32_t -vconn_get_ip(const struct vconn *vconn) +vconn_get_remote_ip(const struct vconn *vconn) { - return vconn->ip; + return vconn->remote_ip; +} + +/* Returns the transport port of the peer, or 0 if the connection does not + * contain a port or if the port is not yet known. */ +uint16_t +vconn_get_remote_port(const struct vconn *vconn) +{ + return vconn->remote_port; +} + +/* Returns the IP address used to connect to the peer, or 0 if the + * connection is not an IP-based protocol or if its IP address is not + * yet known. */ +uint32_t +vconn_get_local_ip(const struct vconn *vconn) +{ + return vconn->local_ip; +} + +/* Returns the transport port used to connect to the peer, or 0 if the + * connection does not contain a port or if the port is not yet known. */ +uint16_t +vconn_get_local_port(const struct vconn *vconn) +{ + return vconn->local_port; } static void @@ -1382,7 +1407,8 @@ normalize_match(struct ofp_match *m) void vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status, - uint32_t ip, const char *name, bool reconnectable) + uint32_t remote_ip, uint16_t remote_port, const char *name, + bool reconnectable) { vconn->class = class; vconn->state = (connect_status == EAGAIN ? VCS_CONNECTING @@ -1391,11 +1417,26 @@ vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status, vconn->error = connect_status; vconn->version = -1; vconn->min_version = -1; - vconn->ip = ip; + vconn->remote_ip = remote_ip; + vconn->remote_port = remote_port; + vconn->local_ip = 0; + vconn->local_port = 0; vconn->name = xstrdup(name); vconn->reconnectable = reconnectable; } +void +vconn_set_local_ip(struct vconn *vconn, uint32_t ip) +{ + vconn->local_ip = ip; +} + +void +vconn_set_local_port(struct vconn *vconn, uint16_t port) +{ + vconn->local_port = port; +} + void pvconn_init(struct pvconn *pvconn, struct pvconn_class *class, const char *name) diff --git a/lib/vconn.h b/lib/vconn.h index b94eeb3c..9e012bcf 100644 --- a/lib/vconn.h +++ b/lib/vconn.h @@ -38,7 +38,10 @@ void vconn_usage(bool active, bool passive, bool bootstrap); int vconn_open(const char *name, int min_version, struct vconn **); void vconn_close(struct vconn *); const char *vconn_get_name(const struct vconn *); -uint32_t vconn_get_ip(const struct vconn *); +uint32_t vconn_get_remote_ip(const struct vconn *); +uint16_t vconn_get_remote_port(const struct vconn *); +uint32_t vconn_get_local_ip(const struct vconn *); +uint16_t vconn_get_local_port(const struct vconn *); int vconn_connect(struct vconn *); int vconn_recv(struct vconn *, struct ofpbuf **); int vconn_send(struct vconn *, struct ofpbuf *); diff --git a/secchan/in-band.c b/secchan/in-band.c index 9dccf5f1..7cbcaa99 100644 --- a/secchan/in-band.c +++ b/secchan/in-band.c @@ -92,7 +92,7 @@ get_controller_mac(struct in_band *ib) time_t now = time_now(); uint32_t ip; - ip = rconn_get_ip(ib->controller); + ip = rconn_get_remote_ip(ib->controller); if (ip != ib->ip || now >= ib->next_refresh) { bool have_mac; @@ -165,7 +165,7 @@ in_band_status_cb(struct status_reply *sr, void *in_band_) ETH_ADDR_ARGS(local_mac)); } - controller_ip = rconn_get_ip(in_band->controller); + controller_ip = rconn_get_remote_ip(in_band->controller); if (controller_ip) { status_reply_put(sr, "controller-ip="IP_FMT, IP_ARGS(&controller_ip)); |