#include #include #include #include #include #include #include #include #include "dialout.h" #include "dialout.m" #include "pppdial.h" #include #include #include "daemoni.h" static CONFIG_FILE f_dynaddr (PROC_SYS_NET_IPV4_DYNADDR ,help_nil,CONFIGF_PROBED|CONFIGF_OPTIONAL); /* Format the path of the PID file allocated to the diald managing this link. */ PUBLIC void PPPONE::setdialdpidpath(char *pidpath) { sprintf (pidpath,"%s-%s.pid",VAR_RUN_PPPD_DIALD,name.get()); } /* Format the path of the configuration file allocated to the diald managing this link. */ PUBLIC void PPPONE::setdialdconfpath(char *diapath) { sprintf (diapath,"%s-%s.conf",VAR_RUN_PPPD_DIALD,name.get()); } /* Format the path of the FIFO used to control this diald session. */ PUBLIC void PPPONE::setfifopath(char *diapath) { sprintf (diapath,"%s-%s.fifo",VAR_RUN_PPPD_DIALD,name.get()); } static void diald_append (SSTRING &setup, const char *ctl, ...) { va_list list; va_start (list,ctl); char buf[500]; vsprintf (buf,ctl,list); setup.append (buf); va_end (list); } /* Check that the ip_dynaddr processing is in place See /usr/src/linux/Documentation/networking/ip_dynaddr.txt */ static void diald_checkdynaddr() { FILE_CFG *fin = f_dynaddr.fopen("r"); if (fin != NULL){ int val; int ret = fscanf(fin,"%d\n",&val); fclose (fin); if (ret==1){ if (val < 1){ net_prtlog (NETLOG_CMD,MSG_U(I_SETDYNADDR,"Setting %s to 1\n") ,f_dynaddr.getpath()); if (!simul_ison()){ FILE_CFG *fout = f_dynaddr.fopen ("w"); if (fout != NULL){ fputs ("1\n",fout); fclose (fout); } } } } } } /* generate the configuration in a SSTRING for diald */ PRIVATE void PPPONE::setupdiald( int id, SSTRING &setup) { setup.append ("mode ppp\n"); setup.append ("include /usr/lib/diald/standard.filter\n"); diald_append (setup,"speed %d\n",baud); #if 0 // Which version of diald supports this feature ? if (!prediscmd.is_empty()){ diald_append (setup,"ip-going-down \"%s\"\n",prediscmd.get()); } #endif char fifopath[PATH_MAX]; setfifopath(fifopath); diald_append (setup,"fifo %s\n",fifopath); if (modem) setup.append ("modem\ncrtscts\n"); if (lock) setup.append ("lock\n"); if (defaultroute) setup.append ("defaultroute\n"); SSTRING pppdopt; if (!asyncmap.is_empty()){ diald_append (pppdopt,"asyncmap %s ",asyncmap.get()); } if (mtu != 0) diald_append (setup,"mtu %d\n",mtu); if (mru != 0) diald_append (setup,"mru %d\n",mru); diald_append (setup,"device %s\n",device.get()); diald_append (pppdopt,"ipparam \"linuxconf_dialout %s\" ",name.get()); char pathchat_sh[PATH_MAX]; setpppchat(pathchat_sh); char papopt[PATH_MAX]; setpapchap(papopt,NULL); if (papopt[0] != '\0') diald_append (pppdopt,"%s ",papopt); diald_append (setup,"connect %s\n",pathchat_sh); if (remoteip.is_empty()){ diald_append (setup,"remote 127.0.0.%d\n",id*2+10); }else{ diald_append (setup,"remote %s\n",remoteip.get()); } if (ourip.is_empty()){ diald_append (setup,"local 127.0.0.%d\n",id*2+11); setup.append ("dynamic\n"); setup.append ("buffer-packets off\n"); }else{ diald_append (setup,"local %s\n",ourip.get()); } char pidpath[PATH_MAX]; setdialdpidpath(pidpath); diald_append (setup,"pidfile %s-%s.pid\n",PPPD_DIALD,name.get()); if (iproutes.getnb() > 0){ diald_append (setup,"# Special routes which will be installed\n"); diald_append (setup,"addroute \"/bin/netconf --setupdiald %s\"\n" ,name.get()); // We generate comments in the config file because the content // of this (future) file is compared blindly with the current one // to know if we will restart diald for (int i=0; idest.get() ,ip->mask.get()); } } diald_append (pppdopt,"%s ",options.get()); diald_append (setup,"pppd-options %s\n",pppdopt.get()); } /* generate the configuration file for diald The configuration is generate (updated on disk) only if different from what is currrently there, so diald won't be restart uselessly. Return -1 if any error, 0 otherwise. */ PUBLIC int PPPONE::setupdiald(int id) // To build a local IP number { int ret = 0; char diapath[PATH_MAX]; setdialdconfpath(diapath); CONFIG_FILE cfile (diapath,help_nil,CONFIGF_OPTIONAL|CONFIGF_MANAGED ,"root","root",0600); SSTRING cur_setup; { FILE_CFG *fin = cfile.fopen ("r"); if (fin != NULL){ char buf[300]; while (fgets(buf,sizeof(buf)-1,fin)!=NULL) cur_setup.append(buf); fclose (fin); } } SSTRING new_setup; setupdiald (id,new_setup); if (new_setup.cmp(cur_setup)!=0){ net_prtlog (NETLOG_VERB,MSG_U(I_GENFILE,"Generating config file %s\n") ,diapath); FILE_CFG *fout = cfile.fopen ("w"); if (fout == NULL){ ret = -1; }else{ fputs (new_setup.get(),fout); ret = fclose (fout); } } return ret; } /* Locate the diald process for this dialup configuration. Return NULL if not found. */ PUBLIC PROC *PPPONE::getdialdproc() { PROC *ret = NULL; char pidpath[PATH_MAX]; setdialdpidpath(pidpath); CONFIG_FILE cfile (pidpath,help_nil ,CONFIGF_OPTIONAL|CONFIGF_MANAGED ,"root","root",0600); if (cfile.exist ()){ ret = process_find ("diald",&cfile); } return ret; } /* Erase generated diald configuration files */ PUBLIC void PPPONE::dialdcleanup() { char path[PATH_MAX]; setdialdpidpath(path); unlink (path); setdialdconfpath(path); unlink (path); } /* Kill the diald process associated with this configuration */ PUBLIC int PPPONE::killdiald() { int ret = 0; PROC *proc = getdialdproc(); if (proc != NULL){ net_prtlog (NETLOG_CMD,MSG_U(X_KILLDIALD ,"Killing on demand IP for config %s\n") ,name.get()); ret = proc->kill(SIGTERM); } return ret; } PUBLIC int PPPONE::startdiald (int id) { int ret = -1; if (setupdiald(id)!=-1){ char diapath[PATH_MAX]; setdialdconfpath (diapath); long date = file_date (diapath); PROC *proc = getdialdproc(); ret = 0; if (proc != NULL && proc->getstarttime() < date){ killdiald(); proc = NULL; } if (proc == NULL){ char arg[500]; sprintf (arg,"-f %s",diapath); ret = netconf_system_if ("diald",arg); } } return ret; } PUBLIC int PPPONE::connect_diald() { int ret = -1; if (perm_rootaccess(MSG_R(P_ACTLINK))){ char fifo[PATH_MAX]; setfifopath(fifo); int fd = open (fifo,O_WRONLY|O_NDELAY); if (fd != -1){ write (fd,"up\n",3); ret = close(fd); // The pppwait_cmd expect to execute something. // This is a hack. Let it do something // We know if diald succeed because /etc/ppp/ip-up will tell // us (linuxconf is hooked there), but we don't know if it // failed if (ret == 0) ret = pppwait_cmd ("sleep 200; exit 1"); } } return ret; } PUBLIC int PPPONE::disconnect_diald() { int ret = -1; if (perm_rootaccess(MSG_R(P_ACTLINK))){ char fifo[PATH_MAX]; setfifopath(fifo); int fd = open (fifo,O_WRONLY|O_NDELAY); if (fd != -1){ write (fd,"down\n",5); ret = close(fd); } } return ret; } /* */ int diald_setroutes ( const char *config, // Configuration const char *iface, // Target interface const char *, // Remote IP of the interface int metric) { int ret = -1; if (getuid()!=0){ fprintf (stderr,MSG_U(E_DIALDCONUID,"netconf --setupdiald can only be used by root (by diald)\n")); }else{ PPPONE *one = ppp_getconfig (config); if (one != NULL){ net_introlog (NETINTRO_PPPDIALD); net_prtlog (NETLOG_SECTION ,MSG_U(M_SETDIALDRT,"Setting routes for PPP on demand dialout %s\n") ,config); char suffix[200]; #if 0 sprintf (suffix,"gw %s metric %d" //,metric ? "0.0.0.0" : targetip ,targetip ,metric); #else sprintf (suffix,"metric %d dev %s",metric,iface); #endif ret = one->setroutes (suffix); delete one; } } return ret; } /* Start/stop the different diald process and the 24/24 links */ void ppp_start () { SSTRINGS lst; int nb = ppp_getlist(lst); int nbdefroute = 0; bool dynaddr_done = false; for (int i=0; iget()); const char *name = one.name.get(); bool mustkill = false; bool muststart = false; if (one.type == TYPE_PPP_SERIAL && one.getusetype() == PPP_USE_DEMAND){ pppcon_check_ipup(); if (one.ourip.is_empty() && !dynaddr_done){ diald_checkdynaddr(); dynaddr_done = true; } if (one.defaultroute){ nbdefroute++; if (nbdefroute > 1){ xconf_error (MSG_U(E_TWODEFROUTE ,"Can't have two dialup configuration with default route\n" "at the same time. Deactivating dialup config %s\n") ,name); net_prtlog (NETLOG_ERR ,MSG_U(E_TWODEFAULT ,"Can't activate on demand dialup for %s: " "duplicate default route\n") ,name); mustkill = true; }else{ muststart = true; } }else{ muststart = true; } }else{ mustkill = true; } if (mustkill){ one.killdiald(); if (!simul_ison()) one.dialdcleanup(); }else if (muststart){ one.startdiald(i); } if (one.getusetype() == PPP_USE_24on24){ if (one.getpppd_pid() == -1){ one.connect(false); } } } } /* Unlink all the diald related files at boot time */ void diald_bootcleanup() { net_prtlog (NETLOG_VERB ,MSG_U(X_DIALDCLEAN,"Cleaning on demand IP (diald) work files\n")); SSTRINGS lst; int nb = ppp_getlist(lst); for (int i=0; iget()); one.dialdcleanup(); } }