📄 ip_options.c
字号:
/* This file is taken from Linux 2.0.36 kernel source. Modified in Jun 99 by Nergal.*/#include <string.h>#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 255struct 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 16struct 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) 0int 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -