Quellcode durchsuchen

Fix bindtointerface code

mingodad vor 11 Jahren
Ursprung
Commit
675127b095
2 geänderte Dateien mit 77 neuen und 1 gelöschten Zeilen
  1. 23 1
      SquiLu-ext/sq_socket.cpp
  2. 54 0
      SquiLu/samples/test-tcp-virtual-ip.nut

+ 23 - 1
SquiLu-ext/sq_socket.cpp

@@ -47,13 +47,35 @@ static int opt_meth_setoption(HSQUIRRELVM v, p_opt opt, p_socket ps)
     return opt->func(v, ps);
 }
 
+#ifdef linux
+#include <linux/if.h>
+#include <sys/ioctl.h>
+#endif
+
 /* enables reuse of local address */
 static int opt_bindtodevice(HSQUIRRELVM v, p_socket ps)
 {
     SQ_FUNC_VARS_NO_TOP(v);
     if(sq_gettype(v, 3) != OT_STRING) return sq_throwerror(v, _SC("string expected as parameter 2"));
     SQ_GET_STRING(v, 3, device);
-    return opt_set(v, ps, SOL_SOCKET, SO_BINDTODEVICE, (void *)device, device_size+1);
+#ifdef linux
+	struct ifreq ifr;
+
+    if(device_size >= IFNAMSIZ) {
+        return sq_throwerror(v, _SC("interface name %s too long"), device);
+    }
+	memset(&ifr, 0, sizeof(ifr));	// see man 2 bind why needed
+	strncpy(ifr.ifr_name, device, IFNAMSIZ);
+	if (-1 == ioctl(*ps, SIOCGIFADDR, &ifr)) {
+		return sq_throwerror(v, _SC("ioctl failed"));
+	}
+	if (-1 == bind(*ps, &ifr.ifr_addr, sizeof(ifr))) {
+		return sq_throwerror(v, _SC("bind to interface %s failed"), device);
+	}
+	return 0;
+#else
+    return sq_throwerror(v, _SC("bind to interface not supported"));
+#endif
 }
 
 /* enables reuse of local address */

+ 54 - 0
SquiLu/samples/test-tcp-virtual-ip.nut

@@ -0,0 +1,54 @@
+function download(host, file, extra_header=null, device=null){
+	local sock = socket.tcp();
+	if(device)
+	{
+		print(device);
+		try
+		{
+			sock.setoption("bindtodevice", device); //requires root privileges
+		}
+		catch(e)
+		{}
+	}
+	sock.connect(host, 8070);
+	local info = sock.getpeername()
+	print(info.address, info.port);
+	//sock.settimeout(1);
+
+	local count = 0;    // counts number of bytes read
+	local req = "GET " + file + " HTTP/1.1\r\nHost: " + host + "\r\n";
+	if (extra_header) req += extra_header + "\r\n";
+	req += "\r\n";
+	print(req, req.len());
+	sock.send(req);
+	local s, rc;
+	local tbl = {};
+	local len = 0;
+	while (true){
+		rc = sock.receive("*l");
+		s = rc[0];
+		print("s", s, rc[1]);
+		//if err == "closed" then break end
+		if (s.len() == 0) break;
+		//if (rc[1] == socket.IO_CLOSED) break;
+		local slen;
+		s.gmatch("Content%-Length: (%d+)", function(m){ slen=m; return false;});
+		if (slen) {
+			len = slen.tointeger();
+		}
+	}
+	rc = sock.receive(len);
+	s = rc[0];
+	sock.close();
+	//print(file, count)
+	return s;
+}
+
+local page;
+
+for(local i=70; i<=80; ++i)
+{
+	page = download("10.10.6.4", "/", null, "eth0:" + i);
+}
+//local page = download("www.google.co.uk", "/");
+print(page);