1: 
   2: 
   3: /**********************
   4: *                     *
   5: *  COMPILER INCLUDES  *
   6: *                     *
   7: **********************/
   8: 
   9: 
  10: #include <cassert> 
  11: 
  12: 
  13: /*********************
  14: *                    *
  15: *  PROJECT INCLUDES  *
  16: *                    *
  17: *********************/
  18: 
  19: 
  20: #include "dnsutil.h" 
  21: #include "dnspacket.h" 
  22: #include "rrfactory.h" 
  23: 
  24: 
  25: /***************************
  26: *                          *
  27: *  DNSPACKET CONSTRUCTORS  *
  28: *                          *
  29: ***************************/
  30: 
  31: 
  32: DNSPacket::DNSPacket() : Buffer(scm_szPacketMax) {
  33:   m_sipRemote = new SockAddrIn;
  34: }
  35: 
  36: 
  37: DNSPacket::DNSPacket(SockAddrIn* &i_siprRemote, unsigned short i_usID, RequestConstPtr ci_rqp, ResponseConstPtr ci_rsp) : Buffer(scm_szPacketMax) {
  38:   m_sipRemote = i_siprRemote;
  39:   i_siprRemote = NULL;
  40:   this->Format(i_usID,ci_rqp,ci_rsp);
  41: }
  42: 
  43: 
  44: DNSPacket::DNSPacket(SockAddrIn* &i_siprRemote, unsigned short i_usID, QuestionConstPtr ci_qnp) : Buffer(scm_szPacketMax) {
  45:   RequestPtr rqp;
  46:   QuestionPtr qnp;
  47: 
  48:   m_sipRemote = i_siprRemote;
  49:   i_siprRemote = NULL;
  50:   qnp = new Question(*ci_qnp);
  51:   rqp = new Request(false,OPCODE_QUERY,qnp);
  52:   this->Format(i_usID,rqp,NULL); 
  53:   SoftDelete(rqp);
  54: }
  55: 
  56: 
  57: /******************
  58: *                 *
  59: *  METHOD FORMAT  *
  60: *                 *
  61: ******************/
  62: 
  63: 
  64: #define XBIT(XXX,YYY)    ((XXX>>YYY)&1) 
  65: #define NULL0(XXX,YYY)   (((XXX)==NULL) ? 0 : (XXX)->YYY) 
  66: #define NULLF(XXX,YYY)   (((XXX)==NULL) ? false : (XXX)->YYY) 
  67: 
  68: 
  69: void DNSPacket::Format(unsigned short i_usID, RequestConstPtr ci_rqp, ResponseConstPtr ci_rsp) {
  70:   bool bTCFatal = true;
  71:   unsigned short usRRs;
  72: 
  73:   try { 
  74:     m_ofPos = 0;
  75:     m_ofRollBack = 0;
  76: 
  77:     this->WriteNBO(i_usID);
  78:     this->WriteBits( (ci_rsp!=NULL),                          // QR
  79:                      XBIT(ci_rqp->GetOpcode(),3),             // Opcode 3
  80:                      XBIT(ci_rqp->GetOpcode(),2),             // Opcode 2
  81:                      XBIT(ci_rqp->GetOpcode(),1),             // Opcode 1
  82:                      XBIT(ci_rqp->GetOpcode(),0),             // Opcode 0
  83:                      (ci_rsp==NULL)?false:(ci_rsp->GetAA()),  // AA
  84:                      (ci_rsp==NULL)?false:(ci_rsp->GetTC()),  // TC
  85:                      (ci_rqp->GetRD()) );                     // RD
  86:     this->WriteBits( (ci_rsp==NULL)?false:true,               // RA
  87:                      false, false, false,                     // Z
  88:                      (ci_rsp==NULL)?false:(XBIT(ci_rsp->GetRCode(),3)),   // RC3
  89:                      (ci_rsp==NULL)?false:(XBIT(ci_rsp->GetRCode(),2)),   // RC2
  90:                      (ci_rsp==NULL)?false:(XBIT(ci_rsp->GetRCode(),1)),   // RC1
  91:                      (ci_rsp==NULL)?false:(XBIT(ci_rsp->GetRCode(),0)) ); // RC0
  92:     this->WriteNBO(ci_rqp->GetQuestionCount());
  93:     this->WriteNBO((unsigned short)0);
  94:     this->WriteNBO((unsigned short)0);
  95:     this->WriteNBO((unsigned short)0);
  96:     m_ofRollBack = m_ofPos;
  97:     this->WriteQuestion(ci_rqp->GetQuestion());
  98:     m_ofRollBack = m_ofPos;
  99:     if (ci_rsp!=NULL) {
 100:       usRRs = this->WriteRRList(ci_rsp->GetANList());
 101:       this->PWriteNBO(usRRs,6);
 102:       m_ofRollBack = m_ofPos;
 103:       bTCFatal = false;
 104: 
 105:       usRRs = this->WriteRRList(ci_rsp->GetNSList());
 106:       this->PWriteNBO(usRRs,8);
 107:       m_ofRollBack = m_ofPos;
 108: 
 109:       usRRs = this->WriteRRList(ci_rsp->GetARList());
 110:       this->PWriteNBO(usRRs,10);
 111:     }
 112:     this->Truncate();
 113: 
 114:   } catch (BufferEx &exr) {
 115:     LogHandle lh(LF_PACKETFORMAT,LY_ERROR);
 116:     lh << "Format exception: " << exr.what();
 117:     if (bTCFatal) lh << " (required packet will be truncated; TC set)";
 118:     else lh << " (only optional data will be lost; no TC)";
 119:     lh << LY_DEBUG << "rollback from " << m_ofPos << " to " << m_ofRollBack; lh();
 120:     m_ofPos = (size_t)m_ofRollBack;
 121:     this->Truncate();
 122:     assert(m_szBuffer>=12);
 123:     // Force the TC bit high.
 124:     if (bTCFatal) this->WriteBit(true,2,1);
 125:   }
 126: }
 127:                     
 128: 
 129: /*****************
 130: *                *
 131: *  METHOD PARSE  *
 132: *                *
 133: *****************/
 134: 
 135: 
 136: void DNSPacket::Parse(unsigned short &io_usrID, RequestPtr &o_rqpr, ResponsePtr &o_rspr) const {
 137:   bool bQR, bOp3, bOp2, bOp1, bOp0, bAA, bTC, bRD;
 138:   bool bRA, bZ2, bZ1, bZ0, bRC3, bRC2, bRC1, bRC0;
 139:   unsigned short usQDCount, usANCount, usNSCount, usARCount;
 140:   QuestionPtr qnp = NULL;
 141:   RRListPtr rlpAN = NULL;
 142:   RRListPtr rlpNS = NULL;
 143:   RRListPtr rlpAR = NULL;
 144: 
 145:   o_rqpr = NULL;
 146:   o_rspr = NULL;
 147: 
 148:   m_ofPos = 0;
 149: 
 150:   try {
 151:  
 152:     this->ReadNBO(io_usrID);
 153:     this->ReadBits(bQR,bOp3,bOp2,bOp1,bOp0,bAA,bTC,bRD);
 154:     this->ReadBits(bRA,bZ2,bZ1,bZ0,bRC3,bRC2,bRC1,bRC0);
 155:     this->ReadNBO(usQDCount);
 156:     assert(usQDCount==1);
 157:     this->ReadNBO(usANCount);
 158:     this->ReadNBO(usNSCount);
 159:     this->ReadNBO(usARCount);
 160:     this->ReadQuestion(qnp);
 161:     if (bQR==true) {
 162:       this->ReadRRList(rlpAN,usANCount);
 163:       this->ReadRRList(rlpNS,usNSCount);
 164:       this->ReadRRList(rlpAR,usARCount);
 165:     }
 166: 
 167:   } catch (BufferEx &exr) {
 168:     LogHandle lh(LF_PACKETFORMAT,LY_ERROR);
 169:     lh << "Read exception:" << exr.what() << " (packet will be discarded)";
 170:     lh << LY_DEBUG;
 171:     this->DumpRange(lh,0,this->GetSize());
 172:     lh();
 173:     return;
 174:   }
 175:   o_rqpr = new Request(bRD,(Opcode)FromBits(bOp3,bOp2,bOp1,bOp0),qnp);
 176:   if (bQR) 
 177:     o_rspr = new Response(bAA,bTC,(RCode)FromBits(bRC3,bRC2,bRC1,bRC0),rlpAN,rlpNS,rlpAR);
 178:   assert(qnp==NULL);
 179:   assert(rlpAN==NULL);
 180:   assert(rlpNS==NULL);
 181:   assert(rlpAR==NULL);
 182: }
 183: 
 184: 
 185: /************************
 186: *                       *
 187: *  METHOD READQUESTION  *
 188: *                       *
 189: ************************/
 190: 
 191: 
 192: void DNSPacket::ReadQuestion(QuestionPtr &o_qnpr) const {
 193:   LabelListPtr llp = NULL;
 194:   unsigned short us;
 195:   RRType ty;
 196:   RRClass cl;
 197: 
 198:   this->ReadLabelList(llp,true);
 199:   this->ReadNBO(us); ty = (RRType)us;
 200:   this->ReadNBO(us); cl = (RRClass)us;
 201: 
 202:   o_qnpr = new Question(llp,ty,cl);
 203: }
 204: 
 205: 
 206: /******************
 207: *                 *
 208: *  METHOD READRR  *
 209: *                 *
 210: ******************/
 211: 
 212: 
 213: void DNSPacket::ReadRR(RRPtr &o_rrpr) const {
 214:   LabelListPtr llpName;
 215:   unsigned short us;
 216:   RRType ty;
 217:   RRClass cl;
 218:   unsigned uTTL;
 219:   RDataPtr rdp;
 220: 
 221:   this->ReadLabelList(llpName,true); 
 222:   this->ReadNBO(us); ty = (RRType)us;
 223:   this->ReadNBO(us); cl = (RRClass)us;
 224:   this->ReadNBO(uTTL);
 225:   rdp = RData::New(ty,cl);
 226:   rdp->ReadRData(this);
 227:   o_rrpr = RRFactory::NewRR(llpName,ty,cl,uTTL,rdp);
 228: }
 229: 
 230: 
 231: /**********************
 232: *                     *
 233: *  METHOD READRRLIST  *
 234: *                     *
 235: **********************/
 236: 
 237: 
 238: void DNSPacket::ReadRRList(RRListPtr &o_rlpr, unsigned short i_usCount) const {
 239:   unsigned short us;
 240:   RRPtr rrp;
 241: 
 242:   o_rlpr = new RRList;
 243:   for(us=0;us<i_usCount;us++) {
 244:     this->ReadRR(rrp);
 245:     o_rlpr->push_back(rrp);
 246:   }
 247: }
 248: 
 249: 
 250: /*************************
 251: *                        *
 252: *  METHOD WRITEQUESTION  *
 253: *                        *
 254: *************************/
 255: 
 256: 
 257: void DNSPacket::WriteQuestion(QuestionConstPtr ci_qnp) {
 258:   if (ci_qnp==NULL) return;
 259:   this->WriteLabelList(ci_qnp->GetName(),true);
 260:   this->WriteNBO((unsigned short)ci_qnp->GetType());
 261:   this->WriteNBO((unsigned short)ci_qnp->GetClass());
 262: }
 263: 
 264: 
 265: /*******************
 266: *                  *
 267: *  METHOD WRITERR  *
 268: *                  *
 269: *******************/
 270: 
 271: 
 272: void DNSPacket::WriteRR(RRConstPtr ci_rrp) {
 273:   this->WriteLabelList(ci_rrp->GetName(),true);
 274:   this->WriteNBO((unsigned short)ci_rrp->GetType());
 275:   this->WriteNBO((unsigned short)ci_rrp->GetClass());
 276:   this->WriteNBO((unsigned)ci_rrp->GetTTL());
 277:   ci_rrp->GetRData()->WriteRData(this);
 278: }
 279: 
 280: 
 281: /***********************
 282: *                      *
 283: *  METHOD WRITERRLIST  *
 284: *                      *
 285: ***********************/
 286: 
 287: 
 288: unsigned short DNSPacket::WriteRRList(RRListConstPtr ci_rlp) {
 289:   RRList::const_iterator c_rrpi;
 290:   unsigned short usCount = 0;
 291: 
 292:   if (ci_rlp==NULL) return 0;
 293: 
 294:   for(c_rrpi=ci_rlp->begin();c_rrpi!=ci_rlp->end();++c_rrpi) {
 295:     this->WriteRR(*c_rrpi);
 296:     usCount++;
 297:   }
 298:   return usCount;
 299: }
 300: 
 301:  
 302: /*************************
 303: *                        *
 304: *  DNSPACKET DESTRUCTOR  *
 305: *                        *
 306: *************************/
 307: 
 308: 
 309: DNSPacket::~DNSPacket() {
 310:   SoftDelete(m_sipRemote);
 311: }
 312: 
 313: 
 314: /****************
 315: *               *
 316: *  OPERATOR <<  *
 317: *               *
 318: ****************/
 319: 
 320: 
 321: ostream& operator<<(ostream& io_smr, const DNSPacket &ci_dpr) {
 322:   io_smr << (const Buffer&)ci_dpr;
 323:   return io_smr;
 324: }
 325: 
 326: 
 327: ostream& operator<<(ostream& io_smr, DNSPacketConstPtr ci_dpp) {
 328:   io_smr << *ci_dpp;
 329:   return io_smr;
 330: }
 331: 
 332: 
 333: