+ }
+
+ if (!ok)
+ {
+ driver_version =
+ driver_modification =
+ driver_patch = 0;
+ }
+/*
+ * Validate the version of the driver against the version that we used.
+ */
+ decode_version (VERSION,
+ &my_version,
+ &my_modification,
+ &my_patch);
+
+ /* The version numbers must match */
+ if (driver_version != my_version)
+ {
+ ok = 0;
+ }
+
+ /* The modification levels must be legal */
+ if (driver_modification < my_modification)
+ {
+ if (driver_modification >= 2) {
+ /* we can cope with 2.2.0 and above */
+ driver_is_old = 1;
+ } else {
+ ok = 0;
+ }
+ }
+
+ close (s);
+ if (!ok)
+ {
+ sprintf (route_buffer,
+ "Sorry - PPP driver version %d.%d.%d is out of date\n",
+ driver_version, driver_modification, driver_patch);
+
+ no_ppp_msg = route_buffer;
+ }
+ }
+ return ok;
+ }
+
+/********************************************************************
+ *
+ * Update the wtmp file with the appropriate user name and tty device.
+ */
+
+void logwtmp (const char *line, const char *name, const char *host)
+ {
+ int wtmp;
+ struct utmp ut, *utp;
+ pid_t mypid = getpid();
+/*
+ * Update the signon database for users.
+ * Christoph Lameter: Copied from poeigl-1.36 Jan 3, 1996
+ */
+ utmpname(_PATH_UTMP);
+ setutent();
+ while ((utp = getutent()) && (utp->ut_pid != mypid))
+ /* nothing */;
+
+ /* Is this call really necessary? There is another one after the 'put' */
+ endutent();
+
+ if (utp)
+ {
+ memcpy(&ut, utp, sizeof(ut));
+ }
+ else
+ {
+ /* some gettys/telnetds don't initialize utmp... */
+ memset(&ut, 0, sizeof(ut));
+ }
+
+ if (ut.ut_id[0] == 0)
+ {
+ strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
+ }
+
+ strncpy(ut.ut_user, name, sizeof(ut.ut_user));
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+
+ time(&ut.ut_time);
+
+ ut.ut_type = USER_PROCESS;
+ ut.ut_pid = mypid;
+
+ /* Insert the host name if one is supplied */
+ if (*host)
+ {
+ strncpy (ut.ut_host, host, sizeof(ut.ut_host));
+ }
+
+ /* Insert the IP address of the remote system if IP is enabled */
+ if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
+ {
+ memcpy (&ut.ut_addr, (char *) &ipcp_hisoptions[0].hisaddr,
+ sizeof(ut.ut_addr));
+ }
+
+ /* CL: Makes sure that the logout works */
+ if (*host == 0 && *name==0)
+ {
+ ut.ut_host[0]=0;
+ }
+
+ pututline(&ut);
+ endutent();
+/*
+ * Update the wtmp file.
+ */
+ wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY);
+ if (wtmp >= 0)
+ {
+ flock(wtmp, LOCK_EX);
+
+ /* we really should check for error on the write for a full disk! */
+ write (wtmp, (char *)&ut, sizeof(ut));
+ close (wtmp);
+
+ flock(wtmp, LOCK_UN);
+ }
+ }
+
+/********************************************************************
+ * Code for locking/unlocking the serial device.
+ * This code is derived from chat.c.
+ */
+
+/*
+ * lock - create a lock file for the named device
+ */
+
+int lock (char *dev)
+ {
+#ifdef LOCKLIB
+ int result;
+ lock_file = malloc(strlen(dev) + 1);
+ if (lock_file == NULL)
+ {
+ novm("lock file name");
+ }
+ strcpy (lock_file, dev);
+ result = mklock (dev, (void *) 0);
+
+ if (result > 0)
+ {
+ syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, result);
+ free (lock_file);
+ lock_file = NULL;
+ result = -1;
+ }
+ else
+ {
+ if (result < 0)
+ {
+ syslog (LOG_ERR, "Can't create lock file %s", lock_file);
+ free (lock_file);
+ lock_file = NULL;
+ result = -1;
+ }
+ }
+ return (result);
+#else
+ char hdb_lock_buffer[12];
+ int fd, n;
+ int pid = getpid();
+ char *p;
+
+ p = strrchr(dev, '/');
+ if (p != NULL)
+ {
+ dev = ++p;
+ }
+
+ lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
+ if (lock_file == NULL)
+ {
+ novm("lock file name");
+ }
+
+ strcpy (lock_file, LOCK_PREFIX);
+ strcat (lock_file, dev);
+/*
+ * Attempt to create the lock file at this point.
+ */
+ while (1)
+ {
+ fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644);
+ if (fd >= 0)
+ {
+ pid = getpid();
+#ifndef PID_BINARY
+ sprintf (hdb_lock_buffer, "%010d\n", pid);
+ write (fd, hdb_lock_buffer, 11);
+#else
+ write(fd, &pid, sizeof (pid));
+#endif
+ close(fd);
+ return 0;
+ }
+/*
+ * If the file exists then check to see if the pid is stale
+ */
+ if (errno == EEXIST)
+ {
+ fd = open(lock_file, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ if (errno == ENOENT) /* This is just a timing problem. */
+ {
+ continue;
+ }
+ break;
+ }
+
+ /* Read the lock file to find out who has the device locked */
+ n = read (fd, hdb_lock_buffer, 11);
+ close (fd);
+ if (n < 0)
+ {
+ syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
+ break;
+ }
+
+ /* See the process still exists. */
+ if (n > 0)
+ {
+#ifndef PID_BINARY
+ hdb_lock_buffer[n] = '\0';
+ sscanf (hdb_lock_buffer, " %d", &pid);
+#else
+ pid = ((int *) hdb_lock_buffer)[0];
+#endif
+ if (pid == 0 || pid == getpid()
+ || (kill(pid, 0) == -1 && errno == ESRCH))
+ {
+ n = 0;
+ }
+ }
+
+ /* If the process does not exist then try to remove the lock */
+ if (n == 0 && unlink (lock_file) == 0)
+ {
+ syslog (LOG_NOTICE, "Removed stale lock on %s (pid %d)",
+ dev, pid);
+ continue;
+ }
+
+ syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, pid);
+ break;
+ }
+
+ syslog(LOG_ERR, "Can't create lock file %s: %m(%d)", lock_file, errno);
+ break;
+ }
+
+ free(lock_file);
+ lock_file = NULL;
+ return -1;
+#endif
+}
+
+
+/********************************************************************
+ *
+ * unlock - remove our lockfile
+ */
+
+void unlock(void)
+ {
+ if (lock_file)
+ {
+#ifdef LOCKLIB
+ (void) rmlock (lock_file, (void *) 0);
+#else
+ unlink(lock_file);
+#endif
+ free(lock_file);
+ lock_file = NULL;
+ }
+ }
+
+/********************************************************************
+ *
+ * sifvjcomp - config tcp header compression
+ */
+
+int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
+ {
+ u_int x = get_flags();
+
+ if (vjcomp)
+ {
+ if (ioctl (ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
+ {
+ if (! ok_error (errno))
+ {
+ syslog (LOG_ERR, "ioctl(PPPIOCSMAXCID): %m(%d)", errno);
+ }
+ vjcomp = 0;
+ }
+ }
+
+ x = vjcomp ? x | SC_COMP_TCP : x &~ SC_COMP_TCP;
+ x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
+ set_flags (x);
+
+ return 1;
+ }
+
+/********************************************************************
+ *
+ * sifup - Config the interface up and enable IP packets to pass.
+ */
+
+int sifup (int u)
+ {
+ struct ifreq ifr;
+
+ memset (&ifr, '\0', sizeof (ifr));
+ strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+ if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
+ {
+ if (! ok_error (errno))
+ {
+ syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m(%d)", errno);
+ }
+ return 0;
+ }
+
+ ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
+ if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
+ {
+ if (! ok_error (errno))
+ {
+ syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m(%d)", errno);
+ }
+ return 0;
+ }
+ if_is_up = 1;
+ return 1;
+ }
+
+/********************************************************************
+ *
+ * sifdown - Config the interface down and disable IP.
+ */
+
+int sifdown (int u)
+ {
+ struct ifreq ifr;
+
+ if_is_up = 0;
+
+ memset (&ifr, '\0', sizeof (ifr));
+ strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+ if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
+ {
+ if (! ok_error (errno))
+ {
+ syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m(%d)", errno);
+ }
+ return 0;
+ }
+
+ ifr.ifr_flags &= ~IFF_UP;
+ ifr.ifr_flags |= IFF_POINTOPOINT;
+ if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
+ {
+ if (! ok_error (errno))
+ {
+ syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m(%d)", errno);
+ }
+ return 0;
+ }
+ return 1;
+ }
+
+/********************************************************************
+ *
+ * sifaddr - Config the interface IP addresses and netmask.
+ */
+
+int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
+ u_int32_t net_mask)
+ {
+ struct ifreq ifr;
+ struct rtentry rt;
+
+ memset (&ifr, '\0', sizeof (ifr));
+ memset (&rt, '\0', sizeof (rt));
+
+ SET_SA_FAMILY (ifr.ifr_addr, AF_INET);
+ SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
+ SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
+
+ strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+/*
+ * Set our IP address
+ */
+ ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
+ if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
+ {
+ if (errno != EEXIST)
+ {
+ if (! ok_error (errno))
+ {
+ syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m(%d)", errno);
+ }
+ }
+ else
+ {
+ syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
+ }
+ return (0);
+ }
+/*
+ * Set the gateway address
+ */
+ ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
+ if (ioctl(sock_fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0)
+ {
+ if (! ok_error (errno))
+ {
+ syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m(%d)", errno);
+ }
+ return (0);
+ }
+/*
+ * Set the netmask.
+ * For recent kernels, force the netmask to 255.255.255.255.
+ */
+ if (strcmp(utsname.release, "2.1.16") >= 0)
+ net_mask = ~0L;
+ if (net_mask != 0)
+ {
+ ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
+ if (ioctl(sock_fd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0)
+ {
+ if (! ok_error (errno))
+ {
+ syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m(%d)", errno);
+ }
+ return (0);
+ }
+ }
+/*
+ * Add the device route
+ */
+ if (strcmp(utsname.release, "2.1.16") < 0) {
+ SET_SA_FAMILY (rt.rt_dst, AF_INET);
+ SET_SA_FAMILY (rt.rt_gateway, AF_INET);
+ rt.rt_dev = ifname;
+
+ ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0L;
+ ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr;
+ rt.rt_flags = RTF_UP | RTF_HOST;
+
+ if (strcmp(utsname.release, "2.1.0") > 0) {
+ SET_SA_FAMILY (rt.rt_genmask, AF_INET);
+ ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L;
+ }
+
+ if (ioctl(sock_fd, SIOCADDRT, &rt) < 0)
+ {
+ if (! ok_error (errno))
+ {
+ syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m(%d)", errno);
+ }
+ return (0);