X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fsys-linux.c;h=46e1ed419f4b494fb3d6f4781fdc0120ca808fab;hp=b675c9765718c26ef9d547ac9d1f5f4cb9dca0ae;hb=53aeb75a17f1118db121088269b38a097283126f;hpb=9856f47063c01096fe6649a21be9a021e42a45fe diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index b675c97..46e1ed4 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -73,12 +73,12 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -205,6 +205,7 @@ static char loop_name[20]; static unsigned char inbuf[512]; /* buffer for chars read from loopback */ static int if_is_up; /* Interface has been marked up */ +static int if6_is_up; /* Interface has been marked up for IPv6, to help differentiate */ static int have_default_route; /* Gateway for default route added */ static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry added */ static char proxy_arp_dev[16]; /* Device for proxy arp entry */ @@ -232,16 +233,19 @@ static int baud_rate_of (int speed); static void close_route_table (void); static int open_route_table (void); static int read_route_table (struct rtentry *rt); -static int defaultroute_exists (struct rtentry *rt); +static int defaultroute_exists (struct rtentry *rt, int metric); static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr, char *name, int namelen); static void decode_version (char *buf, int *version, int *mod, int *patch); static int set_kdebugflag(int level); static int ppp_registered(void); static int make_ppp_unit(void); +static int setifstate (int u, int state); extern u_char inpacket_buf[]; /* borrowed from main.c */ +extern int dfl_route_metric; + /* * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, * if it exists. @@ -338,6 +342,9 @@ void sys_cleanup(void) if_is_up = 0; sifdown(0); } + if (if6_is_up) + sif6down(0); + /* * Delete any routes through the device. */ @@ -636,6 +643,21 @@ static int make_ppp_unit() } if (x < 0) error("Couldn't create new ppp unit: %m"); + + if (x == 0 && req_ifname[0] != '\0') { + struct ifreq ifr; + char t[MAXIFNAMELEN]; + memset(&ifr, 0, sizeof(struct ifreq)); + slprintf(t, sizeof(t), "%s%d", PPP_DRV_NAME, ifunit); + strncpy(ifr.ifr_name, t, IF_NAMESIZE); + strncpy(ifr.ifr_newname, req_ifname, IF_NAMESIZE); + x = ioctl(sock_fd, SIOCSIFNAME, &ifr); + if (x < 0) + error("Couldn't rename interface %s to %s: %m", t, req_ifname); + else + info("Renamed interface %s to %s", t, req_ifname); + } + return x; } @@ -966,6 +988,9 @@ void set_up_tty(int tty_fd, int local) break; } + if (stop_bits >= 2) + tios.c_cflag |= CSTOPB; + speed = translate_speed(inspeed); if (speed) { cfsetospeed (&tios, speed); @@ -1439,7 +1464,7 @@ static char *path_to_procfs(const char *tail) FILE *route_fd = (FILE *) 0; static char route_buffer[512]; static int route_dev_col, route_dest_col, route_gw_col; -static int route_flags_col, route_mask_col; +static int route_flags_col, route_metric_col, route_mask_col; static int route_num_cols; static int open_route_table (void); @@ -1482,6 +1507,7 @@ static int open_route_table (void) route_dest_col = 1; route_gw_col = 2; route_flags_col = 3; + route_metric_col = 6; route_mask_col = 7; route_num_cols = 8; @@ -1542,6 +1568,7 @@ static int read_route_table(struct rtentry *rt) SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16); rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16); + rt->rt_metric = (short) strtoul(cols[route_metric_col], NULL, 10); rt->rt_dev = cols[route_dev_col]; return 1; @@ -1550,9 +1577,10 @@ static int read_route_table(struct rtentry *rt) /******************************************************************** * * defaultroute_exists - determine if there is a default route + * with the given metric (or negative for any) */ -static int defaultroute_exists (struct rtentry *rt) +static int defaultroute_exists (struct rtentry *rt, int metric) { int result = 0; @@ -1565,7 +1593,8 @@ static int defaultroute_exists (struct rtentry *rt) if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0) continue; - if (SIN_ADDR(rt->rt_dst) == 0L) { + if (SIN_ADDR(rt->rt_dst) == 0L && (metric < 0 + || rt->rt_metric == metric)) { result = 1; break; } @@ -1612,13 +1641,13 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) { struct rtentry rt; - if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0) { + if (defaultroute_exists(&rt, dfl_route_metric) && strcmp(rt.rt_dev, ifname) != 0) { if (rt.rt_flags & RTF_GATEWAY) - error("not replacing existing default route via %I", - SIN_ADDR(rt.rt_gateway)); + error("not replacing existing default route via %I with metric %d", + SIN_ADDR(rt.rt_gateway), dfl_route_metric); else - error("not replacing existing default route through %s", - rt.rt_dev); + error("not replacing existing default route through %s with metric %d", + rt.rt_dev, dfl_route_metric); return 0; } @@ -1626,6 +1655,7 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) SET_SA_FAMILY (rt.rt_dst, AF_INET); rt.rt_dev = ifname; + rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */ if (kernel_version > KVERSION(2,1,0)) { SET_SA_FAMILY (rt.rt_genmask, AF_INET); @@ -1660,6 +1690,9 @@ int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway) rt.rt_dev = ifname; + rt.rt_dev = ifname; + rt.rt_metric = dfl_route_metric + 1; /* +1 for binary compatibility */ + if (kernel_version > KVERSION(2,1,0)) { SET_SA_FAMILY (rt.rt_genmask, AF_INET); SIN_ADDR(rt.rt_genmask) = 0L; @@ -2018,7 +2051,7 @@ ppp_registered(void) int ppp_available(void) { - int s, ok, fd, err; + int s, ok, fd; struct ifreq ifr; int size; int my_version, my_modification, my_patch; @@ -2041,7 +2074,6 @@ int ppp_available(void) close(fd); return 1; } - err = errno; if (kernel_version >= KVERSION(2,3,13)) { error("Couldn't open the /dev/ppp device: %m"); @@ -2148,6 +2180,7 @@ int ppp_available(void) return ok; } +#ifndef HAVE_LOGWTMP /******************************************************************** * * Update the wtmp file with the appropriate user name and tty device. @@ -2221,7 +2254,7 @@ void logwtmp (const char *line, const char *name, const char *host) } #endif } - +#endif /* HAVE_LOGWTMP */ /******************************************************************** * @@ -2233,9 +2266,10 @@ int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid) u_int x; if (vjcomp) { - if (ioctl(ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) + if (ioctl(ppp_dev_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) { error("Couldn't set up TCP header compression: %m"); - vjcomp = 0; + vjcomp = 0; + } } x = (vjcomp? SC_COMP_TCP: 0) | (cidcomp? 0: SC_NO_TCP_CCID); @@ -2251,25 +2285,12 @@ int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid) int sifup(int u) { - struct ifreq ifr; + int ret; - memset (&ifr, '\0', sizeof (ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); - if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { - if (! ok_error (errno)) - error("ioctl (SIOCGIFFLAGS): %m (line %d)", __LINE__); - return 0; - } - - ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT); - if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - if (! ok_error (errno)) - error("ioctl(SIOCSIFFLAGS): %m (line %d)", __LINE__); - return 0; - } - if_is_up++; + if ((ret = setifstate(u, 1))) + if_is_up++; - return 1; + return ret; } /******************************************************************** @@ -2280,11 +2301,59 @@ int sifup(int u) int sifdown (int u) { - struct ifreq ifr; - if (if_is_up && --if_is_up > 0) return 1; +#ifdef INET6 + if (if6_is_up) + return 1; +#endif /* INET6 */ + + return setifstate(u, 0); +} + +#ifdef INET6 +/******************************************************************** + * + * sif6up - Config the interface up for IPv6 + */ + +int sif6up(int u) +{ + int ret; + + if ((ret = setifstate(u, 1))) + if6_is_up = 1; + + return ret; +} + +/******************************************************************** + * + * sif6down - Disable the IPv6CP protocol and config the interface + * down if there are no remaining protocols. + */ + +int sif6down (int u) +{ + if6_is_up = 0; + + if (if_is_up) + return 1; + + return setifstate(u, 0); +} +#endif /* INET6 */ + +/******************************************************************** + * + * setifstate - Config the interface up or down + */ + +static int setifstate (int u, int state) +{ + struct ifreq ifr; + memset (&ifr, '\0', sizeof (ifr)); strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { @@ -2293,7 +2362,10 @@ int sifdown (int u) return 0; } - ifr.ifr_flags &= ~IFF_UP; + if (state) + ifr.ifr_flags |= IFF_UP; + else + ifr.ifr_flags &= ~IFF_UP; ifr.ifr_flags |= IFF_POINTOPOINT; if (ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { if (! ok_error (errno)) @@ -2878,7 +2950,7 @@ ether_to_eui64(eui64_t *p_eui64) /* * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1] */ - ptr = ifr.ifr_hwaddr.sa_data; + ptr = (unsigned char *) ifr.ifr_hwaddr.sa_data; p_eui64->e8[0] = ptr[0] | 0x02; p_eui64->e8[1] = ptr[1]; p_eui64->e8[2] = ptr[2];