TunOutDevice.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include "IPDatagram_m.h"
00025 #include "UDPPacket.h"
00026
00027 #include "TunOutDevice.h"
00028
00029 Define_Module(TunOutDevice);
00030
00031 #if not defined _WIN32 && not defined __APPLE__
00032
00033 #include <netinet/ip.h>
00034 #include <netinet/udp.h>
00035
00036 char* TunOutDevice::encapsulate(cPacket *msg,
00037 unsigned int* length,
00038 sockaddr** addr,
00039 socklen_t* addrlen)
00040 {
00041 *addr = 0;
00042 *addrlen = 0;
00043
00044 struct udppseudohdr {
00045 uint32_t saddr;
00046 uint32_t daddr;
00047 uint8_t zero;
00048 uint8_t protocol;
00049 uint16_t lenght;
00050 }*pseudohdr;
00051
00052 unsigned int payloadlen;
00053 static unsigned int iplen = 20;
00054 static unsigned int udplen = 8;
00055 cPacket* payloadMsg = NULL;
00056 char* buf = NULL, *payload = NULL;
00057 uint32_t saddr, daddr;
00058 volatile iphdr* ip_buf;
00059 volatile udphdr* udp_buf;
00060
00061 IPDatagram* IP = check_and_cast<IPDatagram*>(msg);
00062
00063
00064 UDPPacket* UDP = dynamic_cast<UDPPacket*>(IP->decapsulate());
00065 if (!UDP) {
00066 EV << "[TunOutDevice::encapsulate()]\n"
00067 << " Can't parse non-UDP packets (e.g. ICMP) (yet)"
00068 << endl;
00069 goto parse_error;
00070 }
00071
00072
00073 if( IP->getMoreFragments() ) {
00074 EV << "[TunOutDevice::encapsulate()]\n"
00075 << " Can't parse fragmented packets"
00076 << endl;
00077 goto parse_error;
00078 }
00079 payloadMsg = UDP->decapsulate();
00080
00081
00082 payload = parser->encapsulatePayload(payloadMsg, &payloadlen);
00083 if (!payload ) {
00084 EV << "[TunOutDevice::encapsulate()]\n"
00085 << " Can't parse packet payload, dropping packet"
00086 << endl;
00087 goto parse_error;
00088 }
00089
00090 *length = payloadlen + iplen + udplen;
00091 if( *length > mtu ) {
00092 EV << "[TunOutDevice::encapsulate()]\n"
00093 << " Error: Packet too big! Size = " << *length << " MTU = " << mtu
00094 << endl;
00095 goto parse_error;
00096 }
00097
00098 buf = new char[*length];
00099
00100
00101
00102
00103 memcpy( (buf + iplen + udplen), payload, payloadlen);
00104
00105
00106 udp_buf = (udphdr*) (buf + iplen);
00107 udp_buf->source = htons(UDP->getSourcePort());
00108 udp_buf->dest = htons(UDP->getDestinationPort());
00109 udp_buf->len = htons(udplen + payloadlen);
00110 udp_buf->check = 0;
00111
00112
00113
00114 pseudohdr = (udppseudohdr*) (buf + iplen - sizeof(struct udppseudohdr));
00115 saddr = htonl(IP->getSrcAddress().getInt());
00116 daddr = htonl(IP->getDestAddress().getInt());
00117 pseudohdr->saddr = saddr;
00118 pseudohdr->daddr = daddr;
00119 pseudohdr->zero = 0;
00120 pseudohdr->protocol = IPPROTO_UDP;
00121 pseudohdr->lenght = udp_buf->len;
00122
00123
00124 udp_buf->check = cksum((uint16_t*) pseudohdr, sizeof(struct udppseudohdr) + udplen + payloadlen);
00125
00126
00127 ip_buf = (iphdr*) buf;
00128 ip_buf->version = 4;
00129 ip_buf->ihl = iplen / 4;
00130 ip_buf->tos = IP->getDiffServCodePoint();
00131 ip_buf->tot_len = htons(*length);
00132 ip_buf->id = htons(IP->getIdentification());
00133 ip_buf->frag_off = htons(IP_DF);
00134 ip_buf->ttl = IP->getTimeToLive();
00135 ip_buf->protocol = IPPROTO_UDP;
00136 ip_buf->saddr = saddr;
00137 ip_buf->daddr = daddr;
00138 ip_buf->check = 0;
00139 ip_buf->check = cksum((uint16_t*) ip_buf, iplen);
00140
00141 delete IP;
00142 delete UDP;
00143 delete payloadMsg;
00144 delete payload;
00145
00146 return buf;
00147
00148 parse_error:
00149 delete IP;
00150 delete UDP;
00151 delete payloadMsg;
00152 delete payload;
00153 return NULL;
00154
00155 }
00156
00157 cPacket* TunOutDevice::decapsulate(char* buf,
00158 uint32_t length,
00159 sockaddr* addr,
00160 socklen_t addrlen)
00161 {
00162
00163 iphdr* ip_buf = (iphdr*) buf;
00164 udphdr* udp_buf;
00165 IPDatagram* IP = new IPDatagram;
00166 UDPPacket* UDP = new UDPPacket;
00167 cPacket* payload = 0;
00168 unsigned int payloadLen, datagramlen;
00169 unsigned int packetlen = ntohs(ip_buf->tot_len);
00170
00171
00172 if ( packetlen != length ) {
00173 EV << "[TunOutDevice::decapsulate()]\n"
00174 << " Dropping bogus packet, header says: length = " << packetlen << "\n"
00175 << " but actual length = " << length
00176 << endl;
00177 goto parse_error;
00178 }
00179 if ( packetlen > mtu ) {
00180 EV << "[TunOutDevice::decapsulate()]\n"
00181 << " Dropping bogus packet, length = " << packetlen << "\n"
00182 << " but mtu = " << mtu
00183 << endl;
00184 goto parse_error;
00185 }
00186 if ( ip_buf->version != 4 ) {
00187 EV << "[TunOutDevice::decapsulate()]\n"
00188 << " Dropping Packet: Packet is not IPv4"
00189 << endl;
00190 goto parse_error;
00191 }
00192 if ( ntohs(ip_buf->frag_off) & 0xBFFF ) {
00193 EV << "[TunOutDevice::decapsulate()]\n"
00194 << " Dropping Packet: Can't handle fragmented packets"
00195 << endl;
00196 goto parse_error;
00197 }
00198 if ( ip_buf->protocol != IPPROTO_UDP ) {
00199 EV << "[TunOutDevice::decapsulate()]\n"
00200 << " Dropping Packet: Packet is not UDP"
00201 << endl;
00202 goto parse_error;
00203 }
00204 IP->setSrcAddress( IPAddress( ntohl(ip_buf->saddr) ));
00205 IP->setDestAddress( IPAddress( ntohl(ip_buf->daddr) ));
00206 IP->setTransportProtocol( ip_buf->protocol );
00207 IP->setTimeToLive( ip_buf->ttl );
00208 IP->setIdentification( ntohs(ip_buf->id) );
00209 IP->setMoreFragments( false );
00210 IP->setDontFragment( true );
00211 IP->setFragmentOffset( 0 );
00212 IP->setDiffServCodePoint( ip_buf->tos );
00213 IP->setBitLength( ip_buf->ihl*32 );
00214
00215
00216
00217 udp_buf = (udphdr*)( ((uint32_t *)ip_buf) + ip_buf->ihl );
00218 datagramlen = ntohs(udp_buf->len);
00219 if ( (datagramlen != packetlen - ip_buf->ihl*4) ) {
00220 EV << "[TunOutDevice::decapsulate()]\n"
00221 << " Dropping Packet: Bogus UDP datagram length: len = " << datagramlen << "\n"
00222 << " packetlen = " << packetlen << " ihl*4 " << ip_buf->ihl*4
00223 << endl;
00224 goto parse_error;
00225 }
00226 UDP->setSourcePort( ntohs( udp_buf->source ));
00227 UDP->setDestinationPort( ntohs( udp_buf->dest ));
00228 UDP->setByteLength( sizeof( struct udphdr ) );
00229
00230
00231 payloadLen = datagramlen - sizeof( struct udphdr );
00232 payload = parser->decapsulatePayload( ((char*) udp_buf) + sizeof( struct udphdr ), payloadLen );
00233 if (!payload) {
00234 EV << "[TunOutDevice::decapsulate()]\n"
00235 << " Parsing of Payload failed, dropping packet"
00236 << endl;
00237 goto parse_error;
00238 }
00239
00240 UDP->encapsulate( payload );
00241 IP->encapsulate( UDP );
00242
00243 delete[] buf;
00244 delete addr;
00245 return IP;
00246
00247
00248 parse_error:
00249 delete[] buf;
00250 delete addr;
00251 delete IP;
00252 delete UDP;
00253 return NULL;
00254 }
00255
00256 #else
00257
00258 cPacket* TunOutDevice::decapsulate(char* buf,
00259 uint32_t length,
00260 sockaddr* addr,
00261 socklen_t addrlen)
00262 {
00263 throw cRuntimeError("TunOutDevice::decapsulate(): Not supported on Windows/Mac OS yet");
00264 }
00265
00266 char* TunOutDevice::encapsulate(cPacket *msg,
00267 unsigned int* length,
00268 sockaddr** addr,
00269 socklen_t* addrlen)
00270 {
00271 throw cRuntimeError("TunOutDevice::encapsulate(): Not supported on Windows/Mac OS yet");
00272 }
00273
00274 #endif