File: talk.FvK.patch

package info (click to toggle)
netstd 3.07-7slink.3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 6,312 kB
  • ctags: 9,027
  • sloc: ansic: 72,107; cpp: 6,144; makefile: 1,650; yacc: 1,614; sh: 1,164; perl: 308; awk: 46
file content (59 lines) | stat: -rw-r--r-- 1,735 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
--- get_addrs.c
+++ get_addrs.c	1994/02/23 12:41:31
@@ -44,11 +44,33 @@
 #include <stdio.h>
 #include "talk_ctl.h"
 
+/*
+ * Hah.  BSD folks may have thought too simple on this one.
+ * If you are a multihomed host, this program will miserably fail,
+ * as it will use the IP address of "hostname" as the source of the
+ * messages, not the address of the interface over which the packet
+ * will be routed.
+ *
+ * With Linux NET-2E, a possible solution is to perform an UDP CONNECT
+ * operation on a socket, so the kernel sets the correct source address
+ * of the socket's packets.  Then we do a getsockname on that socket,
+ * and voila... we have the correct source address!
+ *
+ * Note that this only works with NET-2E BETA-4 and newer kernels.
+ */
 get_addrs(my_machine_name, his_machine_name)
 	char *my_machine_name, *his_machine_name;
 {
 	struct hostent *hp;
 	struct servent *sp;
+#ifdef __linux__
+	struct sockaddr_in sin;
+	struct sockaddr_in foo;
+	int sock, i;
+
+	/* If socket fails, code will see it. */
+	sock = socket(AF_INET, SOCK_DGRAM, 0);
+#endif
 
 	msg.pid = htonl(getpid());
 	/* look up the address of the local host */
@@ -81,4 +103,22 @@
 		exit(-1);
 	}
 	daemon_port = sp->s_port;
+#ifdef __linux__
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = his_machine_addr.s_addr;
+	sin.sin_port = sp->s_port;
+
+	/* Now here is the trick.  We connect to the other side. */
+	if ((sock >= 0) &&
+	    (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) == 0)) {
+		/* Bingo.  Now fetch the address. */
+		foo = sin;
+		i = sizeof(foo);
+		if (getsockname(sock, (struct sockaddr *) &foo, &i) == 0) {
+			my_machine_addr = foo.sin_addr;
+		}
+	}
+	/* Loose the socket. */
+	(void) close(sock);
+#endif
 }