|
/*
This file is taken from Linux 2.0.36 kernel source.
Modified in Jun 99 by Nergal.
*/
#include <string.h>
#ifdef WIN32
#include "nids.h"
#endif
#define __u8 unsigned char
#define __u16 unsigned short
#define __u32 unsigned int
#define IPOPT_END 0
#define IPOPT_NOOP 1
#define IPOPT_SEC 130
#define IPOPT_LSRR 131
#define IPOPT_SSRR 137
#define IPOPT_RR 7
#define IPOPT_SID 136
#define IPOPT_TIMESTAMP 68
#define MAXTTL 255
struct timestamp {
__u8 len;
__u8 ptr;
#if defined(LIBNET_LIL_ENDIAN)
__u8 flags:4, overflow:4;
#elif defined(LIBNET_BIG_ENDIAN)
__u8 overflow:4, flags:4;
#else
#error "unknown byte ordering"
#endif
__u32 data[9];
};
#define MAX_ROUTE 16
struct route {
char route_size;
char pointer;
unsigned long route[MAX_ROUTE];
};
#define IPOPT_OPTVAL 0
#define IPOPT_OLEN 1
#define IPOPT_OFFSET 2
#define IPOPT_MINOFF 4
#define MAX_IPOPTLEN 40
#define IPOPT_NOP IPOPT_NOOP
#define IPOPT_EOL IPOPT_END
#define IPOPT_TS IPOPT_TIMESTAMP
#define IPOPT_TS_TSONLY 0 /* timestamps only */
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
struct options {
__u32 faddr; /* Saved first hop address */
unsigned char optlen;
unsigned char srr;
unsigned char rr;
unsigned char ts;
unsigned char is_setbyuser:1, /* Set by setsockopt? */
is_data:1, /* Options in __data, rather than skb */
is_strictroute:1, /* Strict source route */
srr_is_hit:1, /* Packet destination addr was our one */
is_changed:1, /* IP checksum more not valid */
rr_needaddr:1, /* Need to record addr of outgoing dev */
ts_needtime:1, /* Need to record timestamp */
ts_needaddr:1; /* Need to record addr of outgoing dev */
unsigned char __pad1;
unsigned char __pad2;
unsigned char __pad3;
unsigned char __data[0];
};
struct iphdr {
#if defined(LIBNET_LIL_ENDIAN)
__u8 ihl:4, version:4;
#elif defined (LIBNET_BIG_ENDIAN)
__u8 version:4, ihl:4;
#else
#error "unknown byte ordering"
#endif
__u8 tos;
__u16 tot_len;
__u16 id;
__u16 frag_off;
__u8 ttl;
__u8 protocol;
__u16 check;
__u32 saddr;
__u32 daddr;
/* The options start here. */
};
#define ip_chk_addr(x) 0
int
ip_options_compile(unsigned char *iph)
{
int l;
unsigned char *optptr;
int optlen;
unsigned char *pp_ptr = 0;
char optholder[16];
struct options *opt;
int skb = 1;
int skb_pa_addr = 314159;
opt = (struct options *) optholder;
memset(opt, 0, sizeof(struct options));
opt->optlen = ((struct iphdr *) iph)->ihl * 4 - sizeof(struct iphdr);
optptr = iph + sizeof(struct iphdr);
opt->is_data = 0;
for (l = opt->optlen; l > 0;) {
switch (*optptr) {
case IPOPT_END:
for (optptr++, l--; l > 0; l--) {
if (*optptr != IPOPT_END) {
*optptr = IPOPT_END;
opt->is_changed = 1;
}
}
goto eol;
case IPOPT_NOOP:
l--;
optptr++;
continue;
}
optlen = optptr[1];
if (optlen < 2 || optlen > l) {
pp_ptr = optptr;
goto error;
}
switch (*optptr) {
case IPOPT_SSRR:
case IPOPT_LSRR:
if (optlen < 3) {
pp_ptr = optptr + 1;
goto error;
}
if (optptr[2] < 4) {
pp_ptr = optptr + 2;
goto error;
}
/* NB: cf RFC-1812 5.2.4.1 */
if (opt->srr) {
pp_ptr = optptr;
goto error;
}
if (!skb) {
if (optptr[2] != 4 || optlen < 7 || ((optlen - 3) & 3)) {
pp_ptr = optptr + 1;
goto error;
}
memcpy(&opt->faddr, &optptr[3], 4);
if (optlen > 7)
memmove(&optptr[3], &optptr[7], optlen - 7);
}
opt->is_strictroute = (optptr[0] == IPOPT_SSRR);
opt->srr = optptr - iph;
break;
case IPOPT_RR:
if (opt->rr) {
pp_ptr = optptr;
goto error;
}
if (optlen < 3) {
pp_ptr = optptr + 1;
goto error;
}
if (optptr[2] < 4) {
pp_ptr = optptr + 2;
goto error;
}
if (optptr[2] <= optlen) {
if (optptr[2] + 3 > optlen) {
pp_ptr = optptr + 2;
goto error;
}
if (skb) {
memcpy(&optptr[optptr[2] - 1], &skb_pa_addr, 4);
opt->is_changed = 1;
}
optptr[2] += 4;
opt->rr_needaddr = 1;
}
opt->rr = optptr - iph;
break;
case IPOPT_TIMESTAMP:
if (opt->ts) {
pp_ptr = optptr;
goto error;
}
if (optlen < 4) {
pp_ptr = optptr + 1;
goto error;
}
if (optptr[2] < 5) {
pp_ptr = optptr + 2;
goto error;
}
if (optptr[2] <= optlen) {
struct timestamp *ts = (struct timestamp *) (optptr + 1);
__u32 *timeptr = 0;
if (ts->ptr + 3 > ts->len) {
pp_ptr = optptr + 2;
goto error;
}
switch (ts->flags) {
case IPOPT_TS_TSONLY:
opt->ts = optptr - iph;
if (skb)
timeptr = (__u32 *) & optptr[ts->ptr - 1];
opt->ts_needtime = 1;
ts->ptr += 4;
break;
case IPOPT_TS_TSANDADDR:
if (ts->ptr + 7 > ts->len) {
pp_ptr = optptr + 2;
goto error;
}
opt->ts = optptr - iph;
if (skb) {
memcpy(&optptr[ts->ptr - 1], &skb_pa_addr, 4);
timeptr = (__u32 *) & optptr[ts->ptr + 3];
}
opt->ts_needaddr = 1;
opt->ts_needtime = 1;
ts->ptr += 8;
break;
case IPOPT_TS_PRESPEC:
if (ts->ptr + 7 > ts->len) {
pp_ptr = optptr + 2;
goto error;
}
opt->ts = optptr - iph;
{
__u32 addr;
memcpy(&addr, &optptr[ts->ptr - 1], 4);
if (ip_chk_addr(addr) == 0)
break;
if (skb)
timeptr = (__u32 *) & optptr[ts->ptr + 3];
}
opt->ts_needaddr = 1;
opt->ts_needtime = 1;
ts->ptr += 8;
break;
default:
pp_ptr = optptr + 3;
goto error;
}
if (timeptr) {
//struct timeval tv;
__u32 midtime = 1;
//do_gettimeofday(&tv);
//midtime = htonl((tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000);
memcpy(timeptr, &midtime, sizeof(__u32));
opt->is_changed = 1;
}
}
else {
struct timestamp *ts = (struct timestamp *) (optptr + 1);
if (ts->overflow == 15) {
pp_ptr = optptr + 3;
goto error;
}
opt->ts = optptr - iph;
if (skb) {
ts->overflow++;
opt->is_changed = 1;
}
}
break;
case IPOPT_SEC:
case IPOPT_SID:
default:
if (!skb) {
pp_ptr = optptr;
goto error;
}
break;
}
l -= optlen;
optptr += optlen;
}
eol:
if (!pp_ptr)
if (!((struct options *) optholder)->srr)
return 0;
error:
return -1;
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Saar, has been programing since 1997. He enjoys taking things a part and designing simple solutions to complex problems. Currently, works for Microsoft writing in a variety of languages and flavors. During the last year he is taking a closer look into mobile and web development.