3 * PACrunner - Proxy configuration daemon
5 * Copyright (C) 2010-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <sys/ioctl.h>
32 #include <arpa/inet.h>
33 #include <linux/if_arp.h>
35 #pragma GCC diagnostic ignored "-Wredundant-decls"
37 #pragma GCC diagnostic error "-Wredundant-decls"
39 #include "javascript.h"
41 #include "pacrunner.h"
44 static GStaticMutex mozjs_mutex = G_STATIC_MUTEX_INIT;
46 static struct pacrunner_proxy *current_proxy = NULL;
48 static int getaddr(const char *node, char *host, size_t hostlen)
50 struct sockaddr_in addr;
54 sk = socket(PF_INET, SOCK_DGRAM, 0);
58 memset(&ifr, 0, sizeof(ifr));
59 strncpy(ifr.ifr_name, node, sizeof(ifr.ifr_name));
61 err = ioctl(sk, SIOCGIFADDR, &ifr);
68 memcpy(&addr, &ifr.ifr_addr, sizeof(addr));
69 snprintf(host, hostlen, "%s", inet_ntoa(addr.sin_addr));
74 static int resolve(const char *node, char *host, size_t hostlen)
76 struct addrinfo *info;
79 if (getaddrinfo(node, NULL, NULL, &info) < 0)
82 err = getnameinfo(info->ai_addr, info->ai_addrlen,
83 host, hostlen, NULL, 0, NI_NUMERICHOST);
93 static JSBool myipaddress(JSContext *ctx, uintN argc, jsval *vp)
95 const char *interface;
96 char address[NI_MAXHOST];
100 JS_SET_RVAL(ctx, vp, JSVAL_NULL);
102 if (current_proxy == NULL)
105 interface = pacrunner_proxy_get_interface(current_proxy);
106 if (interface == NULL)
109 if (getaddr(interface, address, sizeof(address)) < 0)
112 DBG("address %s", address);
114 JS_SET_RVAL(ctx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(ctx, address)));
119 static JSBool dnsresolve(JSContext *ctx, uintN argc, jsval *vp)
121 char address[NI_MAXHOST];
122 jsval *argv = JS_ARGV(ctx, vp);
123 char *host = JS_EncodeString(ctx, JS_ValueToString(ctx, argv[0]));
125 DBG("host %s", host);
127 JS_SET_RVAL(ctx, vp, JSVAL_NULL);
129 if (resolve(host, address, sizeof(address)) < 0)
132 DBG("address %s", address);
134 JS_SET_RVAL(ctx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(ctx, address)));
142 static JSClass jscls = {
143 "global", JSCLASS_GLOBAL_FLAGS,
144 JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
145 JS_StrictPropertyStub,
146 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
147 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
150 static JSRuntime *jsrun;
151 static JSContext *jsctx = NULL;
152 static JSObject *jsobj = NULL;
154 static void create_object(void)
159 if (current_proxy == NULL)
162 script = pacrunner_proxy_get_script(current_proxy);
166 jsctx = JS_NewContext(jsrun, 8 * 1024);
168 #if JS_VERSION >= 185
169 jsobj = JS_NewCompartmentAndGlobalObject(jsctx, &jscls, NULL);
171 jsobj = JS_NewObject(jsctx, &jscls, NULL, NULL);
174 if (!JS_InitStandardClasses(jsctx, jsobj))
175 pacrunner_error("Failed to init JS standard classes");
177 JS_DefineFunction(jsctx, jsobj, "myIpAddress", myipaddress, 0, 0);
178 JS_DefineFunction(jsctx, jsobj, "dnsResolve", dnsresolve, 1, 0);
180 JS_EvaluateScript(jsctx, jsobj, JAVASCRIPT_ROUTINES,
181 strlen(JAVASCRIPT_ROUTINES), NULL, 0, &rval);
183 JS_EvaluateScript(jsctx, jsobj, script, strlen(script),
184 "wpad.dat", 0, &rval);
187 static void destroy_object(void)
192 JS_DestroyContext(jsctx);
198 static int mozjs_set_proxy(struct pacrunner_proxy *proxy)
200 DBG("proxy %p", proxy);
202 if (current_proxy != NULL)
205 current_proxy = proxy;
207 if (current_proxy != NULL)
213 static char * mozjs_execute(const char *url, const char *host)
217 char *answer, *g_answer;
219 DBG("url %s host %s", url, host);
224 g_static_mutex_lock(&mozjs_mutex);
226 JS_BeginRequest(jsctx);
228 args[0] = STRING_TO_JSVAL(JS_NewStringCopyZ(jsctx, url));
229 args[1] = STRING_TO_JSVAL(JS_NewStringCopyZ(jsctx, host));
231 result = JS_CallFunctionName(jsctx, jsobj, "FindProxyForURL",
234 JS_EndRequest(jsctx);
238 g_static_mutex_unlock(&mozjs_mutex);
241 answer = JS_EncodeString(jsctx, JS_ValueToString(jsctx, rval));
242 g_answer = g_strdup(answer);
243 JS_free(jsctx, answer);
250 static struct pacrunner_js_driver mozjs_driver = {
252 .priority = PACRUNNER_JS_PRIORITY_DEFAULT,
253 .set_proxy = mozjs_set_proxy,
254 .execute = mozjs_execute,
257 static int mozjs_init(void)
261 jsrun = JS_NewRuntime(8 * 1024 * 1024);
263 return pacrunner_js_driver_register(&mozjs_driver);
266 static void mozjs_exit(void)
270 pacrunner_js_driver_unregister(&mozjs_driver);
272 mozjs_set_proxy(NULL);
274 JS_DestroyRuntime(jsrun);
277 PACRUNNER_PLUGIN_DEFINE(mozjs, mozjs_init, mozjs_exit)