LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   bind source (https://www.linuxquestions.org/questions/programming-9/bind-source-4175419310/)

Balvinder87 07-30-2012 03:22 AM

bind source
 
I want to write the logs to A File based on client's ip tell me where it is printing the ip in the source the output of log is as follows
18-Jul-2012 17:18:01.902 client 192.168.2.4#59526: query: www.google.co.in IN A + (192.168.2.4)
18-Jul-2012 17:18:01.909 client 192.168.2.4#46998: query: apis.google.com IN A + (192.168.2.4)
bi
void
log_vwrite(log_context lc, int category, int level, const char *format,
va_list args) {
log_channel_list lcl;
int pri, debugging, did_vsprintf = 0;
int original_category;
FILE *stream;
log_channel chan;
struct timeval tv;
struct tm *local_tm;
#ifdef HAVE_TIME_R
struct tm tm_tmp;
#endif
time_t tt;
const char *category_name;
const char *level_str;
char time_buf[256];
char level_buf[256];

REQUIRE(lc != NULL);

debugging = (lc->flags & LOG_OPTION_DEBUG);

/*
* If not debugging, short circuit debugging messages very early.
*/
if (level > 0 && !debugging)
return;

if (category < 0 || category > lc->num_categories)
category = 0; /* use default */
original_category = category;
lcl = lc->categories[category];
if (lcl == NULL) {
category = 0;
lcl = lc->categories[0];

}oid
log_vwrite(log_context lc, int category, int level, const char *format,
va_list args) {
log_channel_list lcl;
int pri, debugging, did_vsprintf = 0;
int original_category;
FILE *stream;
log_channel chan;
struct timeval tv;
struct tm *local_tm;
#ifdef HAVE_TIME_R
struct tm tm_tmp;
#endif
time_t tt;
const char *category_name;
const char *level_str;
char time_buf[256];
char level_buf[256];

REQUIRE(lc != NULL);

debugging = (lc->flags & LOG_OPTION_DEBUG);

/*
* If not debugging, short circuit debugging messages very early.
*/
if (level > 0 && !debugging)
return;

if (category < 0 || category > lc->num_categories)
category = 0; /* use default */
original_category = category;
lcl = lc->categories[category];
if (lcl == NULL) {
category = 0;
lcl = lc->categories[0];
}

/*
* Get the current time and format it.
*/
time_buf[0]='\0';
if (gettimeofday(&tv, NULL) < 0) {
syslog(LOG_INFO, "gettimeofday failed in log_vwrite()");
} else {
tt = tv.tv_sec;
#ifdef HAVE_TIME_R
local_tm = localtime_r(&tt, &tm_tmp);
#else
local_tm = localtime(&tt);
#endif
if (local_tm != NULL) {
sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ",
local_tm->tm_mday, months[local_tm->tm_mon],
local_tm->tm_year+1900, local_tm->tm_hour,
local_tm->tm_min, local_tm->tm_sec,
(long)tv.tv_usec/1000);

NevemTeve 07-31-2012 01:23 PM

> tell me where it is printing the ip in the source

Nowhere. It is easy to tell if you search for the word "query". This is just an wrapper-function that forwards the message to syslog.

Balvinder87 07-31-2012 11:48 PM

The caller of log_vwrite is log_write.. see this code in logging.c
here is logging.c

http://www.linuxquestions.org/questi...ce-4175418744/
log_write(log_context lc, int category, int level, const char *format, ...) {
va_list args;

va_start(args, format);
log_vwrite(lc, category, level, format, args);
va_end(args);
}

one of the provided inputs to log_write has the ip address in it.

(log_context lc, int category, int level, const char *format, ...
I am not able to understand which one of the parameters, lc, catgory, format or args have the ip address.

NevemTeve 08-01-2012 12:47 AM

log_write is just another wrapper, as you can see...

Balvinder87 08-01-2012 12:55 AM

can you tell me what wrapper actually means as i am new to programming?

NevemTeve 08-01-2012 01:48 AM

synonyms: forwarder, proxy, helper, mapper, in-between, transfer, relay -- meaning: it doesn't actually do the main processing... so simply find the points where log_write is called

Balvinder87 08-01-2012 05:15 AM

thanku

Balvinder87 08-02-2012 05:59 AM

log_write is called just once and inside it there is log_vwrite which is taking 5 arguments
i need to find out the argument that contains the ip part

NevemTeve 08-02-2012 06:09 AM

I've just downloaded bind-9.9.1-P2, the logging in question can be found in file bin/named/client.c function ns_client_logv:

Code:

        isc_log_write(ns_g_lctx, category, module, level,
                      "client %s%s%s%s%s%s%s%s: %s",
                      peerbuf, sep1, signer, sep2, qname, sep3,
                      sep4, viewname, msgbuf);

does it help you? What your actual question is?

NevemTeve 08-02-2012 10:03 AM

(To tell the truth, I think you real question is something very trivial, like 'how to convert IP address from binary to text, or vice versa'...)

Balvinder87 08-03-2012 12:34 AM

hii nevem
first of all thanks for the reply my question is quite simple
My network has IP addresses from 192.168.2.1...10
I have installed bind 9.7.3 on my system whose ip is 192.168.2.4.
the log file is named as named_querylog.the sample contents of my log file are
03-Aug-2012 10:02:16.797 client 192.168.2.4#36264: query: lh6.googleusercontent.com IN A + (192.168.2.4)
I want to see the individual client logs in separate files based on client ip address.
So I want to modify the bind source
for this i need to do some changes in log.c file.
In this file we have a function
isc_log_write(ns_g_lctx, category, module, level,
"client %s%s%s%s%s%s%s%s: %s",
peerbuf, sep1, signer, sep2, qname, sep3,
sep4, viewname, msgbuf
based on client ip i want to write to a Particular File.
Can you suggest me where I Can Do these changes??

NevemTeve 08-03-2012 02:43 AM

You could add a little part after/before it, eg:

Code:

{
    char filename [512];
    FILE *f;

    sprintf (filename, "/var/log/bind-%s", peerbuff);
    f= fopen (filename, "a");
    if (f) {
        fpintf (f, "client %s%s%s%s%s%s%s%s: %s",
                peerbuf, sep1, signer, sep2, qname, sep3,
                sep4, viewname, msgbuf);
        fclose (f);
    }
}


Balvinder87 08-03-2012 04:49 AM

thanks just one doubt
how does bind get the peerbuf to contain the IP address?

NevemTeve 08-03-2012 05:00 AM

I think it could be traced back to a recvfrom(2) system-call:

Code:

ssize_t recvfrom (int sockfd, void *buf, size_t len, int flags,
                  struct sockaddr *src_addr, socklen_t *addrlen);


Balvinder87 08-03-2012 05:41 AM

Thanks can you tell me which file has this code??this code is in resolver.c???
And where he inserts that into peerbuf?

NevemTeve 08-03-2012 06:04 AM

> i want to write a routine that can read ip address from the peerbuf

You may, but why? (Use inet_aton if you want to convert it to binary format.)

> and log to a different log file

You have already been given code for that.

> ??

What is the question?

Balvinder87 08-04-2012 08:15 AM

my question is where is this code ?
in which file??
ssize_t recvfrom (int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);

---------- Post added 08-04-12 at 06:46 PM ----------

my question is where is this code ?
in which file??
ssize_t recvfrom (int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);

---------- Post added 08-04-12 at 06:46 PM ----------

my question is where is this code ?
in which file??
ssize_t recvfrom (int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);

Balvinder87 08-04-2012 08:17 AM

my question is where is this code ?
in which file??
ssize_t recvfrom (int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);

NevemTeve 08-04-2012 09:30 AM

That's what 'grep -r' is good for (note: bind/named consists of dozens (or hundreds) of source files)... but please try to understand: you don't need it at all, you only have to use the bit of code I gave you yesterday.

Balvinder87 08-04-2012 11:56 AM

In the log_write funcion I want to see the contents of category and pick up ip address from category buffer
so that i can log to different files using ip address .peerbuf is an array that holds the client information.this client information will have ip address.Your code is not picking the ip it is simply writing to a file

NevemTeve 08-05-2012 05:07 AM

The name of the file is constructed from a static part and the IP-address.
Code:

{
    char filename [512];
    FILE *f;

    sprintf (filename, "/var/log/bind-%s", peerbuff);
    f= fopen (filename, "a");
    if (f) {
        fpintf (f, "client %s%s%s%s%s%s%s%s: %s",
                peerbuf, sep1, signer, sep2, qname, sep3,
                sep4, viewname, msgbuf);
        fclose (f);
    }
}


Balvinder87 08-05-2012 06:55 AM

peerbuf is an array with other values other than ip address
we want to know the ip part only
because there are different clients configured.based on their respective ips and thier logs i want to write to different files?
so i need to know from where the ip is passed to peerbuf array?

NevemTeve 08-05-2012 07:10 AM

> peerbuf is an array with other values other than ip address

It is a character-array (aka string). The IP-address is delimited by a #hashmark. Use strchr to find it in the string.

Code:

{
    char filename [512];
    FILE *f;
    const char *p;
    size_t plen;

    p= strchr (peerbuff, '#');
    if (p) plen= p-peerbuff;
    else  plen= strlen (peerbuff);
    sprintf (filename, "/var/log/bind-%.*s", (int)plen, peerbuff);
    f= fopen (filename, "a");
    if (f) {
        fpintf (f, "client %s%s%s%s%s%s%s%s: %s",
                peerbuf, sep1, signer, sep2, qname, sep3,
                sep4, viewname, msgbuf);
        fclose (f);
    }
}


Balvinder87 08-05-2012 07:41 AM

thanks for the reply It was a great learning experience as i am new to linux and programming world
thanks once again will talk to you tomorrow after implementing this code.

Balvinder87 08-06-2012 01:58 AM

Can we do the changes in the log_write function in order to pickup the ip address from the category buffer
and print the logs based on the respective ids
isc_log_write(ns_g_lctx, category, module, level,
"client %s%s%s: %s", peerbuf, sep, name, msgbuf);
}

NevemTeve 08-06-2012 02:50 AM

Perhaps, but a variable called 'category' is not likely to hold the IP-address.
BTW: What version of bind are you using? Tha latest is 9.9.1-P2, it doesn't have function called log_write.

Balvinder87 08-06-2012 06:27 AM

yes everything working perfectly as of now
i made a program sample.c
I Hard coded a global variable peerbuff to
char *peerbuff = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

get_ipstring ()
{
/* The code you submitted goes here */
{
char filename [512];
FILE *f;
const char *p;
size_t plen;

p= strchr (peerbuff, '#');
if (p) plen= p-peerbuff;
else plen= strlen (peerbuff);
sprintf (filename, "/var/log/bind-%.*s", (int)plen, peerbuff);
f= fopen (filename, "a");
if (f) {
fpintf (f, "client %s%s%s%s%s%s%s%s: %s",
peerbuf, sep1, signer, sep2, qname, sep3,
sep4, viewname, msgbuf);
fclose (f);
}
}

}

main ()
{
get_ipstring();
}


i need to remove the filename from my program . Just store the ip address in another string and return it and simply call the program
just help me with the way we return the string to a function and changes needed to return the ip only
Thanks in advance
Balvinder Singh

NevemTeve 08-06-2012 08:39 AM

Something like this (untested):
Code:

/* getprefix.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

size_t getprefix (char *to, size_t tomaxsize, const char *from, char separator)
{
    const char *p;
    size_t plen;

    *to= '\0';

    if (!from || !*from) return 0;

    p= strchr (from, separator);
    if (p) plen= p-from;
    else plen= strlen (from);

    if (plen>tomaxsize-1) plen= tomaxsize-1;

    memcpy (to, from, plen);
    to[plen]= '\0';
    return plen;
}

int main (void)
{
    char outbuff [16];

    getprefix (outbuff, sizeof (outbuff), "10.20.30.40#other", '#');
    printf ("Test1: out='%s'\n", outbuff);

    getprefix (outbuff, sizeof (outbuff), "255.255.255.255", '#');
    printf ("Test2: out='%s'\n", outbuff);

    return 0;
}


Balvinder87 08-07-2012 12:28 AM

hii nevem i just tested the code it is giving the output based on your code as
Test1: out='192.168.2.4'
Test2: out='255.255.255.255'
our log output is like this way
"02-Aug-2012 16:02:54.189 client 192.168.2.4#53554: query: account.thequestionsnetwork.org IN A + (192.168.2.4)
we have to pass the string this way
"02-Aug-2012 16:02:17.941 client 192.168.2.4#37492:
based on this input the code is just printing the date and half time

Test1: out='02-Aug-2012 16:'
Test2: out='255.255.255.255'
i have another algo please help me write code for this
1.use a char *start to point to the start of the string.
2.use another char *sep to point to the start of the string
3.moving sep character by character start of the string till we reach your separator i.e. #
like this way(may be i have doubt)
while (*sep != #) {
sep++;
if (*sep = " ") { start = sep }
}
that way start will point to the last space before the #
and sep will point to the separator #
by the time the while is over r copy those contents.. to the output buff
Waiting for the C code for this
thanks
balvinder

NevemTeve 08-07-2012 02:10 AM

It's still about writing into separate log-files from bind, or it's about something else (like processing bind-log with a separate program)? If the former, then simply check what the content of 'peerbuff' is (my guess is: IP#port, eg 192.168.2.4#59526, 192.168.2.4#46998), then you will know how to get the IP from it (the part before the hashmark).

PS: Why is it so bloody hard to remember using [code] and [/code] when pasting source?

Balvinder87 08-07-2012 02:13 AM

can you help me with the c code for the above algo?

Balvinder87 08-07-2012 02:21 AM

Help me write the code for above algo i know the logic but i am learning the syntax please give me the code for that?

NevemTeve 08-07-2012 02:26 AM

Can you answer my previous question:

It's still about writing into separate log-files from bind, or it's about something else (like processing bind-log with a separate program)? If the former, then simply check what the content of 'peerbuff' is (my guess is: IP#port, eg 192.168.2.4#59526, 192.168.2.4#46998), then you will know how to get the IP from it (the part before the hashmark).

Balvinder87 08-07-2012 02:28 AM

i want to write to separate file later on but at present i simply want to store ip address and print it

NevemTeve 08-07-2012 02:35 AM

Very good. Now let's see the concrete specification: you have a string like '02-Aug-2012 16:02:54.189 client 192.168.2.4#53554: query: account.thequestionsnetwork.org IN A + (192.168.2.4)' and you want to cut out the IP-address. There are programming tools for that like 'cut' -- are your sure you want it in C?

Balvinder87 08-07-2012 02:42 AM

thanku

NevemTeve 08-07-2012 03:24 AM

Code:

/* parselog.c */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

size_t getfield (char *to, size_t tomaxsize, const char *from, int nfld)
{
    int state;
    const char *p, *plim;
    const char *fldbeg;
    size_t fldlen;
    int fldfound;

    *to= '\0';

    if (!from || !*from || nfld<0) return 0;

    p= from;
    plim= from + strlen (from);
    state= 'A';
    fldfound= 0;
    fldbeg= NULL;
    fldlen= 0;

    for (; fldfound<nfld && p<plim; ++p) {
        int c= *p;

        if (state=='A') {
            if (!isspace (c)) {
                fldbeg= p;
                state= 'B';
            }
        } else {
            if (isspace (c)) {
                fldlen= p-fldbeg;
                ++fldfound;
                state= 'A';
            }
        }
    }
    if (state=='B') {
        fldlen= p-fldbeg;
        ++fldfound;
    }

    if (fldfound != nfld) {
        return EOF;

    } else {
        if (fldlen>tomaxsize-1) fldlen= tomaxsize-1;

        memcpy (to, fldbeg, fldlen);
        to[fldlen]= '\0';
        return 0;
    }
}

size_t getprefix (char *to, size_t tomaxsize, const char *from, char separator)
{
    const char *p;
    size_t plen;

    *to= '\0';

    if (!from || !*from) return 0;

    p= strchr (from, separator);
    if (p) plen= p-from;
    else plen= strlen (from);

    if (plen>tomaxsize-1) plen= tomaxsize-1;

    memcpy (to, from, plen);
    to[plen]= '\0';
    return plen;
}

int main (void)
{
    char tmpbuff [24];
    char outbuff [16];

    getfield (tmpbuff, sizeof (tmpbuff)
        , "2-Aug-2012 16:02:54.189 client 192.168.2.4#53554: query: account.thequestionsnetwork.org IN A + (192.168.2.4)"
        , 4);
    getprefix (outbuff, sizeof (outbuff), tmpbuff, '#');
    printf ("Test1: out='%s'\n", outbuff);

    getfield (tmpbuff, sizeof (tmpbuff)
        , "18-Jul-2012 17:18:01.909 client 192.168.2.4#46998: query: apis.google.com IN A + (192.168.2.4)"
        , 4);
    getprefix (outbuff, sizeof (outbuff), tmpbuff, '#');
    printf ("Test2: out='%s'\n", outbuff);

    return 0;
}

It consists of two functions: first 'getfield' cuts the specified field (#4: IP#port) from the line into tmpbuff, then 'getprefix' gets to 'IP' into outbuff.

Note: It was an honor to be allowed to write your programs, but sadly I don't have more free-time to do that, so you are on your own from now.

Balvinder87 08-07-2012 04:11 AM

it was really a great experience learning from you sir i will not ask you to write the full programs in future but will put my doubts and hope you will reply soon

Balvinder87 08-09-2012 12:35 AM

can you tell me which file in bin/named is responsible for logging to the /var/log/filename
now i need to append the ip address to the log file name

if the log file is named_query.log.I need to have the file as named_query.log.192.168.132.1 and it should be created in the same place i.e. in /var/log/
in client.c they call isc_log_write so we need to see what that calls internally and see how that maps to log_write
then in isc_log_write in logconf.c, when we get peerbuf as one of the parameters, we need to call getip and log to a different file.
How can we do that any hint?

NevemTeve 08-09-2012 02:14 AM

Check these msgs:
http://www.linuxquestions.org/questi...0/#post4743976
http://www.linuxquestions.org/questi...ml#post4746345

Balvinder87 08-09-2012 05:56 AM

will you please elaborate the behaviour of the isc__log_write function?
how this functin is writing logs?
this is the function?

isc_log_write(ns_g_lctx, category, module, level,
"client %s%s%s%s%s%s%s%s: %s",
peerbuf, sep1, signer, sep2, qname, sep3,
sep4, viewname, msgbuf);

Balvinder87 08-09-2012 10:56 PM

hey nevem its really important for me to complete this task by today.i have added a plugin in bind9 source which gets the ip address from the output string now in the final string.based on this ip i need to append it to filename( if my file name is named_querylog then the cooresponding logs of the ip will be in the file name as named_query.log.192.168.132.1
so i need to find out the behaviour of isc_log_write can you help me find out what is happening in this function?
what context it passes to log_write in the case where it logs peerbuf?
i am using bind 9.7.3 please reply its really important?

NevemTeve 08-09-2012 11:21 PM

You don't have to trace and modify the existing function, just add a few line to create client-specific file-name, open it, write the log-record, then close the file. And, as it happens, you are already given code to do that.
http://www.linuxquestions.org/questi...ml#post4746345
That's what you have to add after/before the calling of isc_log_write.

Balvinder87 08-09-2012 11:44 PM

I guess the code that you have given is writing the logs of clients to different files
i need to pick up the ip address from peerbuf and based on that ip i need to write the log in the files as
filename.ipaddress?
will your code behave that way?

NevemTeve 08-10-2012 02:26 AM

Indeed, it does.


All times are GMT -5. The time now is 05:23 PM.