Projet

Général

Profil

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

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

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
	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
	} else if (!inet_pton(AF_INET, ip, &xent->k.addr6)) {
774
		efree(op3);
775
		RETURN_FALSE;
776
	}
777

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

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

    
786
	if (pipe)
787
		xent->value = (u_int32_t)pipe;
788

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

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

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

    
820
	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) {
821
		RETURN_FALSE;
822
	}
823

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

    
827

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

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

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

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

    
855
	RETURN_TRUE;
856
#endif
857
}
858

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

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

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

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

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

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

    
898
	if (!strchr(ip, ':'))
899
		xent->flags = IPFW_TCF_INET;
900

    
901
	if (mask)
902
		xent->masklen = (u_int8_t)mask;
903
	else
904
		xent->masklen = 32;
905

    
906
	if (mac_len > 0) {
907
		if (ether_aton_r(mac, (struct ether_addr *)&xent->mac_addr) == NULL)
908
			RETURN_FALSE;
909
		//xent->masklen += ETHER_ADDR_LEN;
910
	}
911

    
912
	xent->type = IPFW_TABLE_CIDR;
913
	size = sizeof(*op3) + sizeof(*xent);
914
	if (getsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW3, op3, &size) < 0) {
915
		efree(op3);
916
		RETURN_FALSE;
917
	}
918

    
919
	xent = (ipfw_table_xentry *)(op3);
920
	array_init(return_value);
921
	add_assoc_long(return_value, "packets", pfSense_align_uint64(&xent->packets));
922
	add_assoc_long(return_value, "bytes", pfSense_align_uint64(&xent->bytes));
923
	add_assoc_long(return_value, "timestamp", xent->timestamp);
924
	add_assoc_long(return_value, "dnpipe", xent->value);
925

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

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

    
941

    
942
	memset(&option, 0, sizeof(option));
943
	sprintf(option.context, "%s", name);
944

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

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

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

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

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

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

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

    
996
	data = emalloc(sizeof(*data));
997
	data->handle = conn;
998

    
999
	ZEND_REGISTER_RESOURCE(return_value, data, pfSense_dhcpd);
1000
}
1001

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

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

    
1018
	ZEND_FETCH_RESOURCE(conn, omapi_data *, &res, -1, PHP_PFSENSE_RES_NAME, pfSense_dhcpd);
1019
	ZEND_VERIFY_RESOURCE(conn);
1020

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

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

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

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

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

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

    
1070
	omapi_object_dereference(&hp,__FILE__,__LINE__);
1071

    
1072
	RETURN_TRUE;
1073
}
1074

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

    
1087
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &mac, &mac_len) == FAILURE) {
1088
		RETURN_FALSE;
1089
	}
1090

    
1091
	ZEND_FETCH_RESOURCE(conn, omapi_data *, &res, -1, PHP_PFSENSE_RES_NAME, pfSense_dhcpd);
1092
	ZEND_VERIFY_RESOURCE(conn);
1093

    
1094
	if ((status = dhcpctl_new_object(&hp, conn->handle, "host")))
1095
		RETURN_FALSE;
1096

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

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

    
1133
	RETURN_TRUE;
1134
}
1135

    
1136
PHP_FUNCTION(pfSense_close_dhcpd)
1137
{
1138
	zval *data;
1139

    
1140
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &data) == FAILURE) {
1141
		RETURN_FALSE;
1142
	}
1143

    
1144
	zend_list_delete(Z_LVAL_P(data));
1145

    
1146
	RETURN_TRUE;
1147
}
1148
#endif
1149

    
1150
PHP_FUNCTION(pfSense_ip_to_mac)
1151
{
1152
	char *ip = NULL, *rifname = NULL;
1153
	int ip_len, ifname_len = 0;
1154

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

    
1165
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &ip, &ip_len, &rifname, &ifname_len) == FAILURE)
1166
		RETURN_NULL();
1167

    
1168
	bzero(&addr, sizeof(addr));
1169
	if (!inet_pton(AF_INET, ip, &addr.sin_addr.s_addr))
1170
		RETURN_NULL();
1171
	addr.sin_len = sizeof(addr);
1172
	addr.sin_family = AF_INET;
1173

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

    
1220
	if (found_entry == 0)
1221
		RETURN_NULL();
1222

    
1223
	array_init(return_value);
1224
	bzero(outputbuf, sizeof outputbuf);
1225
	ether_ntoa_r((struct ether_addr *)LLADDR(sdl), outputbuf);
1226
	add_assoc_string(return_value, "macaddr", outputbuf, 1);
1227
}
1228

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

    
1239
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE)
1240
		RETURN_NULL();
1241

    
1242
	getifaddrs(&ifdata);
1243
	if (ifdata == NULL)
1244
		RETURN_NULL();
1245

    
1246
	array_init(return_value);
1247

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

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

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

    
1311
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE)
1312
		RETURN_NULL();
1313

    
1314
	getifaddrs(&ifdata);
1315
	if (ifdata == NULL)
1316
		RETURN_NULL();
1317

    
1318
	array_init(return_value);
1319

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

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

    
1501
			bzero(outputbuf, sizeof outputbuf);
1502
			inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1503
			add_assoc_string(return_value, "subnet", outputbuf, 1);
1504

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

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

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

    
1547
		break;
1548
		}
1549
	}
1550
	freeifaddrs(ifdata);
1551
}
1552

    
1553
PHP_FUNCTION(pfSense_bridge_add_member) {
1554
	char *ifname, *ifchld;
1555
	int ifname_len, ifchld_len;
1556
	struct ifdrv drv;
1557
	struct ifbreq req;
1558

    
1559
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ifchld, &ifchld_len) == FAILURE) {
1560
		RETURN_NULL();
1561
	}
1562

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

    
1573
	RETURN_TRUE;
1574
}
1575

    
1576
PHP_FUNCTION(pfSense_bridge_del_member) {
1577
	char *ifname, *ifchld;
1578
	int ifname_len, ifchld_len;
1579
	struct ifdrv drv;
1580
	struct ifbreq req;
1581

    
1582
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ifchld, &ifchld_len) == FAILURE) {
1583
		RETURN_NULL();
1584
	}
1585

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

    
1596
	RETURN_TRUE;
1597
}
1598

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

    
1606
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &ifname, &ifname_len, &ifchld, &ifchld_len, &flags) == FAILURE) {
1607
		RETURN_NULL();
1608
	}
1609

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

    
1620
	if (flags < 0) {
1621
		flags = -flags;
1622
		req.ifbr_ifsflags &= ~(int)flags;
1623
	} else
1624
		req.ifbr_ifsflags |= (int)flags;
1625

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

    
1632
	RETURN_TRUE;
1633
}
1634

    
1635
PHP_FUNCTION(pfSense_interface_listget) {
1636
	struct ifaddrs *ifdata, *mb;
1637
	char *ifname;
1638
	int ifname_len;
1639
	long flags = 0;
1640

    
1641
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE)
1642
		RETURN_NULL();
1643

    
1644
	getifaddrs(&ifdata);
1645
	if (ifdata == NULL)
1646
		RETURN_NULL();
1647

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

    
1655
		if (flags != 0) {
1656
			if (mb->ifa_flags & IFF_UP && flags < 0)
1657
				continue;
1658
			if (!(mb->ifa_flags & IFF_UP) && flags > 0)
1659
				continue;
1660
		}
1661

    
1662
		if (ifname != NULL && ifname_len == strlen(mb->ifa_name) && strcmp(ifname, mb->ifa_name) == 0)
1663
			continue;
1664
		ifname = mb->ifa_name;
1665
		ifname_len = strlen(mb->ifa_name);
1666

    
1667
		add_next_index_string(return_value, mb->ifa_name, 1);
1668
	}
1669

    
1670
	freeifaddrs(ifdata);
1671
}
1672

    
1673
PHP_FUNCTION(pfSense_interface_create) {
1674
	char *ifname;
1675
	int ifname_len, len;
1676
	struct ifreq ifr;
1677
	struct vlanreq params;
1678

    
1679
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1680
		RETURN_NULL();
1681
	}
1682

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

    
1692
PHP_FUNCTION(pfSense_interface_destroy) {
1693
	char *ifname;
1694
	int ifname_len;
1695
	struct ifreq ifr;
1696

    
1697
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1698
		RETURN_NULL();
1699
	}
1700

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

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

    
1716
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ip, &ip_len) == FAILURE) {
1717
		RETURN_NULL();
1718
	}
1719

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

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

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

    
1758
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ip, &ip_len) == FAILURE) {
1759
		RETURN_NULL();
1760
	}
1761

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

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

    
1777
PHP_FUNCTION(pfSense_interface_rename) {
1778
	char *ifname, *newifname;
1779
	int ifname_len, newifname_len;
1780
	struct ifreq ifr;
1781

    
1782
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1783
		RETURN_NULL();
1784
	}
1785

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

    
1796
PHP_FUNCTION(pfSense_ngctl_name) {
1797
	char *ifname, *newifname;
1798
	int ifname_len, newifname_len;
1799

    
1800
	if (PFSENSE_G(csock) == -1)
1801
		RETURN_NULL();
1802

    
1803
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1804
		RETURN_NULL();
1805
	}
1806

    
1807
	/* Send message */
1808
	if (NgNameNode(PFSENSE_G(csock), ifname, newifname) < 0)
1809
		RETURN_NULL();
1810

    
1811
	RETURN_TRUE;
1812
}
1813

    
1814
PHP_FUNCTION(pfSense_ngctl_attach) {
1815
	char *ifname, *newifname;
1816
	int ifname_len, newifname_len;
1817
	struct ngm_name name;
1818

    
1819
	if (PFSENSE_G(csock) == -1)
1820
		RETURN_NULL();
1821

    
1822
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1823
		RETURN_NULL();
1824
	}
1825

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

    
1832
	RETURN_TRUE;
1833
}
1834

    
1835
PHP_FUNCTION(pfSense_ngctl_detach) {
1836
	char *ifname, *newifname;
1837
	int ifname_len, newifname_len;
1838
	struct ngm_name name;
1839

    
1840
	if (PFSENSE_G(csock) == -1)
1841
		RETURN_NULL();
1842

    
1843
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1844
		RETURN_NULL();
1845
	}
1846

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

    
1853
	RETURN_TRUE;
1854
}
1855

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

    
1864
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &ifname, &ifname_len, &parentifname, &parent_len, &tag) == FAILURE) {
1865
		RETURN_NULL();
1866
	}
1867

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

    
1877
	RETURN_TRUE;
1878
}
1879

    
1880
PHP_FUNCTION(pfSense_interface_mtu) {
1881
	char *ifname;
1882
	int ifname_len;
1883
	long mtu;
1884
	struct ifreq ifr;
1885

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

    
1897
PHP_FUNCTION(pfSense_interface_flags) {
1898
	struct ifreq ifr;
1899
	char *ifname;
1900
	int flags, ifname_len;
1901
	long value;
1902

    
1903
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &value) == FAILURE) {
1904
		RETURN_NULL();
1905
	}
1906

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

    
1925
PHP_FUNCTION(pfSense_interface_capabilities) {
1926
	struct ifreq ifr;
1927
	char *ifname;
1928
	int flags, ifname_len;
1929
	long value;
1930

    
1931
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &value) == FAILURE) {
1932
		RETURN_NULL();
1933
	}
1934

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

    
1952
}
1953

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

    
1969
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1970
		RETURN_NULL();
1971
	}
1972

    
1973
	if ((dev = open("/dev/pf", O_RDWR)) < 0)
1974
		RETURN_NULL();
1975

    
1976
	getifaddrs(&ifdata);
1977
	if (ifdata == NULL) {
1978
		close(dev);
1979
		RETURN_NULL();
1980
	}
1981

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

    
1990
		if (found == 0)
1991
			array_init(return_value);
1992

    
1993
		found = 1;
1994

    
1995
		switch (mb->ifa_addr->sa_family) {
1996
		case AF_LINK:
1997

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

    
2007
		break;
2008
		}
2009
	}
2010
	freeifaddrs(ifdata);
2011

    
2012
	if (found == 0) {
2013
		close(dev);
2014
		RETURN_NULL();
2015
	}
2016

    
2017
	if (pfi_get_ifaces(dev, ifname, &kif, &size))
2018
		error = 1;
2019

    
2020
	if (error == 0) {
2021
		add_assoc_string(return_value, "interface", kif.pfik_name, 1);
2022

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

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

    
2036
		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]));
2037
		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]));
2038
		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]));
2039
		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]));
2040
#undef PPF_IN
2041
#undef PPF_OUT
2042
#undef PAF_INET
2043
	}
2044
	close(dev);
2045
}
2046

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

    
2058
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
2059
		RETURN_NULL();
2060
	}
2061

    
2062
	ifidx = if_nametoindex(ifname);
2063
	if (ifidx == 0)
2064
		RETURN_NULL();
2065

    
2066
	name[0] = CTL_NET;
2067
	name[1] = PF_LINK;
2068
	name[2] = NETLINK_GENERIC;
2069
	name[3] = IFMIB_IFDATA;
2070
	name[4] = ifidx;
2071
	name[5] = IFDATA_GENERAL;
2072

    
2073
	len = sizeof(ifmd);
2074

    
2075
	if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) < 0)
2076
		RETURN_NULL();
2077
	
2078
	tmpd = &ifmd.ifmd_data;
2079

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

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

    
2104
	array_init(return_value);
2105

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

    
2110

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

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

    
2139
		add_assoc_long(return_value, "statesearch", (unsigned long long)status.fcounters[FCNT_STATE_SEARCH]);
2140
		add_assoc_long(return_value, "stateinsert", (unsigned long long)status.fcounters[FCNT_STATE_INSERT]);
2141
		add_assoc_long(return_value, "stateremovals", (unsigned long long)status.fcounters[FCNT_STATE_REMOVALS]);
2142

    
2143
		add_assoc_long(return_value, "srcnodessearch", (unsigned long long)status.scounters[SCNT_SRC_NODE_SEARCH]);
2144
		add_assoc_long(return_value, "srcnodesinsert", (unsigned long long)status.scounters[SCNT_SRC_NODE_INSERT]);
2145
		add_assoc_long(return_value, "srcnodesremovals", (unsigned long long)status.scounters[SCNT_SRC_NODE_REMOVALS]);
2146

    
2147
#if (__FreeBSD_version < 1000000)
2148
		add_assoc_long(return_value, "stateid", (unsigned long long)status.stateid);
2149
#endif
2150

    
2151
		add_assoc_long(return_value, "running", status.running);
2152
		add_assoc_long(return_value, "states", status.states);
2153
		add_assoc_long(return_value, "srcnodes", status.src_nodes);
2154

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

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

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

    
2200
PHP_FUNCTION(pfSense_sync) {
2201
	sync();
2202
}
2203

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

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

    
2222
	array_init(return_value);
2223

    
2224
	bzero(&g, sizeof g);
2225
	glob("/dev/cua*", 0, NULL, &g);
2226
	glob("/dev/modem*", GLOB_APPEND, NULL, &g);
2227

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

    
2243
		/* Set non-blocking I/O  */
2244
		if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
2245
			goto errormodem;
2246

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

    
2251
		origattr = attr;
2252
		cfmakeraw(&attr);
2253

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

    
2261
#define MODEM_DEFAULT_SPEED              115200
2262
		cfsetspeed(&attr, (speed_t) MODEM_DEFAULT_SPEED);
2263
#undef	MODEM_DEFAULT_SPEED
2264

    
2265
		if (tcsetattr(fd, TCSANOW, &attr) < 0)
2266
			goto errormodem;
2267

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

    
2278
				if (show_info)
2279
					php_printf("\tError ocurred\n");
2280
				goto errormodem;
2281
			}
2282
		}
2283
		if (retries >= 3)
2284
			goto errormodem;
2285

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

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

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

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

    
2339
PHP_FUNCTION(pfSense_get_os_hw_data) {
2340
	int i, mib[4], idata;
2341
	size_t len;	
2342
	char *data;
2343

    
2344
	array_init(return_value);
2345

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

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

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

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

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

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

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

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

    
2413
	array_init(return_value);
2414

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

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

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

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

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

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

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

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

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

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

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