2 * sys-linux.c - System-dependent procedures for setting up
3 * PPP interfaces on Linux systems
5 * Copyright (c) 1989 Carnegie Mellon University.
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by Carnegie Mellon University. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25 #include <sys/ioctl.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
29 #include <sys/errno.h>
43 #include <net/ppp_defs.h>
44 #include <net/if_arp.h>
45 #include <net/if_ppp.h>
46 #include <net/route.h>
47 #include <linux/if_ether.h>
48 #include <netinet/in.h>
54 static int initdisc = -1; /* Initial TTY discipline */
55 static int prev_kdebugflag = 0;
57 static int restore_term; /* 1 => we've munged the terminal */
58 static struct termios inittermios; /* Initial TTY termios */
60 int sockfd; /* socket for doing interface ioctls */
62 static int driver_version = 0;
63 static int driver_modification = 0;
64 static int driver_patch = 0;
66 static char *lock_file;
70 #define FLAGS_GOOD (IFF_UP | IFF_BROADCAST)
71 #define FLAGS_MASK (IFF_UP | IFF_BROADCAST | \
72 IFF_POINTOPOINT | IFF_LOOPBACK | IFF_NOARP)
75 * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
79 #define SET_SA_FAMILY(addr, family) \
80 memset ((char *) &(addr), '\0', sizeof(addr)); \
81 addr.sa_family = (family);
84 * Functions to read and set the flags value in the device driver
91 if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0)
93 syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
97 MAINDEBUG ((LOG_DEBUG, "get flags = %x\n", flags));
101 void set_flags (int flags)
103 MAINDEBUG ((LOG_DEBUG, "set flags = %x\n", flags));
104 if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
106 syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS, %x): %m", flags);
112 * sys_init - System-dependent initialization.
117 openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
118 setlogmask(LOG_UPTO(LOG_INFO));
121 setlogmask(LOG_UPTO(LOG_DEBUG));
124 /* Get an internet socket for doing socket ioctls. */
125 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
128 syslog(LOG_ERR, "Couldn't create IP socket: %m");
134 * note_debug_level - note a change in the debug level.
137 void note_debug_level (void)
141 MAINDEBUG ((LOG_INFO, "Debug turned ON, Level %d", debug));
142 setlogmask(LOG_UPTO(LOG_DEBUG));
146 setlogmask(LOG_UPTO(LOG_WARNING));
151 * set_kdebugflag - Define the debugging level for the kernel
154 int set_kdebugflag (int requested_level)
156 if (ioctl(fd, PPPIOCGDEBUG, &prev_kdebugflag) < 0)
158 syslog(LOG_ERR, "ioctl(PPPIOCGDEBUG): %m");
162 if (prev_kdebugflag != requested_level)
164 if (ioctl(fd, PPPIOCSDEBUG, &requested_level) < 0)
166 syslog (LOG_ERR, "ioctl(PPPIOCSDEBUG): %m");
169 MAINDEBUG ((LOG_INFO, "set kernel debugging level to %d", requested_level));
175 * establish_ppp - Turn the serial port into a ppp interface.
178 void establish_ppp (void)
183 if (ioctl(fd, TIOCEXCL, 0) < 0)
185 syslog (LOG_WARNING, "ioctl(TIOCEXCL): %m");
188 if (ioctl(fd, TIOCGETD, &initdisc) < 0)
190 syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
194 if (ioctl(fd, TIOCSETD, &pppdisc) < 0)
196 syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
200 if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0)
202 syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
206 set_kdebugflag (kdebugflag);
208 set_flags (get_flags() & ~(SC_RCV_B7_0 | SC_RCV_B7_1 |
209 SC_RCV_EVNP | SC_RCV_ODDP));
211 MAINDEBUG ((LOG_NOTICE, "Using version %d.%d.%d of PPP driver",
212 driver_version, driver_modification, driver_patch));
216 * disestablish_ppp - Restore the serial port to normal operation.
217 * This shouldn't call die() because it's called from die().
220 void disestablish_ppp(void)
225 * Check whether the link seems not to be 8-bit clean.
229 if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0)
232 switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP))
234 case SC_RCV_B7_0 | SC_RCV_B7_1 | SC_RCV_EVNP | SC_RCV_ODDP:
235 s = "nothing was received";
239 case SC_RCV_B7_0 | SC_RCV_EVNP:
240 case SC_RCV_B7_0 | SC_RCV_ODDP:
241 case SC_RCV_B7_0 | SC_RCV_ODDP | SC_RCV_EVNP:
242 s = "all had bit 7 set to 1";
246 case SC_RCV_B7_1 | SC_RCV_EVNP:
247 case SC_RCV_B7_1 | SC_RCV_ODDP:
248 case SC_RCV_B7_1 | SC_RCV_ODDP | SC_RCV_EVNP:
249 s = "all had bit 7 set to 0";
253 s = "all had odd parity";
257 s = "all had even parity";
263 syslog(LOG_WARNING, "Receive serial link is not 8-bit clean:");
264 syslog(LOG_WARNING, "Problem: %s", s);
268 set_kdebugflag (prev_kdebugflag);
270 if (ioctl(fd, TIOCSETD, &initdisc) < 0)
272 syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
275 if (ioctl(fd, TIOCNXCL, 0) < 0)
277 syslog (LOG_WARNING, "ioctl(TIOCNXCL): %m");
285 * List of valid speeds.
289 int speed_int, speed_val;
361 * Translate from bits/second to a speed_t.
364 int translate_speed (int bps)
366 struct speed *speedp;
370 for (speedp = speeds; speedp->speed_int; speedp++)
372 if (bps == speedp->speed_int)
374 return speedp->speed_val;
377 syslog(LOG_WARNING, "speed %d not supported", bps);
383 * Translate from a speed_t to bits/second.
386 int baud_rate_of (int speed)
388 struct speed *speedp;
392 for (speedp = speeds; speedp->speed_int; speedp++)
394 if (speed == speedp->speed_val)
396 return speedp->speed_int;
404 * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
405 * at the requested speed, etc. If `local' is true, set CLOCAL
406 * regardless of whether the modem option was specified.
409 void set_up_tty (int fd, int local)
414 if (tcgetattr(fd, &tios) < 0)
416 syslog(LOG_ERR, "tcgetattr: %m");
425 tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
426 tios.c_cflag |= CS8 | CREAD | HUPCL;
428 tios.c_iflag = IGNBRK | IGNPAR;
432 tios.c_cc[VTIME] = 0;
436 tios.c_cflag ^= (CLOCAL | HUPCL);
442 tios.c_cflag |= CRTSCTS;
446 tios.c_iflag |= IXOFF;
447 tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
448 tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
452 tios.c_cflag &= ~CRTSCTS;
459 speed = translate_speed(inspeed);
462 cfsetospeed (&tios, speed);
463 cfsetispeed (&tios, speed);
466 * We can't proceed if the serial port speed is B0,
467 * since that implies that the serial port is disabled.
471 speed = cfgetospeed(&tios);
474 syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
480 if (tcsetattr(fd, TCSAFLUSH, &tios) < 0)
482 syslog(LOG_ERR, "tcsetattr: %m");
486 baud_rate = baud_rate_of(speed);
491 * setdtr - control the DTR line on the serial port.
492 * This is called from die(), so it shouldn't call die().
495 void setdtr (int fd, int on)
497 int modembits = TIOCM_DTR;
499 ioctl(fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);
503 * restore_tty - restore the terminal to the saved settings.
506 void restore_tty (void)
512 * Turn off echoing, because otherwise we can get into
513 * a loop with the tty and the modem echoing to each other.
514 * We presume we are the sole user of this tty device, so
515 * when we close it, it will revert to its defaults anyway.
519 inittermios.c_lflag &= ~(ECHO | ECHONL);
522 if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
526 syslog(LOG_WARNING, "tcsetattr: %m");
533 * output - Output PPP packet.
536 void output (int unit, unsigned char *p, int len)
540 MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
545 log_packet(p, len, "sent ");
548 if (write(fd, p, len) < 0)
550 syslog(LOG_ERR, "write: %m");
556 * wait_input - wait until there is data available on fd,
557 * for the length of time specified by *timo (indefinite
561 void wait_input (struct timeval *timo)
569 n = select(fd+1, &ready, NULL, &ready, timo);
570 if (n < 0 && errno != EINTR)
572 syslog(LOG_ERR, "select: %m");
578 * read_packet - get a PPP packet from the serial device.
581 int read_packet (unsigned char *buf)
585 len = read(fd, buf, PPP_MTU + PPP_HDRLEN);
588 if (errno == EWOULDBLOCK)
592 syslog(LOG_ERR, "read(fd): %m");
599 * ppp_send_config - configure the transmit characteristics of
603 void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
608 MAINDEBUG ((LOG_DEBUG, "send_config: mtu = %d\n", mtu));
609 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
612 if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
614 syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
618 MAINDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
619 if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
621 syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
626 x = pcomp ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
627 x = accomp ? x | SC_COMP_AC : x & ~SC_COMP_AC;
632 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
635 void ppp_set_xaccm (int unit, ext_accm accm)
637 MAINDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
638 accm[0], accm[1], accm[2], accm[3]));
640 if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
642 syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
647 * ppp_recv_config - configure the receive-side characteristics of
651 void ppp_recv_config (int unit,int mru,u_int32_t asyncmap,int pcomp,int accomp)
655 MAINDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
656 if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
658 syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
661 MAINDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
662 if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
664 syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
669 x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
674 * ccp_test - ask kernel whether a given compression method
675 * is acceptable for use.
678 int ccp_test (int unit, u_char *opt_ptr, int opt_len, int for_transmit)
680 struct ppp_option_data data;
683 data.length = opt_len;
684 data.transmit = for_transmit;
686 return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0;
690 * ccp_flags_set - inform kernel about the current state of CCP.
693 void ccp_flags_set (int unit, int isopen, int isup)
696 x = isopen? x | SC_CCP_OPEN : x &~ SC_CCP_OPEN;
697 x = isup? x | SC_CCP_UP : x &~ SC_CCP_UP;
702 * ccp_fatal_error - returns 1 if decompression was disabled as a
703 * result of an error detected after decompression of a packet,
704 * 0 otherwise. This is necessary because of patent nonsense.
707 int ccp_fatal_error (int unit)
711 return x & SC_DC_FERROR;
715 * sifvjcomp - config tcp header compression
718 int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
720 u_int x = get_flags();
724 if (ioctl (fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0)
726 syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
731 x = vjcomp ? x | SC_COMP_TCP : x &~ SC_COMP_TCP;
732 x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
739 * sifup - Config the interface up and enable IP packets to pass.
746 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
747 if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
749 syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
753 ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
754 if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
756 syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
763 * sifdown - Config the interface down and disable IP.
770 strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
771 if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
773 syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
777 ifr.ifr_flags &= ~IFF_UP;
778 ifr.ifr_flags |= IFF_POINTOPOINT;
779 if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0)
781 syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
788 * sifaddr - Config the interface IP addresses and netmask.
791 int sifaddr (int unit, int our_adr, int his_adr, int net_mask)
796 SET_SA_FAMILY (ifr.ifr_addr, AF_INET);
797 SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
798 SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
800 strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
804 ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
805 if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
809 syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m");
813 syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
818 * Set the gateway address
820 ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
821 if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0)
823 syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
831 ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
832 if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0)
834 syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
839 * Add the device route
841 memset (&rt, '\0', sizeof (rt));
843 SET_SA_FAMILY (rt.rt_dst, AF_INET);
844 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
845 rt.rt_dev = ifname; /* MJC */
847 ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
848 ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr;
849 rt.rt_flags = RTF_UP | RTF_HOST;
851 if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
853 syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m");
860 * cifaddr - Clear the interface IP addresses, and delete routes
861 * through the interface if possible.
864 int cifaddr (int unit, int our_adr, int his_adr)
868 * Delete the route through the device
870 memset (&rt, '\0', sizeof (rt));
872 SET_SA_FAMILY (rt.rt_dst, AF_INET);
873 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
874 rt.rt_dev = ifname; /* MJC */
876 ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
877 ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr;
878 rt.rt_flags = RTF_UP | RTF_HOST;
880 if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
882 syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m");
889 * path_to_route - determine the path to the proc file system data
892 FILE *route_fd = (FILE *) 0;
893 static char route_buffer [100];
895 static char *path_to_route (void);
896 static int open_route_table (void);
897 static void close_route_table (void);
898 static int read_route_table (struct rtentry *rt);
899 static int defaultroute_exists (void);
902 * path_to_route - find the path to the route tables in the proc file system
905 static char *path_to_route (void)
907 struct mntent *mntent;
910 fp = fopen (MOUNTED, "r");
913 mntent = getmntent (fp);
914 while (mntent != (struct mntent *) 0)
916 if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) != 0)
918 if (strcmp (mntent->mnt_type, "proc") == 0)
920 strncpy (route_buffer, mntent->mnt_dir,
921 sizeof (route_buffer)-10);
922 route_buffer [sizeof (route_buffer)-10] = '\0';
923 strcat (route_buffer, "/net/route");
926 return (route_buffer);
929 mntent = getmntent (fp);
934 syslog (LOG_ERR, "proc file system not mounted");
939 * open_route_table - open the interface to the route table
942 static int open_route_table (void)
946 if (route_fd != (FILE *) 0)
951 path = path_to_route();
957 route_fd = fopen (path, "r");
958 if (route_fd == (FILE *) 0)
960 syslog (LOG_ERR, "can not open %s: %m", path);
964 /* read and discard the header line. */
965 if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
974 * close_route_table - close the interface to the route table
977 static void close_route_table (void)
979 if (route_fd != (FILE *) 0)
982 route_fd = (FILE *) 0;
987 * read_route_table - read the next entry from the route table
990 static int read_route_table (struct rtentry *rt)
992 static char delims[] = " \t\n";
993 char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
995 if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
1000 memset (rt, '\0', sizeof (struct rtentry));
1002 dev_ptr = strtok (route_buffer, delims); /* interface name */
1003 dst_ptr = strtok (NULL, delims); /* destination address */
1004 gw_ptr = strtok (NULL, delims); /* gateway */
1005 flag_ptr = strtok (NULL, delims); /* flags */
1007 ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
1008 strtoul (dst_ptr, NULL, 16);
1010 ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
1011 strtoul (gw_ptr, NULL, 16);
1013 rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
1014 rt->rt_dev = dev_ptr;
1020 * defaultroute_exists - determine if there is a default route
1023 static int defaultroute_exists (void)
1028 if (!open_route_table())
1033 while (read_route_table(&rt) != 0)
1035 if (rt.rt_flags & RTF_UP == 0)
1040 if (((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr == 0L)
1043 "ppp not replacing existing default route to %s[%s]",
1045 inet_ntoa (((struct sockaddr_in *) &rt.rt_gateway)->
1052 close_route_table();
1057 * sifdefaultroute - assign a default route through the address given.
1060 int sifdefaultroute (int unit, int gateway)
1064 if (defaultroute_exists())
1069 memset (&rt, '\0', sizeof (rt));
1070 SET_SA_FAMILY (rt.rt_dst, AF_INET);
1071 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1072 ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1074 rt.rt_flags = RTF_UP | RTF_GATEWAY;
1075 if (ioctl(sockfd, SIOCADDRT, &rt) < 0)
1077 syslog (LOG_ERR, "default route ioctl(SIOCADDRT): %m");
1084 * cifdefaultroute - delete a default route through the address given.
1087 int cifdefaultroute (int unit, int gateway)
1091 SET_SA_FAMILY (rt.rt_dst, AF_INET);
1092 SET_SA_FAMILY (rt.rt_gateway, AF_INET);
1093 ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
1095 rt.rt_flags = RTF_UP | RTF_GATEWAY;
1096 if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
1098 syslog (LOG_ERR, "default route ioctl(SIOCDELRT): %m");
1105 * sifproxyarp - Make a proxy ARP entry for the peer.
1108 int sifproxyarp (int unit, u_int32_t his_adr)
1110 struct arpreq arpreq;
1112 memset (&arpreq, '\0', sizeof(arpreq));
1114 * Get the hardware address of an interface on the same subnet
1115 * as our local address.
1117 if (!get_ether_addr(his_adr, &arpreq.arp_ha))
1119 syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
1123 SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1124 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1125 arpreq.arp_flags = ATF_PERM | ATF_PUBL;
1127 if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0)
1129 syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
1136 * cifproxyarp - Delete the proxy ARP entry for the peer.
1139 int cifproxyarp (int unit, u_int32_t his_adr)
1141 struct arpreq arpreq;
1143 memset (&arpreq, '\0', sizeof(arpreq));
1144 SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
1146 ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
1147 if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0)
1149 syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
1156 * get_ether_addr - get the hardware address of an interface on the
1157 * the same subnet as ipaddr.
1160 int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr)
1162 struct ifreq *ifr, *ifend, *ifp;
1164 u_int32_t ina, mask;
1165 struct sockaddr_dl *dla;
1168 struct ifreq ifs[MAX_IFS];
1170 ifc.ifc_len = sizeof(ifs);
1172 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
1174 syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
1178 MAINDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s",
1179 ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));
1181 * Scan through looking for an interface with an Internet
1182 * address on the same subnet as `ipaddr'.
1184 ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
1185 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1187 if (ifr->ifr_addr.sa_family == AF_INET)
1189 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1190 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1191 MAINDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
1194 * Check that the interface is up, and not point-to-point
1197 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1202 if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1207 * Get its netmask and check that it's on the right subnet.
1209 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1214 mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
1215 MAINDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx",
1216 ip_ntoa(ina), ntohl(mask)));
1218 if (((ipaddr ^ ina) & mask) != 0)
1231 syslog(LOG_INFO, "found interface %s for proxy arp", ifreq.ifr_name);
1233 * Now get the hardware address.
1235 if (ioctl (sockfd, SIOCGIFHWADDR, &ifreq) < 0)
1237 syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m", ifreq.ifr_name);
1241 hwaddr->sa_family = ARPHRD_ETHER;
1242 memcpy (&hwaddr->sa_data, &ifreq.ifr_hwaddr.sa_data, ETH_ALEN);
1244 MAINDEBUG ((LOG_DEBUG,
1245 "proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x",
1246 (int) ((unsigned char *) &hwaddr->sa_data)[0],
1247 (int) ((unsigned char *) &hwaddr->sa_data)[1],
1248 (int) ((unsigned char *) &hwaddr->sa_data)[2],
1249 (int) ((unsigned char *) &hwaddr->sa_data)[3],
1250 (int) ((unsigned char *) &hwaddr->sa_data)[4],
1251 (int) ((unsigned char *) &hwaddr->sa_data)[5]));
1256 * Return user specified netmask, modified by any mask we might determine
1257 * for address `addr' (in network byte order).
1258 * Here we scan through the system's list of interfaces, looking for
1259 * any non-point-to-point interfaces which might appear to be on the same
1260 * network as `addr'. If we find any, we OR in their netmask to the
1261 * user-specified netmask.
1264 u_int32_t GetMask (u_int32_t addr)
1266 u_int32_t mask, nmask, ina;
1267 struct ifreq *ifr, *ifend, ifreq;
1269 struct ifreq ifs[MAX_IFS];
1273 if (IN_CLASSA(addr)) /* determine network mask for address class */
1275 nmask = IN_CLASSA_NET;
1279 if (IN_CLASSB(addr))
1281 nmask = IN_CLASSB_NET;
1285 nmask = IN_CLASSC_NET;
1289 /* class D nets are disallowed by bad_ip_adrs */
1290 mask = netmask | htonl(nmask);
1292 * Scan through the system's network interfaces.
1294 ifc.ifc_len = sizeof(ifs);
1296 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
1298 syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
1302 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1303 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
1306 * Check the interface's internet address.
1308 if (ifr->ifr_addr.sa_family != AF_INET)
1312 ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
1313 if (((ntohl(ina) ^ addr) & nmask) != 0)
1318 * Check that the interface is up, and not point-to-point or loopback.
1320 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
1321 if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
1326 if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
1331 * Get its netmask and OR it into our mask.
1333 if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
1337 mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
1345 * Internal routine to decode the version.modification.patch level
1348 static void decode_version (char *buf, int *version,
1349 int *modification, int *patch)
1352 *version = (int) strtoul (buf, &buf, 10);
1359 *modification = (int) strtoul (buf, &buf, 10);
1363 *patch = (int) strtoul (buf, &buf, 10);
1376 * Procedure to determine if the PPP line dicipline is registered.
1380 ppp_registered(void)
1383 int ppp_disc = N_PPP;
1387 local_fd = open(devnam, O_NONBLOCK | O_RDWR, 0);
1390 syslog(LOG_ERR, "Failed to open %s: %m", devnam);
1394 initfdflags = fcntl(local_fd, F_GETFL);
1395 if (initfdflags == -1)
1397 syslog(LOG_ERR, "Couldn't get device fd flags: %m");
1402 initfdflags &= ~O_NONBLOCK;
1403 fcntl(local_fd, F_SETFL, initfdflags);
1405 * Read the initial line dicipline and try to put the device into the
1408 if (ioctl(local_fd, TIOCGETD, &init_disc) < 0)
1410 syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
1415 if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0)
1417 syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
1422 if (ioctl(local_fd, TIOCSETD, &init_disc) < 0)
1424 syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
1434 * ppp_available - check whether the system has any ppp interfaces
1435 * (in fact we check whether we can do an ioctl on ppp0).
1438 int ppp_available(void)
1442 int my_version, my_modification, my_patch;
1444 * Open a socket for doing the ioctl operations.
1446 s = socket(AF_INET, SOCK_DGRAM, 0);
1452 strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1453 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1455 * If the device did not exist then attempt to create one by putting the
1456 * current tty into the PPP discipline. If this works then obtain the
1457 * flags for the device again.
1461 if (ppp_registered())
1463 strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1464 ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
1468 * Ensure that the hardware address is for PPP and not something else
1472 ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
1475 if (ok && ifr.ifr_hwaddr.sa_family != ARPHRD_PPP)
1480 * This is the PPP device. Validate the version of the driver at this
1481 * point to ensure that this program will work with the driver.
1485 char abBuffer [1024];
1488 ifr.ifr_data = abBuffer;
1489 size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
1494 decode_version (abBuffer,
1496 &driver_modification,
1504 driver_modification =
1508 * Validate the version of the driver against the version that we used.
1510 decode_version (PPP_VERSION,
1515 /* The version numbers must match */
1516 if (driver_version != my_version)
1521 /* The modification levels must be legal */
1522 if (driver_modification < my_modification)
1529 fprintf(stderr, "Sorry - PPP driver version %d.%d.%d is out of date\n",
1530 driver_version, driver_modification, driver_patch);
1539 int logwtmp (char *line, char *name, char *host)
1544 * Control the 'mesg' function based upon the state of the logon
1547 mode = (*name != '\0') ? 0600 : 0622;
1548 if (chmod (devnam, mode) < 0)
1550 syslog (LOG_ERR, "chmod(\"%s\", 0%o): %m", devnam, mode);
1553 * Update the signon database for users.
1555 memset (&ut, 0, sizeof (ut));
1556 (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
1557 (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
1558 (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
1559 (void)time(&ut.ut_time);
1561 pututline (&ut); /* Write the line to the proper place */
1562 endutent(); /* Indicate operation is complete */
1566 * Code for locking/unlocking the serial device.
1567 * This code is derived from chat.c.
1570 #define LOCK_PREFIX "/var/lock/LCK.."
1573 * lock - create a lock file for the named device
1576 int lock (char *dev)
1578 char hdb_lock_buffer[12];
1582 p = strrchr(dev, '/');
1588 lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
1589 if (lock_file == NULL)
1591 novm("lock file name");
1594 strcpy (lock_file, LOCK_PREFIX);
1595 strcat (lock_file, dev);
1597 * Attempt to create the lock file at this point.
1601 fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644);
1604 sprintf(hdb_lock_buffer, "%010d\n", getpid());
1605 write(fd, hdb_lock_buffer, 11);
1610 * If the file exists then check to see if the pid is stale
1612 if (errno == EEXIST)
1614 fd = open(lock_file, O_RDONLY, 0);
1617 if (errno == ENOENT) /* This is just a timing problem. */
1624 /* Read the lock file to find out who has the device locked */
1625 n = read (fd, hdb_lock_buffer, 11);
1629 syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
1636 syslog (LOG_NOTICE, "Removed stale lock on %s", lock_file);
1640 hdb_lock_buffer[n] = '\0';
1641 sscanf (hdb_lock_buffer, " %d", &pid);
1643 if (kill(pid, 0) == -1 && errno == ESRCH)
1645 /* pid no longer exists - remove the lock file */
1646 if (unlink (lock_file) == 0)
1648 syslog (LOG_NOTICE, "Removed stale lock on %s (pid %d)",
1654 syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, pid);
1658 syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
1668 * unlock - remove our lockfile