#pragma implementation #include #include #include #include #include #include "netsimul.h" #include "netsimul.m" #include #include static HELP_FILE help_netsimul ("netsimul","netsimul"); static HELP_FILE help_trace ("netsimul","trace"); static HELP_FILE help_browse ("netsimul","browse"); MODULE_DEFINE_VERSION(netsimul); static const char K_NETSIMULCASES[]="netsimulcases"; static const char K_INDEX[]="index"; static const char K_FROMIP[]="fromip"; static const char K_FROMPORT[]="fromport"; static const char K_TOIP[]="toip"; static const char K_TOPORT[]="toport"; static const char K_PROTO[]="proto"; static const char K_INTERIN[]="interin"; static const char K_INTEROUT[]="interout"; static const char K_DESCRIP[]="descrip"; static const char K_TESTINPUT[]="testinput"; static const char K_TESTFORWARD[]="testforward"; static const char K_TESTOUTPUT[]="testoutput"; static const char K_BOTHDIR[]="bothdir"; static const char *netsimul_getval (const char *key1, const char *key2) { char tmp[200]; sprintf (tmp,"%s.%s",key1,key2); return linuxconf_getval (K_NETSIMULCASES,tmp); } static void netsimul_getval ( const char *key1, const char *key2, SSTRING &val) { val.setfrom (netsimul_getval (key1,key2)); } static void netsimul_getval ( const char *key1, const char *key2, char &val) { const char *tmp = netsimul_getval (key1,key2); val = tmp == NULL ? 0 : atoi(tmp); } static void netsimul_setval ( const char *key1, const char *key2, const SSTRING &val) { char tmp[200]; sprintf (tmp,"%s.%s",key1,key2); linuxconf_replace (K_NETSIMULCASES,tmp,val); } static void netsimul_setval ( const char *key1, const char *key2, const char val) { char tmp[200]; sprintf (tmp,"%s.%s",key1,key2); linuxconf_replace (K_NETSIMULCASES,tmp,val); } static void netsimul_trace ( FIRE_CHAINS &chains, FIRE_PACKET &pk, const char *set, const char *interface, SSTRINGS &tb) { FIRE_RULES rules; int ok = chains.trace (rules,pk,set,interface); SSTRING *res = new SSTRING; static const char *tbres[]={ MSG_U(E_TRACEERR,"Error"), MSG_U(I_FAIL,"Failed"), MSG_U(I_ACCEPT,"Accepted"), MSG_U(I_MASQ,"Masqueraded") }; res->setfromf (MSG_U(T_TESTINGRULE,"Testing ruleset %s: %s") ,set,tbres[ok+1]); tb.add (res); for (int i=0; idump(*res); res->setfromf (" %s",res->get()); tb.add (res); } } /* Convert an IP protocol by name or by number to an integer. Return -1 if is it invalid */ static int netsimul_cnvproto (const SSTRING &proto) { int ret = -1; const char *s = proto.get(); if (isdigit(*s)){ const char *end = str_skipdig(s); if (*end == '\0'){ ret = atoi(s); } }else{ struct protoent *p = getprotobyname(s); if (p != NULL){ ret = p->p_proto; } } return ret; } /* Convert an IP port by name or by number to an integer. Return -1 if is it invalid */ static int netsimul_cnvport (const SSTRING &port, const SSTRING &proto) { int ret = -1; const char *s = port.get(); if (proto.cmp("tcp")==0 || proto.cmp("udp")==0){ if (isdigit(*s)){ const char *end = str_skipdig(s); if (*end == '\0'){ ret = atoi(s); } }else{ struct servent *p = getservbyname(s,proto.get()); if (p != NULL){ ret = ntohs(p->s_port); } } }else if (s[0] == '\0'){ ret = 0; } return ret; } /* Convert a host or IP number into an unsigned long. Return 0xffffffff if invalid. */ static unsigned long netsimul_cnvip (const char *s) { unsigned long ret = 0xffffffffl; if (ipnum_validip(s,false)){ ret = ipnum_aip2l(s); }else{ struct hostent *e = gethostbyname (s); if (e != NULL){ memcpy (&ret,e->h_addr,sizeof(ret)); ret = ntohl (ret); } } return ret; } static unsigned long netsimul_cnvip (const SSTRING &s) { return netsimul_cnvip(s.get()); } static void netsimul_firewall() { DIALOG dia; SSTRING desc; SSTRING from,proto,interin,interout,fromport,toport; SSTRING to; char testinput,testforward,testoutput,bothdir; glocal.testinput = glocal.testforward = glocal.testoutput = 1; glocal.bothdir = 1; glocal.dia.gui_form (); glocal.dia.newf_str (MSG_U(F_TESTCASE,"Test case"),glocal.desc,70); glocal.dia.gui_dispolast (GUI_H_LEFT,6,GUI_V_CENTER,1); glocal.dia.newline(); int field_proto = glocal.dia.getnb(); glocal.dia.newf_str (MSG_U(F_PROTOCOL,"Protocol"),glocal.proto,10); glocal.dia.gui_end(); glocal.dia.gui_dispolast (GUI_H_LEFT,2,GUI_V_CENTER,1); glocal.dia.newline(); glocal.dia.gui_group (MSG_U(T_FROM,"From")); int field_fromip = glocal.dia.getnb(); glocal.dia.newf_str (MSG_U(F_FROM,"IP number"),glocal.from,15); int field_fromport = glocal.dia.getnb(); glocal.dia.newf_str (MSG_U(F_PORT,"port"),glocal.fromport,8); glocal.dia.newline(); glocal.dia.newf_str (MSG_U(F_INTER,"Interface"),glocal.interin,10); glocal.dia.gui_end(); glocal.dia.gui_group (MSG_U(T_TO,"To")); int field_toip = glocal.dia.getnb(); glocal.dia.newf_str (MSG_U(F_TO,"IP number"),glocal.to,15); int field_toport = glocal.dia.getnb(); glocal.dia.newf_str (MSG_U(F_TOPORT,"port"),glocal.toport,8); glocal.dia.newline(); glocal.dia.newf_str (MSG_R(F_INTER),glocal.interout,10); glocal.dia.gui_end(); glocal.dia.newline(); glocal.dia.gui_group (MSG_U(T_TEST,"Test")); glocal.dia.newf_chk (MSG_U(F_TESTINPUT,"Input"),glocal.testinput,""); glocal.dia.newf_chk (MSG_U(F_TESTFORWARD,"Forward"),glocal.testforward,""); glocal.dia.newf_chk (MSG_U(F_TESTOUTPUT,"Output"),glocal.testoutput,""); glocal.dia.newf_chk (MSG_U(F_BOTHDIR,"Both direction"),glocal.bothdir,""); glocal.dia.gui_end(); glocal.dia.gui_dispolast (GUI_H_LEFT,2,GUI_V_CENTER,1); int nof = 0; glocal.dia.setbutinfo (MENU_USR1,MSG_U(B_TEST,"Test"),MSG_R(B_TEST)); glocal.dia.setbutinfo (MENU_USR2,MSG_U(B_SAVE,"Save test case"),MSG_R(B_SAVE)); glocal.dia.setbutinfo (MENU_USR3,MSG_U(B_RECALL,"Recall a test case"),MSG_R(B_RECALL)); glocal.dia.setbutinfo (MENU_USR4,MSG_U(B_BROWSE,"Browse rules"),MSG_R(B_BROWSE)); while (1){ MENU_STATUS code = glocal.dia.edit (MSG_U(T_TRACEFIREWALL ,"Testing firewall") ,MSG_U(I_TRACEFIREWALL ,"You can test various network paquets and see how the\n" "firewall will react.") ,help_trace ,nof ,MENUBUT_CANCEL|MENUBUT_USR1|MENUBUT_USR2|MENUBUT_USR3|MENUBUT_USR4); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_USR2){ glocal.dia.save(); SSTRINGS tb; linuxconf_getall (K_NETSIMULCASES,K_INDEX,tb,true); // We must find a slot where to replace the entry // We use the description as the search key const char *key = NULL; for (int i=0; iget(); if (glocal.desc.cmp(netsimul_getval(K_DESCRIP,tmp))==0){ key = tmp; break; } } char tmpkey[10]; linuxconf_setcursys ("netsimul"); if (key == NULL){ sprintf (tmpkey,"%d",tb.getnb()); key = tmpkey; linuxconf_add (K_NETSIMULCASES,K_INDEX,key); } netsimul_setval(K_FROMIP,key,glocal.from); netsimul_setval(K_FROMPORT,key,glocal.fromport); netsimul_setval(K_TOIP,key,glocal.to); netsimul_setval(K_TOPORT,key,glocal.toport); netsimul_setval(K_PROTO,key,glocal.proto); netsimul_setval(K_INTERIN,key,glocal.interin); netsimul_setval(K_INTEROUT,key,glocal.interout); netsimul_setval(K_DESCRIP,key,glocal.desc); netsimul_setval(K_TESTINPUT,key,glocal.testinput); netsimul_setval(K_TESTFORWARD,key,glocal.testforward); netsimul_setval(K_TESTOUTPUT,key,glocal.testoutput); netsimul_setval(K_BOTHDIR,key,glocal.bothdir); linuxconf_save(); }else if (code == MENU_USR3){ SSTRINGS tb; (MSG_U(T_TESTCASES,"Test cases") ,MSG_U(I_TESTCASES,"Here are the test cases currently defined") ,help_trace); newf_head (MSG_U(H_TESTCASES,"From\tTo\tDescription")); settype (DIATYPE_POPUP); glocal.tb.remove_all(); linuxconf_getall (K_NETSIMULCASES,K_INDEX,glocal.tb,true); for (int i=0; iget(); SSTRING fromip (netsimul_getval(K_FROMIP,key)); SSTRING toip (netsimul_getval(K_TOIP,key)); SSTRING desc (netsimul_getval(K_DESCRIP,key)); new_menuitemf (fromip.get(),"%s\t%s",toip.get(),desc.get()); } const char *key = glocal.tb.getitem(no)->get(); netsimul_getval(K_FROMIP,key,glocal.from); netsimul_getval(K_FROMPORT,key,glocal.fromport); netsimul_getval(K_TOIP,key,glocal.to); netsimul_getval(K_TOPORT,key,glocal.toport); netsimul_getval(K_PROTO,key,glocal.proto); netsimul_getval(K_INTERIN,key,glocal.interin); netsimul_getval(K_INTEROUT,key,glocal.interout); netsimul_getval(K_DESCRIP,key,glocal.desc); netsimul_getval(K_TESTINPUT,key,glocal.testinput); netsimul_getval(K_TESTFORWARD,key,glocal.testforward); netsimul_getval(K_TESTOUTPUT,key,glocal.testoutput); netsimul_getval(K_BOTHDIR,key,glocal.bothdir); glocal.dia.reload(); }else if (code == MENU_USR1 || code == MENU_USR4){ glocal.dia.save(); if (glocal.proto.is_empty()){ xconf_error (MSG_U(E_PROTO,"You must specify the IP protocol")); nof = field_proto; }else if (netsimul_cnvproto(glocal.proto)==-1){ xconf_error (MSG_U(E_IVLDPROTO,"Invalid IP protocol: %s") ,glocal.proto.get()); nof = field_proto; }else if (netsimul_cnvport(glocal.fromport,glocal.proto)==-1){ xconf_error (MSG_U(E_IVLDPORT,"Invalid PORT: %s") ,glocal.fromport.get()); nof = field_fromport; }else if (netsimul_cnvport(glocal.toport,glocal.proto)==-1){ xconf_error (MSG_R(E_IVLDPORT),glocal.toport.get()); nof = field_toport; }else if (glocal.from.is_empty()){ xconf_error (MSG_U(E_EMPTYIP,"You must specify the IP number")); nof = field_fromip; }else if (glocal.to.is_empty()){ xconf_error (MSG_R(E_EMPTYIP)); nof = field_toip; }else if (netsimul_cnvip(glocal.from)==0xffffffff){ xconf_error (MSG_U(E_IVLDHOSTORIP,"Invalid host or IP number : %s") ,glocal.from.get()); nof = field_fromip; }else if (netsimul_cnvip(glocal.from)==0xffffffff){ xconf_error (MSG_R(E_IVLDHOSTORIP),glocal.to.get()); nof = field_toip; }else if (code == MENU_USR1){ FIRE_CHAINS chains; if (chains.read()!=-1){ SSTRINGS tb; for (int i=0; i<2; i++){ const char *interin = glocal.interin.get(); const char *interout = glocal.interout.get(); const char *from = glocal.from.get(); const char *fromport = glocal.fromport.get(); const char *to = glocal.to.get(); const char *toport = glocal.toport.get(); if (i == 1){ interout = glocal.interin.get(); interin = glocal.interout.get(); to = glocal.from.get(); toport = glocal.fromport.get(); from = glocal.to.get(); fromport = glocal.toport.get(); } FIRE_PACKET pk( netsimul_cnvip(from),atoi(fromport) ,netsimul_cnvip(to),atoi(toport) ,netsimul_cnvproto(glocal.proto),interin); if (glocal.testinput){ netsimul_trace (chains,pk,"input",interin,tb); } if (glocal.testforward){ netsimul_trace (chains,pk,"forward",interout,tb); } if (glocal.testoutput){ netsimul_trace (chains,pk,"output",interout,tb); } if (!glocal.bothdir) break; } dialog_textbox (MSG_U(T_TESTRESULT,"Test result"),"",help_nil,tb); } }else if (code == MENU_USR4){ DIALOG_MENUPOPUP pop; pop.new_menuitem ("-",MSG_U(M_FROMTO,"From -> To")); pop.new_menuitem ("",MSG_U(M_INPUT,"Input")); pop.new_menuitem ("",MSG_U(M_FORWARD,"Forward")); pop.new_menuitem ("",MSG_U(M_OUTPUT,"Output")); pop.new_menuitem ("-",MSG_U(M_TOFROM,"To -> From")); pop.new_menuitem ("",MSG_R(M_INPUT)); pop.new_menuitem ("",MSG_R(M_FORWARD)); pop.new_menuitem ("",MSG_R(M_OUTPUT)); int sel = 0; if (pop.editmenu (MSG_R(T_BROWSE),sel)==MENU_OK){ FIRE_CHAINS chains; SSTRINGS sels; // Nesting of chains selected // since editrecords is used too dig // further in sub-chains. bool use_from; // User from interface bool tofrom; // Test from -> to or to -> from static const char *tbch[]={"input","forward","output"}; glocal.sels.add (new SSTRING(sel >= 5 ? tbch[sel-5] : tbch[sel-1])); glocal.chains.read(); glocal.use_from = sel == 1 || sel > 5; glocal.tofrom = sel >= 5; (MSG_U(T_BROWSE,"Firewall rules"),"",help_browse); newf_head (MSG_U(H_RULES,"Match\tChain\tTarget\tProto\tInter\tFrom\tRange\tTo\tRange")); setbutinfo (MENU_USR1,MSG_U(B_BACK,"Back"),MSG_R(B_BACK)); int last = glocal.sels.getnb()-1; const char *name = glocal.sels.getitem(last)->get(); FIRE_CHAIN *chain = glocal.chains.locate (name); if (chain != NULL){ const char *from = glocal.from.get(); int fromport = netsimul_cnvport (glocal.fromport,glocal.proto); const char *to = glocal.to.get(); int toport = netsimul_cnvport (glocal.toport,glocal.proto); if (glocal.tofrom){ const char *tmp = from; from = to; to = tmp; int porttmp = fromport; fromport = toport; toport = porttmp; } FIRE_PACKET pk( netsimul_cnvip(from),fromport ,netsimul_cnvip(to),toport ,netsimul_cnvproto(glocal.proto) ,glocal.use_from ? glocal.interin.get() : glocal.interout.get()); for (int i=0; igetnb(); i++){ FIRE_RULE *r = chain->getitem(i); SSTRING d; r->dump (d); new_menuitem (r->match(pk) ? MSG_U(I_YES,"Yes") : "" ,d.get()); } } int last = glocal.sels.getnb()-1; const char *name = glocal.sels.getitem(last)->get(); FIRE_CHAIN *chain = glocal.chains.locate (name); if (chain != NULL){ FIRE_RULE *r = chain->getitem(no); if (!r->is_terminal()){ glocal.sels.add (new SSTRING(r->gettarget())); } } int last = glocal.sels.getnb()-1; if (last > 0){ glocal.sels.remove_del (last); } } } } } } static void netsimul_mainmenu() { static const char *opts[]={ MSG_U(M_INSPECT,"Inspect"),MSG_U(M_FIREWALL,"the firewall"), NULL }; (MSG_R(M_netsimul),"",help_netsimul,opts); if (perm_rootaccess(MSG_U(P_INSPECT,"to inspect the networking"))){ if (no == 0){ netsimul_firewall(); } } } static const char *keymenu=NULL; ("netsimul",PACKAGE_REV); tb.add (new SSTRING(MSG_U(T_USAGE ,"linuxconf --modulemain netsimul usage\n" "\n" " netsimul --option ...\n"))); if (context == MENU_NETWORK_MISC){ keymenu = MSG_U(M_netsimul,"Network simulation and debugging"); dia.new_menuitem ("netsimul","",keymenu); } if (context == MENU_NETWORK_MISC){ if (key == keymenu){ CONTEXT_LOCK l("netsimul"); if (l.isok()){ netsimul_mainmenu(); } } } return 0; int ret = LNCF_NOT_APPLICABLE; return ret; int ret = -1; if (argc == 1){ CONTEXT_LOCK l("netsimul"); if (l.isok()){ netsimul_mainmenu(); } }else{ printusage(); } return ret;