Functions for doing DNS lookups. First, lookup() - get the IP address for a given host. Secondly, reverse_lookup() - get the hostname for a given IP address.
====================
/* Copyright Abandoned 1998 TCX DataKonsult AB & Monty Program KB & Detron HB & Alexis Mikhailov <root@medinf.chuvashia.su> This file is public domain and comes with NO WARRANTY of any kind */
/* ** example file of UDF (user definable functions) that are dynamicly loaded ** into the standard mysqld core. ** ** The functions name, type and shared library is saved in the new system ** table 'func'. To be able to create new functions one must have write ** privilege for the database 'mysql'. If one starts MySQL with ** --skip-grant, then UDF initialization will also be skipped. ** ** Syntax for the new commands are: ** create function <function_name> returns {string|real|integer} ** soname <name_of_shared_library> ** drop function <function_name> ** ** Each defined function may have a xxxx_init function and a xxxx_deinit ** function. The init function should alloc memory for the function ** and tell the main function about the max length of the result ** (for string functions), number of decimals (for double functions) and ** if the result may be a null value. ** ** If a function sets the 'error' argument to 1 the function will not be ** called anymore and mysqld will return NULL for all calls to this copy ** of the function. ** ** All strings arguments to functions are given as string pointer + length ** to allow handling of binary data. ** Remember that all functions must be thread safe. This means that one is not ** allowed to alloc any global or static variables that changes! ** If one needs memory one should alloc this in the init function and free ** this on the __deinit function. ** ** ** Function 'metaphon' returns a metaphon string of the string argument. ** This is something like a soundex string, but it's more tuned for English. ** ** Function 'myfunc_double' returns summary of codes of all letters ** of arguments divided by summary length of all its arguments. ** ** Function 'myfunc_int' returns summary length of all its arguments. ** ** On the end is a couple of functions that converts hostnames to ip and ** vice versa. ** ** A dynamicly loadable file should be compiled sharable ** (something like: gcc -shared -o udf_example.so myfunc.cc). ** You can easily get all switches right by doing: ** cd sql ; make udf_example.o ** Take the compile line that make writes, remove the '-c' near the end of ** the line and add -o udf_example.so to the end of the compile line. ** The resulting library (udf_example.so) should be copied to some dir ** searched by ld. (/usr/lib ?) ** ** After the library is made one must notify mysqld about the new ** functions with the commands: ** ** CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so"; ** CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so"; ** ** After this the functions will work exactly like native MySQL functions. ** Functions should be created only once. ** ** The functions can be deleted by: ** ** DROP FUNCTION lookup; ** DROP FUNCTION reverse_lookup; ** ** The CREATE FUNCTION and DROP FUNCTION update the func@mysql table. All ** Active function will be reloaded on every restart of server ** (if --skip-grant-tables is not given) ** */
#ifdef STANDARD #include <stdio.h> #include <string.h> #else #include <global.h> #include <my_sys.h> #endif #include <mysql.h> #include <m_ctype.h> #include <m_string.h> // To get strmov()
#ifdef HAVE_DLOPEN
/**************************************************************************** ** Some functions that handles IP and hostname conversions ** The orignal function was from Zeev Suraski. ** ** CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so"; ** CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so"; ** ****************************************************************************/
#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h>
extern "C" { my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message); char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *null_value, char *error); my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message); char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *null_value, char *error); }
/**************************************************************************** ** lookup IP for an hostname. ** ** This code assumes that gethostbyname_r exists and inet_ntoa() is thread ** safe (As it is in Solaris) ****************************************************************************/
my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { if (args->arg_count != 1 || args->arg_type[0] != STRING_RESULT) { strmov(message,"Wrong arguments to lookup; Use the source"); return 1; } initid->max_length=11; initid->maybe_null=1; return 0; }
char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *null_value, char *error) { uint length; int tmp_errno; char name_buff[256],hostname_buff[2048]; struct hostent tmp_hostent,*hostent;
if (!args->args[0] || !(length=args->lengths[0])) { *null_value=1; return 0; } if (length >= sizeof(name_buff)) length=sizeof(name_buff)-1; memcpy(name_buff,args->args[0],length); name_buff[length]=0;
if (!(hostent=gethostbyname_r(name_buff,&tmp_hostent,hostname_buff, sizeof(hostname_buff), &tmp_errno))) { *null_value=1; return 0; } struct in_addr in; memcpy((char*) &in,(char*) *hostent->h_addr_list, sizeof(in.s_addr)); *res_length= (ulong) (strmov(result, inet_ntoa(in)) - result); return result; }
/**************************************************************************** ** return hostname for an IP number. ** The functions can take as arguments a string "xxx.xxx.xxx.xxx" or ** four numbers. ****************************************************************************/
my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { if (args->arg_count == 1) args->arg_type[0]= STRING_RESULT; else if (args->arg_count == 4) args->arg_type[0]=args->arg_type[1]=args->arg_type[2]=args->arg_type[3]= INT_RESULT; else { strmov(message, "Wrong number of arguments to reverse_lookup; Use the source"); return 1; } initid->max_length=32; initid->maybe_null=1; return 0; }
char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *null_value, char *error) { char name_buff[256]; struct hostent tmp_hostent; uint length;
if (args->arg_count == 4) { if (!args->args[0] || !args->args[1] ||!args->args[2] ||!args->args[3]) { *null_value=1; return 0; } sprintf(result,"%d.%d.%d.%d", (int) *((long long*) args->args[0]), (int) *((long long*) args->args[1]), (int) *((long long*) args->args[2]), (int) *((long long*) args->args[3])); } else { // string argument if (!args->args[0]) // Return NULL for NULL values { *null_value=1; return 0; } length=args->lengths[0]; if (length >= (uint) *res_length-1) length=(uint) *res_length; memcpy(result,args->args[0],length); result[length]=0; }
unsigned long taddr = inet_addr(result); if (taddr == (unsigned long) -1L) { *null_value=1; return 0; } struct hostent *hp; int tmp_errno; if (!(hp=gethostbyaddr_r((char*) &taddr,sizeof(taddr), AF_INET, &tmp_hostent, name_buff,sizeof(name_buff), &tmp_errno))) { *null_value=1; return 0; } *res_length=(ulong) (strmov(result,hp->h_name) - result); return result; }
#endif // defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) #endif /* HAVE_DLOPEN */
|