Hello! В сообщении от Wednesday 23 July 2008 19:07:59 вы написали: > Hello, > > Le 23 juil. 08 à 09:14, Alexey Pechnikov a écrit : > > Hello! > > > > Send me please code as attached file. > > In mail body there are a lot of non-ascii symbols and compiler show > > a lot of > > errors on symbols ‘\240’ and ‘\302’. > > didn't thought of that, sorry. > Here is a little zip archive with all needed files and explainations. > you can find it here in case it gets hurt in the email : > > http://schplurtz.free.fr/schplurtziel/sqlite3-ipv4-ext/ipv4ext.html > > Regards, > Christophe
I'm reimplement function ISINNET to use inet_pton/htonl/inet_ntop/ntohl and add functions IP2INT, INT2IP, NET2INT, NET2LENGTH, NETMASK2LENGTH. See attached file for code and description. It's beta software and distributed as public domain license. Thanks for idea! /* This library will provide the ipv4 ISINNET, IP2INT, INT2IP, NET2INT, NET2LENGTH, NETMASK2LENGTH functions in SQL queries. The functions coded by Alexey Pechnikov ([EMAIL PROTECTED]) and tested on linux only. The code is public domain. Author use these functions for store ip addresses as integers and networks as intervals of integers and search as select * from table_addr where IP2INT('172.16.1.193') between ip_from and ip_to; For example, ip_from = ('172.16.1.193/255.255.255.0') ip_to = ('172.16.1.193/255.255.255.0') + NET2LENGTH('172.16.1.193/255.255.255.0') or ip_to = ('172.16.1.193/24') + NET2LENGTH('172.16.1.193/24') or ip_to = ('172.16.1.193/24') + NETMASK2LENGTH('24'); SELECT IP2INT('172.16.1.193'); 2886730177 SELECT INT2IP(2886730177); 172.16.1.193 SELECT NET2INT('172.16.1.193/255.255.255.0'); 2886729984 SELECT NET2INT('172.16.1.193/24'); 2886729984 SELECT NET2INT('172.16.1.193','255.255.255.0'); 2886729984 SELECT NET2INT('172.16.1.193','24'); 2886729984 SELECT NET2LENGTH('172.16.1.193/255.255.255.0'); 256 SELECT NET2LENGTH('172.16.1.193/24'); 256 SELECT NETMASK2LENGTH('24'); 256 The ISINNET function reimplemented by Alexey Pechnikov ([EMAIL PROTECTED]). Tests is saved as original author provide it. Thanks for idea! The code is public domain. ISINNET( ip, network, mask ) mask may be specified the CIDR way as a number of bits, or as a standard 4 bytes notation. if CIDR notation is used, mask may be a string ('13' for example) or a number (13 for example) ISINNET returns NULL if there is any kind of error, mainly : - strings are not valid IPV4 addresses or - number of bits is not a number or is out of range ISINNET returns 1 if (ip & mask) = (net & mask) ISINNET returns 0 otherwise SELECT ISINNET( '172.16.1.193', '172.16.1.0', 24 ); SELECT ISINNET( '172.16.1.193', '172.16.1.0/24' ); ==> 1 SELECT ISINNET( '172.16.1.193', '172.16.1.0', 25 ); SELECT ISINNET( '172.16.1.193', '172.16.1.0/25' ); ==> 0 SELECT ISINNET( '172.16.1.193', '172.16.1.0', '255.255.255.0' ); SELECT ISINNET( '172.16.1.193', '172.16.1.0/255.255.255.0' ); ==> 1 SELECT ISINNET( '172.16.1.193', '172.16.1.0', '255.255.255.128' ); SELECT ISINNET( '172.16.1.193', '172.16.1.0/255.255.255.128' ); ==> 0 CREATE TABLE ip_add ( ip varchar( 16 ) ); INSERT INTO ip_add VALUES('172.16.1.40'); INSERT INTO ip_add VALUES('172.16.1.93'); INSERT INTO ip_add VALUES('172.16.1.204'); INSERT INTO ip_add VALUES('172.16.4.203'); INSERT INTO ip_add VALUES('172.16.4.205'); INSERT INTO ip_add VALUES('172.16.4.69'); INSERT INTO ip_add VALUES('10.0.1.204'); INSERT INTO ip_add VALUES('10.0.1.16'); INSERT INTO ip_add VALUES('10.1.0.16'); INSERT INTO ip_add VALUES('192.168.1.5'); INSERT INTO ip_add VALUES('192.168.1.7'); INSERT INTO ip_add VALUES('192.168.1.19'); SELECT ip FROM ip_add WHERE ISINNET( ip, '172.16.1.0', 16 ); SELECT ip FROM ip_add WHERE ISINNET( ip, '172.16.1.0/16' ); 172.16.1.40 172.16.1.93 172.16.1.204 172.16.4.203 172.16.4.205 172.16.4.69 SELECT ip FROM ip_add WHERE ISINNET( ip, '172.16.1.0', 24 ); SELECT ip FROM ip_add WHERE ISINNET( ip, '172.16.1.0/24' ); 172.16.1.40 172.16.1.93 172.16.1.204 SELECT * FROM ip_add WHERE NOT ISINNET( ip, '128.0.0.0', 1 ); SELECT * FROM ip_add WHERE NOT ISINNET( ip, '128.0.0.0/1' ); 10.0.1.204 10.0.1.16 10.1.0.16 DELETE FROM ip_add WHERE NOT ISINNET( ip, '128.0.0.0', 1 ); DELETE FROM ip_add WHERE NOT ISINNET( ip, '128.0.0.0/1' ); SELECT * FROM ip_add; 172.16.1.40 172.16.1.93 172.16.1.204 172.16.4.203 172.16.4.205 172.16.4.69 192.168.1.5 192.168.1.7 192.168.1.19 programm template was taken from http://sqlite.org/contrib/ http://sqlite.org/contrib/download/extension-functions.c?get=25 Mer 23 jul 2008 16:24:01 CEST Schplurtz le deboulonne. Instructions (mostly from extension-functions.c): 1) Compile with Linux: gcc -fPIC -lm -shared ipv4-ext.c -o libsqliteipv4.so Mac OS X: gcc -fno-common -dynamiclib ipv4-ext.c -o libsqliteipv4.dylib (You may need to add flags -I /opt/local/include/ if your sqlite3 is installed from Mac ports, or -I /sw/include/ if installed with Fink.) Please, note that sqlite3 from macport 1.6.0 is not compiled with --enable-load-extension. So you cannot try this extension from within the sqlite3 shell. The same applies to leopard's /usr/bin/sqlite3 2) In your application, call sqlite3_enable_load_extension(db,1) to allow loading external libraries. Then load the library libsqliteipv4 using sqlite3_load_extension; the third argument should be 0. See http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. 3) Use, for example: SELECT ISINNET( '10.0.0.1', '10.0.0.0', 8 ); Note: Loading extensions is by default prohibited as a security measure; see "Security Considerations" in http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. If the sqlite3 program and library are built this way, you cannot use these functions from the program, you must write your own program using the sqlite3 API, and call sqlite3_enable_load_extension as described above. If the program is built so that loading extensions is permitted, the following will work: sqlite> SELECT load_extension('./libsqliteipv4.so'); sqlite> select isinnet( '123.234.210.109', '123.123.23.18', '255.248.0.0' ); 0 Alterations: The instructions are for Linux or Mac OS X; users of other OSes may need to modify this procedure. If you do not wish to make a loadable module, #define SQLITE_ENABLE_INET Liam Healy (with little modifications by Schplurtz le deboulonne) */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_INET) #include <stdlib.h> #include <sys/types.h> #include <string.h> #include <arpa/inet.h> #include <assert.h> #ifndef SQLITE_CORE #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #else #include "sqlite3.h" #endif /* * The isinnet() SQL function returns true if ip is in network/netmask. * isinnet( '172.16.1.23', '172.16.1.0', 18 ) * isinnet( '172.16.1.23', '172.16.1.0', '18' ) * isinnet( '172.16.1.23', '172.16.1.0', '255.255.192.0' ) */ static void isinnet3Func( sqlite3_context *context, int argc, sqlite3_value **argv ) { u_int32_t ad, net, mask; int rval, maskLen; if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL || sqlite3_value_type(argv[2]) == SQLITE_NULL ){ sqlite3_result_null(context); return; } if( (rval = inet_pton(AF_INET,(char*)sqlite3_value_text(argv[0]),&ad) < 1) || (rval = inet_pton(AF_INET,(char*)sqlite3_value_text(argv[1]),&net) < 1) ) { sqlite3_result_null(context); return; } ad = htonl(ad); net = htonl(net); maskLen =strlen((char*)sqlite3_value_text(argv[2])); /* put mask in hex form */ if (maskLen < 3) { mask = atoi((char*)sqlite3_value_text(argv[2])); mask = ~ ( (((u_int32_t)1) << (32 - mask)) -1 ); } else { /* mask is in dotted form */ if( (rval = inet_pton(AF_INET,(char*)sqlite3_value_text(argv[2]),&mask) < 1) ) { sqlite3_result_null(context); return; } mask = htonl(mask); } sqlite3_result_int( context, ((ad & mask) == (net & mask )) ); } /* * The isinnet() SQL function returns true if ip is in network/netmask. * isinnet( '172.16.1.23', '172.16.1.0/18' ) * isinnet( '172.16.1.23', '172.16.1.0/255.255.192.0' ) */ static void isinnet2Func( sqlite3_context *context, int argc, sqlite3_value **argv ) { u_int32_t ad, net, mask; int rval, maskLen; char *slashPos, *stringMask, *stringIP; if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){ sqlite3_result_null(context); return; } if( (rval = inet_pton(AF_INET,(char*)sqlite3_value_text(argv[0]),&ad) < 1) ) { sqlite3_result_null(context); return; } ad = htonl(ad); /* split the ip address and mask */ slashPos = strchr((char*)sqlite3_value_text(argv[1]), (int) '/'); if (slashPos == NULL) { /* straight ip address without mask */ mask = (u_int32_t)1; } else { /* ipaddress has the mask, handle the mask and seperate out the */ /* ip address */ stringMask = slashPos +1; maskLen =strlen(stringMask); /* put mask in hex form */ if (maskLen < 3) { mask = atoi(stringMask); mask = ~ ( (((u_int32_t)1) << (32 - mask)) -1 ); } else { /* mask is in dotted form */ if ((rval = inet_pton(AF_INET,stringMask,&mask)) < 1 ) { sqlite3_result_null(context); return; } mask = htonl(mask); } int ipLen = (uintptr_t)slashPos - (uintptr_t) (char*)sqlite3_value_text(argv[1]); /* divide the string into ip and mask portion */ stringIP = sqlite3_malloc( ipLen +1 ); strncpy( stringIP, (char*)sqlite3_value_text(argv[1]), ipLen ); stringIP[ipLen] = '\0'; } if ( (rval = inet_pton(AF_INET,(char*)stringIP,&net)) < 1) { sqlite3_result_null(context); return; }; net = htonl(net); sqlite3_result_int( context, ((ad & mask) == (net & mask)) ); sqlite3_free(stringIP); } static void ip2intFunc( sqlite3_context *context, int argc, sqlite3_value **argv ) { u_int32_t ad; int rval; if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ sqlite3_result_null(context); } else { if( (rval = inet_pton(AF_INET,(char*)sqlite3_value_text(argv[0]),&ad) < 1) ) { sqlite3_result_null(context); return; } ad = htonl(ad); sqlite3_result_int64( context, ad ); } } static void int2ipFunc( sqlite3_context *context, int argc, sqlite3_value **argv ) { u_int32_t ip; unsigned char ad[32]; if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ sqlite3_result_null(context); } else { ip = sqlite3_value_int64(argv[0]); ip = ntohl(ip); if( inet_ntop(AF_INET, &ip, ad, 32) == NULL ) { sqlite3_result_null(context); return; } sqlite3_result_text( context, (char*)ad, -1, SQLITE_TRANSIENT); } } static void net2int1Func( sqlite3_context *context, int argc, sqlite3_value **argv ) { u_int32_t net, mask; int rval, maskLen; char *slashPos, *stringMask, *stringIP; if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ sqlite3_result_null(context); return; } /* split the ip address and mask */ slashPos = strchr((char*)sqlite3_value_text(argv[0]), (int) '/'); if (slashPos == NULL) { /* straight ip address without mask */ mask = (u_int32_t)1; } else { /* ipaddress has the mask, handle the mask and seperate out the */ /* ip address */ stringMask = slashPos +1; maskLen =strlen(stringMask); /* put mask in hex form */ if (maskLen < 3) { mask = atoi(stringMask); mask = ~ ( (((u_int32_t)1) << (32 - mask)) -1 ); } else { /* mask is in dotted form */ if ((rval = inet_pton(AF_INET,stringMask,&mask)) < 1 ) { sqlite3_result_null(context); return; } mask = htonl(mask); } int ipLen = (uintptr_t)slashPos - (uintptr_t) (char*)sqlite3_value_text(argv[0]); /* divide the string into ip and mask portion */ stringIP = sqlite3_malloc( ipLen +1 ); strncpy( stringIP, (char*)sqlite3_value_text(argv[0]), ipLen ); stringIP[ipLen] = '\0'; } if ( (rval = inet_pton(AF_INET,(char*)stringIP,&net)) < 1) { sqlite3_result_null(context); return; }; net = htonl(net); sqlite3_result_int64( context, ((net & mask)) ); sqlite3_free(stringIP); } static void net2int2Func( sqlite3_context *context, int argc, sqlite3_value **argv ) { u_int32_t net, mask; int rval, maskLen; if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){ sqlite3_result_null(context); return; } if( (rval = inet_pton(AF_INET,(char*)sqlite3_value_text(argv[0]),&net) < 1) ) { sqlite3_result_null(context); return; } net = htonl(net); maskLen =strlen((char*)sqlite3_value_text(argv[1])); /* put mask in hex form */ if (maskLen < 3) { mask = atoi((char*)sqlite3_value_text(argv[1])); mask = ~ ( (((u_int32_t)1) << (32 - mask)) -1 ); } else { /* mask is in dotted form */ if( (rval = inet_pton(AF_INET,(char*)sqlite3_value_text(argv[1]),&mask) < 1) ) { sqlite3_result_null(context); return; } mask = htonl(mask); } sqlite3_result_int64( context, ((net & mask )) ); } static void net2lengthFunc( sqlite3_context *context, int argc, sqlite3_value **argv ) { u_int32_t mask; int rval, maskLen; char *slashPos, *stringMask; if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ sqlite3_result_null(context); return; } /* split the ip address and mask */ slashPos = strchr((char*)sqlite3_value_text(argv[0]), (int) '/'); if (slashPos == NULL) { /* straight ip address without mask */ mask = (u_int32_t)1; } else { /* ipaddress has the mask, handle the mask and seperate out the */ /* ip address */ stringMask = slashPos +1; maskLen =strlen(stringMask); /* put mask in hex form */ if (maskLen < 3) { mask = atoi(stringMask); mask = ( (u_int32_t)1 << (32 - mask) ); } else { /* mask is in dotted form */ if ((rval = inet_pton(AF_INET,stringMask,&mask)) < 1 ) { sqlite3_result_null(context); return; } mask = htonl(mask); mask = (~(u_int32_t)mask) + 1; } } sqlite3_result_int64( context, mask ); } static void netmask2lengthFunc( sqlite3_context *context, int argc, sqlite3_value **argv ) { u_int32_t mask; if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ sqlite3_result_null(context); return; } mask = atoi((char*)sqlite3_value_text(argv[0])); mask = ( (u_int32_t)1 << (32 - mask) ); sqlite3_result_int64( context, mask ); } /* SQLite invokes this routine once when it loads the extension. ** Create new functions, collating sequences, and virtual table ** modules here. This is usually the only exported symbol in ** the shared library. */ int sqlite3InetInit(sqlite3 *db){ sqlite3_create_function(db, "ip2int", 1, SQLITE_ANY, 0, ip2intFunc, 0, 0); sqlite3_create_function(db, "int2ip", 1, SQLITE_ANY, 0, int2ipFunc, 0, 0); sqlite3_create_function(db, "net2int", 1, SQLITE_ANY, 0, net2int1Func, 0, 0); sqlite3_create_function(db, "net2int", 2, SQLITE_ANY, 0, net2int2Func, 0, 0); sqlite3_create_function(db, "net2length", 1, SQLITE_ANY, 0, net2lengthFunc, 0, 0); sqlite3_create_function(db, "netmask2length", 1, SQLITE_ANY, 0, netmask2lengthFunc, 0, 0); sqlite3_create_function(db, "isinnet", 3, SQLITE_ANY, 0, isinnet3Func, 0, 0); sqlite3_create_function(db, "isinnet", 2, SQLITE_ANY, 0, isinnet2Func, 0, 0); return 0; } #if !SQLITE_CORE int sqlite3_extension_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3InetInit(db); } #endif #endif Best regards, Alexey.
_______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users