Projet

Général

Profil

Télécharger (72 ko) Statistiques
| Branche: | Révision:

univnautes-tools / pfPorts / php55-pfSense-module / files / pfSense.c @ 841c2b6e

1
/*
2
        Copyright (C) 2010 Ermal Lu?i
3
        All rights reserved.
4

    
5
        Redistribution and use in source and binary forms, with or without
6
        modification, are permitted provided that the following conditions are met:
7

    
8
        1. Redistributions of source code must retain the above copyright notice,
9
           this list of conditions and the following disclaimer.
10

    
11
        2. Redistributions in binary form must reproduce the above copyright
12
           notice, this list of conditions and the following disclaimer in the
13
           documentation and/or other materials provided with the distribution.
14

    
15
        THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16
        INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17
        AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18
        AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
19
        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
        ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
        POSSIBILITY OF SUCH DAMAGE.
25

    
26
*/
27

    
28
/*
29

    
30
Functions copied from util.c and modem.c of mpd5 source are protected by
31
this copyright.
32
They are ExclusiveOpenDevice/ExclusiveCloseDevice and
33
OpenSerialDevice.
34

    
35
Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
36

    
37
Subject to the following obligations and disclaimer of warranty,
38
use and redistribution of this software, in source or object code
39
forms, with or without modifications are expressly permitted by
40
Whistle Communications; provided, however, that:   (i) any and
41
all reproductions of the source or object code must include the
42
copyright notice above and the following disclaimer of warranties;
43
and (ii) no rights are granted, in any manner or form, to use
44
Whistle Communications, Inc. trademarks, including the mark "WHISTLE
45
COMMUNICATIONS" on advertising, endorsements, or otherwise except
46
as such appears in the above copyright notice or in the software.
47

    
48
THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS",
49
AND TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS
50
MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED,
51
REGARDING THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND
52
ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
53
PURPOSE, OR NON-INFRINGEMENT.  WHISTLE COMMUNICATIONS DOES NOT
54
WARRANT, GUARANTEE, OR MAKE ANY REPRESENTATIONS REGARDING THE USE
55
OF, OR THE RESULTS OF THE USE OF THIS SOFTWARE IN TERMS OF ITS
56
CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.  IN NO EVENT
57
SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES RESULTING
58
FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING WITHOUT
59
LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
60
PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE
61
GOODS OR SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED
62
AND UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
64
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS
65
IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66

    
67
*/
68

    
69
#define IS_EXT_MODULE
70

    
71
#ifdef HAVE_CONFIG_H
72
#include "config.h"
73
#endif
74

    
75
#include "php.h"
76
#include "php_ini.h"
77
#include "php_pfSense.h"
78

    
79
#include <sys/types.h>
80
#include <sys/socket.h>
81
#include <ifaddrs.h>
82
#include <net/ethernet.h>
83
#include <net/if_types.h>
84
#include <net/if.h>
85
#include <net/if_var.h>
86
#include <net/if_vlan_var.h>
87
#include <net/if_dl.h>
88
#include <net/if_mib.h>
89
#include <net/if_bridgevar.h>
90
#include <netinet/in.h>
91
#include <netinet/in_var.h>
92
#include <net/pfvar.h>
93
#include <net/route.h>
94

    
95
#include <netinet/ip_fw.h>
96
#include <sys/ioctl.h>
97
#include <sys/sysctl.h>
98
#include <netinet/in.h>
99
#include <arpa/inet.h>
100
#include <net/ethernet.h>
101
#include <netinet/if_ether.h>
102

    
103
#include <netgraph/ng_message.h>
104
#include <netgraph/ng_ether.h>
105

    
106
#include <netinet/ip_fw.h>
107

    
108
#include <vm/vm_param.h>
109

    
110
#include <fcntl.h>
111
#include <stdio.h>
112
#include <stdlib.h>
113
#include <unistd.h>
114
#include <strings.h>
115

    
116
#include <glob.h>
117
#include <termios.h>
118
#include <poll.h>
119

    
120
#include <netgraph.h>
121
#include <netdb.h>
122

    
123
int pfSense_dhcpd;
124

    
125
ZEND_DECLARE_MODULE_GLOBALS(pfSense)
126

    
127
static zend_function_entry pfSense_functions[] = {
128
    PHP_FE(pfSense_get_interface_info, NULL)
129
    PHP_FE(pfSense_get_interface_addresses, NULL)
130
    PHP_FE(pfSense_getall_interface_addresses, NULL)
131
    PHP_FE(pfSense_get_interface_stats, NULL)
132
    PHP_FE(pfSense_get_pf_stats, NULL)
133
    PHP_FE(pfSense_get_os_hw_data, NULL)
134
    PHP_FE(pfSense_get_os_kern_data, NULL)
135
    PHP_FE(pfSense_vlan_create, NULL)
136
    PHP_FE(pfSense_interface_rename, NULL)
137
    PHP_FE(pfSense_interface_mtu, NULL)
138
    PHP_FE(pfSense_bridge_add_member, NULL)
139
    PHP_FE(pfSense_bridge_del_member, NULL)
140
    PHP_FE(pfSense_bridge_member_flags, NULL)
141
    PHP_FE(pfSense_interface_listget, NULL)
142
    PHP_FE(pfSense_interface_create, NULL)
143
    PHP_FE(pfSense_interface_destroy, NULL)
144
    PHP_FE(pfSense_interface_flags, NULL)
145
    PHP_FE(pfSense_interface_capabilities, NULL)
146
    PHP_FE(pfSense_interface_setaddress, NULL)
147
    PHP_FE(pfSense_interface_deladdress, NULL)
148
    PHP_FE(pfSense_ngctl_name, NULL)
149
    PHP_FE(pfSense_ngctl_attach, NULL)
150
    PHP_FE(pfSense_ngctl_detach, NULL)
151
    PHP_FE(pfSense_get_modem_devices, NULL)
152
    PHP_FE(pfSense_sync, NULL)
153
    PHP_FE(pfSense_kill_states, NULL)
154
    PHP_FE(pfSense_kill_srcstates, NULL)
155
    PHP_FE(pfSense_ip_to_mac, NULL)
156
#ifdef DHCP_INTEGRATION
157
    PHP_FE(pfSense_open_dhcpd, NULL)
158
    PHP_FE(pfSense_close_dhcpd, NULL)
159
    PHP_FE(pfSense_register_lease, NULL)
160
    PHP_FE(pfSense_delete_lease, NULL)
161
#endif
162
#ifdef IPFW_FUNCTIONS
163
   PHP_FE(pfSense_ipfw_getTablestats, NULL)
164
   PHP_FE(pfSense_ipfw_Tableaction, NULL)
165
   PHP_FE(pfSense_pipe_action, NULL)
166
#endif
167
    {NULL, NULL, NULL}
168
};
169

    
170
zend_module_entry pfSense_module_entry = {
171
#if ZEND_MODULE_API_NO >= 20010901
172
    STANDARD_MODULE_HEADER,
173
#endif
174
    PHP_PFSENSE_WORLD_EXTNAME,
175
    pfSense_functions,
176
    PHP_MINIT(pfSense_socket),
177
    PHP_MSHUTDOWN(pfSense_socket_close),
178
    NULL,
179
    NULL,
180
    NULL,
181
#if ZEND_MODULE_API_NO >= 20010901
182
    PHP_PFSENSE_WORLD_VERSION,
183
#endif
184
    STANDARD_MODULE_PROPERTIES
185
};
186

    
187
#ifdef COMPILE_DL_PFSENSE
188
ZEND_GET_MODULE(pfSense)
189
#endif
190

    
191
#ifdef DHCP_INTEGRATION
192
static void
193
php_pfSense_destroy_dhcpd(zend_rsrc_list_entry *rsrc TSRMLS_DC)
194
{
195
	omapi_data *conn = (omapi_data *)rsrc->ptr;
196

    
197
	if (conn)
198
		efree(conn);
199
}
200
#endif
201

    
202
/* interface management code */
203
static int
204
pfi_get_ifaces(int dev, const char *filter, struct pfi_kif *buf, int *size)
205
{
206
	struct pfioc_iface io;
207
	caddr_t buff[sizeof(struct pfi_kif) + 1] = { 0 };
208

    
209
	bzero(&io, sizeof io);
210
	if (filter != NULL)
211
		if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >=
212
		    sizeof(io.pfiio_name)) {
213
			errno = EINVAL;
214
			return (-1);
215
		}
216
	io.pfiio_buffer = buf;
217
	io.pfiio_esize = sizeof(struct pfi_kif);
218
	io.pfiio_size = *size;
219
	if (ioctl(dev, DIOCIGETIFACES, &io))
220
		return (-1);
221
	*size = io.pfiio_size;
222
	return (0);
223
}
224

    
225
/* returns prefixlen, obtained from sbin/ifconfig/af_inet6.c */
226
static int
227
prefix(void *val, int size)
228
{
229
	u_char *name = (u_char *)val;
230
	int byte, bit, plen = 0;
231

    
232
	for (byte = 0; byte < size; byte++, plen += 8)
233
		if (name[byte] != 0xff)
234
			break;
235
	if (byte == size)
236
		return (plen);
237
	for (bit = 7; bit != 0; bit--, plen++)
238
		if (!(name[byte] & (1 << bit)))
239
			break;
240
	for (; bit != 0; bit--)
241
		if (name[byte] & (1 << bit))
242
			return(0);
243
	byte++;
244
	for (; byte < size; byte++)
245
		if (name[byte])
246
			return(0);
247
	return (plen);
248
}
249

    
250
PHP_MINIT_FUNCTION(pfSense_socket)
251
{
252
	int csock;
253

    
254
	PFSENSE_G(s) = socket(AF_LOCAL, SOCK_DGRAM, 0);
255
	if (PFSENSE_G(s) < 0)
256
		return FAILURE;
257

    
258
	PFSENSE_G(inets) = socket(AF_INET, SOCK_DGRAM, 0);
259
	if (PFSENSE_G(inets) < 0) {
260
		close(PFSENSE_G(s));
261
		return FAILURE;
262
	}
263

    
264
	if (geteuid() == 0 || getuid() == 0) {
265
#ifdef IPFW_FUNCTIONS
266
		PFSENSE_G(ipfw) = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
267
		if (PFSENSE_G(ipfw) < 0) {
268
			close(PFSENSE_G(s));
269
			close(PFSENSE_G(inets));
270
			return FAILURE;
271
		} else
272
			fcntl(PFSENSE_G(ipfw), F_SETFD, fcntl(PFSENSE_G(ipfw), F_GETFD, 0) | FD_CLOEXEC);
273
	
274
#endif
275
		/* Create a new socket node */
276
		if (NgMkSockNode(NULL, &csock, NULL) < 0)
277
			csock = -1;
278
		else
279
			fcntl(csock, F_SETFD, fcntl(csock, F_GETFD, 0) | FD_CLOEXEC);
280

    
281
		PFSENSE_G(csock) = csock;
282

    
283
#ifdef DHCP_INTEGRATION
284
		pfSense_dhcpd = zend_register_list_destructors_ex(php_pfSense_destroy_dhcpd, NULL, PHP_PFSENSE_RES_NAME, module_number);
285
		dhcpctl_initialize();
286
		omapi_init();
287
#endif
288
	} else
289
		PFSENSE_G(csock) = -1;
290

    
291
	/* Don't leak these sockets to child processes */
292
	fcntl(PFSENSE_G(s), F_SETFD, fcntl(PFSENSE_G(s), F_GETFD, 0) | FD_CLOEXEC);
293
	fcntl(PFSENSE_G(inets), F_SETFD, fcntl(PFSENSE_G(inets), F_GETFD, 0) | FD_CLOEXEC);
294

    
295
	REGISTER_LONG_CONSTANT("IFF_UP", IFF_UP, CONST_PERSISTENT | CONST_CS);
296
	REGISTER_LONG_CONSTANT("IFF_LINK0", IFF_LINK0, CONST_PERSISTENT | CONST_CS);
297
	REGISTER_LONG_CONSTANT("IFF_LINK1", IFF_LINK1, CONST_PERSISTENT | CONST_CS);
298
	REGISTER_LONG_CONSTANT("IFF_LINK2", IFF_LINK2, CONST_PERSISTENT | CONST_CS);
299
	REGISTER_LONG_CONSTANT("IFF_NOARP", IFF_NOARP, CONST_PERSISTENT | CONST_CS);
300
	REGISTER_LONG_CONSTANT("IFF_STATICARP", IFF_STATICARP, CONST_PERSISTENT | CONST_CS);
301
	REGISTER_LONG_CONSTANT("IFCAP_RXCSUM", IFCAP_RXCSUM, CONST_PERSISTENT | CONST_CS);
302
	REGISTER_LONG_CONSTANT("IFCAP_TXCSUM", IFCAP_TXCSUM, CONST_PERSISTENT | CONST_CS);
303
	REGISTER_LONG_CONSTANT("IFCAP_POLLING", IFCAP_POLLING, CONST_PERSISTENT | CONST_CS);
304
	REGISTER_LONG_CONSTANT("IFCAP_TSO", IFCAP_TSO, CONST_PERSISTENT | CONST_CS);
305
	REGISTER_LONG_CONSTANT("IFCAP_LRO", IFCAP_LRO, CONST_PERSISTENT | CONST_CS);
306
	REGISTER_LONG_CONSTANT("IFCAP_WOL", IFCAP_WOL, CONST_PERSISTENT | CONST_CS);
307
	REGISTER_LONG_CONSTANT("IFCAP_WOL_UCAST", IFCAP_WOL_UCAST, CONST_PERSISTENT | CONST_CS);
308
	REGISTER_LONG_CONSTANT("IFCAP_WOL_MCAST", IFCAP_WOL_MCAST, CONST_PERSISTENT | CONST_CS);
309
	REGISTER_LONG_CONSTANT("IFCAP_WOL_MAGIC", IFCAP_WOL_MAGIC, CONST_PERSISTENT | CONST_CS);
310

    
311
	REGISTER_LONG_CONSTANT("IFCAP_VLAN_HWTAGGING", IFCAP_VLAN_HWTAGGING, CONST_PERSISTENT | CONST_CS);
312
	REGISTER_LONG_CONSTANT("IFCAP_VLAN_MTU", IFCAP_VLAN_MTU, CONST_PERSISTENT | CONST_CS);
313
	REGISTER_LONG_CONSTANT("IFCAP_VLAN_HWFILTER", IFCAP_VLAN_HWFILTER, CONST_PERSISTENT | CONST_CS);
314
#ifdef IFCAP_VLAN_HWCSUM
315
	REGISTER_LONG_CONSTANT("IFCAP_VLAN_HWCSUM", IFCAP_VLAN_HWCSUM, CONST_PERSISTENT | CONST_CS);
316
#endif
317
#ifdef IFCAP_VLAN_HWTSO
318
	REGISTER_LONG_CONSTANT("IFCAP_VLAN_HWTSO", IFCAP_VLAN_HWTSO, CONST_PERSISTENT | CONST_CS);
319
#endif
320

    
321
	REGISTER_LONG_CONSTANT("IFBIF_LEARNING", IFBIF_LEARNING, CONST_PERSISTENT | CONST_CS);
322
	REGISTER_LONG_CONSTANT("IFBIF_DISCOVER", IFBIF_DISCOVER, CONST_PERSISTENT | CONST_CS);
323
	REGISTER_LONG_CONSTANT("IFBIF_STP", IFBIF_STP, CONST_PERSISTENT | CONST_CS);
324
	REGISTER_LONG_CONSTANT("IFBIF_SPAN", IFBIF_SPAN, CONST_PERSISTENT | CONST_CS);
325
	REGISTER_LONG_CONSTANT("IFBIF_STICKY", IFBIF_STICKY, CONST_PERSISTENT | CONST_CS);
326
	REGISTER_LONG_CONSTANT("IFBIF_BSTP_EDGE", IFBIF_BSTP_EDGE, CONST_PERSISTENT | CONST_CS);
327
	REGISTER_LONG_CONSTANT("IFBIF_BSTP_AUTOEDGE", IFBIF_BSTP_AUTOEDGE, CONST_PERSISTENT | CONST_CS);
328
	REGISTER_LONG_CONSTANT("IFBIF_BSTP_PTP", IFBIF_BSTP_PTP, CONST_PERSISTENT | CONST_CS);
329
	REGISTER_LONG_CONSTANT("IFBIF_BSTP_AUTOPTP", IFBIF_BSTP_AUTOPTP, CONST_PERSISTENT | CONST_CS);
330
	REGISTER_LONG_CONSTANT("IFBIF_BSTP_ADMEDGE", IFBIF_BSTP_ADMEDGE, CONST_PERSISTENT | CONST_CS);
331
	REGISTER_LONG_CONSTANT("IFBIF_BSTP_ADMCOST", IFBIF_BSTP_ADMCOST, CONST_PERSISTENT | CONST_CS);
332
	REGISTER_LONG_CONSTANT("IFBIF_PRIVATE", IFBIF_PRIVATE, CONST_PERSISTENT | CONST_CS);
333

    
334
#ifdef IPFW_FUNCTIONS
335
#if (__FreeBSD_version >= 1000000)
336
	REGISTER_LONG_CONSTANT("IP_FW_TABLE_XADD", IP_FW_TABLE_XADD, CONST_PERSISTENT | CONST_CS);
337
	REGISTER_LONG_CONSTANT("IP_FW_TABLE_XDEL", IP_FW_TABLE_XDEL, CONST_PERSISTENT | CONST_CS);
338
	REGISTER_LONG_CONSTANT("IP_FW_TABLE_XZEROENTRY", IP_FW_TABLE_XZEROENTRY, CONST_PERSISTENT | CONST_CS);
339
#else
340
	REGISTER_LONG_CONSTANT("IP_FW_TABLE_ADD", IP_FW_TABLE_ADD, CONST_PERSISTENT | CONST_CS);
341
	REGISTER_LONG_CONSTANT("IP_FW_TABLE_DEL", IP_FW_TABLE_DEL, CONST_PERSISTENT | CONST_CS);
342
	REGISTER_LONG_CONSTANT("IP_FW_TABLE_ZERO_ENTRY_STATS", IP_FW_TABLE_ZERO_ENTRY_STATS, CONST_PERSISTENT | CONST_CS);
343
#endif
344
#endif
345

    
346
	return SUCCESS;
347
}
348

    
349
PHP_MSHUTDOWN_FUNCTION(pfSense_socket_close)
350
{
351
	if (PFSENSE_G(csock) != -1)
352
		close(PFSENSE_G(csock));
353
	if (PFSENSE_G(inets) != -1)
354
		close(PFSENSE_G(inets));
355
	if (PFSENSE_G(s) != -1)
356
		close(PFSENSE_G(s));
357

    
358
	return SUCCESS;
359
}
360

    
361
static int
362
pfctl_addrprefix(char *addr, struct pf_addr *mask)
363
{
364
	char *p;
365
	const char *errstr;
366
	int prefix, ret_ga, q, r;
367
	struct addrinfo hints, *res;
368

    
369
	if ((p = strchr(addr, '/')) == NULL)
370
		return 0;
371

    
372
	*p++ = '\0';
373
	prefix = strtonum(p, 0, 128, &errstr);
374
	if (errstr) {
375
		php_printf("prefix is %s: %s", errstr, p);
376
		return (-1);
377
	}
378

    
379
	bzero(&hints, sizeof(hints));
380
	/* prefix only with numeric addresses */
381
	hints.ai_flags |= AI_NUMERICHOST;
382

    
383
	if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) {
384
		php_printf("getaddrinfo: %s", gai_strerror(ret_ga));
385
		return (-1);
386
		/* NOTREACHED */
387
	}
388

    
389
	if (res->ai_family == AF_INET && prefix > 32) {
390
		php_printf("prefix too long for AF_INET");
391
		return (-1);
392
	} else if (res->ai_family == AF_INET6 && prefix > 128) {
393
		php_printf("prefix too long for AF_INET6");
394
		return (-1);
395
	}
396

    
397
	q = prefix >> 3;
398
	r = prefix & 7;
399
	switch (res->ai_family) {
400
	case AF_INET:
401
		bzero(&mask->v4, sizeof(mask->v4));
402
		mask->v4.s_addr = htonl((u_int32_t)
403
		    (0xffffffffffULL << (32 - prefix)));
404
		break;
405
	case AF_INET6:
406
		bzero(&mask->v6, sizeof(mask->v6));
407
		if (q > 0)
408
			memset((void *)&mask->v6, 0xff, q);
409
		if (r > 0)
410
			*((u_char *)&mask->v6 + q) =
411
			    (0xff00 >> r) & 0xff;
412
		break;
413
	}
414
	freeaddrinfo(res);
415

    
416
	return (0);
417
}
418

    
419
PHP_FUNCTION(pfSense_kill_srcstates)
420
{
421
	struct pfioc_src_node_kill psnk;
422
	struct addrinfo *res[2], *resp[2];
423
	struct sockaddr last_src, last_dst;
424
	int killed, sources, dests;
425
	int ret_ga;
426

    
427
        int dev;
428
	char *ip1 = NULL, *ip2 = NULL;
429
	int ip1_len = 0, ip2_len = 0;
430

    
431
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &ip1, &ip1_len, &ip2, &ip2_len) == FAILURE) {
432
		RETURN_NULL();
433
	}
434

    
435
	if ((dev = open("/dev/pf", O_RDWR)) < 0)
436
		RETURN_NULL();
437

    
438
	killed = sources = dests = 0;
439

    
440
	memset(&psnk, 0, sizeof(psnk));
441
	memset(&psnk.psnk_src.addr.v.a.mask, 0xff,
442
	    sizeof(psnk.psnk_src.addr.v.a.mask));
443
	memset(&last_src, 0xff, sizeof(last_src));
444
	memset(&last_dst, 0xff, sizeof(last_dst));
445

    
446
	pfctl_addrprefix(ip1, &psnk.psnk_src.addr.v.a.mask);
447

    
448
	if ((ret_ga = getaddrinfo(ip1, NULL, NULL, &res[0]))) {
449
		php_printf("getaddrinfo: %s", gai_strerror(ret_ga));
450
		RETURN_NULL();
451
		/* NOTREACHED */
452
	}
453
	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
454
		if (resp[0]->ai_addr == NULL)
455
			continue;
456
		/* We get lots of duplicates.  Catch the easy ones */
457
		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
458
			continue;
459
		last_src = *(struct sockaddr *)resp[0]->ai_addr;
460

    
461
		psnk.psnk_af = resp[0]->ai_family;
462
		sources++;
463

    
464
		if (psnk.psnk_af == AF_INET)
465
			psnk.psnk_src.addr.v.a.addr.v4 =
466
			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
467
		else if (psnk.psnk_af == AF_INET6)
468
			psnk.psnk_src.addr.v.a.addr.v6 =
469
			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
470
			    sin6_addr;
471
		else {
472
			php_printf("Unknown address family %d", psnk.psnk_af);
473
			continue;
474
		}
475

    
476
		if (ip2 != NULL) {
477
			dests = 0;
478
			memset(&psnk.psnk_dst.addr.v.a.mask, 0xff,
479
			    sizeof(psnk.psnk_dst.addr.v.a.mask));
480
			memset(&last_dst, 0xff, sizeof(last_dst));
481
			pfctl_addrprefix(ip2,
482
			    &psnk.psnk_dst.addr.v.a.mask);
483
			if ((ret_ga = getaddrinfo(ip2, NULL, NULL,
484
			    &res[1]))) {
485
				php_printf("getaddrinfo: %s", gai_strerror(ret_ga));
486
				break;
487
			}
488
			for (resp[1] = res[1]; resp[1];
489
			    resp[1] = resp[1]->ai_next) {
490
				if (resp[1]->ai_addr == NULL)
491
					continue;
492
				if (psnk.psnk_af != resp[1]->ai_family)
493
					continue;
494

    
495
				if (memcmp(&last_dst, resp[1]->ai_addr,
496
				    sizeof(last_dst)) == 0)
497
					continue;
498
				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
499

    
500
				dests++;
501

    
502
				if (psnk.psnk_af == AF_INET)
503
					psnk.psnk_dst.addr.v.a.addr.v4 =
504
					    ((struct sockaddr_in *)resp[1]->
505
					    ai_addr)->sin_addr;
506
				else if (psnk.psnk_af == AF_INET6)
507
					psnk.psnk_dst.addr.v.a.addr.v6 =
508
					    ((struct sockaddr_in6 *)resp[1]->
509
					    ai_addr)->sin6_addr;
510
				else {
511
					php_printf("Unknown address family %d",
512
					    psnk.psnk_af);
513
					continue;
514
				}
515

    
516
				if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
517
					php_printf("DIOCKILLSRCNODES");
518
				killed += psnk.psnk_af;
519
				/* fixup psnk.psnk_af */
520
				psnk.psnk_af = resp[1]->ai_family;
521
			}
522
			freeaddrinfo(res[1]);
523
		} else {
524
			if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) {
525
				php_printf("DIOCKILLSRCNODES");
526
				break;
527
			}
528
			killed += psnk.psnk_af;
529
			/* fixup psnk.psnk_af */
530
			psnk.psnk_af = res[0]->ai_family;
531
		}
532
	}
533

    
534
	freeaddrinfo(res[0]);
535

    
536
	RETURN_TRUE;
537
}
538

    
539
PHP_FUNCTION(pfSense_kill_states)
540
{
541
	struct pfioc_state_kill psk;
542
	struct addrinfo *res[2], *resp[2];
543
	struct sockaddr last_src, last_dst;
544
	int killed, sources, dests;
545
	int ret_ga;
546

    
547
	int dev;
548
	char *ip1 = NULL, *ip2 = NULL;
549
	int ip1_len = 0, ip2_len = 0;
550

    
551
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &ip1, &ip1_len, &ip2, &ip2_len) == FAILURE) {
552
		RETURN_NULL();
553
	}
554

    
555
	if ((dev = open("/dev/pf", O_RDWR)) < 0)
556
		RETURN_NULL();
557

    
558
	killed = sources = dests = 0;
559

    
560
	memset(&psk, 0, sizeof(psk));
561
	memset(&psk.psk_src.addr.v.a.mask, 0xff,
562
	    sizeof(psk.psk_src.addr.v.a.mask));
563
	memset(&last_src, 0xff, sizeof(last_src));
564
	memset(&last_dst, 0xff, sizeof(last_dst));
565
#if 0
566
	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
567
	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
568
		errx(1, "invalid interface: %s", iface);
569
#endif
570

    
571
	if (pfctl_addrprefix(ip1, &psk.psk_src.addr.v.a.mask) < 0)
572
		RETURN_NULL();
573

    
574
	if ((ret_ga = getaddrinfo(ip1, NULL, NULL, &res[0]))) {
575
		php_printf("getaddrinfo: %s", gai_strerror(ret_ga));
576
		RETURN_NULL();
577
		/* NOTREACHED */
578
	}
579
	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
580
		if (resp[0]->ai_addr == NULL)
581
			continue;
582
		/* We get lots of duplicates.  Catch the easy ones */
583
		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
584
			continue;
585
		last_src = *(struct sockaddr *)resp[0]->ai_addr;
586

    
587
		psk.psk_af = resp[0]->ai_family;
588
		sources++;
589

    
590
		if (psk.psk_af == AF_INET)
591
			psk.psk_src.addr.v.a.addr.v4 =
592
			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
593
		else if (psk.psk_af == AF_INET6)
594
			psk.psk_src.addr.v.a.addr.v6 =
595
			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
596
			    sin6_addr;
597
		else {
598
			php_printf("Unknown address family %d", psk.psk_af);
599
			continue;
600
		}
601

    
602
		if (ip2 != NULL) {
603
			dests = 0;
604
			memset(&psk.psk_dst.addr.v.a.mask, 0xff,
605
			    sizeof(psk.psk_dst.addr.v.a.mask));
606
			memset(&last_dst, 0xff, sizeof(last_dst));
607
			pfctl_addrprefix(ip2,
608
			    &psk.psk_dst.addr.v.a.mask);
609
			if ((ret_ga = getaddrinfo(ip2, NULL, NULL,
610
			    &res[1]))) {
611
				php_printf("getaddrinfo: %s",
612
				    gai_strerror(ret_ga));
613
				break;
614
				/* NOTREACHED */
615
			}
616
			for (resp[1] = res[1]; resp[1];
617
			    resp[1] = resp[1]->ai_next) {
618
				if (resp[1]->ai_addr == NULL)
619
					continue;
620
				if (psk.psk_af != resp[1]->ai_family)
621
					continue;
622

    
623
				if (memcmp(&last_dst, resp[1]->ai_addr,
624
				    sizeof(last_dst)) == 0)
625
					continue;
626
				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
627

    
628
				dests++;
629

    
630
				if (psk.psk_af == AF_INET)
631
					psk.psk_dst.addr.v.a.addr.v4 =
632
					    ((struct sockaddr_in *)resp[1]->
633
					    ai_addr)->sin_addr;
634
				else if (psk.psk_af == AF_INET6)
635
					psk.psk_dst.addr.v.a.addr.v6 =
636
					    ((struct sockaddr_in6 *)resp[1]->
637
					    ai_addr)->sin6_addr;
638
				else {
639
					php_printf("Unknown address family %d", psk.psk_af);
640
					continue;
641
				}
642

    
643
				if (ioctl(dev, DIOCKILLSTATES, &psk))
644
					php_printf("Could not kill states\n");
645
				killed += psk.psk_af;
646
				/* fixup psk.psk_af */
647
				psk.psk_af = resp[1]->ai_family;
648
			}
649
			freeaddrinfo(res[1]);
650
		} else {
651
			if (ioctl(dev, DIOCKILLSTATES, &psk)) {
652
				php_printf("Could not kill states\n");
653
				break;
654
			}
655
			killed += psk.psk_af;
656
			/* fixup psk.psk_af */
657
			psk.psk_af = res[0]->ai_family;
658
		}
659
	}
660

    
661
	freeaddrinfo(res[0]);
662

    
663
	RETURN_TRUE;
664
}
665

    
666
#ifdef IPFW_FUNCTIONS
667
/* Stolen from ipfw2.c code */
668
static unsigned long long
669
pfSense_align_uint64(const uint64_t *pll)
670
{
671
	uint64_t ret;
672

    
673
	bcopy (pll, &ret, sizeof(ret));
674
	return ret;
675
}
676

    
677
PHP_FUNCTION(pfSense_pipe_action)
678
{
679
	int ac, do_pipe = 1, param_len = 0;
680
	enum { bufsize = 2048 };
681
	char **ap, *av[bufsize], *param = NULL;
682

    
683
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &param, &param_len) == FAILURE) {
684
		RETURN_FALSE;
685
	}
686

    
687
	memset(av, 0, sizeof(av));
688
	ac = 0;
689
	for (ap = av; (*ap = strsep(&param, " \t")) != NULL;) {
690
		if (**ap != '\0') {
691
			if (++ap >= &av[bufsize])
692
				break;
693
		}
694
		ac++;
695
	}
696
	if (ac > 0)
697
		ac = ac - 1;
698

    
699
	if (!strncmp(*av, "pipe", strlen(*av)))
700
		do_pipe = 1;
701
	else if (!strncmp(*av, "queue", strlen(*av)))
702
		do_pipe = 2;
703
	else if (!strncmp(*av, "flowset", strlen(*av)))
704
		do_pipe = 2;
705
	else if (!strncmp(*av, "sched", strlen(*av)))
706
		do_pipe = 3;
707
	else
708
		RETURN_FALSE;
709

    
710
	ap = av;
711
	ac--;
712
	ap++;
713

    
714
	if (!strncmp(*ap, "delete", strlen(*ap))) {
715
		ipfw_delete_pipe(do_pipe, strtol(ap[1], NULL, 10));
716
	} else if (!strncmp(ap[1], "config", strlen(ap[1]))) {
717
		/*
718
		 * For pipes, queues and nats we normally say 'nat|pipe NN config'
719
		 * but the code is easier to parse as 'nat|pipe config NN'
720
		 * so we swap the two arguments.
721
		 */
722
		if (ac > 1 && isdigit(*ap[0])) {
723
			char *p = ap[0];
724

    
725
			ap[0] = ap[1];
726
			ap[1] = p;
727
		}
728

    
729
		if (ipfw_config_pipe(ac, ap, do_pipe) < 0) {
730
			RETURN_FALSE;
731
		}
732
	} else
733
		RETURN_FALSE;
734

    
735
	RETURN_TRUE;
736
}
737

    
738
PHP_FUNCTION(pfSense_ipfw_Tableaction)
739
{
740
#if (__FreeBSD_version >= 1000000)
741
	ip_fw3_opheader *op3;
742
	ipfw_table_xentry *xent;
743
	socklen_t size;
744
	long mask = 0, table = 0, pipe = 0, zone = 0;
745
	char *ip, *mac = NULL, *p;
746
	int ip_len, mac_len = 0;
747
	long action = IP_FW_TABLE_ADD;
748
	int err;
749

    
750
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llls|l!sl", &zone, &action, &table, &ip, &ip_len, &mask, &mac, &mac_len, &pipe) == FAILURE) {
751
		RETURN_FALSE;
752
	}
753

    
754
	if (action != IP_FW_TABLE_XDEL && action != IP_FW_TABLE_XADD && action != IP_FW_TABLE_XZEROENTRY)
755
		RETURN_FALSE;
756

    
757
	if ((op3 = emalloc(sizeof(*op3) + sizeof(*xent))) == NULL)
758
		RETURN_FALSE;
759

    
760
	memset(op3, 0, sizeof(*op3));
761
	op3->ctxid = (uint16_t)zone;
762
	op3->opcode = action;
763
	xent = (ipfw_table_xentry *)(op3 + 1);
764
	memset(xent, 0, sizeof(*xent));
765
	xent->tbl = (u_int16_t)table;
766

    
767
	if (strchr(ip, ':')) {
768
		if (!inet_pton(AF_INET6, ip, &xent->k.addr6)) {
769
			efree(op3);
770
			RETURN_FALSE;
771
		}
772
	} else if (!inet_pton(AF_INET, ip, &xent->k.addr6)) {
773
		efree(op3);
774
		RETURN_FALSE;
775
	} else {
776
		efree(op3);
777
		RETURN_FALSE;
778
	}
779

    
780
	if (!strchr(ip, ':'))
781
		xent->flags = IPFW_TCF_INET;
782

    
783
	if (mask)
784
		xent->masklen = (u_int8_t)mask;
785
	else
786
		xent->masklen = 32;
787

    
788
	if (pipe)
789
		xent->value = (u_int32_t)pipe;
790

    
791
	if (mac_len > 0) {
792
		if (ether_aton_r(mac, (struct ether_addr *)&xent->mac_addr) == NULL) {
793
			efree(op3);
794
			RETURN_FALSE;
795
		}
796
		//xent->masklen += ETHER_ADDR_LEN;
797
	}
798

    
799
	xent->type = IPFW_TABLE_CIDR;
800
	size = sizeof(*op3) + sizeof(*xent);
801
	err = setsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW3, op3, size);
802
	if (err < 0 && err != EEXIST) {
803
		efree(op3);
804
		RETURN_FALSE;
805
	}
806
	efree(op3);
807

    
808
	RETURN_TRUE;
809
#else
810
	struct {
811
		char context[64]; /* IP_FW_CTX_MAXNAME */
812
		ipfw_table_entry ent;
813
	} option;
814
	socklen_t size;
815
	long mask = 0, table = 0, pipe = 0;
816
	char *ip, *zone, *mac = NULL, *p;
817
	int ip_len, zone_len, mac_len = 0;
818
	long action = IP_FW_TABLE_ADD;
819
	int err;
820

    
821
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slls|l!sl", &zone, &zone_len, &action, &table, &ip, &ip_len, &mask, &mac, &mac_len, &pipe) == FAILURE) {
822
		RETURN_FALSE;
823
	}
824

    
825
	memset(&option, 0, sizeof(option));
826
	sprintf(option.context, "%s", zone);
827

    
828

    
829
	if (action != IP_FW_TABLE_DEL && action != IP_FW_TABLE_ADD && action != IP_FW_TABLE_ZERO_ENTRY_STATS)
830
		RETURN_FALSE;
831

    
832
	if (strchr(ip, ':')) {
833
		if (!inet_pton(AF_INET6, ip, &option.ent.addr))
834
			RETURN_FALSE;
835
	} else if (!inet_pton(AF_INET, ip, &option.ent.addr)) {
836
		RETURN_FALSE;
837
	}
838

    
839
	if (mask)
840
		option.ent.masklen = (u_int8_t)mask;
841
	else
842
		option.ent.masklen = 32;
843
	if (pipe)
844
		option.ent.value = (u_int32_t)pipe;
845

    
846
	if (mac_len > 0) {
847
		if (ether_aton_r(mac, (struct ether_addr *)&option.ent.mac_addr) == NULL)
848
			RETURN_FALSE;
849
	}
850
	size = sizeof(option);
851
	option.ent.tbl = (u_int16_t)table;
852
	err = setsockopt(PFSENSE_G(ipfw), IPPROTO_IP, (int)action, &option, size);
853
	if (err < 0 && err != EEXIST)
854
		RETURN_FALSE;
855

    
856
	RETURN_TRUE;
857
#endif
858
}
859

    
860
PHP_FUNCTION(pfSense_ipfw_getTablestats)
861
{
862
#if (__FreeBSD_version >= 1000000)
863
	ip_fw3_opheader *op3;
864
	ipfw_table_xentry *xent;
865
	socklen_t size;
866
	long mask = 0, table = 0, zone = 0;
867
	char *ip, *mac = NULL, *p;
868
	int ip_len, mac_len = 0;
869
	long action = IP_FW_TABLE_ADD;
870
	int err;
871

    
872
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llls!s|l", &zone, &action, &table, &ip, &ip_len, &mac, &mac_len, &mask) == FAILURE) {
873
		RETURN_FALSE;
874
	}
875

    
876
	if (action != IP_FW_TABLE_XLISTENTRY)
877
		RETURN_FALSE;
878

    
879
	if ((op3 = emalloc(sizeof(*op3) + sizeof(*xent))) == NULL)
880
		RETURN_FALSE;
881

    
882
	memset(op3, 0, sizeof(*op3));
883
	op3->ctxid = (uint16_t)zone;
884
	op3->opcode = IP_FW_TABLE_XLISTENTRY;
885
	xent = (ipfw_table_xentry *)(op3 + 1);
886
	memset(xent, 0, sizeof(*xent));
887
	xent->tbl = (u_int16_t)table;
888

    
889
	if (strchr(ip, ':')) {
890
		if (!inet_pton(AF_INET6, ip, &xent->k.addr6)) {
891
			efree(op3);
892
			RETURN_FALSE;
893
		}
894
	} else if (!inet_pton(AF_INET, ip, &xent->k.addr6)) {
895
		efree(op3);
896
		RETURN_FALSE;
897
	} else {
898
		efree(op3);
899
		RETURN_FALSE;
900
	}
901

    
902
	if (!strchr(ip, ':'))
903
		xent->flags = IPFW_TCF_INET;
904

    
905
	if (mask)
906
		xent->masklen = (u_int8_t)mask;
907
	else
908
		xent->masklen = 32;
909

    
910
	if (mac_len > 0) {
911
		if (ether_aton_r(mac, (struct ether_addr *)&xent->mac_addr) == NULL)
912
			RETURN_FALSE;
913
		//xent->masklen += ETHER_ADDR_LEN;
914
	}
915

    
916
	xent->type = IPFW_TABLE_CIDR;
917
	size = sizeof(*op3) + sizeof(*xent);
918
	if (getsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW3, op3, &size) < 0) {
919
		efree(op3);
920
		RETURN_FALSE;
921
	}
922

    
923
	array_init(return_value);
924
	add_assoc_long(return_value, "packets", pfSense_align_uint64(&xent->packets));
925
	add_assoc_long(return_value, "bytes", pfSense_align_uint64(&xent->bytes));
926
	add_assoc_long(return_value, "timestamp", xent->timestamp);
927
	add_assoc_long(return_value, "dnpipe", xent->value);
928

    
929
	efree(op3);
930
#else
931
	struct {
932
		char context[64]; /* IP_FW_CTX_MAXNAME */
933
		ipfw_table_entry ent;
934
	} option;
935
	socklen_t size;
936
	long mask = 0, table = 0;
937
	char *ip, *name;
938
	int ip_len, name_len;
939

    
940
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|l", &name, &name_len, &table, &ip, &ip_len, &mask) == FAILURE) {
941
		RETURN_FALSE;
942
	}
943

    
944

    
945
	memset(&option, 0, sizeof(option));
946
	sprintf(option.context, "%s", name);
947

    
948
	if (strchr(ip, ':')) {
949
		if (!inet_pton(AF_INET6, ip, &option.ent.addr))
950
			RETURN_FALSE;
951
	} else if (!inet_pton(AF_INET, ip, &option.ent.addr)) {
952
		RETURN_FALSE;
953
	}
954

    
955
	if (mask)
956
		option.ent.masklen = (u_int8_t)mask;
957
	else
958
		option.ent.masklen = 32;
959
	size = sizeof(option);
960
	option.ent.tbl = (u_int16_t)table;
961
	if (getsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW_TABLE_GET_ENTRY, &option, &size) < 0)
962
		RETURN_FALSE;
963

    
964
	array_init(return_value);
965
	add_assoc_long(return_value, "packets", pfSense_align_uint64(&option.ent.packets));
966
	add_assoc_long(return_value, "bytes", pfSense_align_uint64(&option.ent.bytes));
967
	add_assoc_long(return_value, "timestamp", option.ent.timestamp);
968
	add_assoc_long(return_value, "dnpipe", option.ent.value);
969
#endif
970
}
971
#endif
972

    
973
#ifdef DHCP_INTEGRATION
974
PHP_FUNCTION(pfSense_open_dhcpd)
975
{
976
	omapi_data *data;
977
	char *key, *addr, *name;
978
	int key_len, addr_len, name_len;
979
	long port;
980
	dhcpctl_status status;
981
	dhcpctl_handle auth = dhcpctl_null_handle, conn = dhcpctl_null_handle;
982

    
983
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl", &name, &name_len, &key, &key_len, &addr, &addr_len, &port) == FAILURE) {
984
		RETURN_FALSE;
985
	}
986

    
987
	status = dhcpctl_new_authenticator(&auth, name, "hmac-md5", key, key_len);
988
	if (status != ISC_R_SUCCESS) {
989
		//php_printf("Failed to get aythenticator: %s - %s\n", isc_result_totext(status), key);
990
		RETURN_NULL();
991
	}
992

    
993
	status = dhcpctl_connect(&conn, addr, (int)port, auth);
994
	if (status != ISC_R_SUCCESS) {
995
		//php_printf("Error occured during connecting: %s\n", isc_result_totext(status));
996
		RETURN_NULL();
997
	}
998

    
999
	data = emalloc(sizeof(*data));
1000
	data->handle = conn;
1001

    
1002
	ZEND_REGISTER_RESOURCE(return_value, data, pfSense_dhcpd);
1003
}
1004

    
1005
PHP_FUNCTION(pfSense_register_lease)
1006
{
1007
	dhcpctl_status status = ISC_R_SUCCESS;
1008
	dhcpctl_status status2 = ISC_R_SUCCESS;
1009
	dhcpctl_handle hp = NULL;
1010
	struct ether_addr *ds;
1011
	struct in_addr nds;
1012
	char *mac, *ip, *name;
1013
	int mac_len, ip_len, name_len;
1014
	zval *res;
1015
	omapi_data *conn;
1016

    
1017
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zsss", &res, &name, &name_len, &mac, &mac_len, &ip, &ip_len) == FAILURE) {
1018
		RETURN_FALSE;
1019
	}
1020

    
1021
	ZEND_FETCH_RESOURCE(conn, omapi_data *, &res, -1, PHP_PFSENSE_RES_NAME, pfSense_dhcpd);
1022
	ZEND_VERIFY_RESOURCE(conn);
1023

    
1024
	if ((status = dhcpctl_new_object(&hp, conn->handle, "host")) != ISC_R_SUCCESS) {
1025
		//php_printf("1Error occured during connecting: %s\n", isc_result_totext(status));
1026
		RETURN_FALSE;
1027
	}
1028

    
1029
	inet_aton(ip, &nds);
1030
	if ((status = dhcpctl_set_data_value(hp, (char *)&nds, sizeof(struct in_addr), "ip-address")) != ISC_R_SUCCESS) {
1031
		//php_printf("3Error occured during connecting: %s\n", isc_result_totext(status));
1032
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1033
		RETURN_FALSE;
1034
	}
1035

    
1036
	if ((status = dhcpctl_set_string_value(hp, name, "name")) != ISC_R_SUCCESS) {
1037
		//php_printf("4Error occured during connecting: %s\n", isc_result_totext(status));
1038
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1039
		RETURN_FALSE;
1040
	}
1041

    
1042
	if (!(ds = ether_aton(mac)))
1043
		RETURN_FALSE;
1044
	if ((status = dhcpctl_set_data_value(hp, (u_char *)ds, sizeof(struct ether_addr), "hardware-address")) != ISC_R_SUCCESS) {
1045
		//php_printf("2Error occured during connecting: %s\n", isc_result_totext(status));
1046
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1047
		RETURN_FALSE;
1048
	}
1049

    
1050
	if ((status= dhcpctl_set_int_value(hp, 1,"hardware-type")) != ISC_R_SUCCESS)  {
1051
		//php_printf("2Error occured during connecting: %s\n", isc_result_totext(status));
1052
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1053
		RETURN_FALSE;
1054
	}
1055

    
1056
	//php_printf("Coonection handle %d\n", conn->handle);
1057
	if ((status = dhcpctl_open_object(hp, conn->handle, DHCPCTL_CREATE|DHCPCTL_EXCL)) != ISC_R_SUCCESS) {
1058
		//php_printf("5Error occured during connecting: %s\n", isc_result_totext(status));
1059
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1060
		RETURN_FALSE;
1061
	}
1062
        if ((status = dhcpctl_wait_for_completion(hp, &status2)) != ISC_R_SUCCESS) {
1063
		//php_printf("6Error occured during connecting: %s-  %s\n", isc_result_totext(status), isc_result_totext(status2));
1064
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1065
		RETURN_FALSE;
1066
	}
1067
	if (status2 != ISC_R_SUCCESS) {
1068
		//php_printf("7Error occured during connecting: %s\n", isc_result_totext(status2));
1069
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1070
		RETURN_FALSE;
1071
	}
1072

    
1073
	omapi_object_dereference(&hp,__FILE__,__LINE__);
1074

    
1075
	RETURN_TRUE;
1076
}
1077

    
1078
PHP_FUNCTION(pfSense_delete_lease)
1079
{
1080
	dhcpctl_status status;
1081
	dhcpctl_status status2;
1082
	dhcpctl_handle hp = NULL;
1083
	dhcpctl_data_string ds = NULL;
1084
	omapi_data_string_t *nds;
1085
	char *mac;
1086
	int mac_len;
1087
	zval *res;
1088
	omapi_data *conn;
1089

    
1090
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &mac, &mac_len) == FAILURE) {
1091
		RETURN_FALSE;
1092
	}
1093

    
1094
	ZEND_FETCH_RESOURCE(conn, omapi_data *, &res, -1, PHP_PFSENSE_RES_NAME, pfSense_dhcpd);
1095
	ZEND_VERIFY_RESOURCE(conn);
1096

    
1097
	if ((status = dhcpctl_new_object(&hp, conn->handle, "host")))
1098
		RETURN_FALSE;
1099

    
1100
	if (mac) {
1101
		omapi_data_string_new(&ds, sizeof(struct ether_addr), __FILE__, __LINE__);
1102
		memcpy(ds->value,ether_aton(mac),sizeof(struct ether_addr));
1103
		if ((status = dhcpctl_set_value(hp, ds, "hardware-address"))) {
1104
			omapi_object_dereference(&hp,__FILE__,__LINE__);
1105
			RETURN_FALSE;
1106
		}
1107
	} else
1108
		RETURN_FALSE;
1109

    
1110
	if ((status = dhcpctl_open_object(hp, conn->handle, 0))) {
1111
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1112
		RETURN_FALSE;
1113
	}
1114
	if ((status = dhcpctl_wait_for_completion(hp, &status2))) {
1115
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1116
		RETURN_FALSE;
1117
	}
1118
	if (status2) {
1119
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1120
		RETURN_FALSE;
1121
	}
1122
	if ((status = dhcpctl_object_remove(conn->handle, hp))) {
1123
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1124
		RETURN_FALSE;
1125
	}
1126
	if ((status = dhcpctl_wait_for_completion(hp, &status2))) {
1127
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1128
		RETURN_FALSE;
1129
	}
1130
	if (status2) {
1131
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1132
		RETURN_FALSE;
1133
	}
1134
	omapi_object_dereference(&hp,__FILE__,__LINE__);
1135

    
1136
	RETURN_TRUE;
1137
}
1138

    
1139
PHP_FUNCTION(pfSense_close_dhcpd)
1140
{
1141
	zval *data;
1142

    
1143
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &data) == FAILURE) {
1144
		RETURN_FALSE;
1145
	}
1146

    
1147
	zend_list_delete(Z_LVAL_P(data));
1148

    
1149
	RETURN_TRUE;
1150
}
1151
#endif
1152

    
1153
PHP_FUNCTION(pfSense_ip_to_mac)
1154
{
1155
	char *ip = NULL, *rifname = NULL;
1156
	int ip_len, ifname_len = 0;
1157

    
1158
	int mib[6];
1159
	size_t needed;
1160
	char *lim, *buf, *next;
1161
	struct rt_msghdr *rtm;
1162
	struct sockaddr_inarp *sin2, addr;
1163
	struct sockaddr_dl *sdl;
1164
	char ifname[IF_NAMESIZE];
1165
	int st, found_entry = 0;
1166
	char outputbuf[128];
1167

    
1168
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &ip, &ip_len, &rifname, &ifname_len) == FAILURE)
1169
		RETURN_NULL();
1170

    
1171
	bzero(&addr, sizeof(addr));
1172
	if (!inet_pton(AF_INET, ip, &addr.sin_addr.s_addr))
1173
		RETURN_NULL();
1174
	addr.sin_len = sizeof(addr);
1175
	addr.sin_family = AF_INET;
1176

    
1177
	mib[0] = CTL_NET;
1178
	mib[1] = PF_ROUTE;
1179
	mib[2] = 0;
1180
	mib[3] = AF_INET;
1181
	mib[4] = NET_RT_FLAGS;
1182
#ifdef RTF_LLINFO
1183
	mib[5] = RTF_LLINFO;
1184
#else
1185
	mib[5] = 0;
1186
#endif	
1187
	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
1188
		php_printf("route-sysctl-estimate");
1189
		RETURN_NULL();
1190
	}
1191
	if (needed == 0)	/* empty table */
1192
		RETURN_NULL();
1193
	buf = NULL;
1194
	for (;;) {
1195
		buf = reallocf(buf, needed);
1196
		if (buf == NULL) {
1197
			php_printf("could not reallocate memory");
1198
			free(buf);
1199
			RETURN_NULL();
1200
		}
1201
		st = sysctl(mib, 6, buf, &needed, NULL, 0);
1202
		if (st == 0 || errno != ENOMEM)
1203
			break;
1204
		needed += needed / 8;
1205
	}
1206
	if (st == -1)
1207
		php_printf("actual retrieval of routing table");
1208
	lim = buf + needed;
1209
	for (next = buf; next < lim; next += rtm->rtm_msglen) {
1210
		rtm = (struct rt_msghdr *)next;
1211
		sin2 = (struct sockaddr_inarp *)(rtm + 1);
1212
		sdl = (struct sockaddr_dl *)((char *)sin2 + SA_SIZE(sin2));
1213
		if (rifname && if_indextoname(sdl->sdl_index, ifname) &&
1214
		    strcmp(ifname, rifname))
1215
			continue;
1216
		if (addr.sin_addr.s_addr == sin2->sin_addr.s_addr) {
1217
			found_entry = 1;
1218
			break;
1219
		}
1220
	}
1221
	free(buf);
1222

    
1223
	if (found_entry == 0)
1224
		RETURN_NULL();
1225

    
1226
	array_init(return_value);
1227
	bzero(outputbuf, sizeof outputbuf);
1228
	ether_ntoa_r((struct ether_addr *)LLADDR(sdl), outputbuf);
1229
	add_assoc_string(return_value, "macaddr", outputbuf, 1);
1230
}
1231

    
1232
PHP_FUNCTION(pfSense_getall_interface_addresses)
1233
{
1234
	struct ifaddrs *ifdata, *mb;
1235
	struct if_data *md;
1236
	struct sockaddr_in *tmp;
1237
	struct sockaddr_in6 *tmp6;
1238
	char outputbuf[132];
1239
	char *ifname;
1240
	int ifname_len, s;
1241

    
1242
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE)
1243
		RETURN_NULL();
1244

    
1245
	getifaddrs(&ifdata);
1246
	if (ifdata == NULL)
1247
		RETURN_NULL();
1248

    
1249
	array_init(return_value);
1250

    
1251
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1252
		if (mb == NULL)
1253
			continue;
1254
		if (ifname_len != strlen(mb->ifa_name))
1255
			continue;
1256
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1257
			continue;
1258
		if (mb->ifa_addr == NULL)
1259
			continue;
1260

    
1261
		switch (mb->ifa_addr->sa_family) {
1262
		case AF_INET:
1263
			bzero(outputbuf, sizeof outputbuf);
1264
			tmp = (struct sockaddr_in *)mb->ifa_addr;
1265
			inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 132);
1266
			tmp = (struct sockaddr_in *)mb->ifa_netmask;
1267
			unsigned char mask;
1268
			const unsigned char *byte = (unsigned char *)&tmp->sin_addr.s_addr;
1269
			int i = 0, n = sizeof(tmp->sin_addr.s_addr);
1270
			while (n--) {
1271
				mask = ((unsigned char)-1 >> 1) + 1;
1272
					do {
1273
						if (mask & byte[n])
1274
							i++;
1275
						mask >>= 1;
1276
					} while (mask);
1277
			}
1278
			snprintf(outputbuf + strlen(outputbuf), sizeof(outputbuf) - strlen(outputbuf), "/%d", i);
1279
			add_next_index_string(return_value, outputbuf, 1);
1280
			break;
1281
		case AF_INET6:
1282
			bzero(outputbuf, sizeof outputbuf);
1283
			tmp6 = (struct sockaddr_in6 *)mb->ifa_addr;
1284
			if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr)) {
1285
				tmp6->sin6_scope_id = ntohs(*(u_int16_t *)&tmp6->sin6_addr.s6_addr[2]);
1286
				tmp6->sin6_addr.s6_addr[2] = tmp6->sin6_addr.s6_addr[3] = 0;
1287
				if (getnameinfo((struct sockaddr *)tmp6, tmp6->sin6_len, outputbuf, sizeof(outputbuf), NULL, 0, NI_NUMERICHOST))
1288
					inet_ntop(AF_INET6, (void *)&tmp6->sin6_addr, outputbuf, INET6_ADDRSTRLEN);
1289
			} else
1290
				inet_ntop(AF_INET6, (void *)&tmp6->sin6_addr, outputbuf, INET6_ADDRSTRLEN);
1291
			tmp6 = (struct sockaddr_in6 *)mb->ifa_netmask;
1292
			snprintf(outputbuf + strlen(outputbuf), sizeof(outputbuf) - strlen(outputbuf),
1293
				"/%d", prefix(&tmp6->sin6_addr, sizeof(struct in6_addr)));
1294
			add_next_index_string(return_value, outputbuf, 1);
1295
			break;
1296
		}
1297
	}
1298
}
1299

    
1300
PHP_FUNCTION(pfSense_get_interface_addresses)
1301
{
1302
	struct ifaddrs *ifdata, *mb;
1303
	struct if_data *md;
1304
	struct sockaddr_in *tmp;
1305
	struct sockaddr_in6 *tmp6;
1306
	struct sockaddr_dl *tmpdl;
1307
	struct ifreq ifr;
1308
	char outputbuf[128];
1309
	char *ifname;
1310
	int ifname_len, s, addresscnt = 0, addresscnt6 = 0;
1311
	zval *caps;
1312
	zval *encaps;
1313

    
1314
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE)
1315
		RETURN_NULL();
1316

    
1317
	getifaddrs(&ifdata);
1318
	if (ifdata == NULL)
1319
		RETURN_NULL();
1320

    
1321
	array_init(return_value);
1322

    
1323
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1324
		if (mb == NULL)
1325
			continue;
1326
		if (ifname_len != strlen(mb->ifa_name))
1327
			continue;
1328
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1329
			continue;
1330

    
1331
		if (mb->ifa_flags & IFF_UP)
1332
			add_assoc_string(return_value, "status", "up", 1);
1333
		else
1334
			add_assoc_string(return_value, "status", "down", 1);
1335
		if (mb->ifa_flags & IFF_LINK0)
1336
			add_assoc_long(return_value, "link0", 1);
1337
		if (mb->ifa_flags & IFF_LINK1)
1338
			add_assoc_long(return_value, "link1", 1);
1339
		if (mb->ifa_flags & IFF_LINK2)
1340
			add_assoc_long(return_value, "link2", 1);
1341
		if (mb->ifa_flags & IFF_MULTICAST)
1342
			add_assoc_long(return_value, "multicast", 1);
1343
		if (mb->ifa_flags & IFF_LOOPBACK)
1344
			add_assoc_long(return_value, "loopback", 1);
1345
		if (mb->ifa_flags & IFF_POINTOPOINT)
1346
			add_assoc_long(return_value, "pointtopoint", 1);
1347
		if (mb->ifa_flags & IFF_PROMISC)
1348
			add_assoc_long(return_value, "promisc", 1);
1349
		if (mb->ifa_flags & IFF_PPROMISC)
1350
			add_assoc_long(return_value, "permanentpromisc", 1);
1351
		if (mb->ifa_flags & IFF_OACTIVE)
1352
			add_assoc_long(return_value, "oactive", 1);
1353
		if (mb->ifa_flags & IFF_ALLMULTI)
1354
			add_assoc_long(return_value, "allmulti", 1);
1355
		if (mb->ifa_flags & IFF_SIMPLEX)
1356
			add_assoc_long(return_value, "simplex", 1);
1357
		if (mb->ifa_data != NULL) {
1358
			md = mb->ifa_data;
1359
			if (md->ifi_link_state == LINK_STATE_UP)
1360
				add_assoc_long(return_value, "linkstateup", 1);
1361
			//add_assoc_long(return_value, "hwassistflag", md->ifi_hwassist);
1362
			add_assoc_long(return_value, "mtu", md->ifi_mtu);
1363
			switch (md->ifi_type) {
1364
			case IFT_IEEE80211:
1365
				add_assoc_string(return_value, "iftype", "wireless", 1);
1366
				break;
1367
			case IFT_ETHER:
1368
			case IFT_FASTETHER:
1369
			case IFT_FASTETHERFX:
1370
			case IFT_GIGABITETHERNET:
1371
				add_assoc_string(return_value, "iftype", "ether", 1);
1372
				break;
1373
			case IFT_L2VLAN:
1374
				add_assoc_string(return_value, "iftype", "vlan", 1);
1375
				break;
1376
			case IFT_BRIDGE:
1377
				add_assoc_string(return_value, "iftype", "bridge", 1);
1378
				break;
1379
			case IFT_TUNNEL:
1380
			case IFT_GIF:
1381
			case IFT_FAITH:
1382
			case IFT_ENC:
1383
			case IFT_PFLOG: 
1384
			case IFT_PFSYNC:
1385
				add_assoc_string(return_value, "iftype", "virtual", 1);
1386
				break;
1387
#if (__FreeBSD_version < 1000000)
1388
			case IFT_CARP:
1389
				add_assoc_string(return_value, "iftype", "carp", 1);
1390
				break;
1391
#endif
1392
			default:
1393
				add_assoc_string(return_value, "iftype", "other", 1);
1394
			}
1395
		}
1396
		ALLOC_INIT_ZVAL(caps);
1397
		ALLOC_INIT_ZVAL(encaps);
1398
		array_init(caps);
1399
		array_init(encaps);
1400
		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1401
		if (ioctl(PFSENSE_G(s), SIOCGIFCAP, (caddr_t)&ifr) == 0) {
1402
			add_assoc_long(caps, "flags", ifr.ifr_reqcap);
1403
			if (ifr.ifr_reqcap & IFCAP_POLLING)
1404
				add_assoc_long(caps, "polling", 1);
1405
			if (ifr.ifr_reqcap & IFCAP_RXCSUM)
1406
				add_assoc_long(caps, "rxcsum", 1);
1407
			if (ifr.ifr_reqcap & IFCAP_TXCSUM)
1408
				add_assoc_long(caps, "txcsum", 1);
1409
			if (ifr.ifr_reqcap & IFCAP_VLAN_MTU)
1410
				add_assoc_long(caps, "vlanmtu", 1);
1411
			if (ifr.ifr_reqcap & IFCAP_JUMBO_MTU)
1412
				add_assoc_long(caps, "jumbomtu", 1);
1413
			if (ifr.ifr_reqcap & IFCAP_VLAN_HWTAGGING)
1414
				add_assoc_long(caps, "vlanhwtag", 1);
1415
			if (ifr.ifr_reqcap & IFCAP_VLAN_HWCSUM)
1416
				add_assoc_long(caps, "vlanhwcsum", 1);
1417
			if (ifr.ifr_reqcap & IFCAP_TSO4)
1418
				add_assoc_long(caps, "tso4", 1);
1419
			if (ifr.ifr_reqcap & IFCAP_TSO6)
1420
				add_assoc_long(caps, "tso6", 1);
1421
			if (ifr.ifr_reqcap & IFCAP_LRO)
1422
				add_assoc_long(caps, "lro", 1);
1423
			if (ifr.ifr_reqcap & IFCAP_WOL_UCAST)
1424
				add_assoc_long(caps, "wolucast", 1);
1425
			if (ifr.ifr_reqcap & IFCAP_WOL_MCAST)
1426
				add_assoc_long(caps, "wolmcast", 1);
1427
			if (ifr.ifr_reqcap & IFCAP_WOL_MAGIC)
1428
				add_assoc_long(caps, "wolmagic", 1);
1429
			if (ifr.ifr_reqcap & IFCAP_TOE4)
1430
				add_assoc_long(caps, "toe4", 1);
1431
			if (ifr.ifr_reqcap & IFCAP_TOE6)
1432
				add_assoc_long(caps, "toe6", 1);
1433
			if (ifr.ifr_reqcap & IFCAP_VLAN_HWFILTER)
1434
				add_assoc_long(caps, "vlanhwfilter", 1);
1435
#if 0
1436
			if (ifr.ifr_reqcap & IFCAP_POLLING_NOCOUNT)
1437
				add_assoc_long(caps, "pollingnocount", 1);
1438
#endif
1439
			add_assoc_long(encaps, "flags", ifr.ifr_curcap);
1440
			if (ifr.ifr_curcap & IFCAP_POLLING)
1441
				add_assoc_long(encaps, "polling", 1);
1442
			if (ifr.ifr_curcap & IFCAP_RXCSUM)
1443
				add_assoc_long(encaps, "rxcsum", 1);
1444
			if (ifr.ifr_curcap & IFCAP_TXCSUM)
1445
				add_assoc_long(encaps, "txcsum", 1);
1446
			if (ifr.ifr_curcap & IFCAP_VLAN_MTU)
1447
				add_assoc_long(encaps, "vlanmtu", 1);
1448
			if (ifr.ifr_curcap & IFCAP_JUMBO_MTU)
1449
				add_assoc_long(encaps, "jumbomtu", 1);
1450
			if (ifr.ifr_curcap & IFCAP_VLAN_HWTAGGING)
1451
				add_assoc_long(encaps, "vlanhwtag", 1);
1452
			if (ifr.ifr_curcap & IFCAP_VLAN_HWCSUM)
1453
				add_assoc_long(encaps, "vlanhwcsum", 1);
1454
			if (ifr.ifr_curcap & IFCAP_TSO4)
1455
				add_assoc_long(encaps, "tso4", 1);
1456
			if (ifr.ifr_curcap & IFCAP_TSO6)
1457
				add_assoc_long(encaps, "tso6", 1);
1458
			if (ifr.ifr_curcap & IFCAP_LRO)
1459
				add_assoc_long(encaps, "lro", 1);
1460
			if (ifr.ifr_curcap & IFCAP_WOL_UCAST)
1461
				add_assoc_long(encaps, "wolucast", 1);
1462
			if (ifr.ifr_curcap & IFCAP_WOL_MCAST)
1463
				add_assoc_long(encaps, "wolmcast", 1);
1464
			if (ifr.ifr_curcap & IFCAP_WOL_MAGIC)
1465
				add_assoc_long(encaps, "wolmagic", 1);
1466
			if (ifr.ifr_curcap & IFCAP_TOE4)
1467
				add_assoc_long(encaps, "toe4", 1);
1468
			if (ifr.ifr_curcap & IFCAP_TOE6)
1469
				add_assoc_long(encaps, "toe6", 1);
1470
			if (ifr.ifr_curcap & IFCAP_VLAN_HWFILTER)
1471
				add_assoc_long(encaps, "vlanhwfilter", 1);
1472
#if 0
1473
			if (ifr.ifr_reqcap & IFCAP_POLLING_NOCOUNT)
1474
				add_assoc_long(caps, "pollingnocount", 1);
1475
#endif
1476
		}
1477
		add_assoc_zval(return_value, "caps", caps);
1478
		add_assoc_zval(return_value, "encaps", encaps);
1479
		if (mb->ifa_addr == NULL)
1480
			continue;
1481
		switch (mb->ifa_addr->sa_family) {
1482
		case AF_INET:
1483
			if (addresscnt > 0)
1484
				break;
1485
			bzero(outputbuf, sizeof outputbuf);
1486
			tmp = (struct sockaddr_in *)mb->ifa_addr;
1487
			inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1488
			add_assoc_string(return_value, "ipaddr", outputbuf, 1);
1489
			addresscnt++;
1490
			tmp = (struct sockaddr_in *)mb->ifa_netmask;
1491
			unsigned char mask;
1492
			const unsigned char *byte = (unsigned char *)&tmp->sin_addr.s_addr;
1493
			int i = 0, n = sizeof(tmp->sin_addr.s_addr);
1494
			while (n--) {
1495
				mask = ((unsigned char)-1 >> 1) + 1;
1496
					do {
1497
						if (mask & byte[n])
1498
							i++;
1499
						mask >>= 1;
1500
					} while (mask);
1501
			}
1502
			add_assoc_long(return_value, "subnetbits", i);
1503

    
1504
			bzero(outputbuf, sizeof outputbuf);
1505
			inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1506
			add_assoc_string(return_value, "subnet", outputbuf, 1);
1507

    
1508
			if (mb->ifa_flags & IFF_BROADCAST) {
1509
				bzero(outputbuf, sizeof outputbuf);
1510
				tmp = (struct sockaddr_in *)mb->ifa_broadaddr;
1511
				inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1512
				add_assoc_string(return_value, "broadcast", outputbuf, 1);
1513
			}
1514

    
1515
			if (mb->ifa_flags & IFF_POINTOPOINT) {
1516
				bzero(outputbuf, sizeof outputbuf);
1517
				tmp6 = (struct sockaddr_in6 *)mb->ifa_dstaddr;
1518
				inet_ntop(AF_INET, (void *)&tmp6->sin6_addr, outputbuf, 128);
1519
				add_assoc_string(return_value, "tunnel", outputbuf, 1);
1520
			}
1521

    
1522
		break;
1523
		case AF_INET6:
1524
			if (addresscnt6 > 0)
1525
                                break;
1526
                        bzero(outputbuf, sizeof outputbuf);
1527
                        tmp6 = (struct sockaddr_in6 *)mb->ifa_addr;
1528
			if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr))
1529
				break;
1530
                        inet_ntop(AF_INET6, (void *)&tmp6->sin6_addr, outputbuf, 128);
1531
                        add_assoc_string(return_value, "ipaddr6", outputbuf, 1);
1532
                        addresscnt6++;
1533
                        tmp6 = (struct sockaddr_in6 *)mb->ifa_netmask;
1534
                        add_assoc_long(return_value, "subnetbits6", prefix(&tmp6->sin6_addr, sizeof(struct in6_addr)));
1535
                
1536
                        if (mb->ifa_flags & IFF_POINTOPOINT) {
1537
                                bzero(outputbuf, sizeof outputbuf);
1538
                                tmp = (struct sockaddr_in *)mb->ifa_dstaddr;
1539
                                inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1540
                                add_assoc_string(return_value, "tunnel6", outputbuf, 1);
1541
                        }
1542
		break;
1543
		case AF_LINK:
1544
			tmpdl = (struct sockaddr_dl *)mb->ifa_addr;
1545
			bzero(outputbuf, sizeof outputbuf);
1546
			ether_ntoa_r((struct ether_addr *)LLADDR(tmpdl), outputbuf);
1547
			add_assoc_string(return_value, "macaddr", outputbuf, 1);
1548
			md = (struct if_data *)mb->ifa_data;
1549

    
1550
		break;
1551
		}
1552
	}
1553
	freeifaddrs(ifdata);
1554
}
1555

    
1556
PHP_FUNCTION(pfSense_bridge_add_member) {
1557
	char *ifname, *ifchld;
1558
	int ifname_len, ifchld_len;
1559
	struct ifdrv drv;
1560
	struct ifbreq req;
1561

    
1562
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ifchld, &ifchld_len) == FAILURE) {
1563
		RETURN_NULL();
1564
	}
1565

    
1566
	memset(&drv, 0, sizeof(drv));
1567
	memset(&req, 0, sizeof(req));
1568
	strlcpy(drv.ifd_name, ifname, sizeof(drv.ifd_name));
1569
	strlcpy(req.ifbr_ifsname, ifchld, sizeof(req.ifbr_ifsname));
1570
	drv.ifd_cmd = BRDGADD;
1571
	drv.ifd_data = &req;
1572
	drv.ifd_len = sizeof(req);
1573
	if (ioctl(PFSENSE_G(s), SIOCSDRVSPEC, (caddr_t)&drv) < 0)
1574
		RETURN_FALSE;
1575

    
1576
	RETURN_TRUE;
1577
}
1578

    
1579
PHP_FUNCTION(pfSense_bridge_del_member) {
1580
	char *ifname, *ifchld;
1581
	int ifname_len, ifchld_len;
1582
	struct ifdrv drv;
1583
	struct ifbreq req;
1584

    
1585
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ifchld, &ifchld_len) == FAILURE) {
1586
		RETURN_NULL();
1587
	}
1588

    
1589
	memset(&drv, 0, sizeof(drv));
1590
	memset(&req, 0, sizeof(req));
1591
	strlcpy(drv.ifd_name, ifname, sizeof(drv.ifd_name));
1592
	strlcpy(req.ifbr_ifsname, ifchld, sizeof(req.ifbr_ifsname));
1593
	drv.ifd_cmd = BRDGDEL;
1594
	drv.ifd_data = &req;
1595
	drv.ifd_len = sizeof(req);
1596
	if (ioctl(PFSENSE_G(s), SIOCSDRVSPEC, (caddr_t)&drv) < 0)
1597
		RETURN_FALSE;
1598

    
1599
	RETURN_TRUE;
1600
}
1601

    
1602
PHP_FUNCTION(pfSense_bridge_member_flags) {
1603
	char *ifname, *ifchld;
1604
	int ifname_len, ifchld_len;
1605
	struct ifdrv drv;
1606
	struct ifbreq req;
1607
	long flags = 0;
1608

    
1609
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &ifname, &ifname_len, &ifchld, &ifchld_len, &flags) == FAILURE) {
1610
		RETURN_NULL();
1611
	}
1612

    
1613
	memset(&drv, 0, sizeof(drv));
1614
	memset(&req, 0, sizeof(req));
1615
	strlcpy(drv.ifd_name, ifname, sizeof(drv.ifd_name));
1616
	strlcpy(req.ifbr_ifsname, ifchld, sizeof(req.ifbr_ifsname));
1617
	drv.ifd_cmd = BRDGGIFFLGS;
1618
	drv.ifd_data = &req;
1619
	drv.ifd_len = sizeof(req);
1620
	if (ioctl(PFSENSE_G(s), SIOCGDRVSPEC, (caddr_t)&drv) < 0)
1621
		RETURN_FALSE;
1622

    
1623
	if (flags < 0) {
1624
		flags = -flags;
1625
		req.ifbr_ifsflags &= ~(int)flags;
1626
	} else
1627
		req.ifbr_ifsflags |= (int)flags;
1628

    
1629
	drv.ifd_cmd = BRDGSIFFLGS;
1630
	drv.ifd_data = &req;
1631
	drv.ifd_len = sizeof(req);
1632
	if (ioctl(PFSENSE_G(s), SIOCSDRVSPEC, (caddr_t)&drv) < 0)
1633
		RETURN_FALSE;
1634

    
1635
	RETURN_TRUE;
1636
}
1637

    
1638
PHP_FUNCTION(pfSense_interface_listget) {
1639
	struct ifaddrs *ifdata, *mb;
1640
	char *ifname;
1641
	int ifname_len;
1642
	long flags = 0;
1643

    
1644
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE)
1645
		RETURN_NULL();
1646

    
1647
	getifaddrs(&ifdata);
1648
	if (ifdata == NULL)
1649
		RETURN_NULL();
1650

    
1651
	array_init(return_value);
1652
	ifname = NULL;
1653
	ifname_len = 0;
1654
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1655
		if (mb == NULL)
1656
			continue;
1657

    
1658
		if (flags != 0) {
1659
			if (mb->ifa_flags & IFF_UP && flags < 0)
1660
				continue;
1661
			if (!(mb->ifa_flags & IFF_UP) && flags > 0)
1662
				continue;
1663
		}
1664

    
1665
		if (ifname != NULL && ifname_len == strlen(mb->ifa_name) && strcmp(ifname, mb->ifa_name) == 0)
1666
			continue;
1667
		ifname = mb->ifa_name;
1668
		ifname_len = strlen(mb->ifa_name);
1669

    
1670
		add_next_index_string(return_value, mb->ifa_name, 1);
1671
	}
1672

    
1673
	freeifaddrs(ifdata);
1674
}
1675

    
1676
PHP_FUNCTION(pfSense_interface_create) {
1677
	char *ifname;
1678
	int ifname_len, len;
1679
	struct ifreq ifr;
1680
	struct vlanreq params;
1681

    
1682
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1683
		RETURN_NULL();
1684
	}
1685

    
1686
	memset(&ifr, 0, sizeof(ifr));
1687
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1688
	if (ioctl(PFSENSE_G(s), SIOCIFCREATE2, &ifr) < 0) {
1689
		array_init(return_value);
1690
		add_assoc_string(return_value, "error", "Could not create interface", 1);
1691
	} else
1692
		RETURN_STRING(ifr.ifr_name, 1)
1693
}
1694

    
1695
PHP_FUNCTION(pfSense_interface_destroy) {
1696
	char *ifname;
1697
	int ifname_len;
1698
	struct ifreq ifr;
1699

    
1700
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1701
		RETURN_NULL();
1702
	}
1703

    
1704
	memset(&ifr, 0, sizeof(ifr));
1705
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1706
	if (ioctl(PFSENSE_G(s), SIOCIFDESTROY, &ifr) < 0) {
1707
		array_init(return_value);
1708
		add_assoc_string(return_value, "error", "Could not create interface", 1);
1709
	} else
1710
		RETURN_TRUE;
1711
}
1712

    
1713
PHP_FUNCTION(pfSense_interface_setaddress) {
1714
	char *ifname, *ip, *p = NULL;
1715
	int ifname_len, ip_len;
1716
	struct sockaddr_in *sin;
1717
	struct in_aliasreq ifra;
1718

    
1719
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ip, &ip_len) == FAILURE) {
1720
		RETURN_NULL();
1721
	}
1722

    
1723
	memset(&ifra, 0, sizeof(ifra));
1724
	strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1725
	sin =  &ifra.ifra_mask;
1726
	sin->sin_family = AF_INET;
1727
	sin->sin_len = sizeof(*sin);
1728
	sin->sin_addr.s_addr = 0;
1729
	if ((p = strrchr(ip, '/')) != NULL) {
1730
		/* address is `name/masklen' */
1731
		int masklen;
1732
		int ret;
1733
		*p = '\0';
1734
		ret = sscanf(p+1, "%u", &masklen);
1735
		if(ret != 1 || (masklen < 0 || masklen > 32)) {
1736
			*p = '/';
1737
			RETURN_FALSE;
1738
		}
1739
		sin->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) &
1740
			0xffffffff);
1741
	}
1742
	sin =  &ifra.ifra_addr;
1743
	sin->sin_family = AF_INET;
1744
	sin->sin_len = sizeof(*sin);
1745
	if (inet_pton(AF_INET, ip, &sin->sin_addr) <= 0)
1746
		RETURN_FALSE;
1747

    
1748
	if (ioctl(PFSENSE_G(inets), SIOCAIFADDR, &ifra) < 0) {
1749
		array_init(return_value);
1750
		add_assoc_string(return_value, "error", "Could not set interface address", 1);
1751
	} else
1752
		RETURN_TRUE;
1753
}
1754

    
1755
PHP_FUNCTION(pfSense_interface_deladdress) {
1756
	char *ifname, *ip = NULL;
1757
	int ifname_len, ip_len;
1758
	struct sockaddr_in *sin;
1759
	struct in_aliasreq ifra;
1760

    
1761
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ip, &ip_len) == FAILURE) {
1762
		RETURN_NULL();
1763
	}
1764

    
1765
	memset(&ifra, 0, sizeof(ifra));
1766
	strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1767
	sin =  &ifra.ifra_addr;
1768
	sin->sin_family = AF_INET;
1769
	sin->sin_len = sizeof(*sin);
1770
	if (inet_pton(AF_INET, ip, &sin->sin_addr) <= 0)
1771
		RETURN_FALSE;
1772

    
1773
	if (ioctl(PFSENSE_G(inets), SIOCDIFADDR, &ifra) < 0) {
1774
		array_init(return_value);
1775
		add_assoc_string(return_value, "error", "Could not delete interface address", 1);
1776
	} else
1777
		RETURN_TRUE;
1778
}
1779

    
1780
PHP_FUNCTION(pfSense_interface_rename) {
1781
	char *ifname, *newifname;
1782
	int ifname_len, newifname_len;
1783
	struct ifreq ifr;
1784

    
1785
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1786
		RETURN_NULL();
1787
	}
1788

    
1789
	memset(&ifr, 0, sizeof(ifr));
1790
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1791
	ifr.ifr_data = (caddr_t) newifname;
1792
	if (ioctl(PFSENSE_G(s), SIOCSIFNAME, (caddr_t) &ifr) < 0) {
1793
		array_init(return_value);
1794
		add_assoc_string(return_value, "error", "Could not rename interface", 1);
1795
	} else
1796
		RETURN_TRUE;
1797
}
1798

    
1799
PHP_FUNCTION(pfSense_ngctl_name) {
1800
	char *ifname, *newifname;
1801
	int ifname_len, newifname_len;
1802

    
1803
	if (PFSENSE_G(csock) == -1)
1804
		RETURN_NULL();
1805

    
1806
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1807
		RETURN_NULL();
1808
	}
1809

    
1810
	/* Send message */
1811
	if (NgNameNode(PFSENSE_G(csock), ifname, newifname) < 0)
1812
		RETURN_NULL();
1813

    
1814
	RETURN_TRUE;
1815
}
1816

    
1817
PHP_FUNCTION(pfSense_ngctl_attach) {
1818
	char *ifname, *newifname;
1819
	int ifname_len, newifname_len;
1820
	struct ngm_name name;
1821

    
1822
	if (PFSENSE_G(csock) == -1)
1823
		RETURN_NULL();
1824

    
1825
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1826
		RETURN_NULL();
1827
	}
1828

    
1829
	snprintf(name.name, sizeof(name.name), "%s", newifname);
1830
	/* Send message */
1831
	if (NgSendMsg(PFSENSE_G(csock), ifname, NGM_GENERIC_COOKIE,
1832
		NGM_ETHER_ATTACH, &name, sizeof(name)) < 0)
1833
			RETURN_NULL();
1834

    
1835
	RETURN_TRUE;
1836
}
1837

    
1838
PHP_FUNCTION(pfSense_ngctl_detach) {
1839
	char *ifname, *newifname;
1840
	int ifname_len, newifname_len;
1841
	struct ngm_name name;
1842

    
1843
	if (PFSENSE_G(csock) == -1)
1844
		RETURN_NULL();
1845

    
1846
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1847
		RETURN_NULL();
1848
	}
1849

    
1850
	snprintf(name.name, sizeof(name.name), "%s", newifname);
1851
	/* Send message */
1852
	if (NgSendMsg(PFSENSE_G(csock), ifname, NGM_ETHER_COOKIE,
1853
		NGM_ETHER_DETACH, &name, sizeof(name)) < 0)
1854
			RETURN_NULL();
1855

    
1856
	RETURN_TRUE;
1857
}
1858

    
1859
PHP_FUNCTION(pfSense_vlan_create) {
1860
	char *ifname = NULL;
1861
	char *parentifname = NULL;
1862
	int ifname_len, parent_len;
1863
	long tag; 
1864
	struct ifreq ifr;
1865
	struct vlanreq params;
1866

    
1867
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &ifname, &ifname_len, &parentifname, &parent_len, &tag) == FAILURE) {
1868
		RETURN_NULL();
1869
	}
1870

    
1871
	memset(&ifr, 0, sizeof(ifr));
1872
	memset(&params, 0, sizeof(params));
1873
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1874
	strlcpy(params.vlr_parent, parentifname, sizeof(params.vlr_parent));
1875
	params.vlr_tag = (u_short) tag;
1876
	ifr.ifr_data = (caddr_t) &params;
1877
	if (ioctl(PFSENSE_G(s), SIOCSETVLAN, (caddr_t) &ifr) < 0)
1878
		RETURN_NULL();
1879

    
1880
	RETURN_TRUE;
1881
}
1882

    
1883
PHP_FUNCTION(pfSense_interface_mtu) {
1884
	char *ifname;
1885
	int ifname_len;
1886
	long mtu;
1887
	struct ifreq ifr;
1888

    
1889
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &mtu) == FAILURE) {
1890
		RETURN_NULL();
1891
	}
1892
	memset(&ifr, 0, sizeof(ifr));
1893
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1894
	ifr.ifr_mtu = (int) mtu;
1895
	if (ioctl(PFSENSE_G(s), SIOCSIFMTU, (caddr_t)&ifr) < 0)
1896
		RETURN_NULL();
1897
	RETURN_TRUE;
1898
}
1899

    
1900
PHP_FUNCTION(pfSense_interface_flags) {
1901
	struct ifreq ifr;
1902
	char *ifname;
1903
	int flags, ifname_len;
1904
	long value;
1905

    
1906
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &value) == FAILURE) {
1907
		RETURN_NULL();
1908
	}
1909

    
1910
	memset(&ifr, 0, sizeof(ifr));
1911
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1912
	if (ioctl(PFSENSE_G(s), SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
1913
		RETURN_NULL();
1914
	}
1915
	flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
1916
	if (value < 0) {
1917
		value = -value;
1918
		flags &= ~(int)value;
1919
	} else
1920
		flags |= (int)value; 
1921
	ifr.ifr_flags = flags & 0xffff;
1922
	ifr.ifr_flagshigh = flags >> 16;
1923
	if (ioctl(PFSENSE_G(s), SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
1924
		RETURN_NULL();
1925
	RETURN_TRUE;
1926
}
1927

    
1928
PHP_FUNCTION(pfSense_interface_capabilities) {
1929
	struct ifreq ifr;
1930
	char *ifname;
1931
	int flags, ifname_len;
1932
	long value;
1933

    
1934
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &value) == FAILURE) {
1935
		RETURN_NULL();
1936
	}
1937

    
1938
	memset(&ifr, 0, sizeof(ifr));
1939
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1940
	if (ioctl(PFSENSE_G(s), SIOCGIFCAP, (caddr_t)&ifr) < 0) {
1941
		RETURN_NULL();
1942
	}
1943
	flags = ifr.ifr_curcap;
1944
	if (value < 0) {
1945
		value = -value;
1946
		flags &= ~(int)value;
1947
	} else
1948
		flags |= (int)value; 
1949
	flags &= ifr.ifr_reqcap;
1950
	ifr.ifr_reqcap = flags;
1951
	if (ioctl(PFSENSE_G(s), SIOCSIFCAP, (caddr_t)&ifr) < 0)
1952
		RETURN_NULL();
1953
	RETURN_TRUE;
1954

    
1955
}
1956

    
1957
PHP_FUNCTION(pfSense_get_interface_info)
1958
{
1959
	struct ifaddrs *ifdata, *mb;
1960
	struct if_data *tmpd;
1961
	struct sockaddr_in *tmp;
1962
	struct sockaddr_dl *tmpdl;
1963
	struct pfi_kif kif = { 0 };
1964
	int size = 1, found = 0;
1965
	char outputbuf[128];
1966
	char *ifname;
1967
	int ifname_len;
1968
	int i = 0, error = 0;
1969
	int dev;
1970
	char *pf_status;
1971

    
1972
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1973
		RETURN_NULL();
1974
	}
1975

    
1976
	if ((dev = open("/dev/pf", O_RDWR)) < 0)
1977
		RETURN_NULL();
1978

    
1979
	getifaddrs(&ifdata);
1980
	if (ifdata == NULL) {
1981
		close(dev);
1982
		RETURN_NULL();
1983
	}
1984

    
1985
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1986
		if (mb == NULL)
1987
			continue;
1988
		if (ifname_len != strlen(mb->ifa_name))
1989
			continue;
1990
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1991
			continue;
1992

    
1993
		if (found == 0)
1994
			array_init(return_value);
1995

    
1996
		found = 1;
1997

    
1998
		switch (mb->ifa_addr->sa_family) {
1999
		case AF_LINK:
2000

    
2001
			tmpd = (struct if_data *)mb->ifa_data;
2002
			add_assoc_long(return_value, "inerrs", tmpd->ifi_ierrors);
2003
			add_assoc_long(return_value, "outerrs", tmpd->ifi_oerrors);
2004
			add_assoc_long(return_value, "collisions", tmpd->ifi_collisions);
2005
			add_assoc_long(return_value, "inmcasts", tmpd->ifi_imcasts);
2006
			add_assoc_long(return_value, "outmcasts", tmpd->ifi_omcasts);
2007
			add_assoc_long(return_value, "unsuppproto", tmpd->ifi_noproto);
2008
			add_assoc_long(return_value, "mtu", tmpd->ifi_mtu);
2009

    
2010
		break;
2011
		}
2012
	}
2013
	freeifaddrs(ifdata);
2014

    
2015
	if (found == 0) {
2016
		close(dev);
2017
		RETURN_NULL();
2018
	}
2019

    
2020
	if (pfi_get_ifaces(dev, ifname, &kif, &size))
2021
		error = 1;
2022

    
2023
	if (error == 0) {
2024
		add_assoc_string(return_value, "interface", kif.pfik_name, 1);
2025

    
2026
#define PAF_INET 0
2027
#define PPF_IN 0
2028
#define PPF_OUT 1
2029
		add_assoc_long(return_value, "inpktspass", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_IN][PF_PASS]);
2030
		add_assoc_long(return_value, "outpktspass", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_OUT][PF_PASS]);
2031
		add_assoc_long(return_value, "inbytespass", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_IN][PF_PASS]);
2032
		add_assoc_long(return_value, "outbytespass", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_OUT][PF_PASS]);
2033

    
2034
		add_assoc_long(return_value, "inpktsblock", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_IN][PF_DROP]);
2035
		add_assoc_long(return_value, "outpktsblock", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_OUT][PF_DROP]);
2036
		add_assoc_long(return_value, "inbytesblock", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_IN][PF_DROP]);
2037
		add_assoc_long(return_value, "outbytesblock", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_OUT][PF_DROP]);
2038

    
2039
		add_assoc_long(return_value, "inbytes", (unsigned long long)(kif.pfik_bytes[PAF_INET][PPF_IN][PF_DROP] + kif.pfik_bytes[PAF_INET][PPF_IN][PF_PASS]));
2040
		add_assoc_long(return_value, "outbytes", (unsigned long long)(kif.pfik_bytes[PAF_INET][PPF_OUT][PF_DROP] + kif.pfik_bytes[PAF_INET][PPF_OUT][PF_PASS]));
2041
		add_assoc_long(return_value, "inpkts", (unsigned long long)(kif.pfik_packets[PAF_INET][PPF_IN][PF_DROP] + kif.pfik_packets[PAF_INET][PPF_IN][PF_PASS]));
2042
		add_assoc_long(return_value, "outpkts", (unsigned long long)(kif.pfik_packets[PAF_INET][PPF_OUT][PF_DROP] + kif.pfik_packets[PAF_INET][PPF_OUT][PF_PASS]));
2043
#undef PPF_IN
2044
#undef PPF_OUT
2045
#undef PAF_INET
2046
	}
2047
	close(dev);
2048
}
2049

    
2050
PHP_FUNCTION(pfSense_get_interface_stats)
2051
{
2052
	struct ifmibdata ifmd;
2053
	struct if_data *tmpd;
2054
	char outputbuf[128];
2055
	char *ifname;
2056
	int ifname_len, error;
2057
	int name[6];
2058
	size_t len;
2059
	unsigned int ifidx;
2060

    
2061
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
2062
		RETURN_NULL();
2063
	}
2064

    
2065
	ifidx = if_nametoindex(ifname);
2066
	if (ifidx == 0)
2067
		RETURN_NULL();
2068

    
2069
	name[0] = CTL_NET;
2070
	name[1] = PF_LINK;
2071
	name[2] = NETLINK_GENERIC;
2072
	name[3] = IFMIB_IFDATA;
2073
	name[4] = ifidx;
2074
	name[5] = IFDATA_GENERAL;
2075

    
2076
	len = sizeof(ifmd);
2077

    
2078
	if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) < 0)
2079
		RETURN_NULL();
2080
	
2081
	tmpd = &ifmd.ifmd_data;
2082

    
2083
	array_init(return_value);
2084
	add_assoc_long(return_value, "inpkts", (long)tmpd->ifi_ipackets);
2085
	add_assoc_long(return_value, "inbytes", (long)tmpd->ifi_ibytes);
2086
	add_assoc_long(return_value, "outpkts", (long)tmpd->ifi_opackets);
2087
	add_assoc_long(return_value, "outbytes", (long)tmpd->ifi_obytes);
2088
	add_assoc_long(return_value, "inerrs", (long)tmpd->ifi_ierrors);
2089
	add_assoc_long(return_value, "outerrs", (long)tmpd->ifi_oerrors);
2090
	add_assoc_long(return_value, "collisions", (long)tmpd->ifi_collisions);
2091
	add_assoc_long(return_value, "inmcasts", (long)tmpd->ifi_imcasts);
2092
	add_assoc_long(return_value, "outmcasts", (long)tmpd->ifi_omcasts);
2093
	add_assoc_long(return_value, "unsuppproto", (long)tmpd->ifi_noproto);
2094
	add_assoc_long(return_value, "mtu", (long)tmpd->ifi_mtu);
2095
}
2096

    
2097
PHP_FUNCTION(pfSense_get_pf_stats) {
2098
	struct pf_status status;
2099
	time_t runtime;
2100
	unsigned sec, min, hrs, day = runtime;
2101
	char statline[80];
2102
	char buf[PF_MD5_DIGEST_LENGTH * 2 + 1];
2103
	static const char hex[] = "0123456789abcdef";
2104
	int i;
2105
	int dev;
2106

    
2107
	array_init(return_value);
2108

    
2109
	if ((dev = open("/dev/pf", O_RDWR)) < 0) {
2110
		add_assoc_string(return_value, "error", strerror(errno), 1);
2111
	} else {
2112

    
2113

    
2114
	bzero(&status, sizeof(status));
2115
	if (ioctl(dev, DIOCGETSTATUS, &status)) {
2116
		add_assoc_string(return_value, "error", strerror(errno), 1);
2117
	} else {
2118
		add_assoc_long(return_value, "rulesmatch", (unsigned long long)status.counters[PFRES_MATCH]);
2119
		add_assoc_long(return_value, "pullhdrfail", (unsigned long long)status.counters[PFRES_BADOFF]);
2120
		add_assoc_long(return_value, "fragments", (unsigned long long)status.counters[PFRES_FRAG]);
2121
		add_assoc_long(return_value, "shortpacket", (unsigned long long)status.counters[PFRES_SHORT]);
2122
		add_assoc_long(return_value, "normalizedrop", (unsigned long long)status.counters[PFRES_NORM]);
2123
		add_assoc_long(return_value, "nomemory", (unsigned long long)status.counters[PFRES_MEMORY]);
2124
		add_assoc_long(return_value, "badtimestamp", (unsigned long long)status.counters[PFRES_TS]);
2125
		add_assoc_long(return_value, "congestion", (unsigned long long)status.counters[PFRES_CONGEST]);
2126
		add_assoc_long(return_value, "ipoptions", (unsigned long long)status.counters[PFRES_IPOPTIONS]);
2127
		add_assoc_long(return_value, "protocksumbad", (unsigned long long)status.counters[PFRES_PROTCKSUM]);
2128
		add_assoc_long(return_value, "statesbad", (unsigned long long)status.counters[PFRES_BADSTATE]);
2129
		add_assoc_long(return_value, "stateinsertions", (unsigned long long)status.counters[PFRES_STATEINS]);
2130
		add_assoc_long(return_value, "maxstatesdrop", (unsigned long long)status.counters[PFRES_MAXSTATES]);
2131
		add_assoc_long(return_value, "srclimitdrop", (unsigned long long)status.counters[PFRES_SRCLIMIT]);
2132
		add_assoc_long(return_value, "synproxydrop", (unsigned long long)status.counters[PFRES_SYNPROXY]);
2133

    
2134
		add_assoc_long(return_value, "maxstatesreached", (unsigned long long)status.lcounters[LCNT_STATES]);
2135
		add_assoc_long(return_value, "maxsrcstatesreached", (unsigned long long)status.lcounters[LCNT_SRCSTATES]);
2136
		add_assoc_long(return_value, "maxsrcnodesreached", (unsigned long long)status.lcounters[LCNT_SRCNODES]);
2137
		add_assoc_long(return_value, "maxsrcconnreached", (unsigned long long)status.lcounters[LCNT_SRCCONN]);
2138
		add_assoc_long(return_value, "maxsrcconnratereached", (unsigned long long)status.lcounters[LCNT_SRCCONNRATE]);
2139
		add_assoc_long(return_value, "overloadtable", (unsigned long long)status.lcounters[LCNT_OVERLOAD_TABLE]);
2140
		add_assoc_long(return_value, "overloadflush", (unsigned long long)status.lcounters[LCNT_OVERLOAD_FLUSH]);
2141

    
2142
		add_assoc_long(return_value, "statesearch", (unsigned long long)status.fcounters[FCNT_STATE_SEARCH]);
2143
		add_assoc_long(return_value, "stateinsert", (unsigned long long)status.fcounters[FCNT_STATE_INSERT]);
2144
		add_assoc_long(return_value, "stateremovals", (unsigned long long)status.fcounters[FCNT_STATE_REMOVALS]);
2145

    
2146
		add_assoc_long(return_value, "srcnodessearch", (unsigned long long)status.scounters[SCNT_SRC_NODE_SEARCH]);
2147
		add_assoc_long(return_value, "srcnodesinsert", (unsigned long long)status.scounters[SCNT_SRC_NODE_INSERT]);
2148
		add_assoc_long(return_value, "srcnodesremovals", (unsigned long long)status.scounters[SCNT_SRC_NODE_REMOVALS]);
2149

    
2150
#if (__FreeBSD_version < 1000000)
2151
		add_assoc_long(return_value, "stateid", (unsigned long long)status.stateid);
2152
#endif
2153

    
2154
		add_assoc_long(return_value, "running", status.running);
2155
		add_assoc_long(return_value, "states", status.states);
2156
		add_assoc_long(return_value, "srcnodes", status.src_nodes);
2157

    
2158
		add_assoc_long(return_value, "hostid", ntohl(status.hostid));
2159
		for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) {
2160
			buf[i + i] = hex[status.pf_chksum[i] >> 4];
2161
			buf[i + i + 1] = hex[status.pf_chksum[i] & 0x0f];
2162
		}
2163
		buf[i + i] = '\0';
2164
		add_assoc_string(return_value, "pfchecksum", buf, 1);
2165
		printf("Checksum: 0x%s\n\n", buf);
2166

    
2167
		switch(status.debug) {
2168
		case PF_DEBUG_NONE:
2169
			add_assoc_string(return_value, "debuglevel", "none", 1);
2170
			break;
2171
		case PF_DEBUG_URGENT:
2172
			add_assoc_string(return_value, "debuglevel", "urgent", 1);
2173
			break;
2174
		case PF_DEBUG_MISC:
2175
			add_assoc_string(return_value, "debuglevel", "misc", 1);
2176
			break;
2177
		case PF_DEBUG_NOISY:
2178
			add_assoc_string(return_value, "debuglevel", "noisy", 1);
2179
			break;
2180
		default:
2181
			add_assoc_string(return_value, "debuglevel", "unknown", 1);
2182
			break;
2183
		}
2184

    
2185
		runtime = time(NULL) - status.since;
2186
		if (status.since) {
2187
			sec = day % 60;
2188
			day /= 60;
2189
			min = day % 60;
2190
			day /= 60;
2191
			hrs = day % 24;
2192
			day /= 24;
2193
			snprintf(statline, sizeof(statline),
2194
		    		"Running: for %u days %.2u:%.2u:%.2u",
2195
		    		day, hrs, min, sec);
2196
			add_assoc_string(return_value, "uptime", statline, 1);
2197
		}
2198
	}
2199
	close(dev);
2200
	}
2201
}
2202

    
2203
PHP_FUNCTION(pfSense_sync) {
2204
	sync();
2205
}
2206

    
2207
PHP_FUNCTION(pfSense_get_modem_devices) {
2208
	struct termios		attr, origattr;
2209
	struct pollfd		pfd;
2210
	glob_t			g;
2211
	char			buf[2048] = { 0 };
2212
	char			*path;
2213
	int			nw = 0, i, fd, retries;
2214
	zend_bool		show_info = 0;
2215
	long			poll_timeout = 700;
2216

    
2217
	if (ZEND_NUM_ARGS() > 2) {
2218
		RETURN_NULL();
2219
	}
2220
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bl", &show_info, &poll_timeout) == FAILURE) {
2221
		php_printf("Maximum two parameter can be passed\n");
2222
			RETURN_NULL();
2223
	}
2224

    
2225
	array_init(return_value);
2226

    
2227
	bzero(&g, sizeof g);
2228
	glob("/dev/cua*", 0, NULL, &g);
2229
	glob("/dev/modem*", GLOB_APPEND, NULL, &g);
2230

    
2231
	if (g.gl_pathc > 0)
2232
	for (i = 0; g.gl_pathv[i] != NULL; i++) {
2233
		path = g.gl_pathv[i];
2234
		if (strstr(path, "lock") || strstr(path, "init"))
2235
			continue;
2236
		if (show_info)
2237
			php_printf("Found modem device: %s\n", path);
2238
		/* Open & lock serial port */
2239
		if ((fd = open(path, O_RDWR | O_NONBLOCK, 0)) < 0) {
2240
			if (show_info)
2241
				php_printf("Could not open the device exlusively\n");
2242
			add_assoc_string(return_value, path, path, 1);
2243
			continue;
2244
		}
2245

    
2246
		/* Set non-blocking I/O  */
2247
		if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
2248
			goto errormodem;
2249

    
2250
		/* Set serial port raw mode, baud rate, hardware flow control, etc. */
2251
		if (tcgetattr(fd, &attr) < 0)
2252
			goto errormodem;
2253

    
2254
		origattr = attr;
2255
		cfmakeraw(&attr);
2256

    
2257
		attr.c_cflag &= ~(CSIZE|PARENB|PARODD);
2258
		attr.c_cflag |= (CS8|CREAD|CLOCAL|HUPCL|CCTS_OFLOW|CRTS_IFLOW);
2259
		attr.c_iflag &= ~(IXANY|IMAXBEL|ISTRIP|IXON|IXOFF|BRKINT|ICRNL|INLCR);
2260
		attr.c_iflag |= (IGNBRK|IGNPAR);
2261
		attr.c_oflag &= ~OPOST;
2262
		attr.c_lflag = 0;
2263

    
2264
#define MODEM_DEFAULT_SPEED              115200
2265
		cfsetspeed(&attr, (speed_t) MODEM_DEFAULT_SPEED);
2266
#undef	MODEM_DEFAULT_SPEED
2267

    
2268
		if (tcsetattr(fd, TCSANOW, &attr) < 0)
2269
			goto errormodem;
2270

    
2271
		/* OK */
2272
		retries = 0;
2273
		while (retries++ < 3) {
2274
			if ((nw = write(fd, "AT OK\r\n", strlen("AT OK\r\n"))) < 0) {
2275
				if (errno == EAGAIN) {
2276
					if (show_info)
2277
						php_printf("\tRetrying write\n");
2278
					continue;
2279
				}
2280

    
2281
				if (show_info)
2282
					php_printf("\tError ocurred\n");
2283
				goto errormodem;
2284
			}
2285
		}
2286
		if (retries >= 3)
2287
			goto errormodem;
2288

    
2289
		retries = 0;
2290
tryagain2:
2291
		if (show_info)
2292
			php_printf("\tTrying to read data\n");
2293
		bzero(buf, sizeof buf);
2294
		bzero(&pfd, sizeof pfd);
2295
		pfd.fd = fd;
2296
		pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLHUP;
2297
		if ((nw = poll(&pfd, 1, poll_timeout)) > 0) {
2298
			if ((nw = read(fd, buf, sizeof(buf))) < 0) {
2299
				if (errno == EAGAIN) {
2300
					if (show_info)
2301
						php_printf("\tTrying again after errno = EAGAIN\n");
2302
					if (++retries < 3)
2303
						goto tryagain2;
2304
				}
2305
				if (show_info)
2306
					php_printf("\tError ocurred on 1st read\n");
2307
				goto errormodem;
2308
			}
2309

    
2310
			buf[2047] = '\0';
2311
			if (show_info)
2312
				php_printf("\tRead %s\n", buf);
2313
			//if (strnstr(buf, "OK", sizeof(buf)))
2314
			if (nw > 0) {
2315
				/*
2316
				write(fd, "ATI3\r\n", strlen("ATI3\r\n"));
2317
				bzero(buf, sizeof buf);
2318
				bzero(&pfd, sizeof pfd);
2319
				pfd.fd = fd;
2320
				pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLHUP;
2321

    
2322
				if (poll(&pfd, 1, 200) > 0) {
2323
					read(fd, buf, sizeof(buf));
2324
				buf[2047] = '\0';
2325
				if (show_info)
2326
					php_printf("\tRead %s\n", buf);
2327
				}
2328
				*/
2329
				add_assoc_string(return_value, path, path, 1);
2330
			}
2331
		} else if (show_info)
2332
			php_printf("\ttimedout or interrupted: %d\n", nw);
2333

    
2334
		tcsetattr(fd, TCSANOW, &origattr);
2335
errormodem:
2336
		if (show_info)
2337
			php_printf("\tClosing device %s\n", path);
2338
		close(fd);
2339
	}
2340
}
2341

    
2342
PHP_FUNCTION(pfSense_get_os_hw_data) {
2343
	int i, mib[4], idata;
2344
	size_t len;	
2345
	char *data;
2346

    
2347
	array_init(return_value);
2348

    
2349
	mib[0] = CTL_HW;
2350
	mib[1] = HW_MACHINE;
2351
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2352
		data = malloc(len);
2353
		if (data != NULL) {
2354
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2355
				add_assoc_string(return_value, "hwmachine", data, 1);
2356
				free(data);
2357
			}
2358
		}
2359
	}
2360

    
2361
	mib[0] = CTL_HW;
2362
	mib[1] = HW_MODEL;
2363
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2364
		data = malloc(len);
2365
		if (data != NULL) {
2366
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2367
				add_assoc_string(return_value, "hwmodel", data, 1);
2368
				free(data);
2369
			}
2370
		}
2371
	}
2372

    
2373
	mib[0] = CTL_HW;
2374
	mib[1] = HW_MACHINE_ARCH;
2375
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2376
		data = malloc(len);
2377
		if (data != NULL) {
2378
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2379
				add_assoc_string(return_value, "hwarch", data, 1);
2380
				free(data);
2381
			}
2382
		}
2383
	}
2384

    
2385
	mib[0] = CTL_HW;
2386
	mib[1] = HW_NCPU;
2387
	len = sizeof(idata);
2388
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2389
		add_assoc_long(return_value, "ncpus", idata);
2390

    
2391
	mib[0] = CTL_HW;
2392
	mib[1] = HW_PHYSMEM;
2393
	len = sizeof(idata);
2394
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2395
		add_assoc_long(return_value, "physmem", idata);
2396

    
2397
	mib[0] = CTL_HW;
2398
	mib[1] = HW_USERMEM;
2399
	len = sizeof(idata);
2400
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2401
		add_assoc_long(return_value, "usermem", idata);
2402

    
2403
	mib[0] = CTL_HW;
2404
	mib[1] = HW_REALMEM;
2405
	len = sizeof(idata);
2406
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2407
		add_assoc_long(return_value, "realmem", idata);
2408
}
2409

    
2410
PHP_FUNCTION(pfSense_get_os_kern_data) {
2411
	int i, mib[4], idata;
2412
	size_t len;
2413
	char *data;
2414
	struct timeval bootime;
2415

    
2416
	array_init(return_value);
2417

    
2418
	mib[0] = CTL_KERN;
2419
	mib[1] = KERN_HOSTUUID;
2420
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2421
		data = malloc(len);
2422
		if (data != NULL) {
2423
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2424
				add_assoc_string(return_value, "hostuuid", data, 1);
2425
				free(data);
2426
			}
2427
		}
2428
	}
2429

    
2430
	mib[0] = CTL_KERN;
2431
	mib[1] = KERN_HOSTNAME;
2432
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2433
		data = malloc(len);
2434
		if (data != NULL) {
2435
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2436
				add_assoc_string(return_value, "hostname", data, 1);
2437
				free(data);
2438
			}
2439
		}
2440
	}
2441

    
2442
	mib[0] = CTL_KERN;
2443
	mib[1] = KERN_OSRELEASE;
2444
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2445
		data = malloc(len);
2446
		if (data != NULL) {
2447
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2448
				add_assoc_string(return_value, "osrelease", data, 1);
2449
				free(data);
2450
			}
2451
		}
2452
	}
2453

    
2454
	mib[0] = CTL_KERN;
2455
	mib[1] = KERN_VERSION;
2456
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2457
		data = malloc(len);
2458
		if (data != NULL) {
2459
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2460
				add_assoc_string(return_value, "oskernel_version", data, 1);
2461
				free(data);
2462
			}
2463
		}
2464
	}
2465

    
2466
	mib[0] = CTL_KERN;
2467
	mib[1] = KERN_BOOTTIME;
2468
	len = sizeof(bootime);
2469
	if (!sysctl(mib, 2, &bootime, &len, NULL, 0))
2470
		add_assoc_string(return_value, "boottime", ctime(&bootime.tv_sec), 1);
2471

    
2472
	mib[0] = CTL_KERN;
2473
	mib[1] = KERN_HOSTID;
2474
	len = sizeof(idata);
2475
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2476
		add_assoc_long(return_value, "hostid", idata);
2477

    
2478
	mib[0] = CTL_KERN;
2479
	mib[1] = KERN_OSRELDATE;
2480
	len = sizeof(idata);
2481
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2482
		add_assoc_long(return_value, "osreleasedate", idata);
2483

    
2484
	mib[0] = CTL_KERN;
2485
	mib[1] = KERN_OSREV;
2486
	len = sizeof(idata);
2487
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2488
		add_assoc_long(return_value, "osrevision", idata);
2489

    
2490
	mib[0] = CTL_KERN;
2491
	mib[1] = KERN_SECURELVL;
2492
	len = sizeof(idata);
2493
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2494
		add_assoc_long(return_value, "ossecurelevel", idata);
2495

    
2496
	mib[0] = CTL_KERN;
2497
	mib[1] = KERN_OSRELDATE;
2498
	len = sizeof(idata);
2499
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2500
		add_assoc_long(return_value, "osreleasedate", idata);
2501

    
2502
	mib[0] = CTL_KERN;
2503
	mib[1] = KERN_OSRELDATE;
2504
	len = sizeof(idata);
2505
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2506
		add_assoc_long(return_value, "osreleasedate", idata);
2507
}
(4-4/6)