tests: Add bundle action test with buffer realloc.
[cascardo/ovs.git] / lib / socket-util.c
index 8949da7..6f959b2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -101,11 +101,14 @@ setsockopt_tcp_nodelay(int fd)
     }
 }
 
+/* Sets the DSCP value of socket 'fd' to 'dscp', which must be 63 or less.
+ * 'family' must indicate the socket's address family (AF_INET or AF_INET6, to
+ * do anything useful). */
 int
-set_dscp(int fd, uint8_t dscp)
+set_dscp(int fd, int family, uint8_t dscp)
 {
+    int retval;
     int val;
-    bool success;
 
 #ifdef _WIN32
     /* XXX: Consider using QoS2 APIs for Windows to set dscp. */
@@ -115,29 +118,31 @@ set_dscp(int fd, uint8_t dscp)
     if (dscp > 63) {
         return EINVAL;
     }
-
-    /* Note: this function is used for both of IPv4 and IPv6 sockets */
-    success = false;
     val = dscp << 2;
-    if (setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof val)) {
-        if (sock_errno() != ENOPROTOOPT) {
-            return sock_errno();
-        }
-    } else {
-        success = true;
-    }
-    if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof val)) {
-        if (sock_errno() != ENOPROTOOPT) {
-            return sock_errno();
-        }
-    } else {
-        success = true;
-    }
-    if (!success) {
+
+    switch (family) {
+    case AF_INET:
+        retval = setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof val);
+        break;
+
+    case AF_INET6:
+        retval = setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof val);
+        break;
+
+    default:
         return ENOPROTOOPT;
     }
 
-    return 0;
+    return retval ? sock_errno() : 0;
+}
+
+/* Checks whether 'host_name' is an IPv4 or IPv6 address.  It is assumed
+ * that 'host_name' is valid.  Returns false if it is IPv4 address, true if
+ * it is IPv6 address. */
+bool
+addr_is_ipv6(const char *host_name)
+{
+    return strchr(host_name, ':') != NULL;
 }
 
 /* Translates 'host_name', which must be a string representation of an IP
@@ -146,7 +151,7 @@ set_dscp(int fd, uint8_t dscp)
 int
 lookup_ip(const char *host_name, struct in_addr *addr)
 {
-    if (!inet_pton(AF_INET, host_name, addr)) {
+    if (!ip_parse(host_name, &addr->s_addr)) {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
         VLOG_ERR_RL(&rl, "\"%s\" is not a valid IP address", host_name);
         return ENOENT;
@@ -160,7 +165,7 @@ lookup_ip(const char *host_name, struct in_addr *addr)
 int
 lookup_ipv6(const char *host_name, struct in6_addr *addr)
 {
-    if (inet_pton(AF_INET6, host_name, addr) != 1) {
+    if (!ipv6_parse(host_name, addr)) {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
         VLOG_ERR_RL(&rl, "\"%s\" is not a valid IPv6 address", host_name);
         return ENOENT;
@@ -183,7 +188,7 @@ lookup_hostname(const char *host_name, struct in_addr *addr)
     struct addrinfo *result;
     struct addrinfo hints;
 
-    if (inet_pton(AF_INET, host_name, addr)) {
+    if (ip_parse(host_name, &addr->s_addr)) {
         return 0;
     }
 
@@ -366,14 +371,14 @@ parse_sockaddr_components(struct sockaddr_storage *ss,
 
         sin6->sin6_family = AF_INET6;
         sin6->sin6_port = htons(port);
-        if (!inet_pton(AF_INET6, host_s, sin6->sin6_addr.s6_addr)) {
+        if (!ipv6_parse(host_s, &sin6->sin6_addr)) {
             VLOG_ERR("%s: bad IPv6 address \"%s\"", s, host_s);
             goto exit;
         }
     } else {
         sin->sin_family = AF_INET;
         sin->sin_port = htons(port);
-        if (!inet_pton(AF_INET, host_s, &sin->sin_addr.s_addr)) {
+        if (!ip_parse(host_s, &sin->sin_addr.s_addr)) {
             VLOG_ERR("%s: bad IPv4 address \"%s\"", s, host_s);
             goto exit;
         }
@@ -470,7 +475,7 @@ inet_open_active(int style, const char *target, uint16_t default_port,
     /* The dscp bits must be configured before connect() to ensure that the
      * TOS field is set during the connection establishment.  If set after
      * connect(), the handshake SYN frames will be sent with a TOS of 0. */
-    error = set_dscp(fd, dscp);
+    error = set_dscp(fd, ss.ss_family, dscp);
     if (error) {
         VLOG_ERR("%s: set_dscp: %s", target, sock_strerror(error));
         goto exit;
@@ -611,7 +616,7 @@ inet_open_passive(int style, const char *target, int default_port,
     /* The dscp bits must be configured before connect() to ensure that the TOS
      * field is set during the connection establishment.  If set after
      * connect(), the handshake SYN frames will be sent with a TOS of 0. */
-    error = set_dscp(fd, dscp);
+    error = set_dscp(fd, ss.ss_family, dscp);
     if (error) {
         VLOG_ERR("%s: set_dscp: %s", target, sock_strerror(error));
         goto error;