ports/129351: dante patch to tix BSD specific problem with external.rotation
Christoph Weber-Fahr
cwf-ml at arcor.de
Mon Dec 1 21:50:05 UTC 2008
>Number: 129351
>Category: ports
>Synopsis: dante patch to tix BSD specific problem with external.rotation
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Mon Dec 01 21:50:04 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator: Christoph Weber-Fahr
>Release: 6.3-RELEASE
>Organization:
Arcor AG
>Environment:
various
>Description:
there is a bug in dante that prevents it from correctly parsing interface addresses. Therefore the external-rotation mechanism (dealing with more than 1 external interface) doe not work with FreerBSD.
The issue is present in both FreeBSD 5.x and Freebsd 6.x (and possibly earlier).
I submitted a patch that was developed for us to both the Dante and the FreeBSD port maintainer per email in august. Since nothing happened, I'm resubmiitting it here.
>How-To-Repeat:
>Fix:
Patch attached with submission follows:
$Arcor$
--- sockd/getifa.c.orig Tue Jul 1 15:21:40 2003
+++ sockd/getifa.c Mon Aug 14 14:32:57 2006
@@ -58,6 +58,9 @@
* that will be selected by the OS to connect to that destination address.
*==========================================================================*/
#include <net/route.h> /* RTA_xxx constants */
+#if HAVE_ROUTEINFO_BSD
+#include <net/if_dl.h>
+#endif /* HAVE_ROUTEINFO_BSD */
#if HAVE_ROUTEINFO_LINUX
#include <asm/types.h>
#include <linux/netlink.h>
@@ -233,9 +236,11 @@
pid_t pid;
struct rt_msghdr *rtm;
struct sockaddr *sa;
+ char *cp;
+ int i;
uid_t euid;
struct in_addr inaddr_none;
- struct in_addr gwaddr;
+ struct sockaddr ifa;
inaddr_none.s_addr = htonl(INADDR_NONE);
@@ -256,85 +261,123 @@
}
/*===================================================================
- * Do until 2 consecutive RTM_GET return the same gateway address.
- * The first calls may return router addresses in RTA_GATEWAY and
- * those will not match any local external address.
+ * Do a RTM_GET to look up the gateway for the address.
+ * Extract the RTM_IFA from it, which is the source address used
+ * on that interface.
+ * The code is modeled after the code for route(8).
*==================================================================*/
+ /*===========================================================
+ * Build the necessary data structures to get routing info.
+ * The structures are:
+ * rt_msghdr - Specifies RTM_GET for getting routing table
+ * info
+ * sockaddr - contains the destination address
+ * sockaddr_dl - necessary for unkown reasons.
+ *==========================================================*/
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+
+ bzero(buf, sizeof(buf));
+ rtm = (struct rt_msghdr *) buf;
+ rtm->rtm_version = RTM_VERSION;
+ rtm->rtm_type = RTM_GET;
+ rtm->rtm_flags = RTF_UP | RTF_HOST | RTF_GATEWAY | RTF_STATIC;
+ rtm->rtm_addrs = RTA_DST | RTA_IFA;
+ rtm->rtm_pid = pid = getpid();
+ rtm->rtm_seq = SEQ;
+
+ cp = (char *) (rtm + 1);
+ sa = (struct sockaddr *) cp;
+ /* LINTED pointer casts may be troublesome */
+ TOIN(sa)->sin_family = AF_INET;
+ /* LINTED pointer casts may be troublesome */
+ TOIN(sa)->sin_addr = destaddr;
+ /* LINTED pointer casts may be troublesome */
+ TOIN(sa)->sin_port = htons(0);
+ sa->sa_len = sizeof(struct sockaddr_in);
+ ADVANCE(cp, sa);
+ sa = (struct sockaddr *) cp;
+ /* add dummy link layer address */
+ sa->sa_family = AF_LINK;
+ sa->sa_len = sizeof(struct sockaddr_dl);
+ ADVANCE(cp, sa);
+ sa = (struct sockaddr *) cp;
+ rtm->rtm_addrs |= RTA_IFP;
+
+ rtm->rtm_msglen = cp - buf;
+
+ /*===========================================================
+ * Send the request and get the response.
+ *==========================================================*/
+ if (write(sockfd, rtm, (size_t)rtm->rtm_msglen) != rtm->rtm_msglen) {
+ swarn("%s: write() to AF_ROUTE failed", function);
+ close(sockfd);
+ return inaddr_none;
+ }
+
do {
- /*===========================================================
- * Build the necessary data structures to get routing info.
- * The structures are:
- * rt_msghdr - Specifies RTM_GET for getting routing table
- * info
- * sockaddr - contains the destination address
- *==========================================================*/
-
- bzero(buf, sizeof(buf));
- rtm = (struct rt_msghdr *) buf;
- rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
- rtm->rtm_version = RTM_VERSION;
- rtm->rtm_type = RTM_GET;
- rtm->rtm_addrs = RTA_DST;
- rtm->rtm_pid = pid = getpid();
- rtm->rtm_seq = SEQ;
-
- sa = (struct sockaddr *) (rtm + 1);
- /* LINTED pointer casts may be troublesome */
- TOIN(sa)->sin_family = AF_INET;
- /* LINTED pointer casts may be troublesome */
- TOIN(sa)->sin_addr = destaddr;
- /* LINTED pointer casts may be troublesome */
- TOIN(sa)->sin_port = htons(0);
-
- /*===========================================================
- * Send the request and get the response.
- *==========================================================*/
- if (write(sockfd, rtm, (size_t)rtm->rtm_msglen) != rtm->rtm_msglen) {
- swarn("%s: write() to AF_ROUTE failed", function);
+ if (read(sockfd, rtm, sizeof(buf)) == -1) {
+ swarn("%s: read from AF_ROUTE failed", function);
close(sockfd);
return inaddr_none;
}
+ } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ
+ || rtm->rtm_pid != pid);
- do {
- if (read(sockfd, rtm, sizeof(buf)) == -1) {
- swarn("%s: read from AF_ROUTE failed", function);
+ /*================================================================
+ * Iterate over the address structure extracting only the relevant
+ * addresses.
+ *===============================================================*/
+ cp = (char *) (rtm + 1);
+ sa = (struct sockaddr *) cp;
+
+ for (i=0; (i < RTAX_MAX) && (cp < buf + sizeof(buf)); i++) {
+ switch (i) {
+ case RTAX_GATEWAY:
+ if (!(rtm->rtm_addrs & RTA_GATEWAY)) {
+ slog(LOG_DEBUG, "%s: can't find gateway for %s, using defaultexternal",
+ function, inet_ntoa(destaddr));
close(sockfd);
- return inaddr_none;
+ return getdefaultexternal();
}
- } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ
- || rtm->rtm_pid != pid);
-
- /*============================================================
- * Go straight to the RTA_GATEWAY entry for our info.
- *===========================================================*/
- sa = (struct sockaddr *) (rtm + 1);
-
- if (!(rtm->rtm_addrs & RTA_GATEWAY)
- || (sa += RTAX_GATEWAY) == NULL
- || TOIN(sa)->sin_family != AF_INET) {
- slog(LOG_DEBUG, "%s: can't find gateway for %s, using defaultexternal",
- function, inet_ntoa(destaddr));
- close(sockfd);
- return getdefaultexternal();
+ break;
+ case RTAX_IFA:
+ if (!(rtm->rtm_addrs & RTA_IFA)
+ || TOIN(sa)->sin_family != AF_INET) {
+ slog(LOG_DEBUG, "%s: can't find ifa for %s, using defaultexternal",
+ function, inet_ntoa(destaddr));
+ close(sockfd);
+ return getdefaultexternal();
+ }
+ else {
+ memcpy((void*)&ifa, (void*)sa, sa->sa_len);
+ }
+ break;
+ }
+ if (rtm->rtm_addrs & (1<<i)) {
+ ADVANCE(cp, sa);
+ sa = (struct sockaddr *)cp;
}
+#undef ROUNDUP
+#undef ADVANCE
- gwaddr.s_addr = destaddr.s_addr;
- destaddr.s_addr = TOIN(sa)->sin_addr.s_addr;
- } while (destaddr.s_addr != gwaddr.s_addr);
+ }
close(sockfd);
- if (!isonexternal(sa)) {
+ if (!isonexternal(&ifa)) {
char a[MAXSOCKADDRSTRING];
swarnx("%s: address %s selected, but not set for external interface",
- function, sockaddr2string(sa, a, sizeof(a)));
+ function, sockaddr2string(&ifa, a, sizeof(a)));
return getdefaultexternal();
}
/* LINTED pointer casts may be troublesome */
- return TOIN(sa)->sin_addr;
+ return TOIN(&ifa)->sin_addr;
}
#else /* HAVE_ROUTEINFO_BSD */
@@ -393,7 +436,7 @@
struct sockaddr check;
int match = 0;
- switch ((*sockscf.external.addrv).atype) {
+ switch (sockscf.external.addrv[i].atype) {
case SOCKS_ADDR_IFNAME: {
int ifi;
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list