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

Reply via email to