Have rconn and vconn export information about IPs and ports
authorJustin Pettit <jpettit@nicira.com>
Mon, 6 Jul 2009 22:15:11 +0000 (15:15 -0700)
committerJustin Pettit <jpettit@nicira.com>
Wed, 8 Jul 2009 18:19:51 +0000 (11:19 -0700)
Previously, rconn and vconn only allowed users to find out about the
remote IP address.  This set of changes allows users to retrieve the
remote port, local IP, and local port used for the connection.

lib/rconn.c
lib/rconn.h
lib/vconn-provider.h
lib/vconn-ssl.c
lib/vconn-stream.c
lib/vconn-stream.h
lib/vconn-tcp.c
lib/vconn-unix.c
lib/vconn.c
lib/vconn.h
secchan/in-band.c

index b18a2e5..1301f25 100644 (file)
@@ -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.
index 1249b84..ed0780a 100644 (file)
@@ -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 *);
index ada6136..0b25dee 100644 (file)
@@ -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)
 {
index 905996f..d4dbc9f 100644 (file)
@@ -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();
index a9fcd98..46279e5 100644 (file)
@@ -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
index 10e30be..efebdd8 100644 (file)
@@ -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 **),
index 911fe6d..5036780 100644 (file)
@@ -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 */
index aec2e31..fddf6e8 100644 (file)
@@ -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 = {
index a006efb..2940c11 100644 (file)
@@ -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)
index b94eeb3..9e012bc 100644 (file)
@@ -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 *);
index 9dccf5f..7cbcaa9 100644 (file)
@@ -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));