/* This module enhance the PPP user account management by adding a section to control the PPP parameters. This information is stored in the file /etc/pppdialin.conf. The utility /usr/lib/linuxconf/lib/pppparms produce a list of variable suitable to help a normal/generic ppplogin script. This combination should make the ppplogin scripts almost useless, or only useful for really exceptionnal stuff. */ #pragma implementation #include #include #include #include "pppdialin.h" #include "pppdialin.m" #include #include #include #include #include #include #include "../module_apis/fwinfo_api.h" static const char subsys_pppdialin[]="pppdialin"; static LINUXCONF_SUBSYS subb (subsys_pppdialin ,P_MSG_U(I_PPPDIALIN,"PPP dialing configs")); HELP_FILE help_dialin ("pppdialin","dialin"); static CONFIG_FILE f_pppdialin ("/etc/pppdialin.conf",help_dialin ,CONFIGF_MANAGED|CONFIGF_OPTIONAL ,"root","pppusers",0640 ,subsys_pppdialin); MODULE_DEFINE_VERSION(pppdialin); PUBLIC MODULE_pppdialin::MODULE_pppdialin() : LINUXCONF_MODULE("pppdialin") { linuxconf_loadmsg ("pppdialin",PACKAGE_REV); module_register_api ("fwinfo",FWINFO_API_REV,ipupupd_fwinfo_api_get ,ipupupd_fwinfo_api_release); } static const char *defmenu = NULL; PUBLIC void MODULE_pppdialin::setmenu ( DIALOG &dia, MENU_CONTEXT context) { if (context == MENU_USER_POLICIES){ defmenu = MSG_U(M_DEFPPP,"Default PPP paramaters"); dia.new_menuitem ("",defmenu); } } #include "key.h" static void pppdialin_saveif ( CONFDB &conf, const char *name, const char *key, int val) { if (val == 0){ conf.removeall (name,key); }else{ conf.replace (name,key,val); } } static void pppdialin_saveif ( CONFDB &conf, const char *name, const char *key, SSTRING val) { if (val.is_empty()){ conf.removeall (name,key); }else{ conf.replace (name,key,val); } } /* Save conditionnally defaults value */ static void pppdialin_savedefif ( CONFDB &conf, const char *key, int val) { pppdialin_saveif (conf,K_DEFPPP,key,val); } static void pppdialin_savedefif ( CONFDB &conf, const char *key, SSTRING val) { pppdialin_saveif (conf,K_DEFPPP,key,val); } /* Check if an IP number is valid. It may be empty. Return false if not after showing an error message */ static bool pppdialin_validip(const SSTRING &ip) { bool ret = true; const char *ptip = ip.get(); if (ptip[0] != '\0' && strcmp(ptip,"none")!=0 && !ipnum_validip(ptip,true)){ xconf_error (MSG_U(E_IVLDIP,"Invalid IP number: %s"),ptip); ret = false; } return ret; } static void pppdialin_editdefaults() { CONFDB conf (f_pppdialin); char ppp233 = conf.getvalnum (K_DEFPPP,K_PPP233,0); char proxyarp = conf.getvalnum (K_DEFPPP,K_PROXYARP,0); char alloc_from_tty = conf.getvalnum (K_DEFPPP,K_ALLOCFROMTTY,0); int idletime = conf.getvalnum (K_DEFPPP,K_IDLETIME,0); int maxtime = conf.getvalnum (K_DEFPPP,K_MAXTIME,0); SSTRING dns1,dns2,ourip; ourip.setfrom (conf.getval(K_DEFPPP,K_OURIP)); dns1.setfrom (conf.getval(K_DEFPPP,K_DNS1)); dns2.setfrom (conf.getval(K_DEFPPP,K_DNS2)); SSTRING options; options.setfrom (conf.getval(K_DEFPPP,K_OPTIONS)); SSTRING postconcmd,postdisconcmd; postconcmd.setfrom (conf.getval(K_DEFPPP,K_POSTCONCMD)); postdisconcmd.setfrom (conf.getval(K_DEFPPP,K_POSTDISCONCMD)); DIALOG dia; dia.newf_chk ("",ppp233,MSG_U(I_PPP233,"Using pppd 2.3.3")); dia.newf_chk ("",alloc_from_tty,MSG_U(F_ALLOCFROMTTY ,"Allocate remote IP from tty name")); dia.newf_num (MSG_U(F_IDLETIME,"Idle time"),idletime); dia.newf_num (MSG_U(F_MAXTIME,"Maximum connect time"),maxtime); int field_ourip = dia.getnb(); FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_OURIP,"Local IP number") ,ourip); comb->addopt ("",MSG_U(O_ASSIGNETH0,"Use eth0 as the default local IP")); comb->addopt ("none",MSG_U(O_NODEFAULT,"No default, let remote side decides")); dia.newf_chk ("",proxyarp,MSG_U(F_PROXYARP ,"Proxy Arp (fake remote on local net)")); int field_dns1 = dia.getnb(); dia.newf_str (MSG_U(F_DNS1,"Primary dns"),dns1); dia.newf_str (MSG_U(F_DNS2,"Secondary dns"),dns2); dia.newf_str (MSG_U(F_OPTIONS,"other pppd options"),options); dia.newf_str (MSG_U(F_POSTCONCMD,"Post connnect command"),postconcmd); dia.newf_str (MSG_U(F_POSTDISCONCMD,"Post disconnect command") ,postdisconcmd); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_DEFDIALIN ,"Default PPP dialin parameters") ,MSG_U(I_DEFDIALIN ,"You control here the default PPP option.\n" "Those options apply to all PPP accounts\n" "unless overriden.") ,help_dialin ,nof); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (!pppdialin_validip(ourip)){ nof = field_ourip; }else if (!pppdialin_validip(dns1)){ nof = field_dns1; }else if (!pppdialin_validip(dns2)){ nof = field_dns1+1; }else{ pppdialin_savedefif (conf,K_PPP233,ppp233); pppdialin_savedefif (conf,K_PROXYARP,proxyarp); pppdialin_savedefif (conf,K_ALLOCFROMTTY,alloc_from_tty); pppdialin_savedefif (conf,K_IDLETIME,idletime); pppdialin_savedefif (conf,K_MAXTIME,maxtime); pppdialin_savedefif (conf,K_OURIP,ourip); pppdialin_savedefif (conf,K_DNS1,dns1); pppdialin_savedefif (conf,K_DNS2,dns2); pppdialin_savedefif (conf,K_OPTIONS,options); pppdialin_savedefif (conf,K_POSTCONCMD,postconcmd); pppdialin_savedefif (conf,K_POSTDISCONCMD,postdisconcmd); conf.save(NULL); ipupupd_check(); break; } } } PUBLIC int MODULE_pppdialin::domenu ( MENU_CONTEXT context, const char *key) { if (context == MENU_USER_POLICIES){ if (key == defmenu){ pppdialin_editdefaults(); } } return 0; } PUBLIC int MODULE_pppdialin::dohtml (const char *key) { int ret = LNCF_NOT_APPLICABLE; if (strcmp(key,"pppdialin")==0){ ret = 0; } return ret; } static void usage() { xconf_error (MSG_U(T_USAGE ,"Module pppdialin\n" "linuxconf --modulemain pppdialin [ specific options ]\n" "\n" " --disconnect ppp-user-account\n" "\n") ); } PUBLIC int MODULE_pppdialin::execmain (int argc , char *argv[], bool) { int ret = LNCF_NOT_APPLICABLE; const char *pt = strrchr(argv[0],'/'); if (pt != NULL){ pt++; }else{ pt = argv[0]; } if (strcmp(pt,"pppdialin")==0){ ret = -1; if (argc == 1){ ::usage(); }else if (argc == 3 && strcmp(argv[1],"--disconnect")==0){ if (netconf_rootaccess()){ ret = ipupupd_disconnect (argv[2]); } }else{ // ### Add some option parsing for the module ::usage(); } } return ret; } static MODULE_pppdialin pppdialin; class PPPACCT_COMNG: public USERACCT_COMNG{ SSTRING copyaccount; // Use defaults from this account char alloc_from_tty; char proxyarp; char firewall; SSTRING dns1,dns2; SSTRING remoteip; SSTRING ourip; SSTRING options; int idletime; int maxtime; SSTRING postconcmd; SSTRING postdisconcmd; SSTRINGS networks; SSTRINGS netmasks; SSTRING delivermail; // Trigger mail delivery to this domain struct { char enable; int netnum; int localnum; int remotenum; char routingrip; char routingnlsp; SSTRING options; }ipx; int first_field; // Start of the section in the dialog // to position the cursor in case of errors int first_network; // First field of the routing section int first_ipx; // First field of the IPX section bool is_new; // This is a new account, does not exist // yet (and may never exist) /*~PROTOBEG~ PPPACCT_COMNG */ public: PPPACCT_COMNG (DICTIONARY&_dict); int deluser (PRIVILEGE *priv); int save (PRIVILEGE *priv); private: void saveif (CONFDB&conf, const char *key, SSTRING val); void saveif (CONFDB&conf, const char *key, int val); public: void setupdia (DIALOG&dia); int validate (DIALOG&, int &nof); /*~PROTOEND~ PPPACCT_COMNG */ }; PUBLIC PPPACCT_COMNG::PPPACCT_COMNG(DICTIONARY &_dict) : USERACCT_COMNG (_dict) { this->is_new = dict.get_bool ("is_new"); alloc_from_tty = 0; proxyarp = 0; firewall = 0; idletime = 0; maxtime = 0; ipx.enable = 0; ipx.routingrip = 0; ipx.routingnlsp = 0; ipx.netnum = 0; ipx.localnum = 0; ipx.remotenum = 0; if (!is_new){ const char *ptname = dict.get_str ("name"); CONFDB conf (f_pppdialin); alloc_from_tty = conf.getvalnum (ptname,K_ALLOCFROMTTY,0); proxyarp = conf.getvalnum (ptname,K_PROXYARP,0); firewall = conf.getvalnum (ptname,K_FIREWALL,0); idletime = conf.getvalnum (ptname,K_IDLETIME,0); maxtime = conf.getvalnum (ptname,K_MAXTIME,0); copyaccount.setfrom (conf.getval(ptname,K_COPYACCOUNT)); dns1.setfrom (conf.getval(ptname,K_DNS1)); dns2.setfrom (conf.getval(ptname,K_DNS2)); remoteip.setfrom (conf.getval(ptname,K_REMOTEIP)); ourip.setfrom (conf.getval(ptname,K_OURIP)); options.setfrom (conf.getval(ptname,K_OPTIONS)); postconcmd.setfrom (conf.getval(ptname,K_POSTCONCMD)); postdisconcmd.setfrom (conf.getval(ptname,K_POSTDISCONCMD)); delivermail.setfrom (conf.getval(ptname,K_DELIVERMAIL)); ipx.enable = conf.getvalnum (ptname,K_IPXENABLE,0); ipx.routingrip = conf.getvalnum (ptname,K_IPXROUTINGRIP,0); ipx.routingnlsp = conf.getvalnum (ptname,K_IPXROUTINGNLSP,0); ipx.netnum = conf.getvalnum (ptname,K_IPXNETNUM,0); ipx.localnum = conf.getvalnum (ptname,K_IPXLOCALNUM,0); ipx.remotenum = conf.getvalnum (ptname,K_IPXREMOTENUM,0); ipx.options.setfrom (conf.getval(ptname,K_IPXOPTIONS)); SSTRINGS tb; conf.getall (ptname,K_ROUTE,tb,1); for (int i=0; iget(); SSTRING *net = new SSTRING; SSTRING *msk = new SSTRING; rt = net->copyword (rt); msk->copyword (rt); networks.add (net); netmasks.add (msk); } } } PUBLIC void PPPACCT_COMNG::setupdia ( DIALOG &dia) { dia.newf_title (MSG_U(T_PPPPARMS,"PPP parms"),1 ,"",MSG_R(T_PPPPARMS)); first_field = dia.getnb(); dia.newf_str (MSG_U(F_COPYACCT,"Copy from account"),copyaccount); dia.newf_chk ("",alloc_from_tty,MSG_R(F_ALLOCFROMTTY)); dia.newf_str (MSG_U(F_REMOTEIP,"Remote IP number"),remoteip); FIELD_COMBO *comb = dia.newf_combo (MSG_R(F_OURIP),ourip); comb->addopt ("",MSG_U(O_USEDEFAULT,"Use global default")); comb->addopt ("none",MSG_R(O_NODEFAULT)); dia.newf_str (MSG_R(F_DNS1),dns1); dia.newf_str (MSG_R(F_DNS2),dns2); dia.newf_num (MSG_R(F_IDLETIME),idletime); dia.newf_num (MSG_R(F_MAXTIME),maxtime); dia.newf_str (MSG_R(F_OPTIONS),options); dia.newf_str (MSG_R(F_POSTCONCMD),postconcmd); dia.newf_str (MSG_R(F_POSTDISCONCMD),postdisconcmd); dia.newf_str (MSG_U(F_DELIVERMAIL,"Deliver to this domain"),delivermail); dia.newf_title (MSG_U(T_ROUTING,"Routing"),1,"",MSG_R(T_ROUTING)); dia.newf_chk ("",proxyarp,MSG_R(F_PROXYARP)); dia.newf_chk (MSG_U(F_FIREWALL,"Update"),firewall ,MSG_U(I_FIREWALL,"the firewall rules")); first_network = dia.getnb(); int nb_empty = 0; for (int i=0; iis_empty()) nb_empty++; } for (int e=nb_empty; e<2; e++){ networks.add (new SSTRING); netmasks.add (new SSTRING); } for (int j=0; jget(); if (s[0] != '\0'){ char buf[100]; snprintf (buf,100-1,"%s %s" ,s ,netmasks.getitem(i)->get()); conf.add (ptname,K_ROUTE,buf); } } return conf.save(priv); } PUBLIC int PPPACCT_COMNG::validate( DIALOG &, int &nof) { int ret = 0; if (alloc_from_tty && !remoteip.is_empty()){ xconf_error (MSG_U(E_IPFROMTTYORNOT ,"The IP number can't be allocated from the tty\n" "and assigned manually")); nof = first_field + 1; ret = -1; }else if (!pppdialin_validip(remoteip)){ nof = first_field + 2; ret = -1; }else if (!pppdialin_validip(ourip)){ nof = first_field + 3; ret = -1; }else if (!pppdialin_validip(dns1)){ nof = first_field + 4; ret = -1; }else if (!pppdialin_validip(dns2)){ nof = first_field + 5; ret = -1; }else{ for (int i=0; iget(); if (s[0] != '\0'){ if (!ipnum_validip (s,0)){ xconf_error (MSG_R(E_IVLDIP)); nof = first_network + i * 2; ret = -1; break; }else if (!ipnum_validip (netmasks.getitem(i)->get(),0)){ xconf_error (MSG_U(E_IVLDMSK,"Invalid netmask")); nof = first_network + i * 2 + 1; ret = -1; break; } } } } return ret; } PUBLIC int PPPACCT_COMNG::deluser (PRIVILEGE *priv) { CONFDB conf (f_pppdialin); const char *ptname = dict.get_str("name"); conf.removeall (ptname,K_ALLOCFROMTTY); conf.removeall (ptname,K_IDLETIME); conf.removeall (ptname,K_MAXTIME); conf.removeall (ptname,K_COPYACCOUNT); conf.removeall (ptname,K_DNS1); conf.removeall (ptname,K_DNS2); conf.removeall (ptname,K_REMOTEIP); conf.removeall (ptname,K_OPTIONS); conf.removeall (ptname,K_POSTCONCMD); conf.removeall (ptname,K_POSTDISCONCMD); conf.removeall (ptname,K_ROUTE); return conf.save(priv); } static USERACCT_COMNG *pppdialin_newcomng( const char *key, DICTIONARY &dict) { USERACCT_COMNG *ret = NULL; if (strcmp(key,"user")==0){ const char *domain = dict.get_str("domain"); if (strcmp(domain,"/")==0 && dict.get_int ("categ")==TUSER_PPP){ ret = new PPPACCT_COMNG (dict); } } return ret; } static REGISTER_USERACCT_COMNG ppp (pppdialin_newcomng);