From: Ben Pfaff Date: Wed, 16 Jul 2008 19:51:34 +0000 (-0700) Subject: New function vconn_get_ip(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=809743618e4d85aa2906fc30c5da5f667e68b9f3;p=openvswitch New function vconn_get_ip(). The secchan needs to know the IP address of the peer so that it can handles ARP requests from the controller by itself. --- diff --git a/include/vconn.h b/include/vconn.h index 1e0105b8..e536c9a3 100644 --- a/include/vconn.h +++ b/include/vconn.h @@ -48,12 +48,14 @@ struct ofp_header; struct vconn { struct vconn_class *class; int connect_status; + uint32_t ip; }; void vconn_usage(bool active, bool passive); int vconn_open(const char *name, struct vconn **); void vconn_close(struct vconn *); bool vconn_is_passive(const struct vconn *); +uint32_t vconn_get_ip(const struct vconn *); int vconn_connect(struct vconn *); int vconn_accept(struct vconn *, struct vconn **); int vconn_recv(struct vconn *, struct buffer **); diff --git a/lib/vconn-netlink.c b/lib/vconn-netlink.c index ca1f93d5..6e7e152e 100644 --- a/lib/vconn-netlink.c +++ b/lib/vconn-netlink.c @@ -83,6 +83,7 @@ netlink_open(const char *name, char *suffix, struct vconn **vconnp) netlink = xmalloc(sizeof *netlink); netlink->vconn.class = &netlink_vconn_class; netlink->vconn.connect_status = 0; + netlink->vconn.ip = 0; retval = dpif_open(dp_idx, subscribe, &netlink->dp); if (retval) { free(netlink); diff --git a/lib/vconn-ssl.c b/lib/vconn-ssl.c index 244cc60e..922f8a86 100644 --- a/lib/vconn-ssl.c +++ b/lib/vconn-ssl.c @@ -35,6 +35,7 @@ #include "dhparams.h" #include #include +#include #include #include #include @@ -45,6 +46,7 @@ #include "socket-util.h" #include "util.h" #include "openflow.h" +#include "packets.h" #include "poll-loop.h" #include "ofp-print.h" #include "socket-util.h" @@ -171,7 +173,8 @@ want_to_poll_events(int want) static int new_ssl_vconn(const char *name, int fd, enum session_type type, - enum ssl_state state, struct vconn **vconnp) + enum ssl_state state, const struct sockaddr_in *sin, + struct vconn **vconnp) { struct ssl_vconn *sslv; SSL *ssl = NULL; @@ -220,6 +223,7 @@ new_ssl_vconn(const char *name, int fd, enum session_type type, sslv = xmalloc(sizeof *sslv); sslv->vconn.class = &ssl_vconn_class; sslv->vconn.connect_status = EAGAIN; + sslv->vconn.ip = sin->sin_addr.s_addr; sslv->state = state; sslv->type = type; sslv->fd = fd; @@ -294,7 +298,7 @@ ssl_open(const char *name, char *suffix, struct vconn **vconnp) if (retval < 0) { if (errno == EINPROGRESS) { return new_ssl_vconn(name, fd, CLIENT, STATE_TCP_CONNECTING, - vconnp); + &sin, vconnp); } else { int error = errno; VLOG_ERR("%s: connect: %s", name, strerror(error)); @@ -303,7 +307,7 @@ ssl_open(const char *name, char *suffix, struct vconn **vconnp) } } else { return new_ssl_vconn(name, fd, CLIENT, STATE_SSL_CONNECTING, - vconnp); + &sin, vconnp); } } @@ -733,10 +737,13 @@ static int pssl_accept(struct vconn *vconn, struct vconn **new_vconnp) { struct pssl_vconn *pssl = pssl_vconn_cast(vconn); + struct sockaddr_in sin; + socklen_t sin_len = sizeof sin; + char name[128]; int new_fd; int error; - new_fd = accept(pssl->fd, NULL, NULL); + new_fd = accept(pssl->fd, &sin, &sin_len); if (new_fd < 0) { int error = errno; if (error != EAGAIN) { @@ -751,8 +758,12 @@ pssl_accept(struct vconn *vconn, struct vconn **new_vconnp) return error; } - return new_ssl_vconn("ssl" /* FIXME */, new_fd, - SERVER, STATE_SSL_CONNECTING, new_vconnp); + sprintf(name, "ssl:"IP_FMT, IP_ARGS(&sin.sin_addr)); + if (sin.sin_port != htons(OFP_SSL_PORT)) { + sprintf(strchr(name, '\0'), ":%"PRIu16, ntohs(sin.sin_port)); + } + return new_ssl_vconn(name, new_fd, SERVER, STATE_SSL_CONNECTING, &sin, + new_vconnp); } static void diff --git a/lib/vconn-tcp.c b/lib/vconn-tcp.c index ea702605..50304d33 100644 --- a/lib/vconn-tcp.c +++ b/lib/vconn-tcp.c @@ -34,6 +34,7 @@ #include "vconn.h" #include #include +#include #include #include #include @@ -47,6 +48,7 @@ #include "util.h" #include "openflow.h" #include "ofp-print.h" +#include "packets.h" #include "poll-loop.h" #include "vlog.h" @@ -65,7 +67,7 @@ struct tcp_vconn static int new_tcp_vconn(const char *name, int fd, int connect_status, - struct vconn **vconnp) + const struct sockaddr_in *sin, struct vconn **vconnp) { struct tcp_vconn *tcp; int on = 1; @@ -81,6 +83,7 @@ new_tcp_vconn(const char *name, int fd, int connect_status, tcp = xmalloc(sizeof *tcp); tcp->vconn.class = &tcp_vconn_class; tcp->vconn.connect_status = connect_status; + tcp->vconn.ip = sin->sin_addr.s_addr; tcp->fd = fd; tcp->txbuf = NULL; tcp->tx_waiter = NULL; @@ -139,7 +142,7 @@ tcp_open(const char *name, char *suffix, struct vconn **vconnp) retval = connect(fd, (struct sockaddr *) &sin, sizeof sin); if (retval < 0) { if (errno == EINPROGRESS) { - return new_tcp_vconn(name, fd, EAGAIN, vconnp); + return new_tcp_vconn(name, fd, EAGAIN, &sin, vconnp); } else { int error = errno; VLOG_ERR("%s: connect: %s", name, strerror(error)); @@ -147,7 +150,7 @@ tcp_open(const char *name, char *suffix, struct vconn **vconnp) return error; } } else { - return new_tcp_vconn(name, fd, 0, vconnp); + return new_tcp_vconn(name, fd, 0, &sin, vconnp); } } @@ -398,10 +401,13 @@ static int ptcp_accept(struct vconn *vconn, struct vconn **new_vconnp) { struct ptcp_vconn *ptcp = ptcp_vconn_cast(vconn); + struct sockaddr_in sin; + socklen_t sin_len = sizeof sin; + char name[128]; int new_fd; int error; - new_fd = accept(ptcp->fd, NULL, NULL); + new_fd = accept(ptcp->fd, &sin, &sin_len); if (new_fd < 0) { int error = errno; if (error != EAGAIN) { @@ -416,7 +422,11 @@ ptcp_accept(struct vconn *vconn, struct vconn **new_vconnp) return error; } - return new_tcp_vconn("tcp" /* FIXME */, new_fd, 0, new_vconnp); + sprintf(name, "tcp:"IP_FMT, IP_ARGS(&sin.sin_addr)); + if (sin.sin_port != htons(OFP_TCP_PORT)) { + sprintf(strchr(name, '\0'), ":%"PRIu16, ntohs(sin.sin_port)); + } + return new_tcp_vconn(name, new_fd, 0, &sin, new_vconnp); } static void diff --git a/lib/vconn.c b/lib/vconn.c index 6af60e7e..94b4572d 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -204,6 +204,14 @@ vconn_is_passive(const struct vconn *vconn) return vconn->class->accept != NULL; } +/* 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) +{ + return vconn->ip; +} + /* Tries to complete the connection on 'vconn', which must be an active * vconn. If 'vconn''s connection is complete, returns 0 if the connection * was successful or a positive errno value if it failed. If the