Projet

Général

Profil

Télécharger (71,8 ko) Statistiques
| Branche: | Révision:

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

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

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

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

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

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

    
26
*/
27

    
28
/*
29

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

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

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

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

    
67
*/
68

    
69
#define IS_EXT_MODULE
70

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

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

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

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

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

    
106
#include <netinet/ip_fw.h>
107

    
108
#include <vm/vm_param.h>
109

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

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

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

    
123
int pfSense_dhcpd;
124

    
125
ZEND_DECLARE_MODULE_GLOBALS(pfSense)
126

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

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

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

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

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

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

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

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

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

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

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

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

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

    
281
		PFSENSE_G(csock) = csock;
282

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

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

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

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

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

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

    
346
	return SUCCESS;
347
}
348

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

    
358
	return SUCCESS;
359
}
360

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

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

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

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

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

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

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

    
416
	return (0);
417
}
418

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

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

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

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

    
438
	killed = sources = dests = 0;
439

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

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

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

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

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

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

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

    
500
				dests++;
501

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

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

    
534
	freeaddrinfo(res[0]);
535

    
536
	RETURN_TRUE;
537
}
538

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

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

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

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

    
558
	killed = sources = dests = 0;
559

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

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

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

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

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

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

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

    
628
				dests++;
629

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

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

    
661
	freeaddrinfo(res[0]);
662

    
663
	RETURN_TRUE;
664
}
665

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

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

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

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

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

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

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

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

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

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

    
735
	RETURN_TRUE;
736
}
737

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

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

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

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

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

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

    
777
	if (mask)
778
		xent->masklen = (u_int8_t)mask;
779
	else
780
		xent->masklen = 32;
781

    
782
	if (pipe)
783
		xent->value = (u_int32_t)pipe;
784

    
785
	if (mac_len > 0) {
786
		if (ether_aton_r(mac, (struct ether_addr *)&xent->mac_addr) == NULL) {
787
			efree(op3);
788
			RETURN_FALSE;
789
		}
790
		//xent->masklen += ETHER_ADDR_LEN;
791
	}
792

    
793
	xent->type = IPFW_TABLE_CIDR;
794
	size = sizeof(*op3) + sizeof(*xent);
795
	err = setsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW3, op3, size);
796
	if (err < 0 && err != EEXIST) {
797
		efree(op3);
798
		RETURN_FALSE;
799
	}
800
	efree(op3);
801

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

    
815
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slls|l!sl", &zone, &zone_len, &action, &table, &ip, &ip_len, &mask, &mac, &mac_len, &pipe) == FAILURE) {
816
		RETURN_FALSE;
817
	}
818

    
819
	memset(&option, 0, sizeof(option));
820
	sprintf(option.context, "%s", zone);
821

    
822

    
823
	if (action != IP_FW_TABLE_DEL && action != IP_FW_TABLE_ADD && action != IP_FW_TABLE_ZERO_ENTRY_STATS)
824
		RETURN_FALSE;
825

    
826
	if (strchr(ip, ':')) {
827
		if (!inet_pton(AF_INET6, ip, &option.ent.addr))
828
			RETURN_FALSE;
829
	} else if (!inet_pton(AF_INET, ip, &option.ent.addr)) {
830
		RETURN_FALSE;
831
	}
832

    
833
	if (mask)
834
		option.ent.masklen = (u_int8_t)mask;
835
	else
836
		option.ent.masklen = 32;
837
	if (pipe)
838
		option.ent.value = (u_int32_t)pipe;
839

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

    
850
	RETURN_TRUE;
851
#endif
852
}
853

    
854
PHP_FUNCTION(pfSense_ipfw_getTablestats)
855
{
856
#if (__FreeBSD_version >= 1000000)
857
	ip_fw3_opheader *op3;
858
	ipfw_table_xentry *xent;
859
	socklen_t size;
860
	long mask = 0, table = 0, zone = 0;
861
	char *ip, *mac = NULL, *p;
862
	int ip_len, mac_len = 0;
863
	long action = IP_FW_TABLE_ADD;
864
	int err;
865

    
866
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llls!s|l", &zone, &action, &table, &ip, &ip_len, &mac, &mac_len, &mask) == FAILURE) {
867
		RETURN_FALSE;
868
	}
869

    
870
	if (action != IP_FW_TABLE_XLISTENTRY)
871
		RETURN_FALSE;
872

    
873
	if ((op3 = emalloc(sizeof(*op3) + sizeof(*xent))) == NULL)
874
		RETURN_FALSE;
875

    
876
	memset(op3, 0, sizeof(*op3));
877
	op3->ctxid = (uint16_t)zone;
878
	op3->opcode = IP_FW_TABLE_XLISTENTRY;
879
	xent = (ipfw_table_xentry *)(op3 + 1);
880
	memset(xent, 0, sizeof(*xent));
881
	xent->tbl = (u_int16_t)table;
882

    
883
	if (strchr(ip, ':')) {
884
		if (!inet_pton(AF_INET6, ip, &xent->k.addr6))
885
			RETURN_FALSE;
886
	} else if (!inet_pton(AF_INET, ip, &xent->k.addr6)) {
887
		RETURN_FALSE;
888
	}
889

    
890
	if (mask)
891
		xent->masklen = (u_int8_t)mask;
892
	else
893
		xent->masklen = 32;
894

    
895
	if (mac_len > 0) {
896
		if (ether_aton_r(mac, (struct ether_addr *)&xent->k.mix.mac) == NULL)
897
			RETURN_FALSE;
898
		xent->masklen += ETHER_ADDR_LEN;
899
	}
900

    
901
	xent->type = IPFW_TABLE_MIX;
902
	size = sizeof(*op3) + sizeof(*xent);
903
	if (getsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW3, op3, &size) < 0) {
904
		efree(op3);
905
		RETURN_FALSE;
906
	}
907

    
908
	array_init(return_value);
909
	add_assoc_long(return_value, "packets", pfSense_align_uint64(&xent->packets));
910
	add_assoc_long(return_value, "bytes", pfSense_align_uint64(&xent->bytes));
911
	add_assoc_long(return_value, "timestamp", xent->timestamp);
912
	add_assoc_long(return_value, "dnpipe", xent->value);
913

    
914
	efree(op3);
915
#else
916
	struct {
917
		char context[64]; /* IP_FW_CTX_MAXNAME */
918
		ipfw_table_entry ent;
919
	} option;
920
	socklen_t size;
921
	long mask = 0, table = 0;
922
	char *ip, *name;
923
	int ip_len, name_len;
924

    
925
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|l", &name, &name_len, &table, &ip, &ip_len, &mask) == FAILURE) {
926
		RETURN_FALSE;
927
	}
928

    
929

    
930
	memset(&option, 0, sizeof(option));
931
	sprintf(option.context, "%s", name);
932

    
933
	if (strchr(ip, ':')) {
934
		if (!inet_pton(AF_INET6, ip, &option.ent.addr))
935
			RETURN_FALSE;
936
	} else if (!inet_pton(AF_INET, ip, &option.ent.addr)) {
937
		RETURN_FALSE;
938
	}
939

    
940
	if (mask)
941
		option.ent.masklen = (u_int8_t)mask;
942
	else
943
		option.ent.masklen = 32;
944
	size = sizeof(option);
945
	option.ent.tbl = (u_int16_t)table;
946
	if (getsockopt(PFSENSE_G(ipfw), IPPROTO_IP, IP_FW_TABLE_GET_ENTRY, &option, &size) < 0)
947
		RETURN_FALSE;
948

    
949
	array_init(return_value);
950
	add_assoc_long(return_value, "packets", pfSense_align_uint64(&option.ent.packets));
951
	add_assoc_long(return_value, "bytes", pfSense_align_uint64(&option.ent.bytes));
952
	add_assoc_long(return_value, "timestamp", option.ent.timestamp);
953
	add_assoc_long(return_value, "dnpipe", option.ent.value);
954
#endif
955
}
956
#endif
957

    
958
#ifdef DHCP_INTEGRATION
959
PHP_FUNCTION(pfSense_open_dhcpd)
960
{
961
	omapi_data *data;
962
	char *key, *addr, *name;
963
	int key_len, addr_len, name_len;
964
	long port;
965
	dhcpctl_status status;
966
	dhcpctl_handle auth = dhcpctl_null_handle, conn = dhcpctl_null_handle;
967

    
968
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl", &name, &name_len, &key, &key_len, &addr, &addr_len, &port) == FAILURE) {
969
		RETURN_FALSE;
970
	}
971

    
972
	status = dhcpctl_new_authenticator(&auth, name, "hmac-md5", key, key_len);
973
	if (status != ISC_R_SUCCESS) {
974
		//php_printf("Failed to get aythenticator: %s - %s\n", isc_result_totext(status), key);
975
		RETURN_NULL();
976
	}
977

    
978
	status = dhcpctl_connect(&conn, addr, (int)port, auth);
979
	if (status != ISC_R_SUCCESS) {
980
		//php_printf("Error occured during connecting: %s\n", isc_result_totext(status));
981
		RETURN_NULL();
982
	}
983

    
984
	data = emalloc(sizeof(*data));
985
	data->handle = conn;
986

    
987
	ZEND_REGISTER_RESOURCE(return_value, data, pfSense_dhcpd);
988
}
989

    
990
PHP_FUNCTION(pfSense_register_lease)
991
{
992
	dhcpctl_status status = ISC_R_SUCCESS;
993
	dhcpctl_status status2 = ISC_R_SUCCESS;
994
	dhcpctl_handle hp = NULL;
995
	struct ether_addr *ds;
996
	struct in_addr nds;
997
	char *mac, *ip, *name;
998
	int mac_len, ip_len, name_len;
999
	zval *res;
1000
	omapi_data *conn;
1001

    
1002
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zsss", &res, &name, &name_len, &mac, &mac_len, &ip, &ip_len) == FAILURE) {
1003
		RETURN_FALSE;
1004
	}
1005

    
1006
	ZEND_FETCH_RESOURCE(conn, omapi_data *, &res, -1, PHP_PFSENSE_RES_NAME, pfSense_dhcpd);
1007
	ZEND_VERIFY_RESOURCE(conn);
1008

    
1009
	if ((status = dhcpctl_new_object(&hp, conn->handle, "host")) != ISC_R_SUCCESS) {
1010
		//php_printf("1Error occured during connecting: %s\n", isc_result_totext(status));
1011
		RETURN_FALSE;
1012
	}
1013

    
1014
	inet_aton(ip, &nds);
1015
	if ((status = dhcpctl_set_data_value(hp, (char *)&nds, sizeof(struct in_addr), "ip-address")) != ISC_R_SUCCESS) {
1016
		//php_printf("3Error occured during connecting: %s\n", isc_result_totext(status));
1017
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1018
		RETURN_FALSE;
1019
	}
1020

    
1021
	if ((status = dhcpctl_set_string_value(hp, name, "name")) != ISC_R_SUCCESS) {
1022
		//php_printf("4Error occured during connecting: %s\n", isc_result_totext(status));
1023
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1024
		RETURN_FALSE;
1025
	}
1026

    
1027
	if (!(ds = ether_aton(mac)))
1028
		RETURN_FALSE;
1029
	if ((status = dhcpctl_set_data_value(hp, (u_char *)ds, sizeof(struct ether_addr), "hardware-address")) != ISC_R_SUCCESS) {
1030
		//php_printf("2Error occured during connecting: %s\n", isc_result_totext(status));
1031
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1032
		RETURN_FALSE;
1033
	}
1034

    
1035
	if ((status= dhcpctl_set_int_value(hp, 1,"hardware-type")) != ISC_R_SUCCESS)  {
1036
		//php_printf("2Error occured during connecting: %s\n", isc_result_totext(status));
1037
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1038
		RETURN_FALSE;
1039
	}
1040

    
1041
	//php_printf("Coonection handle %d\n", conn->handle);
1042
	if ((status = dhcpctl_open_object(hp, conn->handle, DHCPCTL_CREATE|DHCPCTL_EXCL)) != ISC_R_SUCCESS) {
1043
		//php_printf("5Error occured during connecting: %s\n", isc_result_totext(status));
1044
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1045
		RETURN_FALSE;
1046
	}
1047
        if ((status = dhcpctl_wait_for_completion(hp, &status2)) != ISC_R_SUCCESS) {
1048
		//php_printf("6Error occured during connecting: %s-  %s\n", isc_result_totext(status), isc_result_totext(status2));
1049
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1050
		RETURN_FALSE;
1051
	}
1052
	if (status2 != ISC_R_SUCCESS) {
1053
		//php_printf("7Error occured during connecting: %s\n", isc_result_totext(status2));
1054
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1055
		RETURN_FALSE;
1056
	}
1057

    
1058
	omapi_object_dereference(&hp,__FILE__,__LINE__);
1059

    
1060
	RETURN_TRUE;
1061
}
1062

    
1063
PHP_FUNCTION(pfSense_delete_lease)
1064
{
1065
	dhcpctl_status status;
1066
	dhcpctl_status status2;
1067
	dhcpctl_handle hp = NULL;
1068
	dhcpctl_data_string ds = NULL;
1069
	omapi_data_string_t *nds;
1070
	char *mac;
1071
	int mac_len;
1072
	zval *res;
1073
	omapi_data *conn;
1074

    
1075
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &mac, &mac_len) == FAILURE) {
1076
		RETURN_FALSE;
1077
	}
1078

    
1079
	ZEND_FETCH_RESOURCE(conn, omapi_data *, &res, -1, PHP_PFSENSE_RES_NAME, pfSense_dhcpd);
1080
	ZEND_VERIFY_RESOURCE(conn);
1081

    
1082
	if ((status = dhcpctl_new_object(&hp, conn->handle, "host")))
1083
		RETURN_FALSE;
1084

    
1085
	if (mac) {
1086
		omapi_data_string_new(&ds, sizeof(struct ether_addr), __FILE__, __LINE__);
1087
		memcpy(ds->value,ether_aton(mac),sizeof(struct ether_addr));
1088
		if ((status = dhcpctl_set_value(hp, ds, "hardware-address"))) {
1089
			omapi_object_dereference(&hp,__FILE__,__LINE__);
1090
			RETURN_FALSE;
1091
		}
1092
	} else
1093
		RETURN_FALSE;
1094

    
1095
	if ((status = dhcpctl_open_object(hp, conn->handle, 0))) {
1096
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1097
		RETURN_FALSE;
1098
	}
1099
	if ((status = dhcpctl_wait_for_completion(hp, &status2))) {
1100
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1101
		RETURN_FALSE;
1102
	}
1103
	if (status2) {
1104
		omapi_object_dereference(&hp,__FILE__,__LINE__);
1105
		RETURN_FALSE;
1106
	}
1107
	if ((status = dhcpctl_object_remove(conn->handle, hp))) {
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
	omapi_object_dereference(&hp,__FILE__,__LINE__);
1120

    
1121
	RETURN_TRUE;
1122
}
1123

    
1124
PHP_FUNCTION(pfSense_close_dhcpd)
1125
{
1126
	zval *data;
1127

    
1128
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &data) == FAILURE) {
1129
		RETURN_FALSE;
1130
	}
1131

    
1132
	zend_list_delete(Z_LVAL_P(data));
1133

    
1134
	RETURN_TRUE;
1135
}
1136
#endif
1137

    
1138
PHP_FUNCTION(pfSense_ip_to_mac)
1139
{
1140
	char *ip = NULL, *rifname = NULL;
1141
	int ip_len, ifname_len = 0;
1142

    
1143
	int mib[6];
1144
	size_t needed;
1145
	char *lim, *buf, *next;
1146
	struct rt_msghdr *rtm;
1147
	struct sockaddr_inarp *sin2, addr;
1148
	struct sockaddr_dl *sdl;
1149
	char ifname[IF_NAMESIZE];
1150
	int st, found_entry = 0;
1151
	char outputbuf[128];
1152

    
1153
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &ip, &ip_len, &rifname, &ifname_len) == FAILURE)
1154
		RETURN_NULL();
1155

    
1156
	bzero(&addr, sizeof(addr));
1157
	if (!inet_pton(AF_INET, ip, &addr.sin_addr.s_addr))
1158
		RETURN_NULL();
1159
	addr.sin_len = sizeof(addr);
1160
	addr.sin_family = AF_INET;
1161

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

    
1208
	if (found_entry == 0)
1209
		RETURN_NULL();
1210

    
1211
	array_init(return_value);
1212
	bzero(outputbuf, sizeof outputbuf);
1213
	ether_ntoa_r((struct ether_addr *)LLADDR(sdl), outputbuf);
1214
	add_assoc_string(return_value, "macaddr", outputbuf, 1);
1215
}
1216

    
1217
PHP_FUNCTION(pfSense_getall_interface_addresses)
1218
{
1219
	struct ifaddrs *ifdata, *mb;
1220
	struct if_data *md;
1221
	struct sockaddr_in *tmp;
1222
	struct sockaddr_in6 *tmp6;
1223
	char outputbuf[132];
1224
	char *ifname;
1225
	int ifname_len, s;
1226

    
1227
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE)
1228
		RETURN_NULL();
1229

    
1230
	getifaddrs(&ifdata);
1231
	if (ifdata == NULL)
1232
		RETURN_NULL();
1233

    
1234
	array_init(return_value);
1235

    
1236
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1237
		if (mb == NULL)
1238
			continue;
1239
		if (ifname_len != strlen(mb->ifa_name))
1240
			continue;
1241
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1242
			continue;
1243
		if (mb->ifa_addr == NULL)
1244
			continue;
1245

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

    
1285
PHP_FUNCTION(pfSense_get_interface_addresses)
1286
{
1287
	struct ifaddrs *ifdata, *mb;
1288
	struct if_data *md;
1289
	struct sockaddr_in *tmp;
1290
	struct sockaddr_in6 *tmp6;
1291
	struct sockaddr_dl *tmpdl;
1292
	struct ifreq ifr;
1293
	char outputbuf[128];
1294
	char *ifname;
1295
	int ifname_len, s, addresscnt = 0, addresscnt6 = 0;
1296
	zval *caps;
1297
	zval *encaps;
1298

    
1299
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE)
1300
		RETURN_NULL();
1301

    
1302
	getifaddrs(&ifdata);
1303
	if (ifdata == NULL)
1304
		RETURN_NULL();
1305

    
1306
	array_init(return_value);
1307

    
1308
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1309
		if (mb == NULL)
1310
			continue;
1311
		if (ifname_len != strlen(mb->ifa_name))
1312
			continue;
1313
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1314
			continue;
1315

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

    
1489
			bzero(outputbuf, sizeof outputbuf);
1490
			inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1491
			add_assoc_string(return_value, "subnet", outputbuf, 1);
1492

    
1493
			if (mb->ifa_flags & IFF_BROADCAST) {
1494
				bzero(outputbuf, sizeof outputbuf);
1495
				tmp = (struct sockaddr_in *)mb->ifa_broadaddr;
1496
				inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1497
				add_assoc_string(return_value, "broadcast", outputbuf, 1);
1498
			}
1499

    
1500
			if (mb->ifa_flags & IFF_POINTOPOINT) {
1501
				bzero(outputbuf, sizeof outputbuf);
1502
				tmp6 = (struct sockaddr_in6 *)mb->ifa_dstaddr;
1503
				inet_ntop(AF_INET, (void *)&tmp6->sin6_addr, outputbuf, 128);
1504
				add_assoc_string(return_value, "tunnel", outputbuf, 1);
1505
			}
1506

    
1507
		break;
1508
		case AF_INET6:
1509
			if (addresscnt6 > 0)
1510
                                break;
1511
                        bzero(outputbuf, sizeof outputbuf);
1512
                        tmp6 = (struct sockaddr_in6 *)mb->ifa_addr;
1513
			if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr))
1514
				break;
1515
                        inet_ntop(AF_INET6, (void *)&tmp6->sin6_addr, outputbuf, 128);
1516
                        add_assoc_string(return_value, "ipaddr6", outputbuf, 1);
1517
                        addresscnt6++;
1518
                        tmp6 = (struct sockaddr_in6 *)mb->ifa_netmask;
1519
                        add_assoc_long(return_value, "subnetbits6", prefix(&tmp6->sin6_addr, sizeof(struct in6_addr)));
1520
                
1521
                        if (mb->ifa_flags & IFF_POINTOPOINT) {
1522
                                bzero(outputbuf, sizeof outputbuf);
1523
                                tmp = (struct sockaddr_in *)mb->ifa_dstaddr;
1524
                                inet_ntop(AF_INET, (void *)&tmp->sin_addr, outputbuf, 128);
1525
                                add_assoc_string(return_value, "tunnel6", outputbuf, 1);
1526
                        }
1527
		break;
1528
		case AF_LINK:
1529
			tmpdl = (struct sockaddr_dl *)mb->ifa_addr;
1530
			bzero(outputbuf, sizeof outputbuf);
1531
			ether_ntoa_r((struct ether_addr *)LLADDR(tmpdl), outputbuf);
1532
			add_assoc_string(return_value, "macaddr", outputbuf, 1);
1533
			md = (struct if_data *)mb->ifa_data;
1534

    
1535
		break;
1536
		}
1537
	}
1538
	freeifaddrs(ifdata);
1539
}
1540

    
1541
PHP_FUNCTION(pfSense_bridge_add_member) {
1542
	char *ifname, *ifchld;
1543
	int ifname_len, ifchld_len;
1544
	struct ifdrv drv;
1545
	struct ifbreq req;
1546

    
1547
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ifchld, &ifchld_len) == FAILURE) {
1548
		RETURN_NULL();
1549
	}
1550

    
1551
	memset(&drv, 0, sizeof(drv));
1552
	memset(&req, 0, sizeof(req));
1553
	strlcpy(drv.ifd_name, ifname, sizeof(drv.ifd_name));
1554
	strlcpy(req.ifbr_ifsname, ifchld, sizeof(req.ifbr_ifsname));
1555
	drv.ifd_cmd = BRDGADD;
1556
	drv.ifd_data = &req;
1557
	drv.ifd_len = sizeof(req);
1558
	if (ioctl(PFSENSE_G(s), SIOCSDRVSPEC, (caddr_t)&drv) < 0)
1559
		RETURN_FALSE;
1560

    
1561
	RETURN_TRUE;
1562
}
1563

    
1564
PHP_FUNCTION(pfSense_bridge_del_member) {
1565
	char *ifname, *ifchld;
1566
	int ifname_len, ifchld_len;
1567
	struct ifdrv drv;
1568
	struct ifbreq req;
1569

    
1570
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ifchld, &ifchld_len) == FAILURE) {
1571
		RETURN_NULL();
1572
	}
1573

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

    
1584
	RETURN_TRUE;
1585
}
1586

    
1587
PHP_FUNCTION(pfSense_bridge_member_flags) {
1588
	char *ifname, *ifchld;
1589
	int ifname_len, ifchld_len;
1590
	struct ifdrv drv;
1591
	struct ifbreq req;
1592
	long flags = 0;
1593

    
1594
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &ifname, &ifname_len, &ifchld, &ifchld_len, &flags) == FAILURE) {
1595
		RETURN_NULL();
1596
	}
1597

    
1598
	memset(&drv, 0, sizeof(drv));
1599
	memset(&req, 0, sizeof(req));
1600
	strlcpy(drv.ifd_name, ifname, sizeof(drv.ifd_name));
1601
	strlcpy(req.ifbr_ifsname, ifchld, sizeof(req.ifbr_ifsname));
1602
	drv.ifd_cmd = BRDGGIFFLGS;
1603
	drv.ifd_data = &req;
1604
	drv.ifd_len = sizeof(req);
1605
	if (ioctl(PFSENSE_G(s), SIOCGDRVSPEC, (caddr_t)&drv) < 0)
1606
		RETURN_FALSE;
1607

    
1608
	if (flags < 0) {
1609
		flags = -flags;
1610
		req.ifbr_ifsflags &= ~(int)flags;
1611
	} else
1612
		req.ifbr_ifsflags |= (int)flags;
1613

    
1614
	drv.ifd_cmd = BRDGSIFFLGS;
1615
	drv.ifd_data = &req;
1616
	drv.ifd_len = sizeof(req);
1617
	if (ioctl(PFSENSE_G(s), SIOCSDRVSPEC, (caddr_t)&drv) < 0)
1618
		RETURN_FALSE;
1619

    
1620
	RETURN_TRUE;
1621
}
1622

    
1623
PHP_FUNCTION(pfSense_interface_listget) {
1624
	struct ifaddrs *ifdata, *mb;
1625
	char *ifname;
1626
	int ifname_len;
1627
	long flags = 0;
1628

    
1629
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE)
1630
		RETURN_NULL();
1631

    
1632
	getifaddrs(&ifdata);
1633
	if (ifdata == NULL)
1634
		RETURN_NULL();
1635

    
1636
	array_init(return_value);
1637
	ifname = NULL;
1638
	ifname_len = 0;
1639
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1640
		if (mb == NULL)
1641
			continue;
1642

    
1643
		if (flags != 0) {
1644
			if (mb->ifa_flags & IFF_UP && flags < 0)
1645
				continue;
1646
			if (!(mb->ifa_flags & IFF_UP) && flags > 0)
1647
				continue;
1648
		}
1649

    
1650
		if (ifname != NULL && ifname_len == strlen(mb->ifa_name) && strcmp(ifname, mb->ifa_name) == 0)
1651
			continue;
1652
		ifname = mb->ifa_name;
1653
		ifname_len = strlen(mb->ifa_name);
1654

    
1655
		add_next_index_string(return_value, mb->ifa_name, 1);
1656
	}
1657

    
1658
	freeifaddrs(ifdata);
1659
}
1660

    
1661
PHP_FUNCTION(pfSense_interface_create) {
1662
	char *ifname;
1663
	int ifname_len, len;
1664
	struct ifreq ifr;
1665
	struct vlanreq params;
1666

    
1667
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1668
		RETURN_NULL();
1669
	}
1670

    
1671
	memset(&ifr, 0, sizeof(ifr));
1672
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1673
	if (ioctl(PFSENSE_G(s), SIOCIFCREATE2, &ifr) < 0) {
1674
		array_init(return_value);
1675
		add_assoc_string(return_value, "error", "Could not create interface", 1);
1676
	} else
1677
		RETURN_STRING(ifr.ifr_name, 1)
1678
}
1679

    
1680
PHP_FUNCTION(pfSense_interface_destroy) {
1681
	char *ifname;
1682
	int ifname_len;
1683
	struct ifreq ifr;
1684

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

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

    
1698
PHP_FUNCTION(pfSense_interface_setaddress) {
1699
	char *ifname, *ip, *p = NULL;
1700
	int ifname_len, ip_len;
1701
	struct sockaddr_in *sin;
1702
	struct in_aliasreq ifra;
1703

    
1704
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ip, &ip_len) == FAILURE) {
1705
		RETURN_NULL();
1706
	}
1707

    
1708
	memset(&ifra, 0, sizeof(ifra));
1709
	strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1710
	sin =  &ifra.ifra_mask;
1711
	sin->sin_family = AF_INET;
1712
	sin->sin_len = sizeof(*sin);
1713
	sin->sin_addr.s_addr = 0;
1714
	if ((p = strrchr(ip, '/')) != NULL) {
1715
		/* address is `name/masklen' */
1716
		int masklen;
1717
		int ret;
1718
		*p = '\0';
1719
		ret = sscanf(p+1, "%u", &masklen);
1720
		if(ret != 1 || (masklen < 0 || masklen > 32)) {
1721
			*p = '/';
1722
			RETURN_FALSE;
1723
		}
1724
		sin->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) &
1725
			0xffffffff);
1726
	}
1727
	sin =  &ifra.ifra_addr;
1728
	sin->sin_family = AF_INET;
1729
	sin->sin_len = sizeof(*sin);
1730
	if (inet_pton(AF_INET, ip, &sin->sin_addr) <= 0)
1731
		RETURN_FALSE;
1732

    
1733
	if (ioctl(PFSENSE_G(inets), SIOCAIFADDR, &ifra) < 0) {
1734
		array_init(return_value);
1735
		add_assoc_string(return_value, "error", "Could not set interface address", 1);
1736
	} else
1737
		RETURN_TRUE;
1738
}
1739

    
1740
PHP_FUNCTION(pfSense_interface_deladdress) {
1741
	char *ifname, *ip = NULL;
1742
	int ifname_len, ip_len;
1743
	struct sockaddr_in *sin;
1744
	struct in_aliasreq ifra;
1745

    
1746
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &ip, &ip_len) == FAILURE) {
1747
		RETURN_NULL();
1748
	}
1749

    
1750
	memset(&ifra, 0, sizeof(ifra));
1751
	strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
1752
	sin =  &ifra.ifra_addr;
1753
	sin->sin_family = AF_INET;
1754
	sin->sin_len = sizeof(*sin);
1755
	if (inet_pton(AF_INET, ip, &sin->sin_addr) <= 0)
1756
		RETURN_FALSE;
1757

    
1758
	if (ioctl(PFSENSE_G(inets), SIOCDIFADDR, &ifra) < 0) {
1759
		array_init(return_value);
1760
		add_assoc_string(return_value, "error", "Could not delete interface address", 1);
1761
	} else
1762
		RETURN_TRUE;
1763
}
1764

    
1765
PHP_FUNCTION(pfSense_interface_rename) {
1766
	char *ifname, *newifname;
1767
	int ifname_len, newifname_len;
1768
	struct ifreq ifr;
1769

    
1770
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ifname, &ifname_len, &newifname, &newifname_len) == FAILURE) {
1771
		RETURN_NULL();
1772
	}
1773

    
1774
	memset(&ifr, 0, sizeof(ifr));
1775
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1776
	ifr.ifr_data = (caddr_t) newifname;
1777
	if (ioctl(PFSENSE_G(s), SIOCSIFNAME, (caddr_t) &ifr) < 0) {
1778
		array_init(return_value);
1779
		add_assoc_string(return_value, "error", "Could not rename interface", 1);
1780
	} else
1781
		RETURN_TRUE;
1782
}
1783

    
1784
PHP_FUNCTION(pfSense_ngctl_name) {
1785
	char *ifname, *newifname;
1786
	int ifname_len, newifname_len;
1787

    
1788
	if (PFSENSE_G(csock) == -1)
1789
		RETURN_NULL();
1790

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

    
1795
	/* Send message */
1796
	if (NgNameNode(PFSENSE_G(csock), ifname, newifname) < 0)
1797
		RETURN_NULL();
1798

    
1799
	RETURN_TRUE;
1800
}
1801

    
1802
PHP_FUNCTION(pfSense_ngctl_attach) {
1803
	char *ifname, *newifname;
1804
	int ifname_len, newifname_len;
1805
	struct ngm_name name;
1806

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

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

    
1814
	snprintf(name.name, sizeof(name.name), "%s", newifname);
1815
	/* Send message */
1816
	if (NgSendMsg(PFSENSE_G(csock), ifname, NGM_GENERIC_COOKIE,
1817
		NGM_ETHER_ATTACH, &name, sizeof(name)) < 0)
1818
			RETURN_NULL();
1819

    
1820
	RETURN_TRUE;
1821
}
1822

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

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

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

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

    
1841
	RETURN_TRUE;
1842
}
1843

    
1844
PHP_FUNCTION(pfSense_vlan_create) {
1845
	char *ifname = NULL;
1846
	char *parentifname = NULL;
1847
	int ifname_len, parent_len;
1848
	long tag; 
1849
	struct ifreq ifr;
1850
	struct vlanreq params;
1851

    
1852
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl", &ifname, &ifname_len, &parentifname, &parent_len, &tag) == FAILURE) {
1853
		RETURN_NULL();
1854
	}
1855

    
1856
	memset(&ifr, 0, sizeof(ifr));
1857
	memset(&params, 0, sizeof(params));
1858
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1859
	strlcpy(params.vlr_parent, parentifname, sizeof(params.vlr_parent));
1860
	params.vlr_tag = (u_short) tag;
1861
	ifr.ifr_data = (caddr_t) &params;
1862
	if (ioctl(PFSENSE_G(s), SIOCSETVLAN, (caddr_t) &ifr) < 0)
1863
		RETURN_NULL();
1864

    
1865
	RETURN_TRUE;
1866
}
1867

    
1868
PHP_FUNCTION(pfSense_interface_mtu) {
1869
	char *ifname;
1870
	int ifname_len;
1871
	long mtu;
1872
	struct ifreq ifr;
1873

    
1874
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &mtu) == FAILURE) {
1875
		RETURN_NULL();
1876
	}
1877
	memset(&ifr, 0, sizeof(ifr));
1878
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1879
	ifr.ifr_mtu = (int) mtu;
1880
	if (ioctl(PFSENSE_G(s), SIOCSIFMTU, (caddr_t)&ifr) < 0)
1881
		RETURN_NULL();
1882
	RETURN_TRUE;
1883
}
1884

    
1885
PHP_FUNCTION(pfSense_interface_flags) {
1886
	struct ifreq ifr;
1887
	char *ifname;
1888
	int flags, ifname_len;
1889
	long value;
1890

    
1891
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &value) == FAILURE) {
1892
		RETURN_NULL();
1893
	}
1894

    
1895
	memset(&ifr, 0, sizeof(ifr));
1896
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1897
	if (ioctl(PFSENSE_G(s), SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
1898
		RETURN_NULL();
1899
	}
1900
	flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
1901
	if (value < 0) {
1902
		value = -value;
1903
		flags &= ~(int)value;
1904
	} else
1905
		flags |= (int)value; 
1906
	ifr.ifr_flags = flags & 0xffff;
1907
	ifr.ifr_flagshigh = flags >> 16;
1908
	if (ioctl(PFSENSE_G(s), SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
1909
		RETURN_NULL();
1910
	RETURN_TRUE;
1911
}
1912

    
1913
PHP_FUNCTION(pfSense_interface_capabilities) {
1914
	struct ifreq ifr;
1915
	char *ifname;
1916
	int flags, ifname_len;
1917
	long value;
1918

    
1919
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &ifname, &ifname_len, &value) == FAILURE) {
1920
		RETURN_NULL();
1921
	}
1922

    
1923
	memset(&ifr, 0, sizeof(ifr));
1924
	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1925
	if (ioctl(PFSENSE_G(s), SIOCGIFCAP, (caddr_t)&ifr) < 0) {
1926
		RETURN_NULL();
1927
	}
1928
	flags = ifr.ifr_curcap;
1929
	if (value < 0) {
1930
		value = -value;
1931
		flags &= ~(int)value;
1932
	} else
1933
		flags |= (int)value; 
1934
	flags &= ifr.ifr_reqcap;
1935
	ifr.ifr_reqcap = flags;
1936
	if (ioctl(PFSENSE_G(s), SIOCSIFCAP, (caddr_t)&ifr) < 0)
1937
		RETURN_NULL();
1938
	RETURN_TRUE;
1939

    
1940
}
1941

    
1942
PHP_FUNCTION(pfSense_get_interface_info)
1943
{
1944
	struct ifaddrs *ifdata, *mb;
1945
	struct if_data *tmpd;
1946
	struct sockaddr_in *tmp;
1947
	struct sockaddr_dl *tmpdl;
1948
	struct pfi_kif kif = { 0 };
1949
	int size = 1, found = 0;
1950
	char outputbuf[128];
1951
	char *ifname;
1952
	int ifname_len;
1953
	int i = 0, error = 0;
1954
	int dev;
1955
	char *pf_status;
1956

    
1957
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
1958
		RETURN_NULL();
1959
	}
1960

    
1961
	if ((dev = open("/dev/pf", O_RDWR)) < 0)
1962
		RETURN_NULL();
1963

    
1964
	getifaddrs(&ifdata);
1965
	if (ifdata == NULL) {
1966
		close(dev);
1967
		RETURN_NULL();
1968
	}
1969

    
1970
	for(mb = ifdata; mb != NULL; mb = mb->ifa_next) {
1971
		if (mb == NULL)
1972
			continue;
1973
		if (ifname_len != strlen(mb->ifa_name))
1974
			continue;
1975
		if (strncmp(ifname, mb->ifa_name, ifname_len) != 0)
1976
			continue;
1977

    
1978
		if (found == 0)
1979
			array_init(return_value);
1980

    
1981
		found = 1;
1982

    
1983
		switch (mb->ifa_addr->sa_family) {
1984
		case AF_LINK:
1985

    
1986
			tmpd = (struct if_data *)mb->ifa_data;
1987
			add_assoc_long(return_value, "inerrs", tmpd->ifi_ierrors);
1988
			add_assoc_long(return_value, "outerrs", tmpd->ifi_oerrors);
1989
			add_assoc_long(return_value, "collisions", tmpd->ifi_collisions);
1990
			add_assoc_long(return_value, "inmcasts", tmpd->ifi_imcasts);
1991
			add_assoc_long(return_value, "outmcasts", tmpd->ifi_omcasts);
1992
			add_assoc_long(return_value, "unsuppproto", tmpd->ifi_noproto);
1993
			add_assoc_long(return_value, "mtu", tmpd->ifi_mtu);
1994

    
1995
		break;
1996
		}
1997
	}
1998
	freeifaddrs(ifdata);
1999

    
2000
	if (found == 0) {
2001
		close(dev);
2002
		RETURN_NULL();
2003
	}
2004

    
2005
	if (pfi_get_ifaces(dev, ifname, &kif, &size))
2006
		error = 1;
2007

    
2008
	if (error == 0) {
2009
		add_assoc_string(return_value, "interface", kif.pfik_name, 1);
2010

    
2011
#define PAF_INET 0
2012
#define PPF_IN 0
2013
#define PPF_OUT 1
2014
		add_assoc_long(return_value, "inpktspass", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_IN][PF_PASS]);
2015
		add_assoc_long(return_value, "outpktspass", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_OUT][PF_PASS]);
2016
		add_assoc_long(return_value, "inbytespass", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_IN][PF_PASS]);
2017
		add_assoc_long(return_value, "outbytespass", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_OUT][PF_PASS]);
2018

    
2019
		add_assoc_long(return_value, "inpktsblock", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_IN][PF_DROP]);
2020
		add_assoc_long(return_value, "outpktsblock", (unsigned long long)kif.pfik_packets[PAF_INET][PPF_OUT][PF_DROP]);
2021
		add_assoc_long(return_value, "inbytesblock", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_IN][PF_DROP]);
2022
		add_assoc_long(return_value, "outbytesblock", (unsigned long long)kif.pfik_bytes[PAF_INET][PPF_OUT][PF_DROP]);
2023

    
2024
		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]));
2025
		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]));
2026
		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]));
2027
		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]));
2028
#undef PPF_IN
2029
#undef PPF_OUT
2030
#undef PAF_INET
2031
	}
2032
	close(dev);
2033
}
2034

    
2035
PHP_FUNCTION(pfSense_get_interface_stats)
2036
{
2037
	struct ifmibdata ifmd;
2038
	struct if_data *tmpd;
2039
	char outputbuf[128];
2040
	char *ifname;
2041
	int ifname_len, error;
2042
	int name[6];
2043
	size_t len;
2044
	unsigned int ifidx;
2045

    
2046
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ifname, &ifname_len) == FAILURE) {
2047
		RETURN_NULL();
2048
	}
2049

    
2050
	ifidx = if_nametoindex(ifname);
2051
	if (ifidx == 0)
2052
		RETURN_NULL();
2053

    
2054
	name[0] = CTL_NET;
2055
	name[1] = PF_LINK;
2056
	name[2] = NETLINK_GENERIC;
2057
	name[3] = IFMIB_IFDATA;
2058
	name[4] = ifidx;
2059
	name[5] = IFDATA_GENERAL;
2060

    
2061
	len = sizeof(ifmd);
2062

    
2063
	if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) < 0)
2064
		RETURN_NULL();
2065
	
2066
	tmpd = &ifmd.ifmd_data;
2067

    
2068
	array_init(return_value);
2069
	add_assoc_long(return_value, "inpkts", (long)tmpd->ifi_ipackets);
2070
	add_assoc_long(return_value, "inbytes", (long)tmpd->ifi_ibytes);
2071
	add_assoc_long(return_value, "outpkts", (long)tmpd->ifi_opackets);
2072
	add_assoc_long(return_value, "outbytes", (long)tmpd->ifi_obytes);
2073
	add_assoc_long(return_value, "inerrs", (long)tmpd->ifi_ierrors);
2074
	add_assoc_long(return_value, "outerrs", (long)tmpd->ifi_oerrors);
2075
	add_assoc_long(return_value, "collisions", (long)tmpd->ifi_collisions);
2076
	add_assoc_long(return_value, "inmcasts", (long)tmpd->ifi_imcasts);
2077
	add_assoc_long(return_value, "outmcasts", (long)tmpd->ifi_omcasts);
2078
	add_assoc_long(return_value, "unsuppproto", (long)tmpd->ifi_noproto);
2079
	add_assoc_long(return_value, "mtu", (long)tmpd->ifi_mtu);
2080
}
2081

    
2082
PHP_FUNCTION(pfSense_get_pf_stats) {
2083
	struct pf_status status;
2084
	time_t runtime;
2085
	unsigned sec, min, hrs, day = runtime;
2086
	char statline[80];
2087
	char buf[PF_MD5_DIGEST_LENGTH * 2 + 1];
2088
	static const char hex[] = "0123456789abcdef";
2089
	int i;
2090
	int dev;
2091

    
2092
	array_init(return_value);
2093

    
2094
	if ((dev = open("/dev/pf", O_RDWR)) < 0) {
2095
		add_assoc_string(return_value, "error", strerror(errno), 1);
2096
	} else {
2097

    
2098

    
2099
	bzero(&status, sizeof(status));
2100
	if (ioctl(dev, DIOCGETSTATUS, &status)) {
2101
		add_assoc_string(return_value, "error", strerror(errno), 1);
2102
	} else {
2103
		add_assoc_long(return_value, "rulesmatch", (unsigned long long)status.counters[PFRES_MATCH]);
2104
		add_assoc_long(return_value, "pullhdrfail", (unsigned long long)status.counters[PFRES_BADOFF]);
2105
		add_assoc_long(return_value, "fragments", (unsigned long long)status.counters[PFRES_FRAG]);
2106
		add_assoc_long(return_value, "shortpacket", (unsigned long long)status.counters[PFRES_SHORT]);
2107
		add_assoc_long(return_value, "normalizedrop", (unsigned long long)status.counters[PFRES_NORM]);
2108
		add_assoc_long(return_value, "nomemory", (unsigned long long)status.counters[PFRES_MEMORY]);
2109
		add_assoc_long(return_value, "badtimestamp", (unsigned long long)status.counters[PFRES_TS]);
2110
		add_assoc_long(return_value, "congestion", (unsigned long long)status.counters[PFRES_CONGEST]);
2111
		add_assoc_long(return_value, "ipoptions", (unsigned long long)status.counters[PFRES_IPOPTIONS]);
2112
		add_assoc_long(return_value, "protocksumbad", (unsigned long long)status.counters[PFRES_PROTCKSUM]);
2113
		add_assoc_long(return_value, "statesbad", (unsigned long long)status.counters[PFRES_BADSTATE]);
2114
		add_assoc_long(return_value, "stateinsertions", (unsigned long long)status.counters[PFRES_STATEINS]);
2115
		add_assoc_long(return_value, "maxstatesdrop", (unsigned long long)status.counters[PFRES_MAXSTATES]);
2116
		add_assoc_long(return_value, "srclimitdrop", (unsigned long long)status.counters[PFRES_SRCLIMIT]);
2117
		add_assoc_long(return_value, "synproxydrop", (unsigned long long)status.counters[PFRES_SYNPROXY]);
2118

    
2119
		add_assoc_long(return_value, "maxstatesreached", (unsigned long long)status.lcounters[LCNT_STATES]);
2120
		add_assoc_long(return_value, "maxsrcstatesreached", (unsigned long long)status.lcounters[LCNT_SRCSTATES]);
2121
		add_assoc_long(return_value, "maxsrcnodesreached", (unsigned long long)status.lcounters[LCNT_SRCNODES]);
2122
		add_assoc_long(return_value, "maxsrcconnreached", (unsigned long long)status.lcounters[LCNT_SRCCONN]);
2123
		add_assoc_long(return_value, "maxsrcconnratereached", (unsigned long long)status.lcounters[LCNT_SRCCONNRATE]);
2124
		add_assoc_long(return_value, "overloadtable", (unsigned long long)status.lcounters[LCNT_OVERLOAD_TABLE]);
2125
		add_assoc_long(return_value, "overloadflush", (unsigned long long)status.lcounters[LCNT_OVERLOAD_FLUSH]);
2126

    
2127
		add_assoc_long(return_value, "statesearch", (unsigned long long)status.fcounters[FCNT_STATE_SEARCH]);
2128
		add_assoc_long(return_value, "stateinsert", (unsigned long long)status.fcounters[FCNT_STATE_INSERT]);
2129
		add_assoc_long(return_value, "stateremovals", (unsigned long long)status.fcounters[FCNT_STATE_REMOVALS]);
2130

    
2131
		add_assoc_long(return_value, "srcnodessearch", (unsigned long long)status.scounters[SCNT_SRC_NODE_SEARCH]);
2132
		add_assoc_long(return_value, "srcnodesinsert", (unsigned long long)status.scounters[SCNT_SRC_NODE_INSERT]);
2133
		add_assoc_long(return_value, "srcnodesremovals", (unsigned long long)status.scounters[SCNT_SRC_NODE_REMOVALS]);
2134

    
2135
#if (__FreeBSD_version < 1000000)
2136
		add_assoc_long(return_value, "stateid", (unsigned long long)status.stateid);
2137
#endif
2138

    
2139
		add_assoc_long(return_value, "running", status.running);
2140
		add_assoc_long(return_value, "states", status.states);
2141
		add_assoc_long(return_value, "srcnodes", status.src_nodes);
2142

    
2143
		add_assoc_long(return_value, "hostid", ntohl(status.hostid));
2144
		for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) {
2145
			buf[i + i] = hex[status.pf_chksum[i] >> 4];
2146
			buf[i + i + 1] = hex[status.pf_chksum[i] & 0x0f];
2147
		}
2148
		buf[i + i] = '\0';
2149
		add_assoc_string(return_value, "pfchecksum", buf, 1);
2150
		printf("Checksum: 0x%s\n\n", buf);
2151

    
2152
		switch(status.debug) {
2153
		case PF_DEBUG_NONE:
2154
			add_assoc_string(return_value, "debuglevel", "none", 1);
2155
			break;
2156
		case PF_DEBUG_URGENT:
2157
			add_assoc_string(return_value, "debuglevel", "urgent", 1);
2158
			break;
2159
		case PF_DEBUG_MISC:
2160
			add_assoc_string(return_value, "debuglevel", "misc", 1);
2161
			break;
2162
		case PF_DEBUG_NOISY:
2163
			add_assoc_string(return_value, "debuglevel", "noisy", 1);
2164
			break;
2165
		default:
2166
			add_assoc_string(return_value, "debuglevel", "unknown", 1);
2167
			break;
2168
		}
2169

    
2170
		runtime = time(NULL) - status.since;
2171
		if (status.since) {
2172
			sec = day % 60;
2173
			day /= 60;
2174
			min = day % 60;
2175
			day /= 60;
2176
			hrs = day % 24;
2177
			day /= 24;
2178
			snprintf(statline, sizeof(statline),
2179
		    		"Running: for %u days %.2u:%.2u:%.2u",
2180
		    		day, hrs, min, sec);
2181
			add_assoc_string(return_value, "uptime", statline, 1);
2182
		}
2183
	}
2184
	close(dev);
2185
	}
2186
}
2187

    
2188
PHP_FUNCTION(pfSense_sync) {
2189
	sync();
2190
}
2191

    
2192
PHP_FUNCTION(pfSense_get_modem_devices) {
2193
	struct termios		attr, origattr;
2194
	struct pollfd		pfd;
2195
	glob_t			g;
2196
	char			buf[2048] = { 0 };
2197
	char			*path;
2198
	int			nw = 0, i, fd, retries;
2199
	zend_bool		show_info = 0;
2200
	long			poll_timeout = 700;
2201

    
2202
	if (ZEND_NUM_ARGS() > 2) {
2203
		RETURN_NULL();
2204
	}
2205
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bl", &show_info, &poll_timeout) == FAILURE) {
2206
		php_printf("Maximum two parameter can be passed\n");
2207
			RETURN_NULL();
2208
	}
2209

    
2210
	array_init(return_value);
2211

    
2212
	bzero(&g, sizeof g);
2213
	glob("/dev/cua*", 0, NULL, &g);
2214
	glob("/dev/modem*", GLOB_APPEND, NULL, &g);
2215

    
2216
	if (g.gl_pathc > 0)
2217
	for (i = 0; g.gl_pathv[i] != NULL; i++) {
2218
		path = g.gl_pathv[i];
2219
		if (strstr(path, "lock") || strstr(path, "init"))
2220
			continue;
2221
		if (show_info)
2222
			php_printf("Found modem device: %s\n", path);
2223
		/* Open & lock serial port */
2224
		if ((fd = open(path, O_RDWR | O_NONBLOCK, 0)) < 0) {
2225
			if (show_info)
2226
				php_printf("Could not open the device exlusively\n");
2227
			add_assoc_string(return_value, path, path, 1);
2228
			continue;
2229
		}
2230

    
2231
		/* Set non-blocking I/O  */
2232
		if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
2233
			goto errormodem;
2234

    
2235
		/* Set serial port raw mode, baud rate, hardware flow control, etc. */
2236
		if (tcgetattr(fd, &attr) < 0)
2237
			goto errormodem;
2238

    
2239
		origattr = attr;
2240
		cfmakeraw(&attr);
2241

    
2242
		attr.c_cflag &= ~(CSIZE|PARENB|PARODD);
2243
		attr.c_cflag |= (CS8|CREAD|CLOCAL|HUPCL|CCTS_OFLOW|CRTS_IFLOW);
2244
		attr.c_iflag &= ~(IXANY|IMAXBEL|ISTRIP|IXON|IXOFF|BRKINT|ICRNL|INLCR);
2245
		attr.c_iflag |= (IGNBRK|IGNPAR);
2246
		attr.c_oflag &= ~OPOST;
2247
		attr.c_lflag = 0;
2248

    
2249
#define MODEM_DEFAULT_SPEED              115200
2250
		cfsetspeed(&attr, (speed_t) MODEM_DEFAULT_SPEED);
2251
#undef	MODEM_DEFAULT_SPEED
2252

    
2253
		if (tcsetattr(fd, TCSANOW, &attr) < 0)
2254
			goto errormodem;
2255

    
2256
		/* OK */
2257
		retries = 0;
2258
		while (retries++ < 3) {
2259
			if ((nw = write(fd, "AT OK\r\n", strlen("AT OK\r\n"))) < 0) {
2260
				if (errno == EAGAIN) {
2261
					if (show_info)
2262
						php_printf("\tRetrying write\n");
2263
					continue;
2264
				}
2265

    
2266
				if (show_info)
2267
					php_printf("\tError ocurred\n");
2268
				goto errormodem;
2269
			}
2270
		}
2271
		if (retries >= 3)
2272
			goto errormodem;
2273

    
2274
		retries = 0;
2275
tryagain2:
2276
		if (show_info)
2277
			php_printf("\tTrying to read data\n");
2278
		bzero(buf, sizeof buf);
2279
		bzero(&pfd, sizeof pfd);
2280
		pfd.fd = fd;
2281
		pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLHUP;
2282
		if ((nw = poll(&pfd, 1, poll_timeout)) > 0) {
2283
			if ((nw = read(fd, buf, sizeof(buf))) < 0) {
2284
				if (errno == EAGAIN) {
2285
					if (show_info)
2286
						php_printf("\tTrying again after errno = EAGAIN\n");
2287
					if (++retries < 3)
2288
						goto tryagain2;
2289
				}
2290
				if (show_info)
2291
					php_printf("\tError ocurred on 1st read\n");
2292
				goto errormodem;
2293
			}
2294

    
2295
			buf[2047] = '\0';
2296
			if (show_info)
2297
				php_printf("\tRead %s\n", buf);
2298
			//if (strnstr(buf, "OK", sizeof(buf)))
2299
			if (nw > 0) {
2300
				/*
2301
				write(fd, "ATI3\r\n", strlen("ATI3\r\n"));
2302
				bzero(buf, sizeof buf);
2303
				bzero(&pfd, sizeof pfd);
2304
				pfd.fd = fd;
2305
				pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI | POLLHUP;
2306

    
2307
				if (poll(&pfd, 1, 200) > 0) {
2308
					read(fd, buf, sizeof(buf));
2309
				buf[2047] = '\0';
2310
				if (show_info)
2311
					php_printf("\tRead %s\n", buf);
2312
				}
2313
				*/
2314
				add_assoc_string(return_value, path, path, 1);
2315
			}
2316
		} else if (show_info)
2317
			php_printf("\ttimedout or interrupted: %d\n", nw);
2318

    
2319
		tcsetattr(fd, TCSANOW, &origattr);
2320
errormodem:
2321
		if (show_info)
2322
			php_printf("\tClosing device %s\n", path);
2323
		close(fd);
2324
	}
2325
}
2326

    
2327
PHP_FUNCTION(pfSense_get_os_hw_data) {
2328
	int i, mib[4], idata;
2329
	size_t len;	
2330
	char *data;
2331

    
2332
	array_init(return_value);
2333

    
2334
	mib[0] = CTL_HW;
2335
	mib[1] = HW_MACHINE;
2336
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2337
		data = malloc(len);
2338
		if (data != NULL) {
2339
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2340
				add_assoc_string(return_value, "hwmachine", data, 1);
2341
				free(data);
2342
			}
2343
		}
2344
	}
2345

    
2346
	mib[0] = CTL_HW;
2347
	mib[1] = HW_MODEL;
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, "hwmodel", data, 1);
2353
				free(data);
2354
			}
2355
		}
2356
	}
2357

    
2358
	mib[0] = CTL_HW;
2359
	mib[1] = HW_MACHINE_ARCH;
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, "hwarch", data, 1);
2365
				free(data);
2366
			}
2367
		}
2368
	}
2369

    
2370
	mib[0] = CTL_HW;
2371
	mib[1] = HW_NCPU;
2372
	len = sizeof(idata);
2373
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2374
		add_assoc_long(return_value, "ncpus", idata);
2375

    
2376
	mib[0] = CTL_HW;
2377
	mib[1] = HW_PHYSMEM;
2378
	len = sizeof(idata);
2379
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2380
		add_assoc_long(return_value, "physmem", idata);
2381

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

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

    
2395
PHP_FUNCTION(pfSense_get_os_kern_data) {
2396
	int i, mib[4], idata;
2397
	size_t len;
2398
	char *data;
2399
	struct timeval bootime;
2400

    
2401
	array_init(return_value);
2402

    
2403
	mib[0] = CTL_KERN;
2404
	mib[1] = KERN_HOSTUUID;
2405
	if (!sysctl(mib, 2, NULL, &len, NULL, 0)) {
2406
		data = malloc(len);
2407
		if (data != NULL) {
2408
			if (!sysctl(mib, 2, data, &len, NULL, 0)) {
2409
				add_assoc_string(return_value, "hostuuid", data, 1);
2410
				free(data);
2411
			}
2412
		}
2413
	}
2414

    
2415
	mib[0] = CTL_KERN;
2416
	mib[1] = KERN_HOSTNAME;
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, "hostname", data, 1);
2422
				free(data);
2423
			}
2424
		}
2425
	}
2426

    
2427
	mib[0] = CTL_KERN;
2428
	mib[1] = KERN_OSRELEASE;
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, "osrelease", data, 1);
2434
				free(data);
2435
			}
2436
		}
2437
	}
2438

    
2439
	mib[0] = CTL_KERN;
2440
	mib[1] = KERN_VERSION;
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, "oskernel_version", data, 1);
2446
				free(data);
2447
			}
2448
		}
2449
	}
2450

    
2451
	mib[0] = CTL_KERN;
2452
	mib[1] = KERN_BOOTTIME;
2453
	len = sizeof(bootime);
2454
	if (!sysctl(mib, 2, &bootime, &len, NULL, 0))
2455
		add_assoc_string(return_value, "boottime", ctime(&bootime.tv_sec), 1);
2456

    
2457
	mib[0] = CTL_KERN;
2458
	mib[1] = KERN_HOSTID;
2459
	len = sizeof(idata);
2460
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2461
		add_assoc_long(return_value, "hostid", idata);
2462

    
2463
	mib[0] = CTL_KERN;
2464
	mib[1] = KERN_OSRELDATE;
2465
	len = sizeof(idata);
2466
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2467
		add_assoc_long(return_value, "osreleasedate", idata);
2468

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

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

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

    
2487
	mib[0] = CTL_KERN;
2488
	mib[1] = KERN_OSRELDATE;
2489
	len = sizeof(idata);
2490
	if (!sysctl(mib, 2, &idata, &len, NULL, 0))
2491
		add_assoc_long(return_value, "osreleasedate", idata);
2492
}
(4-4/6)