* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
- * Preload-hacks distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * Preload-hacks are distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*
* You should have received a copy of the GNU General Public License along
- * with mLib; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
+ * with preload-hacks; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
-#include <net/if.h>
+#include <ifaddrs.h>
/*----- Data structures ---------------------------------------------------*/
_(recvfrom, ssize_t, (int, void *buf, size_t, int, \
struct sockaddr *from, socklen_t *fromlen)) \
_(sendmsg, ssize_t, (int, const struct msghdr *, int)) \
- _(recvmsg, ssize_t, (int, struct msghdr *, int)) \
- _(close, int, (int))
+ _(recvmsg, ssize_t, (int, struct msghdr *, int))
/* Function pointers to set up. */
#define DECL(imp, ret, args) static ret (*real_##imp) args;
len = sizeof(ov_); \
if (real_getsockopt(sk, SOL_SOCKET, SO_##opt, &ov_, &len) < 0 || \
real_setsockopt(nsk, SOL_SOCKET, SO_##opt, &ov_, len)) { \
- real_close(nsk); \
+ close(nsk); \
return (-1); \
} \
} while (0);
(fd = fcntl(sk, F_GETFD)) < 0 ||
fcntl(nsk, F_SETFL, f) < 0 ||
dup2(nsk, sk) < 0) {
- real_close(nsk);
+ close(nsk);
return (-1);
}
unlink(sun.sun_path);
- real_close(nsk);
+ close(nsk);
if (fcntl(sk, F_SETFD, fd) < 0) {
perror("noip: fixup_real_ip_socket F_SETFD");
abort();
pf = PF_UNIX;
proto = 0;
case PF_UNIX:
+#ifdef PF_NETLINK
+ case PF_NETLINK:
+#endif
return real_socket(pf, ty, proto);
default:
errno = EAFNOSUPPORT;
int connect(int sk, const struct sockaddr *sa, socklen_t len)
{
struct sockaddr_un sun;
- int fixup_p = 0;
int rc;
switch (sa->sa_family) {
case AF_INET:
PRESERVING_ERRNO({
do_implicit_bind(sk, &sa, &len, &sun);
- fixup_p = 1;
});
rc = real_connect(sk, sa, len);
if (rc < 0) {
*/
static void get_local_ipaddrs(void)
{
- struct if_nameindex *ifn;
- struct ifreq ifr;
- int sk;
+ struct ifaddrs *ifa_head, *ifa;
+ const struct in_addr *a;
int i;
- ifn = if_nameindex();
- if ((sk = real_socket(PF_INET, SOCK_STREAM, 00)) < 0)
- return;
- for (i = n_local_ipaddrs = 0;
- n_local_ipaddrs < MAX_LOCAL_IPADDRS &&
- ifn[i].if_name && *ifn[i].if_name;
- i++) {
- strcpy(ifr.ifr_name, ifn[i].if_name);
- if (ioctl(sk, SIOCGIFADDR, &ifr) || ifr.ifr_addr.sa_family != AF_INET)
+ if (getifaddrs(&ifa_head)) { perror("getifaddrs"); return; }
+ for (n_local_ipaddrs = 0, ifa = ifa_head;
+ n_local_ipaddrs < MAX_LOCAL_IPADDRS && ifa;
+ ifa = ifa->ifa_next) {
+ if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
continue;
- local_ipaddrs[n_local_ipaddrs++] =
- SIN(&ifr.ifr_addr)->sin_addr;
- D( fprintf(stderr, "noip: local addr %s = %s\n", ifn[i].if_name,
- inet_ntoa(local_ipaddrs[n_local_ipaddrs - 1])); )
+ a = &SIN(ifa->ifa_addr)->sin_addr;
+ D( fprintf(stderr, "noip: local addr %s = %s",
+ ifa->ifa_name, inet_ntoa(*a)); )
+ for (i = 0; i < n_local_ipaddrs; i++) {
+ if (local_ipaddrs[i].s_addr == a->s_addr) {
+ D( fprintf(stderr, " (duplicate)\n"); )
+ goto skip;
+ }
+ }
+ D( fprintf(stderr, "\n"); )
+ local_ipaddrs[n_local_ipaddrs] = *a;
+ n_local_ipaddrs++;
+ skip:;
}
- close(sk);
+ freeifaddrs(ifa_head);
}
/* Print the given message to standard error. Avoids stdio. */
static void printerr(const char *p)
- { int hunoz; hunoz = write(STDERR_FILENO, p, strlen(p)); }
+ { if (write(STDERR_FILENO, p, strlen(p))) ; }
/* Create the socket directory, being careful about permissions. */
static void create_sockdir(void)