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 b18a2e59e918c3d4373b3a4e19a0bcf55b6e6af6..1301f25cac2822a427c689ef8f9b4c2634fe9601 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 1249b844fbdc32b6b9fdde28bd45bd6365c0cdbf..ed0780a3f468285ea795ccf9671a61191ea3bbe7 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 ada61368ce9c9dda49a00ebcd5195534659c2267..0b25dee8d58c00d39fc07939559b30bc19c0b615 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 905996fbd1cffb411981e2c51cad91c2401160d5..d4dbc9f7979f627b8de17126a91cbf47a701122b 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 a9fcd98df621643215b1c831eb15f9a0dcef3d10..46279e57ea03ab0a5bf79075e2e1f8235f9cf02f 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 10e30beda71b90592775c2d0b4655f20ad36c71d..efebdd848fb81b3c6f2df3aac8e9bbf17a1e7b91 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 911fe6d84c005783f26cdf9bbea2f33f45274230..50367806f3d420d5b5cd68825f2e26273d1a3163 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 aec2e31d630cbb4b1e956cbd0059580a2eea1d4d..fddf6e85185c6e6a7394bcd6455cf8d55c651d3c 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 a006efbea7f8290c3860ae913bd3411f6604569e..2940c114d65e1390940de5462dd539a576e86fc9 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 b94eeb3c4c047d04e0bb3b03c21415d3b5654d50..9e012bcfbc413a24279f7b9be22e394033777ae3 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 9dccf5f1586b0f11883980b1720cefd0ed519c52..7cbcaa999f8c3ba658cdf1d12b723d48c1710b2e 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));