/* * int zgetbindaddr(char *bindspec, Usockaddr *sap) */ /* Parse first argument for the specification of IP v.4 or v.6 address or network interface. If NULL or empty, fallback to the value of 'BINDADDR' ZENV variable. On success, return zero, otherwise non-zero. That is, if the caller gets zero code, it should bind() to the address returned in *sap, else bind to INADDR_ANY. Possible specification formats are: [0.0.0.0] [IPv6.0::0] iface:eth0:1 Original copyright by Matti Aarnio 1997,2000, modifications by Eugene Crosser 2002 */ #include "hostenv.h" #include #ifdef HAVE_SYS_SOCKET_H #include #endif #include #ifdef HAVE_STDLIB_H #include #endif #include #ifdef HAVE_NETINET_IN6_H # include #endif #ifdef HAVE_NETINET6_IN6_H # include #endif #ifdef HAVE_LINUX_IN6_H # include #endif #include #include #include #include "libc.h" #include "zmalloc.h" #include "libz.h" #include "hostenv.h" #include #include int zgetbindaddr(bindspec, af, sap) char *bindspec; const int af; Usockaddr *sap; { int result = 0; if ((bindspec == NULL) || (*bindspec == '\0')) bindspec = (char *)getzenv("BINDADDR"); /* we modify this..*/ if ((bindspec == NULL) || (*bindspec == '\0')) return 1; /* not specified - bind to INADDR_ANY */ #if defined(AF_INET6) && defined(INET6) if (cistrncmp(bindspec, "[ipv6 ", 6) == 0 || cistrncmp(bindspec, "[ipv6:", 6) == 0 || cistrncmp(bindspec, "[ipv6.", 6) == 0) { char *s = strchr(bindspec, ']'); if (s) *s = 0; if (inet_pton (AF_INET6, bindspec + 6, &sap->v6.sin6_addr) < 1) { /* False IPv6 number literal */ /* ... then we don't set the IP address... */ result = 1; } sap->v6.sin6_family = AF_INET6; } else #endif if (*bindspec == '[') { char *s = strchr(bindspec, ']'); if (s) *s = 0; if (inet_pton(AF_INET, bindspec + 1, &sap->v4.sin_addr) < 1) { /* False IP(v4) number literal */ /* ... then we don't set the IP address... */ result = 1; } sap->v4.sin_family = AF_INET; } else { if (CISTREQN(bindspec, "iface:", 6)) { #if defined(AF_INET6) && defined(INET6) if (af == AF_INET6) { sap->v6.sin6_family = AF_INET6; if (zgetifaddress( AF_INET6, bindspec + 6, sap )) { /* Didn't get IPv6 interface address of given name.. */ if (zgetifaddress( AF_INET6, bindspec + 6, sap )) { /* No recognized interface! */ result = 1; } } return result; } #endif if (af == 0 || af == AF_INET) { if (zgetifaddress( AF_INET, bindspec + 6, sap )) { /* No recognized interface! */ result = 1; } return result; } } else { /* XXX: TODO: Try to see if this is an interface name, and pick IPv4 and/or IPv6 addresses for that interface. */ result = 1; } } return result; }