Projet

Général

Profil

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

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

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, addrlen, 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
	size = sizeof(*op3) + sizeof(*xent);
758

    
759
	if ((op3 = (ip_fw3_opheader *)emalloc(size)) == NULL)
760
		RETURN_FALSE;
761

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

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

    
779
	if (!strchr(ip, ':')) {
780
		xent->flags = IPFW_TCF_INET;
781
		addrlen = sizeof(uint32_t);
782
	}
783

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

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

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

    
801
	xent->type = IPFW_TABLE_CIDR;
802
	xent->len = offsetof(ipfw_table_xentry, k) + addrlen;
803
	err = setsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW3, op3, size);
804
	if (err < 0 && err != EEXIST) {
805
		efree(op3);
806
		php_printf("Failed setsockopt");
807
		RETURN_FALSE;
808
	}
809
	efree(op3);
810

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

    
824
	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) {
825
		RETURN_FALSE;
826
	}
827

    
828
	memset(&option, 0, sizeof(option));
829
	sprintf(option.context, "%s", zone);
830

    
831

    
832
	if (action != IP_FW_TABLE_DEL && action != IP_FW_TABLE_ADD && action != IP_FW_TABLE_ZERO_ENTRY_STATS)
833
		RETURN_FALSE;
834

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

    
842
	if (mask)
843
		option.ent.masklen = (u_int8_t)mask;
844
	else
845
		option.ent.masklen = 32;
846
	if (pipe)
847
		option.ent.value = (u_int32_t)pipe;
848

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

    
859
	RETURN_TRUE;
860
#endif
861
}
862

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

    
875
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llls|sl", &zone, &action, &table, &ip, &ip_len, &mac, &mac_len, &mask) == FAILURE) {
876
		RETURN_FALSE;
877
	}
878

    
879
	if (action != IP_FW_TABLE_XLISTENTRY)
880
		RETURN_FALSE;
881

    
882
	size = sizeof(*op3) + sizeof(*xent);
883

    
884
	if ((op3 = (ip_fw3_opheader *)emalloc(size)) == NULL)
885
		RETURN_FALSE;
886

    
887
	memset(op3, 0, size);
888
	op3->ctxid = (uint16_t)zone;
889
	op3->opcode = IP_FW_TABLE_XLISTENTRY;
890
	xent = (ipfw_table_xentry *)(op3 + 1);
891
	xent->tbl = (u_int16_t)table;
892

    
893
	if (strchr(ip, ':')) {
894
		if (!inet_pton(AF_INET6, ip, &xent->k.addr6)) {
895
			efree(op3);
896
			RETURN_FALSE;
897
		}
898
		addrlen = sizeof(struct in6_addr);
899
	} else if (!inet_pton(AF_INET, ip, &xent->k.addr6)) {
900
		efree(op3);
901
		RETURN_FALSE;
902
	}
903

    
904
	if (!strchr(ip, ':')) {
905
		xent->flags = IPFW_TCF_INET;
906
		addrlen = sizeof(uint32_t);
907
	}
908

    
909
	if (mask)
910
		xent->masklen = (u_int8_t)mask;
911
	else
912
		xent->masklen = 32;
913

    
914
	if (mac_len > 0) {
915
		if (ether_aton_r(mac, (struct ether_addr *)&xent->mac_addr) == NULL)
916
			RETURN_FALSE;
917
		//xent->masklen += ETHER_ADDR_LEN;
918
	}
919

    
920
	xent->type = IPFW_TABLE_CIDR;
921
	xent->len = offsetof(ipfw_table_xentry, k) + addrlen;
922
	if (getsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW3, op3, &size) < 0) {
923
		efree(op3);
924
		RETURN_FALSE;
925
	}
926

    
927
	xent = (ipfw_table_xentry *)(op3);
928
	array_init(return_value);
929
	add_assoc_long(return_value, "packets", pfSense_align_uint64(&xent->packets));
930
	add_assoc_long(return_value, "bytes", pfSense_align_uint64(&xent->bytes));
931
	add_assoc_long(return_value, "timestamp", xent->timestamp);
932
	add_assoc_long(return_value, "dnpipe", xent->value);
933

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

    
945
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|l", &name, &name_len, &table, &ip, &ip_len, &mask) == FAILURE) {
946
		RETURN_FALSE;
947
	}
948

    
949

    
950
	memset(&option, 0, sizeof(option));
951
	sprintf(option.context, "%s", name);
952

    
953
	if (strchr(ip, ':')) {
954
		if (!inet_pton(AF_INET6, ip, &option.ent.addr))
955
			RETURN_FALSE;
956
	} else if (!inet_pton(AF_INET, ip, &option.ent.addr)) {
957
		RETURN_FALSE;
958
	}
959

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

    
969
	array_init(return_value);
970
	add_assoc_long(return_value, "packets", pfSense_align_uint64(&option.ent.packets));
971
	add_assoc_long(return_value, "bytes", pfSense_align_uint64(&option.ent.bytes));
972
	add_assoc_long(return_value, "timestamp", option.ent.timestamp);
973
	add_assoc_long(return_value, "dnpipe", option.ent.value);
974
#endif
975
}
976
#endif
977

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

    
988
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl", &name, &name_len, &key, &key_len, &addr, &addr_len, &port) == FAILURE) {
989
		RETURN_FALSE;
990
	}
991

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

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

    
1004
	data = emalloc(sizeof(*data));
1005
	data->handle = conn;
1006

    
1007
	ZEND_REGISTER_RESOURCE(return_value, data, pfSense_dhcpd);
1008
}
1009

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

    
1022
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zsss", &res, &name, &name_len, &mac, &mac_len, &ip, &ip_len) == FAILURE) {
1023
		RETURN_FALSE;
1024
	}
1025

    
1026
	ZEND_FETCH_RESOURCE(conn, omapi_data *, &res, -1, PHP_PFSENSE_RES_NAME, pfSense_dhcpd);
1027
	ZEND_VERIFY_RESOURCE(conn);
1028

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

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

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

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

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

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

    
1078
	omapi_object_dereference(&hp,__FILE__,__LINE__);
1079

    
1080
	RETURN_TRUE;
1081
}
1082

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

    
1095
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &mac, &mac_len) == FAILURE) {
1096
		RETURN_FALSE;
1097
	}
1098

    
1099
	ZEND_FETCH_RESOURCE(conn, omapi_data *, &res, -1, PHP_PFSENSE_RES_NAME, pfSense_dhcpd);
1100
	ZEND_VERIFY_RESOURCE(conn);
1101

    
1102
	if ((status = dhcpctl_new_object(&hp, conn->handle, "host")))
1103
		RETURN_FALSE;
1104

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

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

    
1141
	RETURN_TRUE;
1142
}
1143

    
1144
PHP_FUNCTION(pfSense_close_dhcpd)
1145
{
1146
	zval *data;
1147

    
1148
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &data) == FAILURE) {
1149
		RETURN_FALSE;
1150
	}
1151

    
1152
	zend_list_delete(Z_LVAL_P(data));
1153

    
1154
	RETURN_TRUE;
1155
}
1156
#endif
1157

    
1158
PHP_FUNCTION(pfSense_ip_to_mac)
1159
{
1160
	char *ip = NULL, *rifname = NULL;
1161
	int ip_len, ifname_len = 0;
1162

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

    
1173
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &ip, &ip_len, &rifname, &ifname_len) == FAILURE)
1174
		RETURN_NULL();
1175

    
1176
	bzero(&addr, sizeof(addr));
1177
	if (!inet_pton(AF_INET, ip, &addr.sin_addr.s_addr))
1178
		RETURN_NULL();
1179
	addr.sin_len = sizeof(addr);
1180
	addr.sin_family = AF_INET;
1181

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

    
1228
	if (found_entry == 0)
1229
		RETURN_NULL();
1230

    
1231
	array_init(return_value);
1232
	bzero(outputbuf, sizeof outputbuf);
1233
	ether_ntoa_r((struct ether_addr *)LLADDR(sdl), outputbuf);
1234
	add_assoc_string(return_value, "macaddr", outputbuf, 1);
1235
}
1236

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

    
1247
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE)
1248
		RETURN_NULL();
1249

    
1250
	getifaddrs(&ifdata);
1251
	if (ifdata == NULL)
1252
		RETURN_NULL();
1253

    
1254
	array_init(return_value);
1255

    
1256
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1257
		if (mb == NULL)
1258
			continue;
1259
		if (ifname_len != strlen(mb->ifa_name))
1260
			continue;
1261
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1262
			continue;
1263
		if (mb->ifa_addr == NULL)
1264
			continue;
1265

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

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

    
1319
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE)
1320
		RETURN_NULL();
1321

    
1322
	getifaddrs(&ifdata);
1323
	if (ifdata == NULL)
1324
		RETURN_NULL();
1325

    
1326
	array_init(return_value);
1327

    
1328
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1329
		if (mb == NULL)
1330
			continue;
1331
		if (ifname_len != strlen(mb->ifa_name))
1332
			continue;
1333
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1334
			continue;
1335

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

    
1509
			bzero(outputbuf, sizeof outputbuf);
1510
			inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1511
			add_assoc_string(return_value, "subnet", outputbuf, 1);
1512

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

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

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

    
1555
		break;
1556
		}
1557
	}
1558
	freeifaddrs(ifdata);
1559
}
1560

    
1561
PHP_FUNCTION(pfSense_bridge_add_member) {
1562
	char *ifname, *ifchld;
1563
	int ifname_len, ifchld_len;
1564
	struct ifdrv drv;
1565
	struct ifbreq req;
1566

    
1567
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ifchld, &ifchld_len) == FAILURE) {
1568
		RETURN_NULL();
1569
	}
1570

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

    
1581
	RETURN_TRUE;
1582
}
1583

    
1584
PHP_FUNCTION(pfSense_bridge_del_member) {
1585
	char *ifname, *ifchld;
1586
	int ifname_len, ifchld_len;
1587
	struct ifdrv drv;
1588
	struct ifbreq req;
1589

    
1590
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ifchld, &ifchld_len) == FAILURE) {
1591
		RETURN_NULL();
1592
	}
1593

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

    
1604
	RETURN_TRUE;
1605
}
1606

    
1607
PHP_FUNCTION(pfSense_bridge_member_flags) {
1608
	char *ifname, *ifchld;
1609
	int ifname_len, ifchld_len;
1610
	struct ifdrv drv;
1611
	struct ifbreq req;
1612
	long flags = 0;
1613

    
1614
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &ifname, &ifname_len, &ifchld, &ifchld_len, &flags) == FAILURE) {
1615
		RETURN_NULL();
1616
	}
1617

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

    
1628
	if (flags < 0) {
1629
		flags = -flags;
1630
		req.ifbr_ifsflags &= ~(int)flags;
1631
	} else
1632
		req.ifbr_ifsflags |= (int)flags;
1633

    
1634
	drv.ifd_cmd = BRDGSIFFLGS;
1635
	drv.ifd_data = &req;
1636
	drv.ifd_len = sizeof(req);
1637
	if (ioctl(PFSENSE_G(s), SIOCSDRVSPEC, (caddr_t)&drv) < 0)
1638
		RETURN_FALSE;
1639

    
1640
	RETURN_TRUE;
1641
}
1642

    
1643
PHP_FUNCTION(pfSense_interface_listget) {
1644
	struct ifaddrs *ifdata, *mb;
1645
	char *ifname;
1646
	int ifname_len;
1647
	long flags = 0;
1648

    
1649
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE)
1650
		RETURN_NULL();
1651

    
1652
	getifaddrs(&ifdata);
1653
	if (ifdata == NULL)
1654
		RETURN_NULL();
1655

    
1656
	array_init(return_value);
1657
	ifname = NULL;
1658
	ifname_len = 0;
1659
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1660
		if (mb == NULL)
1661
			continue;
1662

    
1663
		if (flags != 0) {
1664
			if (mb->ifa_flags & IFF_UP && flags < 0)
1665
				continue;
1666
			if (!(mb->ifa_flags & IFF_UP) && flags > 0)
1667
				continue;
1668
		}
1669

    
1670
		if (ifname != NULL && ifname_len == strlen(mb->ifa_name) && strcmp(ifname, mb->ifa_name) == 0)
1671
			continue;
1672
		ifname = mb->ifa_name;
1673
		ifname_len = strlen(mb->ifa_name);
1674

    
1675
		add_next_index_string(return_value, mb->ifa_name, 1);
1676
	}
1677

    
1678
	freeifaddrs(ifdata);
1679
}
1680

    
1681
PHP_FUNCTION(pfSense_interface_create) {
1682
	char *ifname;
1683
	int ifname_len, len;
1684
	struct ifreq ifr;
1685
	struct vlanreq params;
1686

    
1687
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1688
		RETURN_NULL();
1689
	}
1690

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

    
1700
PHP_FUNCTION(pfSense_interface_destroy) {
1701
	char *ifname;
1702
	int ifname_len;
1703
	struct ifreq ifr;
1704

    
1705
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1706
		RETURN_NULL();
1707
	}
1708

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

    
1718
PHP_FUNCTION(pfSense_interface_setaddress) {
1719
	char *ifname, *ip, *p = NULL;
1720
	int ifname_len, ip_len;
1721
	struct sockaddr_in *sin;
1722
	struct in_aliasreq ifra;
1723

    
1724
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ip, &ip_len) == FAILURE) {
1725
		RETURN_NULL();
1726
	}
1727

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

    
1753
	if (ioctl(PFSENSE_G(inets), SIOCAIFADDR, &ifra) < 0) {
1754
		array_init(return_value);
1755
		add_assoc_string(return_value, "error", "Could not set interface address", 1);
1756
	} else
1757
		RETURN_TRUE;
1758
}
1759

    
1760
PHP_FUNCTION(pfSense_interface_deladdress) {
1761
	char *ifname, *ip = NULL;
1762
	int ifname_len, ip_len;
1763
	struct sockaddr_in *sin;
1764
	struct in_aliasreq ifra;
1765

    
1766
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ip, &ip_len) == FAILURE) {
1767
		RETURN_NULL();
1768
	}
1769

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

    
1778
	if (ioctl(PFSENSE_G(inets), SIOCDIFADDR, &ifra) < 0) {
1779
		array_init(return_value);
1780
		add_assoc_string(return_value, "error", "Could not delete interface address", 1);
1781
	} else
1782
		RETURN_TRUE;
1783
}
1784

    
1785
PHP_FUNCTION(pfSense_interface_rename) {
1786
	char *ifname, *newifname;
1787
	int ifname_len, newifname_len;
1788
	struct ifreq ifr;
1789

    
1790
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1791
		RETURN_NULL();
1792
	}
1793

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

    
1804
PHP_FUNCTION(pfSense_ngctl_name) {
1805
	char *ifname, *newifname;
1806
	int ifname_len, newifname_len;
1807

    
1808
	if (PFSENSE_G(csock) == -1)
1809
		RETURN_NULL();
1810

    
1811
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1812
		RETURN_NULL();
1813
	}
1814

    
1815
	/* Send message */
1816
	if (NgNameNode(PFSENSE_G(csock), ifname, newifname) < 0)
1817
		RETURN_NULL();
1818

    
1819
	RETURN_TRUE;
1820
}
1821

    
1822
PHP_FUNCTION(pfSense_ngctl_attach) {
1823
	char *ifname, *newifname;
1824
	int ifname_len, newifname_len;
1825
	struct ngm_name name;
1826

    
1827
	if (PFSENSE_G(csock) == -1)
1828
		RETURN_NULL();
1829

    
1830
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1831
		RETURN_NULL();
1832
	}
1833

    
1834
	snprintf(name.name, sizeof(name.name), "%s", newifname);
1835
	/* Send message */
1836
	if (NgSendMsg(PFSENSE_G(csock), ifname, NGM_GENERIC_COOKIE,
1837
		NGM_ETHER_ATTACH, &name, sizeof(name)) < 0)
1838
			RETURN_NULL();
1839

    
1840
	RETURN_TRUE;
1841
}
1842

    
1843
PHP_FUNCTION(pfSense_ngctl_detach) {
1844
	char *ifname, *newifname;
1845
	int ifname_len, newifname_len;
1846
	struct ngm_name name;
1847

    
1848
	if (PFSENSE_G(csock) == -1)
1849
		RETURN_NULL();
1850

    
1851
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1852
		RETURN_NULL();
1853
	}
1854

    
1855
	snprintf(name.name, sizeof(name.name), "%s", newifname);
1856
	/* Send message */
1857
	if (NgSendMsg(PFSENSE_G(csock), ifname, NGM_ETHER_COOKIE,
1858
		NGM_ETHER_DETACH, &name, sizeof(name)) < 0)
1859
			RETURN_NULL();
1860

    
1861
	RETURN_TRUE;
1862
}
1863

    
1864
PHP_FUNCTION(pfSense_vlan_create) {
1865
	char *ifname = NULL;
1866
	char *parentifname = NULL;
1867
	int ifname_len, parent_len;
1868
	long tag; 
1869
	struct ifreq ifr;
1870
	struct vlanreq params;
1871

    
1872
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &ifname, &ifname_len, &parentifname, &parent_len, &tag) == FAILURE) {
1873
		RETURN_NULL();
1874
	}
1875

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

    
1885
	RETURN_TRUE;
1886
}
1887

    
1888
PHP_FUNCTION(pfSense_interface_mtu) {
1889
	char *ifname;
1890
	int ifname_len;
1891
	long mtu;
1892
	struct ifreq ifr;
1893

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

    
1905
PHP_FUNCTION(pfSense_interface_flags) {
1906
	struct ifreq ifr;
1907
	char *ifname;
1908
	int flags, ifname_len;
1909
	long value;
1910

    
1911
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &value) == FAILURE) {
1912
		RETURN_NULL();
1913
	}
1914

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

    
1933
PHP_FUNCTION(pfSense_interface_capabilities) {
1934
	struct ifreq ifr;
1935
	char *ifname;
1936
	int flags, ifname_len;
1937
	long value;
1938

    
1939
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &value) == FAILURE) {
1940
		RETURN_NULL();
1941
	}
1942

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

    
1960
}
1961

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

    
1977
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1978
		RETURN_NULL();
1979
	}
1980

    
1981
	if ((dev = open("/dev/pf", O_RDWR)) < 0)
1982
		RETURN_NULL();
1983

    
1984
	getifaddrs(&ifdata);
1985
	if (ifdata == NULL) {
1986
		close(dev);
1987
		RETURN_NULL();
1988
	}
1989

    
1990
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1991
		if (mb == NULL)
1992
			continue;
1993
		if (ifname_len != strlen(mb->ifa_name))
1994
			continue;
1995
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1996
			continue;
1997

    
1998
		if (found == 0)
1999
			array_init(return_value);
2000

    
2001
		found = 1;
2002

    
2003
		switch (mb->ifa_addr->sa_family) {
2004
		case AF_LINK:
2005

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

    
2015
		break;
2016
		}
2017
	}
2018
	freeifaddrs(ifdata);
2019

    
2020
	if (found == 0) {
2021
		close(dev);
2022
		RETURN_NULL();
2023
	}
2024

    
2025
	if (pfi_get_ifaces(dev, ifname, &kif, &size))
2026
		error = 1;
2027

    
2028
	if (error == 0) {
2029
		add_assoc_string(return_value, "interface", kif.pfik_name, 1);
2030

    
2031
#define PAF_INET 0
2032
#define PPF_IN 0
2033
#define PPF_OUT 1
2034
		add_assoc_long(return_value, "inpktspass", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_IN][PF_PASS]);
2035
		add_assoc_long(return_value, "outpktspass", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_OUT][PF_PASS]);
2036
		add_assoc_long(return_value, "inbytespass", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_IN][PF_PASS]);
2037
		add_assoc_long(return_value, "outbytespass", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_OUT][PF_PASS]);
2038

    
2039
		add_assoc_long(return_value, "inpktsblock", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_IN][PF_DROP]);
2040
		add_assoc_long(return_value, "outpktsblock", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_OUT][PF_DROP]);
2041
		add_assoc_long(return_value, "inbytesblock", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_IN][PF_DROP]);
2042
		add_assoc_long(return_value, "outbytesblock", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_OUT][PF_DROP]);
2043

    
2044
		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]));
2045
		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]));
2046
		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]));
2047
		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]));
2048
#undef PPF_IN
2049
#undef PPF_OUT
2050
#undef PAF_INET
2051
	}
2052
	close(dev);
2053
}
2054

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

    
2066
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
2067
		RETURN_NULL();
2068
	}
2069

    
2070
	ifidx = if_nametoindex(ifname);
2071
	if (ifidx == 0)
2072
		RETURN_NULL();
2073

    
2074
	name[0] = CTL_NET;
2075
	name[1] = PF_LINK;
2076
	name[2] = NETLINK_GENERIC;
2077
	name[3] = IFMIB_IFDATA;
2078
	name[4] = ifidx;
2079
	name[5] = IFDATA_GENERAL;
2080

    
2081
	len = sizeof(ifmd);
2082

    
2083
	if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) < 0)
2084
		RETURN_NULL();
2085
	
2086
	tmpd = &ifmd.ifmd_data;
2087

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

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

    
2112
	array_init(return_value);
2113

    
2114
	if ((dev = open("/dev/pf", O_RDWR)) < 0) {
2115
		add_assoc_string(return_value, "error", strerror(errno), 1);
2116
	} else {
2117

    
2118

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

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

    
2147
		add_assoc_long(return_value, "statesearch", (unsigned long long)status.fcounters[FCNT_STATE_SEARCH]);
2148
		add_assoc_long(return_value, "stateinsert", (unsigned long long)status.fcounters[FCNT_STATE_INSERT]);
2149
		add_assoc_long(return_value, "stateremovals", (unsigned long long)status.fcounters[FCNT_STATE_REMOVALS]);
2150

    
2151
		add_assoc_long(return_value, "srcnodessearch", (unsigned long long)status.scounters[SCNT_SRC_NODE_SEARCH]);
2152
		add_assoc_long(return_value, "srcnodesinsert", (unsigned long long)status.scounters[SCNT_SRC_NODE_INSERT]);
2153
		add_assoc_long(return_value, "srcnodesremovals", (unsigned long long)status.scounters[SCNT_SRC_NODE_REMOVALS]);
2154

    
2155
#if (__FreeBSD_version < 1000000)
2156
		add_assoc_long(return_value, "stateid", (unsigned long long)status.stateid);
2157
#endif
2158

    
2159
		add_assoc_long(return_value, "running", status.running);
2160
		add_assoc_long(return_value, "states", status.states);
2161
		add_assoc_long(return_value, "srcnodes", status.src_nodes);
2162

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

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

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

    
2208
PHP_FUNCTION(pfSense_sync) {
2209
	sync();
2210
}
2211

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

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

    
2230
	array_init(return_value);
2231

    
2232
	bzero(&g, sizeof g);
2233
	glob("/dev/cua*", 0, NULL, &g);
2234
	glob("/dev/modem*", GLOB_APPEND, NULL, &g);
2235

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

    
2251
		/* Set non-blocking I/O  */
2252
		if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
2253
			goto errormodem;
2254

    
2255
		/* Set serial port raw mode, baud rate, hardware flow control, etc. */
2256
		if (tcgetattr(fd, &attr) < 0)
2257
			goto errormodem;
2258

    
2259
		origattr = attr;
2260
		cfmakeraw(&attr);
2261

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

    
2269
#define MODEM_DEFAULT_SPEED              115200
2270
		cfsetspeed(&attr, (speed_t) MODEM_DEFAULT_SPEED);
2271
#undef	MODEM_DEFAULT_SPEED
2272

    
2273
		if (tcsetattr(fd, TCSANOW, &attr) < 0)
2274
			goto errormodem;
2275

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

    
2286
				if (show_info)
2287
					php_printf("\tError ocurred\n");
2288
				goto errormodem;
2289
			}
2290
		}
2291
		if (retries >= 3)
2292
			goto errormodem;
2293

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

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

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

    
2339
		tcsetattr(fd, TCSANOW, &origattr);
2340
errormodem:
2341
		if (show_info)
2342
			php_printf("\tClosing device %s\n", path);
2343
		close(fd);
2344
	}
2345
}
2346

    
2347
PHP_FUNCTION(pfSense_get_os_hw_data) {
2348
	int i, mib[4], idata;
2349
	size_t len;	
2350
	char *data;
2351

    
2352
	array_init(return_value);
2353

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

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

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

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

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

    
2402
	mib[0] = CTL_HW;
2403
	mib[1] = HW_USERMEM;
2404
	len = sizeof(idata);
2405
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2406
		add_assoc_long(return_value, "usermem", idata);
2407

    
2408
	mib[0] = CTL_HW;
2409
	mib[1] = HW_REALMEM;
2410
	len = sizeof(idata);
2411
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2412
		add_assoc_long(return_value, "realmem", idata);
2413
}
2414

    
2415
PHP_FUNCTION(pfSense_get_os_kern_data) {
2416
	int i, mib[4], idata;
2417
	size_t len;
2418
	char *data;
2419
	struct timeval bootime;
2420

    
2421
	array_init(return_value);
2422

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

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

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

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

    
2471
	mib[0] = CTL_KERN;
2472
	mib[1] = KERN_BOOTTIME;
2473
	len = sizeof(bootime);
2474
	if (!sysctl(mib, 2, &bootime, &len, NULL, 0))
2475
		add_assoc_string(return_value, "boottime", ctime(&bootime.tv_sec), 1);
2476

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

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

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

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

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

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