File: RelMsg.cpp

package info (click to toggle)
dibbler 1.0.1-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 13,352 kB
  • sloc: cpp: 60,323; ansic: 12,235; sh: 11,951; yacc: 3,418; lex: 969; makefile: 940; perl: 319; xml: 116; python: 74
file content (102 lines) | stat: -rw-r--r-- 2,735 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
 * Dibbler - a portable DHCPv6
 *
 * authors: Tomasz Mrugalski <thomson@klub.com.pl>
 *          Marek Senderski <msend@o2.pl>
 *
 * released under GNU GPL v2 only licence
 *
 */

#include "Portable.h"
#include "Logger.h"
#include "RelMsg.h"
#include "OptDUID.h"
#include "RelOptInterfaceID.h"
#include "RelOptRelayMsg.h"
#include "RelOptGeneric.h"

//Constructor builds message on the basis of received message
TRelMsg::TRelMsg(int iface,  SPtr<TIPv6Addr> addr, char* data,  int dataLen)
    :TMsg(iface, addr, data, dataLen), DestIface(0) {
    // data+=4, dataLen-=4 is modified in TMsg
    if (dataLen<=0) // avoid decoding of empty messages.
        return;

    this->HopCount = 0;
    this->decodeOpts(data, dataLen);
}

void TRelMsg::decodeOpts(char * buf, int bufSize) {
    int pos=0;
    SPtr<TOpt> ptr;

    while (pos<bufSize)	{
	if (pos+4>bufSize) {
	    Log(Error) << "Message " << MsgType << " truncated. There are " << (bufSize-pos) 
		       << " bytes left to parse. Bytes ignored." << LogEnd;
	    break;
	}
        unsigned short code   = readUint16(buf+pos);
        pos += sizeof(uint16_t);
        unsigned short length = readUint16(buf+pos);
        pos += sizeof(uint16_t);
	if (pos+length>bufSize) {
	    Log(Error) << "Invalid option (type=" << code << ", len=" << length 
		       << " received (msgtype=" << MsgType << "). Message dropped." << LogEnd;
	    IsDone = true;
	    return;
	}

	if (!allowOptInMsg(this->MsgType,code)) {
	    Log(Warning) << "Option " << code << " not allowed in message type="<< MsgType <<". Ignoring." << LogEnd;
	    pos+=length;
	    continue;
	}
	if (!allowOptInOpt(this->MsgType,0,code)) {
	    Log(Warning) <<"Option " << code << " can't be present in message (type="
			 << MsgType <<") directly. Ignoring." << LogEnd;
	    pos+=length;
	    continue;
	}

	ptr.reset();
	switch (code) {
	case OPTION_RELAY_MSG:
	    ptr = new TRelOptRelayMsg(buf+pos,length,this);
	    break;
	case OPTION_INTERFACE_ID:
	    ptr = new TRelOptInterfaceID(buf+pos,length,this);
	    break;
        case OPTION_CLIENTID:
            ptr = new TOptDUID(code, buf+pos, length, this);
            break;
	default:
	    ptr = new TRelOptGeneric(code, buf+pos, length, this);
	    break;
	}

	if ( (ptr) && (ptr->isValid()) )
	    Options.push_back( ptr );
	else
	    Log(Warning) << "Option " << code << " is invalid. Option ignored." << LogEnd;
        pos+=length;
    }
}

void TRelMsg::setDestination(int iface, SPtr<TIPv6Addr> dest) {
    this->DestIface = iface;
    this->DestAddr  = dest;
}

int TRelMsg::getDestIface() {
    return this->DestIface;
}

SPtr<TIPv6Addr> TRelMsg::getDestAddr() {
    return this->DestAddr;
}

int TRelMsg::getHopCount() {
    return this->HopCount;
}