"Fossies" - the Fresh Open Source Software Archive

Member "npadmin-0.14/session.C~" (19 Apr 2001, 9404 Bytes) of package /linux/misc/old/npadmin-0.14.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* Copyright (c) 2000 Ben Woodard
    2  * All rights reserved.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public Licence
    6  * as published by the Free Software Foundation; either version 2
    7  * of the Licence, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRENTY; without even the implied warrenty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   12  * GNU General Public Licence in the COPYING file for more
   13  * details.
   14  *
   15  * You should have received a copy of the GNU Library General 
   16  * Public License along with the GNU C Library; see the file 
   17  * COPYING.LIB.  If not, write to the Free Software Foundation, 
   18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
   19  */
   20 
   21 #include <sys/types.h>
   22 #include <sys/socket.h>
   23 #include <sys/time.h>
   24 #include <sys/stat.h>
   25 #include <netinet/in.h>
   26 #include <arpa/inet.h>
   27 #include <assert.h>
   28 #include <fcntl.h>
   29 #include <stdio.h>
   30 #include <stdlib.h>
   31 #include <stdarg.h>
   32 #include <string.h>
   33 #include <netdb.h>
   34 #include <unistd.h>
   35 #include <errno.h>
   36 
   37 #include "compat.h"
   38 #include "ber.h"
   39 #include "session.h"
   40 #include "argflags.h"
   41 
   42 char SNMP_session::need_newline; 
   43 SNMP_session *SNMP_session::lastprint;
   44 pthread_mutex_t SNMP_session::lastprint_m;
   45 
   46 #define MAXPACKSIZE 10240
   47 
   48 void cpy_hostent(hostent *first,hostent *second){
   49   first->h_name=strdup(second->h_name);
   50   first->h_addrtype=second->h_addrtype;
   51   first->h_length=second->h_length;
   52   int i;
   53   for(i=0;second->h_aliases[i]!=NULL;i++);
   54   first->h_aliases=new char*[i+1];
   55   first->h_aliases[i]=NULL;
   56   for(;second->h_aliases[i] && i>=0;i--)
   57     first->h_aliases[i]=strdup(second->h_aliases[i]);
   58 
   59   for(i=0;second->h_addr_list[i]!=NULL;i++);
   60   first->h_addr_list=new char*[i+1];
   61   first->h_addr_list[i]=NULL;
   62   for(--i;i>=0;i--){
   63     first->h_addr_list[i]=new char[second->h_length];
   64     memcpy(first->h_addr_list[i],second->h_addr_list[i],first->h_length);
   65   }
   66 }
   67 
   68 void del_hostent(hostent *dead){
   69   int i;
   70   for(i=0;dead->h_aliases[i]!=NULL;i++)
   71     delete dead->h_aliases[i];
   72   for(i=0;dead->h_addr_list[i]!=NULL;i++)
   73     delete dead->h_addr_list[i];
   74 }
   75 
   76 SNMP_error_oid::SNMP_error_oid(const char* str){
   77   oidstr=strdup(str);
   78 }
   79 
   80 SNMP_error_oid::~SNMP_error_oid(){
   81   free(oidstr);
   82 }
   83 
   84 int SNMP_error_oid::operator==(CONST char* otherstr){
   85   return !strcmp(otherstr,oidstr);
   86 }
   87 
   88 OidSeq *SNMP_session::do_req(Tags tag, OidSeq *oids){
   89   if(flags&SESSION_DISABLED_FLAG)
   90     return NULL;
   91   /* ------- Construct the packet ------- */
   92   BerSequence *opacket,*request;
   93   long int seqno=random(),seq2;
   94   request=new BerSequence(tag,4,new BerInt(seqno),new BerInt(0L),
   95                  new BerInt(0L),oids->Seq());
   96   opacket=new BerSequence(SEQUENCE_TAG,3,new BerInt(0L),
   97                  new BerString(community,strlen(community)),
   98                  request);
   99 
  100   BerEncodedData *opackdat=opacket->encode();
  101 
  102   if(flags&SESSION_DEBUGSNMP_FLAG){
  103     write_debug("Sent", opacket);
  104     write_debug_bin(opackdat->Data(),opackdat->Length());
  105   }
  106 
  107   /* ------- Send the packet ------- */
  108   unsigned char *inbuf;
  109 
  110   BerSequence *top,*cur;
  111   do{
  112     int buflen=opackdat->Length();
  113     //    fprintf(stderr,"debug: Going to do call to %s\n",he->h_name);
  114     while((inbuf=sock->call(he->h_length,he->h_addrtype,he->h_addr_list[ipidx],
  115                 (char*)opackdat->Data(),buflen))==NULL){
  116 //       fprintf(stderr,"Warning: dropping IP addr %u.%u.%u.%u for %s.\n",
  117 //        he->h_addr_list[ipidx][0]&0xff,he->h_addr_list[ipidx][1]&0xff,
  118 //        he->h_addr_list[ipidx][2]&0xff,he->h_addr_list[ipidx][3]&0xff,
  119 //        hostname);
  120       ipidx++;
  121       if(he->h_addr_list[ipidx]==NULL){
  122     //  fprintf(stderr,"Warning: no more IP addrs for %s.\n",hostname);
  123     flags|=SESSION_DISABLED_FLAG;
  124     return NULL;
  125       }
  126     }
  127 
  128 //     inbuf=sock->call(he->h_length,he->h_addrtype,he->h_addr_list[ipidx],
  129 //           (char*)opackdat->Data(),buflen);
  130 //     assert(inbuf);
  131     top=new BerSequence(inbuf);
  132     if(flags&SESSION_DEBUGSNMP_FLAG){
  133       write_debug("Received", top);
  134       write_debug_bin(inbuf,buflen);
  135     }
  136     
  137     // make sure that this is a response
  138     cur=(BerSequence*)top->extract(2);
  139     assert(cur->type()==GET_RESP_TAG);
  140 
  141     /* make sure that this is a response to this request not some
  142        previous request. What was happening with slow was that I would
  143        send a packet then it would time out and then I would assume that
  144        the packet was lost and then I would send another copy. Right
  145        after that, the reply to the first packet would arrive and so I
  146        would move on and send another packet. Then the second reply to
  147        the first packet would arrive and the program would get all
  148        confused. This could also fix the problem where table lines are
  149        sometimes repeated over slow links. */
  150     assert((cur->peek(0)->edatacache->Data())[0]==INT_TAG);
  151     seq2=((BerInt*)cur->peek(0))->value();
  152   }while(seq2!=seqno);
  153   //  printf("Outside the loop.\n");
  154 
  155   // make sure that no errors came back
  156   unsigned char *dat=cur->peek(1)->edatacache->Data();
  157   assert(dat[0]==INT_TAG && dat[1]==1); /* if this fails then the device is not
  158                        sending back a properly constructed
  159                        packet */ 
  160   if(dat[2]!=0){
  161     dat=cur->peek(2)->edatacache->Data();
  162     assert(dat[0]==INT_TAG && dat[1]==1); /* if this fails something more 
  163                         sophisticated will have to be 
  164                         written -- hopefully this will 
  165                         never fail. */
  166     delete top;
  167     top=cur;
  168     /*cur should now point to the problem oid */
  169     top=(BerSequence*)top->peek(3);
  170     top=(BerSequence*)top->peek(dat[2]-1);
  171     cur=(BerSequence*)top->peek(0);
  172     char buf[256];
  173     cur->print(buf,256);
  174     throw new SNMP_error_oid(buf);
  175   } 
  176   delete top;
  177   top=cur;
  178   cur=(BerSequence*)top->extract(3);
  179   delete top;
  180   //  printf("leaving doreq\n");
  181   return new OidSeq(cur);
  182 }
  183 
  184 SNMP_session::SNMP_session(SNMP_socket *sockp, char *host,
  185                const char *comm):
  186   sock(sockp),ipidx(0),flags(0){
  187   if(comm)
  188     community=strdup(comm);
  189   else
  190     community=strdup("public");
  191   hostname=strdup(host);
  192 
  193   hostent *tmp;
  194   if((tmp=gethostbyname(host))==NULL){
  195     fprintf(stderr,"SNMP: cannot resolve hostname \"%s\".\n",host);
  196     exit(-4);
  197   }
  198   he=new hostent;
  199   cpy_hostent(he,tmp);
  200 }
  201 
  202 SNMP_session::~SNMP_session(){
  203   delete community;
  204   del_hostent(he);
  205   delete he;
  206   delete hostname;
  207 }
  208 
  209 void SNMP_session::setDebug(){
  210   flags|=SESSION_DEBUGSNMP_FLAG;      
  211   int filenum=0;
  212   char namebuf[20];
  213   struct stat dummy;
  214   int retval;
  215 
  216   snprintf(namebuf,19,"snmplog.%d",filenum);
  217   while((retval=stat(namebuf,&dummy))!=-1){
  218     filenum++;
  219     snprintf(namebuf,19,"snmplog.%d",filenum);
  220   }
  221   //stat returned a different error than we were expecting.
  222   assert(errno=ENOENT); 
  223   
  224   assert(debugfile=open(namebuf,O_WRONLY|O_CREAT|O_TRUNC,
  225             S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH));
  226   char buf[256];
  227   int buflen=snprintf(buf,256,"Contacting %u.%u.%u.%u\n",
  228               ((unsigned)he->h_addr_list[ipidx][0] & 0xff),
  229               ((unsigned)he->h_addr_list[ipidx][1] & 0xff),
  230               ((unsigned)he->h_addr_list[ipidx][2] & 0xff),
  231               ((unsigned)he->h_addr_list[ipidx][3] & 0xff));
  232   write(debugfile,buf,buflen);
  233 }
  234 
  235 void SNMP_session::write_debug(CONST char *dirstr, BerSequence *packet){
  236   unsigned int sizeleft=MAXPACKSIZE;
  237   char prntbuf[MAXPACKSIZE];
  238   char *curpos=prntbuf;
  239   int lenused;
  240   
  241   lenused=sprintf(prntbuf,"%s\n",dirstr);
  242   sizeleft-=lenused+1;
  243   curpos+=lenused;
  244   
  245   // overflowed the buffer
  246   assert((lenused=packet->print(curpos,sizeleft))!=-1); 
  247   curpos+=lenused;
  248   sizeleft-=lenused;
  249   
  250   assert((lenused=snprintf(curpos,sizeleft,"\n"))!=-1);
  251   sizeleft-=lenused;
  252   curpos+=lenused;
  253   
  254   sizeleft=curpos-prntbuf; // reusing a variable
  255   assert(static_cast<ssize_t>(sizeleft)==write(debugfile,prntbuf,sizeleft));
  256 
  257 }
  258 
  259 // write the binary version of the packet
  260 void SNMP_session::write_debug_bin(unsigned char *data, unsigned len){
  261   unsigned int sizeleft=MAXPACKSIZE;
  262   char prntbuf[MAXPACKSIZE];
  263   char *curpos=prntbuf;
  264   int lenused;
  265 
  266   for( unsigned idx=0; idx<len; idx++){
  267     lenused=snprintf(curpos,sizeleft,"%02x ",data[idx]);
  268     assert(lenused!=-1);
  269     sizeleft-=lenused;
  270     curpos+=lenused;
  271     if(idx>0 && (idx+1)%16==0){
  272       lenused=snprintf(curpos,sizeleft,"\n");
  273       assert(lenused!=-1);
  274       sizeleft-=lenused;
  275       curpos+=lenused;
  276     }
  277   }
  278   lenused=snprintf(curpos,sizeleft,"\n");
  279   assert(lenused!=-1);
  280   sizeleft-=lenused;
  281   curpos+=lenused;
  282 
  283   sizeleft=curpos-prntbuf; // reusing a variable
  284   static_cast<ssize_t>(sizeleft)=write(debugfile,prntbuf,sizeleft);  
  285   assert(sizeleft);
  286 }
  287 
  288 void SNMP_session::printstr(unsigned long *argflags,char neednl,
  289                 const char *str){
  290   static const char *basestr[]={"%s%s","\n%s%s","hostname=\"%s\";%s",
  291                   "\nhostname=\"%s\";%s"};
  292   const char *hn="";
  293   char idx=0;
  294   pthread_mutex_lock(&lastprint_m);
  295   if(lastprint!=this){
  296     if(need_newline)
  297       idx=1;
  298     if(CK_NAME_FLAG){
  299       idx|=2;
  300       hn=hostname;
  301     }
  302   }else{
  303     if(!neednl && CK_NAME_FLAG){
  304       idx|=2;
  305       hn=hostname;
  306     }
  307     if(need_newline && !neednl){
  308       idx=1;
  309     } 
  310   }
  311   need_newline=neednl;
  312   lastprint=this;
  313   pthread_mutex_unlock(&lastprint_m);
  314 
  315   printf(basestr[idx],hn,str);
  316 }
  317 
  318 void SNMP_session::end(){
  319   pthread_mutex_lock(&lastprint_m);
  320   if(need_newline)
  321     printf("\n");
  322   pthread_mutex_unlock(&lastprint_m);
  323 }