/*
* rfc2507c.{cc,hh} -- element compresses IP headers a la RFC 2507
* Robert Morris
*
* Copyright (c) 1999-2000 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the conditions
* listed in the Click LICENSE file. These conditions include: you must
* preserve this copyright notice, and you cannot mention the copyright
* holders in advertising related to the Software without their permission.
* The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
* notice is a summary of the Click LICENSE file; the license in that file is
* legally binding.
*/
#include <click/config.h>
#include "rfc2507d.hh"
#include <click/glue.hh>
CLICK_DECLS
RFC2507d::RFC2507d()
{
}
RFC2507d::~RFC2507d()
{
}
void
RFC2507d::decode(const u_char * &in, unsigned short &x)
{
x = ntohs(x);
if(in[0] != 0){
x += *in;
in++;
} else {
in++;
x += (*in << 8);
in++;
x += *in;
in++;
}
x = htons(x);
}
void
RFC2507d::decode(const u_char * &in, unsigned int &x)
{
x = ntohl(x);
if(in[0] != 0){
x += *in;
in++;
} else {
in++;
x += (*in << 8);
in++;
x += *in;
in++;
}
x = htonl(x);
}
Packet *
RFC2507d::simple_action(Packet *p)
{
WritablePacket *q = 0;
if(p->length() < 2)
goto out;
if (p->data()[0] == PT_OTHER) {
q = Packet::make(p->length() - 1);
memcpy(q->data(), p->data() + 1, p->length() - 1);
} else if (p->data()[0] == PT_FULL_HEADER) {
click_chatter("2507d: got full header\n");
int cid = p->data()[1] & 0xff;
if(cid <= 0 || cid >= TCP_SPACE)
goto out;
struct tcpip *ctx = &_ccbs[cid]._context;
memcpy(&(ctx->_ip), p->data() + 2, sizeof(click_ip));
memcpy(&(ctx->_tcp), p->data() + 2 + sizeof(click_ip),
sizeof(struct click_tcp));
q = Packet::make(p->length() - 2);
memcpy(q->data(), p->data() + 2, p->length() - 2);
} else if (p->data()[0] == PT_COMPRESSED_TCP) {
int cid = p->data()[1] & 0xff;
if(cid <= 0 || cid >= TCP_SPACE)
goto out;
struct tcpip *ctx = &_ccbs[cid]._context;
int flags = p->data()[2];
memcpy(&(ctx->_tcp.th_sum), p->data() + 3, 2);
const u_char *in = p->data() + 5;
if(flags & (1 << 4)) /* P */
ctx->_tcp.th_flags |= TH_PUSH;
else
ctx->_tcp.th_flags &= ~TH_PUSH;
if(flags & 1){ /* U */
ctx->_tcp.th_flags |= TH_URG;
decode(in, ctx->_tcp.th_urp);
} else {
ctx->_tcp.th_flags &= ~TH_URG;
}
if(flags & (1 << 1)){ /* W */
decode(in, ctx->_tcp.th_win);
}
if(flags & (1 << 2)){ /* A */
decode(in, ctx->_tcp.th_ack);
}
if(flags & (1 << 3)){ /* S */
decode(in, ctx->_tcp.th_seq);
}
if(flags & (1 << 5)){ /* I */
decode(in, ctx->_ip.ip_id);
} else {
ctx->_ip.ip_id = htons(ntohs(ctx->_ip.ip_id) + 1);
}
int len = p->length() - (in - p->data());
len += sizeof(click_ip) + sizeof(struct click_tcp);
ctx->_ip.ip_len = htons(len);
ctx->_ip.ip_sum = 0;
ctx->_ip.ip_sum = click_in_cksum((unsigned char *) &(ctx->_ip), sizeof(click_ip));
q = Packet::make(len);
memcpy(q->data(), &(ctx->_ip), sizeof(click_ip));
memcpy(q->data() + sizeof(click_ip),
&(ctx->_tcp),
sizeof(struct click_tcp));
memcpy(q->data() + sizeof(click_ip) + sizeof(struct click_tcp),
in,
p->length() - (in - p->data()));
} else {
goto out;
}
out:
if(q){
click_ip iph;
struct click_tcp tcph;
memcpy(&iph, q->data(), sizeof(iph));
memcpy(&tcph, q->data() + sizeof(click_ip), sizeof(tcph));
click_chatter("seq %d len %d",
(int)ntohl(tcph.th_seq),
q->length() - sizeof(tcph) - sizeof(iph));
{
char *p = new char[q->length()];
memcpy(p, q->data(), q->length());
// check IP checksum
click_ip *ipp = reinterpret_cast<click_ip *>(p);
int hlen = ipp->ip_hl << 2;
if(click_in_cksum((unsigned char *)ipp, hlen) != 0){
click_chatter(" ip cksum failed");
}
// check TCP checksum; include pseudoheader
int len = ntohs(ipp->ip_len);
// zero ip_v, ip_hl, ip_tos, ip_len, ip_off, ip_ttl
memset(ipp, '\0', 9);
ipp->ip_sum = htons(len - sizeof(click_ip));
if(click_in_cksum((unsigned char *)p, len) != 0){
click_chatter(" tcp cksum failed");
}
delete [] p;
}
}
if(q == 0)
click_chatter("RFC2507d: no q");
p->kill();
return(q);
}
CLICK_ENDDECLS
EXPORT_ELEMENT(RFC2507d)
syntax highlighted by Code2HTML, v. 0.9.1