📄 main.c
字号:
#if INSTALL_COURIER#include <courier/common/ut_incl.h>#include <courier/common/port_inc.h>#include <courier/common/avl_incl.h>#include <courier/common/ip_incl.h>#endif#if INSTALL_COURIER_OSPF#include <courier/ospf/ospf_inc.h>#endif#if INSTALL_COURIER_BGP#include <courier/bgp/bgp_inc.h>#endif#if INSTALL_COURIER_RIP#include <courier/rip/rip_inc.h>#endif#if INSTALL_COURIER_BGP_TRAPS#include <courier/common/trap.h>#endif#include <wrn/wm/demo/snarklib.h>#include <wrn/wm/demo/read_ini.h>#if INSTALL_ATTACHE_TELNETextern struct tn_dispatch stytn_dispatch;static struct tn_listener *tn_listener;#endif#if INSTALL_ATTACHE_TCPstatic struct tcb *echo_listener;static struct tcb *source_listener;static struct tcb *sink_listener;#endif#if INSTALL_DECORUM#include <decorum/h/http.h>#include <decorum/h/url.h>#include <decorum/h/dec_proc.h>#endif#if INSTALL_ENVOY#include <wrn/wm/demo/snmpconf.h>#endif#if INSTALL_SNARK_FIREWALL#include <wrn/wm/demo/firewall.h>#endifextern route_table_t *ipv6_routing_table;#if INSTALL_ATTACHE_IPV4_ROUTER_DISCOVERYextern rd_cache_t *ipv4_rd_cache;#endifchar *prompt = "snark> ";static boolean_t cmd_help(struct sty *, enum help_level, int, char **);#define ATEXIT_BROKEN#define TCP_SHOW_TCBS()#if INSTALL_ATTACHE_TELNETstatic struct { enum tn_error code; char *name; } tn_errtab[] = { { TN_ERROR_OK, "no error" }, { TN_ERROR_CONNECTION_RESET, "connection reset" }, { TN_ERROR_CONNECTION_TIMEOUT, "timeout" }, { TN_ERROR_PEER_UNREACHABLE, "unreachable" }, { TN_ERROR_BAD_PROTOCOL, "bad protocol" }, { TN_ERROR_UNSUPPORTED_OPTION, "unsupported option" }, { TN_ERROR_OPTION_UNDER_NEGOTIATION, "option under negotiation" }, { TN_ERROR_OPTION_NOT_ENABLED, "option not enabled" }, { TN_ERROR_CANT_NEST_SUBNEGOTIATIONS, "can't nest subnegotiations" }, { TN_ERROR_NOT_SUBNEGOTIATING, "not subnegotiating" }, { TN_ERROR_BAD_ARGUMENTS, "bad arguments" }, { TN_ERROR_BUFFER_SPACE_EXCEEDED, "buffer space exceeded" }, { TN_ERROR_CONNECTION_NOT_ESTABLISHED, "connection not established" }, { TN_ERROR_WINDOW_CLOSED, "window closed" }, { TN_ERROR_WINDOW_OPENED, "window opened" }, { TN_ERROR_IMPOSSIBLE, "impossible error" },};#define TN_ERRTAB \ (sizeof(tn_errtab)/sizeof(*tn_errtab))#endif /* INSTALL_ATTACHE_TELNET */#if INSTALL_ATTACHE_DNSstatic struct { enum dns_error code; char *name; } dns_errtab[] = { { DNS_ERROR_OK, "No error" }, { DNS_ERROR_NAME_TOO_LONG, "Name too long" }, { DNS_ERROR_BAD_NAME, "Bad name" }, { DNS_ERROR_BAD_ARGS, "Bad args" }, { DNS_ERROR_LABEL_TOO_LONG, "Label too long" }, { DNS_ERROR_ALLOCATION_FAILURE, "Allocation failure" }, { DNS_ERROR_TIMEOUT, "Timeout" }, { DNS_ERROR_UNREACHABLE, "Unreachable" }, { DNS_ERROR_FORMAT, "Format" }, { DNS_ERROR_SERVER_FAILURE, "Server failure" }, { DNS_ERROR_NONEXISTANT_NAME, "Nonexistant name" }, { DNS_ERROR_NIY, "NIY" }, { DNS_ERROR_REFUSED, "Refused" }, { DNS_ERROR_IMPOSSIBLE, "Impossible" }, { DNS_ERROR_NO_RRS, "No RRs" }, { DNS_ERROR_ABORTED, "Aborted" }, { DNS_ERROR_BAD_PROTOCOL, "Bad protocol" }, { DNS_ERROR_TRUNCATED, "Truncated" }, { DNS_ERROR_NO_RECURSION, "No recursion" }, { DNS_ERROR_IRRELEVANT, "Irrelevant" }, { DNS_ERROR_NOT_IN_LOCAL_CACHE, "Not in local cache" }, { DNS_ERROR_NO_PORT, "No port" }, { DNS_ERROR_EMPTY_LABEL, "Zero-length label in name" },};#define DNS_ERRTAB \ (sizeof(dns_errtab)/sizeof(*dns_errtab))void display_dns_error(struct sty *sty, struct dns_query *query, enum dns_error error){ int i; for (i=0; i<DNS_ERRTAB; i++) if (dns_errtab[i].code == error) break; sty_printf(sty, "hostname lookup failed: "); if (i < DNS_ERRTAB) sty_printf(sty, "%s\n", dns_errtab[i].name); else sty_printf(sty, "unknown error %d\n", (int) error);}#endif /* INSTALL_ATTACHE_DNS */#if INSTALL_ATTACHE_TCP#define ECHO_PORT 7#define ECHO_WINDOW 128static bits16_t echo_rcv(struct tcb *tcb, packet *rcv_pkt){ packet *snd_pkt = tcp_alloc(rcv_pkt->pkt_datalen); bits16_t rcv_wnd; if (snd_pkt) { MEMCPY(snd_pkt->pkt_data, rcv_pkt->pkt_data, (snd_pkt->pkt_datalen = rcv_pkt->pkt_datalen)); rcv_wnd = tcp_write(tcb, snd_pkt); } else { tcp_abort(tcb); rcv_wnd = 0; } pkt_free(rcv_pkt); return rcv_wnd;}static void echo_transmit(struct tcb *tcb){ tcp_set_receive_window(tcb, (unsigned) tcp_get_send_window(tcb));}static void echo_fclose(struct tcb *tcb){ if (tcb) tcp_close(tcb);}#endif /* INSTALL_ATTACHE_TCP */#if INSTALL_ATTACHE_TCP#define SOURCE_PORT 19#ifndef SOURCE_WINDOW#define SOURCE_WINDOW 1#endif#ifndef SOURCE_LINES#define SOURCE_LINES 1#endifstruct source_state { unsigned line; struct timer timer;};static char source_chars[] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";#define SOURCE_CHARS (sizeof(source_chars) - 1)static void source_generator(struct tcb *);static void sourcegen_tm_handler(struct timer *tm, void *cookie){ source_generator(cookie);}static void source_generator(struct tcb *tcb){ struct source_state *state = tcp_get_cookie(tcb); unsigned b, e; unsigned char *d; packet *p; do { if ((p = tcp_alloc(74 * SOURCE_LINES)) == 0) { /* * Schedule ourselves to be called again in 10 ms, plus a random * dithering amount not more than .25 second or so. If we don't * do this, we will hang forever because we havent filled up the * send window, so TCP will never call our transmit upcall (this * function) for us. The dithering prevents one instance of * this from hogging all the memory buffers. */ etc_tm_init(&state->timer); etc_tm_set(&state->timer, 10 + ep_weak_prng(0xFF)); return; } p->pkt_datalen = 74 * SOURCE_LINES; for (d = p->pkt_data; d < p->pkt_data + p->pkt_datalen; d += 74) { b = state->line % SOURCE_CHARS; e = (state->line + 72) % SOURCE_CHARS; state->line++; if (b < e) { MEMCPY(d, source_chars + b, e - b); } else { MEMCPY(d, source_chars + b, SOURCE_CHARS - b); MEMCPY(d + SOURCE_CHARS - b, source_chars, e); } d[72] = '\r'; d[73] = '\n'; } } while (tcp_write(tcb, p) > 0);}static void source_open(struct tcb *tcb){ struct source_state *state; if ((state = GLUE_ALLOC(sizeof(*state))) == 0) { tcp_abort(tcb); return; } state->line = 0; state->timer.handler = sourcegen_tm_handler; state->timer.cookie = tcb; tcp_set_cookie(tcb, state); source_generator(tcb);}static void source_transmit(struct tcb *tcb){ source_generator(tcb);}static void source_fclose(struct tcb *tcb){ tcp_close(tcb);}static void source_close(struct tcb *tcb, int reason){ struct source_state *state = tcp_get_cookie(tcb); if (state) { etc_tm_cancel(&state->timer); GLUE_FREE(state); }}#endif /* INSTALL_ATTACHE_TCP */#if INSTALL_ATTACHE_TCP || INSTALL_ATTACHE_UDP#define SINK_PORT 9#endif#if INSTALL_ATTACHE_TCP#define SINK_WINDOW 16384#define SINK_PKTLEN 536 /* an informed guess */static void sink_open(struct tcb *tcb){ tcp_set_ahead_of_seq_max(tcb, tcp_get_receive_window(tcb) / SINK_PKTLEN);}static bits16_t sink_rcv(struct tcb *tcb, packet *rcv_pkt){ pkt_free(rcv_pkt); return SINK_WINDOW;}static void sink_fclose(struct tcb *tcb){ tcp_close(tcb);}#endif /* INSTALL_ATTACHE_TCP */#if INSTALL_ATTACHE_DNS/* * Patch around a version skew problem, sigh. This will go away RSN.... */#ifndef INSTALL_SNARK_ATTACHE_34_DNS_COMPAT#define INSTALL_SNARK_ATTACHE_34_DNS_COMPAT 0#endif#if INSTALL_SNARK_ATTACHE_34_DNS_COMPATvoid snark_attache_dns_34_compat (void (*handler)(struct dns_query *, char *, int, ipaddr_t [], void *), struct dns_query *query, char *dname, int n, inaddr_t addrs[], void *cookie){ ipaddr_t addr; IPADDR_ZERO(&addr); SET_IPADDR_TYPE(&addr, IPV4); MEMCPY(PTR_IPADDR_BITS(&addr), (ipaddr_bits_t *) &addrs[0], IPV4_ADDR_LEN); (*handler)(query, dname, 1, &addr, cookie);}#endif /* INSTALL_SNARK_ATTACHE_34_DNS_COMPAT */#endif#if INSTALL_ATTACHE_UDPstatic int sunk_packets = 0;static int sunk_errs = 0;void udp_sink_rcv (packet *p, void *sink){ sunk_packets++; udp_free(p);}void udp_sink_icmp_rcv (packet *p, void *sink){ sunk_errs++; udp_free(p);}struct udp_sink_state { struct udp_conn conn; struct sty *sty; int size; int srcp;};#if INSTALL_ATTACHE_DNSstatic void udp_sink_dns_won(struct dns_query *query, char *dname, int n, ipaddr_t addrs[], void *cookie){ struct udp_sink_state *state = cookie; packet *p; udp_conn_init(&state->conn); udp_conn_set_src(&state->conn, state->srcp); udp_conn_set_dst(&state->conn, SINK_PORT); ip_conn_set_dst_ip(udp_conn_get_ip_conn(&state->conn), &addrs[0]); p = udp_alloc(state->size, 0); if (p) { memset(p->pkt_data, 0, p->pkt_datalen); udp_send_conn(p, &state->conn); } sty_read(state->sty, do_cmd, prompt, 0); GLUE_FREE(state);}#if INSTALL_SNARK_ATTACHE_34_DNS_COMPATstatic void udp_sink_dns_won_compat (struct dns_query *query, char *dname, int n, inaddr_t addrs[], void *cookie){ snark_attache_dns_34_compat(udp_sink_dns_won, query, dname, n, addrs, cookie);}#endif /* INSTALL_SNARK_ATTACHE_34_DNS_COMPAT */static void udp_sink_dns_err (struct dns_query *query, enum dns_error error, void *cookie){ struct udp_sink_state *state = cookie; display_dns_error(state->sty, query, error); sty_read(state->sty, do_cmd, prompt, 0); GLUE_FREE(state);}static boolean_t cmd_udp_sink(struct sty *sty, enum help_level help, int argc, char **argv){ struct udp_sink_state *state; switch (help) { case help_none: if (argc < 2) { sty_puts(sty, "% You have to tell me who to sink.\n"); break; } if ((state = (struct udp_sink_state *) GLUE_ALLOC(sizeof(*state))) == 0) { sty_puts(sty, "% Couldn't allocate state block\n"); break; } state->srcp = SINK_PORT; state->size = 64; state->sty = sty; if (argc >= 3) state->size = atoi(argv[2]); DNS_NAME_TO_IPADDR(argv[1], udp_sink_dns_won, udp_sink_dns_err, &domain_config, 0, state); return 0; /* don't schedule command scanner yet */ break; case help_short: sty_puts(sty, "sink sink host [size]\n"); break; case help_long: sty_puts(sty, "\The \"udp_sink\" command sends a packet to the UDP sink port of the\n\destination system\n\first argument is name or address of destination.\n\Optional second argument is size of packet\n"); break; } return 1;}#endif#endifstatic boolean_t cmd_quit (struct sty *sty, enum help_level help, int argc, char **argv){ switch (help) { case help_none: if (sty == cty) { snark_exit(0); return 0; } sty_close(sty); break; case help_short: sty_puts(sty, "quit exit program\n"); break; case help_long: sty_puts(sty, "\The \"quit\" command exits this program if given on the console.\n\When given on a telnet connection, just shuts down that connection.\n"); } return 1;}static boolean_t cmd_readme (struct sty *sty, enum help_level help, int argc, char **argv){ switch (help) { case help_none: sty_puts(sty, "\This is just a little test program I wrote to see whether the snark\n\library routines worked at all. If you're reading this, they do.\n\\n\Happy, happy, joy, joy.\n"); break; case help_short:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -