diff --git a/net/mtr/Makefile b/net/mtr/Makefile new file mode 100644 index 0000000000..5d31ef21d7 --- /dev/null +++ b/net/mtr/Makefile @@ -0,0 +1,66 @@ +# +# Copyright (C) 2006-2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mtr +PKG_VERSION:=0.85 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=ftp://ftp.bitwizard.nl/mtr +PKG_MD5SUM:=5e665c617e5659b6ec3e201ee7488eb1 + +PKG_INSTALL:=1 + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/mtr + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libncurses + TITLE:=Full screen ncurses traceroute tool + URL:=http://www.bitwizard.nl/mtr/ + MAINTAINER:=Jonathan McCrohan +endef + +define Package/mtr/description + mtr combines the functionality of the 'traceroute' and 'ping' programs + in a single network diagnostic tool. + As mtr starts, it investigates the network connection between the host + mtr runs on and a user-specified destination host. After it + determines the address of each network hop between the machines, + it sends a sequence ICMP ECHO requests to each one to determine the + quality of the link to each machine. As it does this, it prints + running statistics about each machine. +endef + +CONFIGURE_ARGS += \ + --without-gtk \ + --without-glib \ + +define Build/Configure + (cd $(PKG_BUILD_DIR); touch \ + configure.in \ + aclocal.m4 \ + Makefile.in \ + img/Makefile.in \ + stamp-h.in \ + config.h.in \ + configure \ + ); + $(call Build/Configure/Default) +endef + +define Package/mtr/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mtr $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,mtr)) diff --git a/net/mtr/patches/501-dns.patch b/net/mtr/patches/501-dns.patch new file mode 100644 index 0000000000..50c7230461 --- /dev/null +++ b/net/mtr/patches/501-dns.patch @@ -0,0 +1,510 @@ +--- a/dns.c ++++ b/dns.c +@@ -918,6 +918,507 @@ void restell(char *s) + fputs("\r",stderr); + } + ++#ifdef __UCLIBC__ ++ ++static const char digits[] = "0123456789"; ++#define __set_errno(e) (errno = (e)) ++ ++#define NS_PUT16(s, cp) do { \ ++ register u_int16_t t_s = (u_int16_t)(s); \ ++ register u_char *t_cp = (u_char *)(cp); \ ++ *t_cp++ = t_s >> 8; \ ++ *t_cp = t_s; \ ++ (cp) += NS_INT16SZ; \ ++} while (0) ++ ++ ++ ++#define NS_PUT32(l, cp) do { \ ++ register u_int32_t t_l = (u_int32_t)(l); \ ++ register u_char *t_cp = (u_char *)(cp); \ ++ *t_cp++ = t_l >> 24; \ ++ *t_cp++ = t_l >> 16; \ ++ *t_cp++ = t_l >> 8; \ ++ *t_cp = t_l; \ ++ (cp) += NS_INT32SZ; \ ++} while (0) ++ ++ ++void ++ns_put16(u_int src, u_char *dst) { ++ NS_PUT16(src, dst); ++} ++ ++void ++ns_put32(u_long src, u_char *dst) { ++ NS_PUT32(src, dst); ++} ++ ++void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } ++void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); } ++ ++int ++mklower(int ch) { ++ if (ch >= 0x41 && ch <= 0x5A) ++ return (ch + 0x20); ++ return (ch); ++} ++ ++ ++static int ++dn_find(const u_char *domain, const u_char *msg, ++ const u_char * const *dnptrs, ++ const u_char * const *lastdnptr) ++{ ++ const u_char *dn, *cp, *sp; ++ const u_char * const *cpp; ++ u_int n; ++ ++ for (cpp = dnptrs; cpp < lastdnptr; cpp++) { ++ sp = *cpp; ++ /* ++ * terminate search on: ++ * root label ++ * compression pointer ++ * unusable offset ++ */ ++ while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && ++ (sp - msg) < 0x4000) { ++ dn = domain; ++ cp = sp; ++ while ((n = *cp++) != 0) { ++ /* ++ * check for indirection ++ */ ++ switch (n & NS_CMPRSFLGS) { ++ case 0: /* normal case, n == len */ ++ if (n != *dn++) ++ goto next; ++ for ((void)NULL; n > 0; n--) ++ if (mklower(*dn++) != ++ mklower(*cp++)) ++ goto next; ++ /* Is next root for both ? */ ++ if (*dn == '\0' && *cp == '\0') ++ return (sp - msg); ++ if (*dn) ++ continue; ++ goto next; ++ ++ case NS_CMPRSFLGS: /* indirection */ ++ cp = msg + (((n & 0x3f) << 8) | *cp); ++ break; ++ ++ default: /* illegal type */ ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ } ++ next: ++ sp += *sp + 1; ++ } ++ } ++ __set_errno (ENOENT); ++ return (-1); ++} ++ ++ ++int ++ns_name_pack(const u_char *src, u_char *dst, int dstsiz, ++ const u_char **dnptrs, const u_char **lastdnptr) ++{ ++ u_char *dstp; ++ const u_char **cpp, **lpp, *eob, *msg; ++ const u_char *srcp; ++ int n, l, first = 1; ++ ++ srcp = src; ++ dstp = dst; ++ eob = dstp + dstsiz; ++ lpp = cpp = NULL; ++ if (dnptrs != NULL) { ++ if ((msg = *dnptrs++) != NULL) { ++ for (cpp = dnptrs; *cpp != NULL; cpp++) ++ (void)NULL; ++ lpp = cpp; /* end of list to search */ ++ } ++ } else ++ msg = NULL; ++ ++ /* make sure the domain we are about to add is legal */ ++ l = 0; ++ do { ++ n = *srcp; ++ if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ if (n == 0x41) ++ n = *++srcp / 8; ++ l += n + 1; ++ if (l > MAXCDNAME) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ srcp += n + 1; ++ } while (n != 0); ++ ++ /* from here on we need to reset compression pointer array on error */ ++ srcp = src; ++ do { ++ /* Look to see if we can use pointers. */ ++ n = *srcp; ++ if (n != 0 && n != 0x41 && msg != NULL) { ++ l = dn_find(srcp, msg, (const u_char * const *)dnptrs, ++ (const u_char * const *)lpp); ++ if (l >= 0) { ++ if (dstp + 1 >= eob) { ++ goto cleanup; ++ } ++ *dstp++ = (l >> 8) | NS_CMPRSFLGS; ++ *dstp++ = l % 256; ++ return (dstp - dst); ++ } ++ /* Not found, save it. */ ++ if (lastdnptr != NULL && cpp < lastdnptr - 1 && ++ (dstp - msg) < 0x4000 && first) { ++ *cpp++ = dstp; ++ *cpp = NULL; ++ first = 0; ++ } ++ } ++ /* copy label to buffer */ ++ if ((n & NS_CMPRSFLGS) != 0 && n != 0x41) { /* Should not happen. */ ++ goto cleanup; ++ } ++ if (n == 0x41) { ++ n = *++srcp / 8; ++ if (dstp + 1 >= eob) ++ goto cleanup; ++ *dstp++ = 0x41; ++ } ++ if (dstp + 1 + n >= eob) { ++ goto cleanup; ++ } ++ memcpy(dstp, srcp, n + 1); ++ srcp += n + 1; ++ dstp += n + 1; ++ } while (n != 0); ++ ++ if (dstp > eob) { ++cleanup: ++ if (msg != NULL) ++ *lpp = NULL; ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ return (dstp - dst); ++} ++ ++ ++int ++ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { ++ u_char *label, *bp, *eom; ++ int c, n, escaped; ++ char *cp; ++ ++ escaped = 0; ++ bp = dst; ++ eom = dst + dstsiz; ++ label = bp++; ++ ++ while ((c = *src++) != 0) { ++ if (escaped) { ++ if ((cp = strchr(digits, c)) != NULL) { ++ n = (cp - digits) * 100; ++ if ((c = *src++) == 0 || ++ (cp = strchr(digits, c)) == NULL) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ n += (cp - digits) * 10; ++ if ((c = *src++) == 0 || ++ (cp = strchr(digits, c)) == NULL) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ n += (cp - digits); ++ if (n > 255) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ c = n; ++ } else if (c == '[' && label == bp - 1 && *src == 'x') { ++ /* Theoretically we would have to handle \[o ++ as well but we do not since we do not need ++ it internally. */ ++ *label = 0x41; ++ label = bp++; ++ ++src; ++ while (isxdigit (*src)) { ++ n = *src > '9' ? *src - 'a' + 10 : *src - '0'; ++ ++src; ++ if (! isxdigit(*src)) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ n <<= 4; ++ n += *src > '9' ? *src - 'a' + 10 : *src - '0'; ++ if (bp + 1 >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ *bp++ = n; ++ ++src; ++ } ++ *label = (bp - label - 1) * 8; ++ if (*src++ != ']' || *src++ != '.') { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ escaped = 0; ++ label = bp++; ++ if (bp >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ continue; ++ } ++ escaped = 0; ++ } else if (c == '\\') { ++ escaped = 1; ++ continue; ++ } else if (c == '.') { ++ c = (bp - label - 1); ++ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ if (label >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ *label = c; ++ /* Fully qualified ? */ ++ if (*src == '\0') { ++ if (c != 0) { ++ if (bp >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ *bp++ = '\0'; ++ } ++ if ((bp - dst) > MAXCDNAME) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ return (1); ++ } ++ if (c == 0 || *src == '.') { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ label = bp++; ++ continue; ++ } ++ if (bp >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ *bp++ = (u_char)c; ++ } ++ c = (bp - label - 1); ++ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ if (label >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ *label = c; ++ if (c != 0) { ++ if (bp >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ *bp++ = 0; ++ } ++ if ((bp - dst) > MAXCDNAME) { /* src too big */ ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ return (0); ++} ++ ++ ++ ++int ++ns_name_compress(const char *src, u_char *dst, size_t dstsiz, ++ const u_char **dnptrs, const u_char **lastdnptr) ++{ ++ u_char tmp[NS_MAXCDNAME]; ++ ++ if (ns_name_pton(src, tmp, sizeof tmp) == -1) ++ return (-1); ++ return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); ++} ++ ++ ++int ++dn_comp(const char *src, u_char *dst, int dstsiz, ++ u_char **dnptrs, u_char **lastdnptr) ++{ ++ return (ns_name_compress(src, dst, (size_t)dstsiz, ++ (const u_char **)dnptrs, ++ (const u_char **)lastdnptr)); ++} ++ ++ ++ ++ ++int ++res_nmkquery(res_state statp, ++ int op, /* opcode of query */ ++ const char *dname, /* domain name */ ++ int class, int type, /* class and type of query */ ++ const u_char *data, /* resource record data */ ++ int datalen, /* length of data */ ++ const u_char *newrr_in, /* new rr for modify or append */ ++ u_char *buf, /* buffer to put query */ ++ int buflen) /* size of buffer */ ++{ ++ register HEADER *hp; ++ register u_char *cp; ++ register int n; ++ u_char *dnptrs[20], **dpp, **lastdnptr; ++ ++#ifdef DEBUG ++ if (statp->options & RES_DEBUG) ++ printf(";; res_nmkquery(%s, %s, %s, %s)\n", ++ _res_opcodes[op], dname, p_class(class), p_type(type)); ++#endif ++ /* ++ * Initialize header fields. ++ */ ++ if ((buf == NULL) || (buflen < HFIXEDSZ)) ++ return (-1); ++ memset(buf, 0, HFIXEDSZ); ++ hp = (HEADER *) buf; ++ /* We randomize the IDs every time. The old code just ++ incremented by one after the initial randomization which ++ still predictable if the application does multiple ++ requests. */ ++#if 0 ++ hp->id = htons(++statp->id); ++#else ++ hp->id = htons(statp->id); ++ int randombits; ++ do ++ { ++#ifdef RANDOM_BITS ++ RANDOM_BITS (randombits); ++#else ++ struct timeval tv; ++ gettimeofday (&tv, NULL); ++ randombits = (tv.tv_sec << 8) ^ tv.tv_usec; ++#endif ++ } ++ while ((randombits & 0xffff) == 0); ++ statp->id = (statp->id + randombits) & 0xffff; ++#endif ++ hp->opcode = op; ++ hp->rd = (statp->options & RES_RECURSE) != 0; ++ hp->rcode = NOERROR; ++ cp = buf + HFIXEDSZ; ++ buflen -= HFIXEDSZ; ++ dpp = dnptrs; ++ *dpp++ = buf; ++ *dpp++ = NULL; ++ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; ++ /* ++ * perform opcode specific processing ++ */ ++ switch (op) { ++ case QUERY: /*FALLTHROUGH*/ ++ case NS_NOTIFY_OP: ++ if ((buflen -= QFIXEDSZ) < 0) ++ return (-1); ++ if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) ++ return (-1); ++ cp += n; ++ buflen -= n; ++ __putshort(type, cp); ++ cp += INT16SZ; ++ __putshort(class, cp); ++ cp += INT16SZ; ++ hp->qdcount = htons(1); ++ if (op == QUERY || data == NULL) ++ break; ++ /* ++ * Make an additional record for completion domain. ++ */ ++ buflen -= RRFIXEDSZ; ++ n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr); ++ if (n < 0) ++ return (-1); ++ cp += n; ++ buflen -= n; ++ __putshort(T_NULL, cp); ++ cp += INT16SZ; ++ __putshort(class, cp); ++ cp += INT16SZ; ++ __putlong(0, cp); ++ cp += INT32SZ; ++ __putshort(0, cp); ++ cp += INT16SZ; ++ hp->arcount = htons(1); ++ break; ++ ++ case IQUERY: ++ /* ++ * Initialize answer section ++ */ ++ if (buflen < 1 + RRFIXEDSZ + datalen) ++ return (-1); ++ *cp++ = '\0'; /* no domain name */ ++ __putshort(type, cp); ++ cp += INT16SZ; ++ __putshort(class, cp); ++ cp += INT16SZ; ++ __putlong(0, cp); ++ cp += INT32SZ; ++ __putshort(datalen, cp); ++ cp += INT16SZ; ++ if (datalen) { ++ memcpy(cp, data, datalen); ++ cp += datalen; ++ } ++ hp->ancount = htons(1); ++ break; ++ ++ default: ++ return (-1); ++ } ++ return (cp - buf); ++} ++ ++int ++res_mkquery(int op, /* opcode of query */ ++ const char *dname, /* domain name */ ++ int class, int type, /* class and type of query */ ++ const u_char *data, /* resource record data */ ++ int datalen, /* length of data */ ++ const u_char *newrr_in, /* new rr for modify or append */ ++ u_char *buf, /* buffer to put query */ ++ int buflen) /* size of buffer */ ++{ ++ return (res_nmkquery(&_res, op, dname, class, type, ++ data, datalen, ++ newrr_in, buf, buflen)); ++} ++ ++#endif + + void dorequest(char *s,int type,word id) + { diff --git a/net/mtr/patches/502-fix-res_ninit.patch b/net/mtr/patches/502-fix-res_ninit.patch new file mode 100644 index 0000000000..aeec4edcce --- /dev/null +++ b/net/mtr/patches/502-fix-res_ninit.patch @@ -0,0 +1,31 @@ +--- a/dns.c ++++ b/dns.c +@@ -1305,28 +1305,6 @@ res_nmkquery(res_state statp, + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; +- /* We randomize the IDs every time. The old code just +- incremented by one after the initial randomization which +- still predictable if the application does multiple +- requests. */ +-#if 0 +- hp->id = htons(++statp->id); +-#else +- hp->id = htons(statp->id); +- int randombits; +- do +- { +-#ifdef RANDOM_BITS +- RANDOM_BITS (randombits); +-#else +- struct timeval tv; +- gettimeofday (&tv, NULL); +- randombits = (tv.tv_sec << 8) ^ tv.tv_usec; +-#endif +- } +- while ((randombits & 0xffff) == 0); +- statp->id = (statp->id + randombits) & 0xffff; +-#endif + hp->opcode = op; + hp->rd = (statp->options & RES_RECURSE) != 0; + hp->rcode = NOERROR; diff --git a/net/mtr/patches/521-glib-dependency-fixes.patch b/net/mtr/patches/521-glib-dependency-fixes.patch new file mode 100644 index 0000000000..93c98040e2 --- /dev/null +++ b/net/mtr/patches/521-glib-dependency-fixes.patch @@ -0,0 +1,97 @@ +From 25a2456845b341066adb5f9fcc553dec12a751b7 Mon Sep 17 00:00:00 2001 +From: Roger Wolff +Date: Fri, 5 Jul 2013 11:40:02 +0200 +Subject: [PATCH] glib dependency fixes. + +--- + configure.ac | 32 ++++++++++++++------------------ + mtr.c | 5 +++++ + report.c | 2 ++ + 3 files changed, 21 insertions(+), 18 deletions(-) + +--- a/configure.ac ++++ b/configure.ac +@@ -42,25 +42,22 @@ AC_ARG_WITH(gtk, + [ --without-gtk Do not try to use GTK+ at all], + WANTS_GTK=$withval, WANTS_GTK=yes) + +-AC_ARG_WITH(glib, +-[ --without-glib Do not try to use glib at all], +-WANTS_GLIB=$withval, WANTS_GLIB=yes) +- + AC_ARG_WITH([ipinfo], + [ --without-ipinfo Do not try to use ipinfo lookup at all], +-[case "${withval}" in +- yes) ipinfo=true ;; +- no) ipinfo=false ;; +- *) AC_MSG_ERROR([bad value ${withval} for --with-ipinfo]) ;; +-esac],[ipinfo=true]) +-AM_CONDITIONAL([IPINFO], [test x$ipinfo = xtrue]) +-if test "x$ipinfo" = "xfalse"; then +- AC_DEFINE([NO_IPINFO], [1], [Define to disable ipinfo lookup]) +-fi ++[ipinfo="${withval}"], [ipinfo=yes]) ++AM_CONDITIONAL([IPINFO], [test x$ipinfo = xyes]) + + AC_ARG_ENABLE(ipv6, + [ --disable-ipv6 Do not enable IPv6], + WANTS_IPV6=$enableval, WANTS_IPV6=yes) ++ ++m4_ifndef([AM_PATH_GTK_2_0], [m4_defun([AM_PATH_GTK_2_0], [AC_MSG_ERROR([ ++ Could not locate the gtk2 automake macros, these are usually located in ++ .../share/aclocal/gtk-2.0.m4 ++ Before running bootstrap try setting the environment variable ++ ACLOCAL_PATH="/own/dir" ++ or configure --without-gtk. ++])])]) + + if test "x$WANTS_GTK" = "xyes"; then + AM_PATH_GTK_2_0(2.6.0, CFLAGS="$CFLAGS $GTK_CFLAGS" +@@ -71,11 +68,10 @@ if test "x$WANTS_GTK" = "xyes"; then + else + AC_DEFINE(NO_GTK) + GTK_OBJ="" +- if test "x$WANTS_GLIB" = "xyes"; then +- PKG_CHECK_MODULES([GLIB], [glib-2.0]) +- else +- AC_DEFINE(NO_GLIB, 1, [Define if you don't have the glib libraries available.]) +- fi ++fi ++ ++if test "x$ipinfo" = "xno"; then ++ AC_DEFINE([NO_IPINFO], [1], [Define to disable ipinfo lookup]) + fi + + AC_CHECK_FUNC(socket, , +--- a/mtr.c ++++ b/mtr.c +@@ -464,6 +464,11 @@ void parse_arg (int argc, char **argv) + case 'z': + ipinfo_no = 0; + break; ++#else ++ case 'y': ++ case 'z': ++ fprintf( stderr, "IPINFO not enabled.\n" ); ++ break; + #endif + } + } +--- a/report.c ++++ b/report.c +@@ -340,6 +340,7 @@ void csv_close(time_t now) + snprint_addr(name, sizeof(name), addr); + + int last = net_last(at); ++#ifndef NO_IPINFO + if(!ipinfo_no) { + char* fmtinfo = fmt_ipinfo(addr); + if (fmtinfo != NULL) fmtinfo = trim(fmtinfo); +@@ -349,6 +350,7 @@ void csv_close(time_t now) + printf("MTR.%s;%lu;%s;%s;%d;%s;%d", MTR_VERSION, now, "OK", Hostname, + at+1, name, last); + } ++#endif + + for( i=0; i