📄 netsimul.c
字号:
/* $Id: netsimul.c,v 1.20 2001/09/18 15:16:11 jm Exp $ * Test network simulator * * Dynamic hierarchial IP tunnel * Copyright (C) 2001, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#include <config.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <fcntl.h>#include <net/if.h>#include <unistd.h>#include <sys/time.h>#include <sys/types.h>#include <sys/ioctl.h>#include <netinet/if_ether.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#include <netinet/udp.h>#include <net/if_arp.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <time.h>#include <assert.h>#include "message.h"#include "msgparser.h"#include "auth.h"#include "util.h"#include "agentadv.h"#ifdef HAVE_LINUX_IF_TUN_H#include <linux/if_tun.h>#endif/* couple of defines from linux/if_tun.h if they cannot be included */#ifndef TUNSETIFF#if 0/* up to and including Linux 2.4.5 */#define TUNSETIFF (('T'<< 8) | 202)#else/* TUNSETIFF changed in Linux 2.4.6; at least in i386 version it is now: */#define TUNSETIFF 0x400454ca#endif#endif#ifndef IFF_TUN#define IFF_TUN 0x0001#endif#ifndef IFF_TAP#define IFF_TAP 0x0002#endif#ifndef IFF_NO_PI#define IFF_NO_PI 0x1000#endif/* netsimul uses Linux kernel's "Universal TUN/TAP device driver'; see * kernel source (linux/Documentation/network/tuntap.txt) for instructions on * how to configure TUN/TAP *//* Command line format: * <seconds from start> <command>{<field1>=<value1> ...} [option1]{..} ... * commands: * send{dsthw,srchw,proto,dev} * ip{dstip,srcip,proto} * icmp{type,code,checksum} * udp{dstport,srcport} * req{opts,lifetime,home,ha,coa,id0,id1,saveid} * rep{code,lifetime,home,ha,id0,id1,useid} * mhauth{spi,secret,alg} * mfauth{spi,secret,alg} * fhauth{spi,secret,alg} * encaps{} * raw{data} * expect: like send; fail if expected packet is not received * reject: like expect, but fail if packet is received * note{txt} * exec{cmd} * * <seconds from start> can also be specified as a interval from previous * command (e.g., +0.5 means 0.5 sec after previous command) * * (see msgsimul1.data for an example) *//* Simulated network: * tap0: HA=192.168.250.1, hwaddr 00:00:00:00:00:01 * tap1: HA=192.168.251.1, hwaddr 00:00:00:00:00:02 * tap2: HA=192.168.252.1, hwaddr 00:00:00:00:00:03 * * HA=192.168.25x.1 * MN=192.168.25x.100 .. 199 * GW=192.168.25x.254, hwaddr 00:00:00:01:0x:fe * broadcast=192.168.25x.255 * * foreign net 192.168.150.0/24: route to tap0 */int fd[3];int max_fd;extern int opt_debug;static __u32 nextid = 0;static struct timeval start;void process(int fd, const char *dev);struct parse_data { char *name; char *next; char *field; char *value; int was_last;};int add_ip(char *buf, int left, struct parse_data *parse);#define PARSE_BUF_SIZE 10240static int expect_received;static int expect_error = 0;static int reject_error = 0;char current_command[PARSE_BUF_SIZE];int current_cmd_expect;int reject_cmd;int current_expect;char expect_buf[PARSE_BUF_SIZE];struct parse_data expect_parse;static u32 prev_id[2]; /* id used in previous send/received req/reply */static int is_space(char c){ if (c == ' ' || c == '\t' || c == 13 || c == 10) return 1; return 0;}static int dyn_atoi(const char *c){ int i; if (c[0] == '0' && c[1] == 'x') sscanf(c, "0x%x", &i); else i = atoi(c); return i;}static u32 get_id(const char *c){ if (strcmp(c, "prev0") == 0) return prev_id[0]; else if (strcmp(c, "prev1") == 0) return prev_id[1]; return htonl(dyn_atoi(c));}/* Returns: * 0 = no more entries * 1 = entry available, name in parse->name */int parse_init(struct parse_data *parse, char *buf){ char *t; t = buf; while (is_space(*t)) t++; parse->name = t; while (*t != '\0' && *t != '{') t++; if (*t == '\0') { return 0; } else { *t = '\0'; t++; parse->next = t; } parse->was_last = 0; return 1;}/* Returns: * -1 = invalid input data * 0 = no more entries * 1 = entry available in {parse->field, parse->value} */int parse_get_next(struct parse_data *parse){ if (parse->was_last) return 0; parse->was_last = 0; while (is_space(*parse->next)) parse->next++; if (*parse->next == '\0') return -1; if (*parse->next == '}') { parse->next++; return 0; } parse->field = parse->next; while (*parse->next != '\0' && *parse->next != '=') parse->next++; if (*parse->next == '\0') return -1; *parse->next = '\0'; parse->next++; while (is_space(*parse->next)) parse->next++; if (*parse->next == '"') { parse->next++; parse->value = parse->next; while (*parse->next != '\0' && *parse->next != '"') parse->next++; if (*parse->next == '\0') return -1; *parse->next = '\0'; parse->next++; } else { parse->value = parse->next; while (*parse->next != '\0' && !is_space(*parse->next) && *parse->next != '}') parse->next++; if (*parse->next == '\0') return -1; if (*parse->next == '}') parse->was_last = 1; *parse->next = '\0'; parse->next++; } return 1;}struct saved_id { int num; __u32 id[2]; struct saved_id *next;};struct saved_id *saved_ids = NULL;static void saveid(int num, __u32 id[]){ struct saved_id *entry; printf("\tsaveid[%i] = %08x:%08x\n", num, id[0], id[1]); entry = saved_ids; while (entry != NULL) { if (entry->num == num) { entry->id[0] = id[0]; entry->id[1] = id[1]; return; } entry = entry->next; } entry = (struct saved_id *) malloc(sizeof(struct saved_id)); if (entry == NULL) { fprintf(stderr, "saveid: out of memory\n"); return; } entry->num = num; entry->id[0] = id[0]; entry->id[1] = id[1]; entry->next = saved_ids; saved_ids = entry;}static void useid(int num, __u32 id[]){ struct saved_id *tmp = saved_ids; printf("\tuseid[%i]\n", num); while (tmp != NULL) { if (tmp->num == num) { id[0] = tmp->id[0]; id[1] = tmp->id[1]; return; } tmp = tmp->next; } fprintf(stderr, "useid - saved id=%i not found\n", num);}int add_req(char *buf, int left, struct parse_data *parse){ struct reg_req *req; if (sizeof(struct reg_req) > left) { fprintf(stderr, "add_req - buffer full\n"); return 0; } req = (struct reg_req *) buf; memset(req, 0, sizeof(struct reg_req)); req->type = REG_REQ; req->id[0] = htonl(time(NULL) + UNIX_NTP_DIFF); req->id[1] = htonl(nextid++); while (parse_get_next(parse) == 1) { if (strcmp(parse->field, "lifetime") == 0) req->lifetime = htons(dyn_atoi(parse->value)); else if (strcmp(parse->field, "opts") == 0) req->opts = dyn_atoi(parse->value); else if (strcmp(parse->field, "home") == 0) inet_aton(parse->value, &req->home_addr); else if (strcmp(parse->field, "ha") == 0) inet_aton(parse->value, &req->ha_addr); else if (strcmp(parse->field, "coa") == 0) inet_aton(parse->value, &req->co_addr); else if (strcmp(parse->field, "saveid") == 0) saveid(dyn_atoi(parse->value), req->id); else if (strcmp(parse->field, "id0") == 0) req->id[0] = get_id(parse->value); else if (strcmp(parse->field, "id1") == 0) req->id[1] = get_id(parse->value); else { fprintf(stderr, "add_req - unknown field '%s'\n", parse->field); return 0; } } return sizeof(struct reg_req);}int add_rep(char *buf, int left, struct parse_data *parse){ struct reg_rep *rep; if (sizeof(struct reg_rep) > left) { fprintf(stderr, "add_rep - buffer full\n"); return 0; } rep = (struct reg_rep *) buf; memset(rep, 0, sizeof(struct reg_rep)); rep->type = REG_REP; rep->id[0] = htonl(time(NULL) + UNIX_NTP_DIFF); rep->id[1] = htonl(nextid++); while (parse_get_next(parse) == 1) { if (strcmp(parse->field, "lifetime") == 0) rep->lifetime = htons(dyn_atoi(parse->value)); else if (strcmp(parse->field, "code") == 0) rep->code = dyn_atoi(parse->value); else if (strcmp(parse->field, "home") == 0) inet_aton(parse->value, &rep->home_addr); else if (strcmp(parse->field, "ha") == 0) inet_aton(parse->value, &rep->ha_addr); else if (strcmp(parse->field, "useid") == 0) useid(dyn_atoi(parse->value), rep->id); else if (strcmp(parse->field, "id0") == 0) rep->id[0] = get_id(parse->value); else if (strcmp(parse->field, "id1") == 0) rep->id[1] = get_id(parse->value); else { fprintf(stderr, "add_rep - unknown field '%s'\n", parse->field); return 0; } } return sizeof(struct reg_rep);}int add_auth(int type, char *start, char *buf, int left, struct parse_data *parse){ char *secret = NULL; int alg = AUTH_ALG_MD5_PREFIX_SUFFIX; int spi = 0; if (sizeof(struct msg_auth) + MAX_SK_LEN > left) { fprintf(stderr, "add_auth - buffer full\n"); return 0; } while (parse_get_next(parse) == 1) { if (strcmp(parse->field, "spi") == 0) spi = htonl(dyn_atoi(parse->value)); else if (strcmp(parse->field, "alg") == 0) alg = dyn_atoi(parse->value); else if (strcmp(parse->field, "secret") == 0) secret = parse->value; else { fprintf(stderr, "add_auth - unknown field '%s'\n", parse->field); return 0; } } return auth_add(alg, secret == NULL ? (unsigned char *) "" : (unsigned char *) secret, secret == NULL ? 0 : strlen(secret), (unsigned char *) start, (struct msg_auth *) buf, type, spi);}int add_encaps(char *buf, int left){ struct encaps_delivery_ext *encaps; if (sizeof(struct encaps_delivery_ext) > left) { fprintf(stderr, "add_encaps - buffer full\n"); return 0; } encaps = (struct encaps_delivery_ext *) buf; encaps->type = ENCAPS_DELIVERY_EXT; encaps->length = 0; return sizeof(struct encaps_delivery_ext);}int add_raw(char *buf, int left, struct parse_data *parse){ char *pos = buf, *rpos; int i, count; while (parse_get_next(parse) == 1) { if (strcmp(parse->field, "data") == 0) { count = strlen(parse->value) / 2; if (count > left) { fprintf(stderr, "add_raw - buffer full\n"); return 0; } rpos = parse->value; for (i = 0; i < count; i++) { *pos = get_hex_digit(*rpos) * 16 + get_hex_digit(*(rpos + 1)); pos++; rpos += 2; } } else { fprintf(stderr, "add_raw - unknown field '%s'\n", parse->field); return 0; } } return pos - buf;}#define SENDBUF 8192int add_udp(char *buf, int left, struct parse_data *parse){ struct udphdr *udp; char *mip_start, *pos; struct msg_extensions ext; int mip_msg = 0; udp = (struct udphdr *) buf; udp->source = htons(434); udp->dest = htons(434); udp->check = 0; while (parse_get_next(parse) == 1) { if (strcmp(parse->field, "dstport") == 0) udp->dest = htons(dyn_atoi(parse->value)); else if (strcmp(parse->field, "srcport") == 0) udp->source = htons(dyn_atoi(parse->value)); } mip_start = pos = (char *) (udp + 1); while (parse_init(parse, parse->next) == 1) { int left = pos - buf + SENDBUF; printf("\tudp-data: %s\n", parse->name); if (strcmp(parse->name, "req") == 0) { pos += add_req(pos, left, parse); mip_msg = 1; } else if (strcmp(parse->name, "rep") == 0) { pos += add_rep(pos, left, parse); mip_msg = 1; } else if (strcmp(parse->name, "mhauth") == 0) pos += add_auth(MH_AUTH, mip_start, pos, left, parse); else if (strcmp(parse->name, "mfauth") == 0) pos += add_auth(MF_AUTH, mip_start, pos, left, parse); else if (strcmp(parse->name, "fhauth") == 0) pos += add_auth(FH_AUTH, mip_start, pos, left, parse); else if (strcmp(parse->name, "encaps") == 0) pos += add_encaps(pos, left); else if (strcmp(parse->name, "raw") == 0) pos += add_raw(pos, left, parse); else printf("\tunknown udp data\n"); } udp->len = htons(pos - buf); /* FIX: UDP checksum */ memset(&ext, 0, sizeof(ext)); if (mip_msg && parse_msg(mip_start, pos - mip_start, &ext) != 0) { fprintf(stderr, "\tInvalid message!\n"); } if (ext.req != NULL) { prev_id[0] = ext.req->id[0]; prev_id[1] = ext.req->id[1]; } if (ext.rep != NULL) { prev_id[0] = ext.rep->id[0]; prev_id[1] = ext.rep->id[1]; } return pos - buf;}int add_icmp(char *buf, int left, struct parse_data *parse){ struct icmphdr *icmp; char *pos; int force_checksum = -1; icmp = (struct icmphdr *) buf; memset(icmp, 0, sizeof(*icmp)); pos = buf + sizeof(struct icmphdr); while (parse_get_next(parse) == 1) { if (strcmp(parse->field, "type") == 0) icmp->type = dyn_atoi(parse->value); else if (strcmp(parse->field, "code") == 0) icmp->code = dyn_atoi(parse->value); else if (strcmp(parse->field, "checksum") == 0) force_checksum = dyn_atoi(parse->value); } while (parse_init(parse, parse->next) == 1) { int left = pos - buf + SENDBUF; printf("\ticmp-data: %s\n", parse->name); if (strcmp(parse->name, "ip") == 0) pos += add_ip(pos, left, parse); else if (strcmp(parse->name, "raw") == 0) pos += add_raw(pos, left, parse); else printf("\tunknown icmp data\n"); } icmp->checksum = ip_checksum((unsigned char *) icmp, pos - buf); return pos - buf;}int add_ip(char *buf, int left, struct parse_data *parse){ struct iphdr *ip; char *pos; struct in_addr addr; ip = (struct iphdr *) buf; ip->ihl = 5;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -