Projet

Général

Profil

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

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

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_XADD;
748
	int err;
749

    
750
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llls|lsl", &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|lsl", &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_XADD;
870
	int err;
871

    
872
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llls|sl", &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
	xent = (ipfw_table_xentry *)(op3);
924
	array_init(return_value);
925
	add_assoc_long(return_value, "packets", pfSense_align_uint64(&xent->packets));
926
	add_assoc_long(return_value, "bytes", pfSense_align_uint64(&xent->bytes));
927
	add_assoc_long(return_value, "timestamp", xent->timestamp);
928
	add_assoc_long(return_value, "dnpipe", xent->value);
929

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

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

    
945

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1076
	RETURN_TRUE;
1077
}
1078

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

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

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

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

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

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

    
1137
	RETURN_TRUE;
1138
}
1139

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

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

    
1148
	zend_list_delete(Z_LVAL_P(data));
1149

    
1150
	RETURN_TRUE;
1151
}
1152
#endif
1153

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

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

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

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

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

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

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

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

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

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

    
1250
	array_init(return_value);
1251

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

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

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

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

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

    
1322
	array_init(return_value);
1323

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

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

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

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

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

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

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

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

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

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

    
1577
	RETURN_TRUE;
1578
}
1579

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

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

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

    
1600
	RETURN_TRUE;
1601
}
1602

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

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

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

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

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

    
1636
	RETURN_TRUE;
1637
}
1638

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

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

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

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

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

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

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

    
1674
	freeifaddrs(ifdata);
1675
}
1676

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1815
	RETURN_TRUE;
1816
}
1817

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

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

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

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

    
1836
	RETURN_TRUE;
1837
}
1838

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

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

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

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

    
1857
	RETURN_TRUE;
1858
}
1859

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

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

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

    
1881
	RETURN_TRUE;
1882
}
1883

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

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

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

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

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

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

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

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

    
1956
}
1957

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

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

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

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

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

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

    
1997
		found = 1;
1998

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

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

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

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

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

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

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

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

    
2040
		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]));
2041
		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]));
2042
		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]));
2043
		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]));
2044
#undef PPF_IN
2045
#undef PPF_OUT
2046
#undef PAF_INET
2047
	}
2048
	close(dev);
2049
}
2050

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

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

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

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

    
2077
	len = sizeof(ifmd);
2078

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

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

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

    
2108
	array_init(return_value);
2109

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

    
2114

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

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

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

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

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

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

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

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

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

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

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

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

    
2226
	array_init(return_value);
2227

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2348
	array_init(return_value);
2349

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

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

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

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

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

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

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

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

    
2417
	array_init(return_value);
2418

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

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

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

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

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

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

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

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

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

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

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