1 0 stevel /* 2 0 stevel * System-dependent procedures for pppd under Solaris 2.x (SunOS 5.x). 3 0 stevel * 4 9354 Tim * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 5 0 stevel * Use is subject to license terms. 6 0 stevel * 7 0 stevel * Permission to use, copy, modify, and distribute this software and its 8 0 stevel * documentation is hereby granted, provided that the above copyright 9 0 stevel * notice appears in all copies. 10 0 stevel * 11 0 stevel * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF 12 0 stevel * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 0 stevel * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 14 0 stevel * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR 15 0 stevel * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR 16 0 stevel * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES 17 0 stevel * 18 0 stevel * Copyright (c) 1994 The Australian National University. 19 0 stevel * All rights reserved. 20 0 stevel * 21 0 stevel * Permission to use, copy, modify, and distribute this software and its 22 0 stevel * documentation is hereby granted, provided that the above copyright 23 0 stevel * notice appears in all copies. This software is provided without any 24 0 stevel * warranty, express or implied. The Australian National University 25 0 stevel * makes no representations about the suitability of this software for 26 0 stevel * any purpose. 27 0 stevel * 28 0 stevel * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 29 0 stevel * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 30 0 stevel * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 31 0 stevel * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY 32 0 stevel * OF SUCH DAMAGE. 33 0 stevel * 34 0 stevel * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 35 0 stevel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 36 0 stevel * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 37 0 stevel * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 38 0 stevel * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 39 0 stevel * OR MODIFICATIONS. 40 0 stevel */ 41 0 stevel 42 0 stevel #define RCSID "$Id: sys-solaris.c,v 1.2 2000/04/21 01:27:57 masputra Exp $" 43 0 stevel 44 0 stevel #include <limits.h> 45 0 stevel #include <stdio.h> 46 0 stevel #include <stddef.h> 47 0 stevel #include <stdlib.h> 48 0 stevel #include <ctype.h> 49 0 stevel #include <errno.h> 50 0 stevel #include <fcntl.h> 51 0 stevel #include <unistd.h> 52 0 stevel #include <netdb.h> 53 0 stevel #include <termios.h> 54 0 stevel #include <signal.h> 55 0 stevel #include <string.h> 56 0 stevel #include <stropts.h> 57 0 stevel #include <utmpx.h> 58 0 stevel #include <sys/types.h> 59 0 stevel #include <sys/ioccom.h> 60 0 stevel #include <sys/stream.h> 61 0 stevel #include <sys/stropts.h> 62 0 stevel #include <sys/socket.h> 63 0 stevel #include <sys/sockio.h> 64 0 stevel #include <sys/sysmacros.h> 65 0 stevel #include <sys/systeminfo.h> 66 0 stevel #include <sys/stat.h> 67 0 stevel #include <net/if.h> 68 0 stevel #include <net/if_arp.h> 69 0 stevel #include <net/route.h> 70 0 stevel #include <net/ppp_defs.h> 71 0 stevel #include <net/pppio.h> 72 0 stevel #include <net/if_types.h> 73 0 stevel #include <net/if_dl.h> 74 0 stevel #include <netinet/in.h> 75 0 stevel #include <sys/tihdr.h> 76 0 stevel #include <inet/mib2.h> 77 741 masputra #include <inet/ip.h> 78 0 stevel #include <sys/ethernet.h> 79 0 stevel #include <sys/ser_sync.h> 80 6631 ss150715 #include <libdlpi.h> 81 9751 james #include <arpa/inet.h> 82 0 stevel 83 0 stevel #include "pppd.h" 84 0 stevel #include "fsm.h" 85 0 stevel #include "lcp.h" 86 0 stevel #include "ipcp.h" 87 0 stevel #ifdef INET6 88 0 stevel #include "ipv6cp.h" 89 0 stevel #endif /* INET6 */ 90 0 stevel #include "ccp.h" 91 0 stevel 92 0 stevel #if !defined(lint) && !defined(_lint) 93 0 stevel static const char rcsid[] = RCSID; 94 0 stevel #endif 95 0 stevel 96 0 stevel #define PPPSTRTIMOUT 1 /* Timeout in seconds for ioctl */ 97 0 stevel #define MAX_POLLFDS 32 98 0 stevel #define NMODULES 32 99 0 stevel 100 0 stevel #ifndef MAXIFS 101 0 stevel #define MAXIFS 256 102 0 stevel #endif /* MAXIFS */ 103 0 stevel 104 0 stevel #ifdef INET6 105 0 stevel #define _IN6_LLX_FROM_EUI64(l, s, eui64, as, len) \ 106 0 stevel (s->sin6_addr.s6_addr32[0] = htonl(as), \ 107 0 stevel eui64_copy(eui64, s->sin6_addr.s6_addr32[2]), \ 108 0 stevel s->sin6_family = AF_INET6, \ 109 0 stevel l.lifr_addr.ss_family = AF_INET6, \ 110 0 stevel l.lifr_addrlen = len, \ 111 0 stevel l.lifr_addr = laddr) 112 0 stevel 113 0 stevel /* 114 0 stevel * Generate a link-local address with an interface-id based on the given 115 0 stevel * EUI64 identifier. Note that the len field is unused by SIOCSLIFADDR. 116 0 stevel */ 117 0 stevel #define IN6_LLADDR_FROM_EUI64(l, s, eui64) \ 118 0 stevel _IN6_LLX_FROM_EUI64(l, s, eui64, 0xfe800000, 0) 119 0 stevel 120 0 stevel /* 121 0 stevel * Generate an EUI64 based interface-id for use by stateless address 122 0 stevel * autoconfiguration. These are required to be 64 bits long as defined in 123 0 stevel * the "Interface Identifiers" section of the IPv6 Addressing Architecture 124 0 stevel * (RFC3513). 125 0 stevel */ 126 0 stevel #define IN6_LLTOKEN_FROM_EUI64(l, s, eui64) \ 127 0 stevel _IN6_LLX_FROM_EUI64(l, s, eui64, 0, 64) 128 0 stevel #endif /* INET6 */ 129 0 stevel 130 0 stevel #define IPCP_ENABLED ipcp_protent.enabled_flag 131 0 stevel #ifdef INET6 132 0 stevel #define IPV6CP_ENABLED ipv6cp_protent.enabled_flag 133 0 stevel #endif /* INET6 */ 134 0 stevel 135 0 stevel /* For plug-in usage. */ 136 0 stevel int (*sys_read_packet_hook) __P((int retv, struct strbuf *ctrl, 137 0 stevel struct strbuf *data, int flags)) = NULL; 138 0 stevel bool already_ppp = 0; /* Already in PPP mode */ 139 0 stevel 140 0 stevel static int pppfd = -1; /* ppp driver fd */ 141 0 stevel static int fdmuxid = -1; /* driver mux fd */ 142 0 stevel static int ipfd = -1; /* IPv4 fd */ 143 0 stevel static int ipmuxid = -1; /* IPv4 mux fd */ 144 0 stevel static int ip6fd = -1; /* IPv6 fd */ 145 0 stevel static int ip6muxid = -1; /* IPv6 mux fd */ 146 0 stevel static bool if6_is_up = 0; /* IPv6 if marked as up */ 147 0 stevel static bool if_is_up = 0; /* IPv4 if marked as up */ 148 0 stevel static bool restore_term = 0; /* Restore TTY after closing link */ 149 0 stevel static struct termios inittermios; /* TTY settings */ 150 0 stevel static struct winsize wsinfo; /* Initial window size info */ 151 0 stevel static pid_t tty_sid; /* original sess ID for term */ 152 0 stevel static struct pollfd pollfds[MAX_POLLFDS]; /* array of polled fd */ 153 0 stevel static int n_pollfds = 0; /* total count of polled fd */ 154 0 stevel static int link_mtu; /* link Maximum Transmit Unit */ 155 0 stevel static int tty_nmodules; /* total count of TTY modules used */ 156 0 stevel static char tty_modules[NMODULES][FMNAMESZ+1]; 157 0 stevel /* array of TTY modules used */ 158 0 stevel static int tty_npushed; /* total count of pushed PPP modules */ 159 0 stevel static u_int32_t remote_addr; /* IP address of peer */ 160 0 stevel static u_int32_t default_route_gateway; /* Gateway for default route */ 161 0 stevel static u_int32_t proxy_arp_addr; /* Addr for proxy arp entry */ 162 0 stevel static u_int32_t lastlink_status; /* Last link status info */ 163 0 stevel 164 0 stevel static bool use_plink = 0; /* Use I_LINK by default */ 165 0 stevel static bool plumbed = 0; /* Use existing interface */ 166 0 stevel 167 0 stevel /* Default is to use /dev/sppp as driver. */ 168 0 stevel static const char *drvnam = PPP_DEV_NAME; 169 0 stevel static bool integrated_driver = 0; 170 0 stevel static int extra_dev_fd = -1; /* keep open until ready */ 171 0 stevel 172 0 stevel static option_t solaris_option_list[] = { 173 0 stevel { "plink", o_bool, &use_plink, "Use I_PLINK instead of I_LINK", 174 0 stevel OPT_PRIV|1 }, 175 0 stevel { "noplink", o_bool, &use_plink, "Use I_LINK instead of I_PLINK", 176 0 stevel OPT_PRIV|0 }, 177 0 stevel { "plumbed", o_bool, &plumbed, "Use pre-plumbed interface", 178 0 stevel OPT_PRIV|1 }, 179 0 stevel { NULL } 180 0 stevel }; 181 0 stevel 182 0 stevel /* 183 0 stevel * Prototypes for procedures local to this file. 184 0 stevel */ 185 0 stevel static int translate_speed __P((int)); 186 0 stevel static int baud_rate_of __P((int)); 187 0 stevel static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *, int)); 188 0 stevel static int strioctl __P((int, int, void *, int, int)); 189 0 stevel static int plumb_ipif __P((int)); 190 0 stevel static int unplumb_ipif __P((int)); 191 0 stevel #ifdef INET6 192 0 stevel static int plumb_ip6if __P((int)); 193 0 stevel static int unplumb_ip6if __P((int)); 194 0 stevel static int open_ip6fd(void); 195 0 stevel #endif /* INET6 */ 196 0 stevel static int open_ipfd(void); 197 0 stevel static int sifroute __P((int, u_int32_t, u_int32_t, int, const char *)); 198 0 stevel static int giflags __P((u_int32_t, bool *)); 199 0 stevel static void handle_unbind __P((u_int32_t)); 200 0 stevel static void handle_bind __P((u_int32_t)); 201 0 stevel 202 0 stevel /* 203 0 stevel * Wrapper for regular ioctl; masks out EINTR. 204 0 stevel */ 205 0 stevel static int 206 0 stevel myioctl(int fd, int cmd, void *arg) 207 0 stevel { 208 0 stevel int retv; 209 0 stevel 210 0 stevel errno = 0; 211 0 stevel while ((retv = ioctl(fd, cmd, arg)) == -1) { 212 0 stevel if (errno != EINTR) 213 0 stevel break; 214 0 stevel } 215 0 stevel return (retv); 216 0 stevel } 217 0 stevel 218 0 stevel /* 219 0 stevel * sys_check_options() 220 0 stevel * 221 0 stevel * Check the options that the user specified. 222 0 stevel */ 223 0 stevel int 224 0 stevel sys_check_options(void) 225 0 stevel { 226 0 stevel if (plumbed) { 227 0 stevel if (req_unit == -1) 228 0 stevel req_unit = -2; 229 0 stevel ipmuxid = 0; 230 0 stevel ip6muxid = 0; 231 0 stevel } 232 0 stevel return (1); 233 0 stevel } 234 0 stevel 235 0 stevel /* 236 0 stevel * sys_options() 237 0 stevel * 238 0 stevel * Add or remove system-specific options. 239 0 stevel */ 240 0 stevel void 241 0 stevel sys_options(void) 242 0 stevel { 243 0 stevel (void) remove_option("ktune"); 244 0 stevel (void) remove_option("noktune"); 245 0 stevel add_options(solaris_option_list); 246 0 stevel } 247 0 stevel 248 0 stevel /* 249 0 stevel * sys_ifname() 250 0 stevel * 251 0 stevel * Set ifname[] to contain name of IP interface for this unit. 252 0 stevel */ 253 0 stevel void 254 0 stevel sys_ifname(void) 255 0 stevel { 256 0 stevel const char *cp; 257 0 stevel 258 0 stevel if ((cp = strrchr(drvnam, '/')) == NULL) 259 0 stevel cp = drvnam; 260 0 stevel else 261 0 stevel cp++; 262 0 stevel (void) slprintf(ifname, sizeof (ifname), "%s%d", cp, ifunit); 263 0 stevel } 264 0 stevel 265 0 stevel /* 266 0 stevel * ppp_available() 267 0 stevel * 268 0 stevel * Check whether the system has any ppp interfaces. 269 0 stevel */ 270 0 stevel int 271 0 stevel ppp_available(void) 272 0 stevel { 273 0 stevel struct stat buf; 274 0 stevel int fd; 275 0 stevel uint32_t typ; 276 0 stevel 277 0 stevel if (stat(PPP_DEV_NAME, &buf) >= 0) 278 0 stevel return (1); 279 0 stevel 280 0 stevel /* 281 0 stevel * Simple check for system using Apollo POS without SUNWpppd 282 0 stevel * (/dev/sppp) installed. This is intentionally not kept open 283 0 stevel * here, since the user may not have the same privileges (as 284 0 stevel * determined later). If Apollo were just shipped with the 285 0 stevel * full complement of packages, this wouldn't be an issue. 286 0 stevel */ 287 0 stevel if (devnam[0] == '\0' && 288 0 stevel (fd = open(devnam, O_RDWR | O_NONBLOCK | O_NOCTTY)) >= 0) { 289 0 stevel if (strioctl(fd, PPPIO_GTYPE, &typ, 0, sizeof (typ)) >= 0 && 290 0 stevel typ == PPPTYP_MUX) { 291 0 stevel (void) close(fd); 292 0 stevel return (1); 293 0 stevel } 294 0 stevel (void) close(fd); 295 0 stevel } 296 0 stevel return (0); 297 0 stevel } 298 0 stevel 299 0 stevel static int 300 0 stevel open_ipfd(void) 301 0 stevel { 302 0 stevel ipfd = open(IP_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 303 0 stevel if (ipfd < 0) { 304 0 stevel error("Couldn't open IP device (%s): %m", IP_DEV_NAME); 305 0 stevel } 306 0 stevel return (ipfd); 307 0 stevel } 308 0 stevel 309 0 stevel static int 310 0 stevel read_ip_interface(int unit) 311 0 stevel { 312 0 stevel struct ifreq ifr; 313 0 stevel struct sockaddr_in sin; 314 0 stevel 315 0 stevel if (ipfd == -1 && open_ipfd() == -1) 316 0 stevel return (0); 317 0 stevel 318 0 stevel BZERO(&ifr, sizeof (ifr)); 319 0 stevel (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 320 0 stevel 321 0 stevel /* Get the existing MTU */ 322 0 stevel if (myioctl(ipfd, SIOCGIFMTU, &ifr) < 0) { 323 0 stevel warn("Couldn't get IP MTU on %s: %m", ifr.ifr_name); 324 0 stevel return (0); 325 0 stevel } 326 0 stevel dbglog("got MTU %d from interface", ifr.ifr_metric); 327 0 stevel if (ifr.ifr_metric != 0 && 328 0 stevel (lcp_allowoptions[unit].mru == 0 || 329 6631 ss150715 lcp_allowoptions[unit].mru > ifr.ifr_metric)) 330 0 stevel lcp_allowoptions[unit].mru = ifr.ifr_metric; 331 0 stevel 332 0 stevel /* Get the local IP address */ 333 0 stevel if (ipcp_wantoptions[unit].ouraddr == 0 || 334 0 stevel ipcp_from_hostname) { 335 0 stevel if (myioctl(ipfd, SIOCGIFADDR, &ifr) < 0) { 336 0 stevel warn("Couldn't get local IP address (%s): %m", 337 0 stevel ifr.ifr_name); 338 0 stevel return (0); 339 0 stevel } 340 0 stevel BCOPY(&ifr.ifr_addr, &sin, sizeof (struct sockaddr_in)); 341 0 stevel ipcp_wantoptions[unit].ouraddr = sin.sin_addr.s_addr; 342 0 stevel dbglog("got local address %I from interface", 343 0 stevel ipcp_wantoptions[unit].ouraddr); 344 0 stevel } 345 0 stevel 346 0 stevel /* Get the remote IP address */ 347 0 stevel if (ipcp_wantoptions[unit].hisaddr == 0) { 348 0 stevel if (myioctl(ipfd, SIOCGIFDSTADDR, &ifr) < 0) { 349 0 stevel warn("Couldn't get remote IP address (%s): %m", 350 0 stevel ifr.ifr_name); 351 0 stevel return (0); 352 0 stevel } 353 0 stevel BCOPY(&ifr.ifr_dstaddr, &sin, sizeof (struct sockaddr_in)); 354 0 stevel ipcp_wantoptions[unit].hisaddr = sin.sin_addr.s_addr; 355 0 stevel dbglog("got remote address %I from interface", 356 0 stevel ipcp_wantoptions[unit].hisaddr); 357 0 stevel } 358 0 stevel return (1); 359 0 stevel } 360 0 stevel 361 0 stevel #ifdef INET6 362 0 stevel static int 363 0 stevel open_ip6fd(void) 364 0 stevel { 365 0 stevel ip6fd = open(IP6_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 366 0 stevel if (ip6fd < 0) { 367 0 stevel error("Couldn't open IPv6 device (%s): %m", IP6_DEV_NAME); 368 0 stevel } 369 0 stevel return (ip6fd); 370 0 stevel } 371 0 stevel 372 0 stevel static int 373 0 stevel read_ipv6_interface(int unit) 374 0 stevel { 375 0 stevel struct lifreq lifr; 376 0 stevel struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr; 377 0 stevel 378 0 stevel if (ip6fd == -1 && open_ip6fd() == -1) 379 0 stevel return (0); 380 0 stevel 381 0 stevel BZERO(&lifr, sizeof (lifr)); 382 0 stevel (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 383 0 stevel 384 0 stevel /* Get the existing MTU */ 385 0 stevel if (myioctl(ip6fd, SIOCGLIFMTU, &lifr) < 0) { 386 0 stevel warn("Couldn't get IPv6 MTU on %s: %m", lifr.lifr_name); 387 0 stevel return (0); 388 0 stevel } 389 0 stevel if (lifr.lifr_mtu != 0 && 390 0 stevel (lcp_allowoptions[unit].mru == 0 || 391 6631 ss150715 lcp_allowoptions[unit].mru > lifr.lifr_mtu)) 392 0 stevel lcp_allowoptions[unit].mru = lifr.lifr_mtu; 393 0 stevel 394 0 stevel /* Get the local IPv6 address */ 395 0 stevel if (eui64_iszero(ipv6cp_wantoptions[unit].ourid) || 396 0 stevel (ipcp_from_hostname && ipv6cp_wantoptions[unit].use_ip)) { 397 0 stevel if (myioctl(ip6fd, SIOCGLIFADDR, &lifr) < 0) { 398 0 stevel warn("Couldn't get local IPv6 address (%s): %m", 399 0 stevel lifr.lifr_name); 400 0 stevel return (0); 401 0 stevel } 402 0 stevel eui64_copy(sin6->sin6_addr.s6_addr32[2], 403 0 stevel ipv6cp_wantoptions[unit].ourid); 404 0 stevel } 405 0 stevel 406 0 stevel /* Get the remote IP address */ 407 0 stevel if (eui64_iszero(ipv6cp_wantoptions[unit].hisid)) { 408 0 stevel if (myioctl(ip6fd, SIOCGLIFDSTADDR, &lifr) < 0) { 409 0 stevel warn("Couldn't get remote IPv6 address (%s): %m", 410 0 stevel lifr.lifr_name); 411 0 stevel return (0); 412 0 stevel } 413 0 stevel eui64_copy(sin6->sin6_addr.s6_addr32[2], 414 0 stevel ipv6cp_wantoptions[unit].hisid); 415 0 stevel } 416 0 stevel return (1); 417 0 stevel } 418 0 stevel #endif /* INET6 */ 419 0 stevel 420 0 stevel /* 421 0 stevel * Read information on existing interface(s) and configure ourselves 422 0 stevel * to negotiate appropriately. 423 0 stevel */ 424 0 stevel static void 425 0 stevel read_interface(int unit) 426 0 stevel { 427 0 stevel dbglog("reading existing interface data; %sip %sipv6", 428 0 stevel IPCP_ENABLED ? "" : "!", 429 0 stevel #ifdef INET6 430 0 stevel IPV6CP_ENABLED ? "" : 431 0 stevel #endif 432 0 stevel "!"); 433 0 stevel if (IPCP_ENABLED && !read_ip_interface(unit)) 434 0 stevel IPCP_ENABLED = 0; 435 0 stevel #ifdef INET6 436 0 stevel if (IPV6CP_ENABLED && !read_ipv6_interface(unit)) 437 0 stevel IPV6CP_ENABLED = 0; 438 0 stevel #endif 439 0 stevel } 440 0 stevel 441 0 stevel /* 442 0 stevel * sys_init() 443 0 stevel * 444 0 stevel * System-dependent initialization. 445 0 stevel */ 446 0 stevel void 447 0 stevel sys_init(bool open_as_user) 448 0 stevel { 449 0 stevel uint32_t x; 450 0 stevel uint32_t typ; 451 0 stevel 452 0 stevel if (pppfd != -1) { 453 0 stevel return; 454 0 stevel } 455 0 stevel 456 0 stevel if (!direct_tty && devnam[0] != '\0') { 457 0 stevel /* 458 0 stevel * Check for integrated driver-like devices (such as 459 0 stevel * POS). These identify themselves as "PPP 460 0 stevel * multiplexor" drivers. 461 0 stevel */ 462 0 stevel if (open_as_user) 463 0 stevel (void) seteuid(getuid()); 464 0 stevel pppfd = open(devnam, O_RDWR | O_NONBLOCK); 465 0 stevel if (open_as_user) 466 0 stevel (void) seteuid(0); 467 0 stevel if (pppfd >= 0 && 468 0 stevel strioctl(pppfd, PPPIO_GTYPE, &typ, 0, sizeof (typ)) >= 0 && 469 0 stevel typ == PPPTYP_MUX) { 470 0 stevel integrated_driver = 1; 471 0 stevel drvnam = devnam; 472 0 stevel } else if (demand) { 473 0 stevel (void) close(pppfd); 474 0 stevel pppfd = -1; 475 0 stevel } else { 476 0 stevel extra_dev_fd = pppfd; 477 0 stevel pppfd = -1; 478 0 stevel } 479 0 stevel } 480 0 stevel 481 0 stevel /* 482 0 stevel * Open Solaris PPP device driver. 483 0 stevel */ 484 0 stevel if (pppfd < 0) 485 0 stevel pppfd = open(drvnam, O_RDWR | O_NONBLOCK); 486 0 stevel if (pppfd < 0) { 487 0 stevel fatal("Can't open %s: %m", drvnam); 488 0 stevel } 489 0 stevel if (kdebugflag & 1) { 490 0 stevel x = PPPDBG_LOG + PPPDBG_DRIVER; 491 0 stevel if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 492 0 stevel warn("PPPIO_DEBUG ioctl for mux failed: %m"); 493 0 stevel } 494 0 stevel } 495 0 stevel /* 496 0 stevel * Assign a new PPA and get its unit number. 497 0 stevel */ 498 0 stevel x = req_unit; 499 0 stevel if (strioctl(pppfd, PPPIO_NEWPPA, &x, sizeof (x), sizeof (x)) < 0) { 500 0 stevel if (errno == ENXIO && plumbed) 501 0 stevel fatal("No idle interfaces available for use"); 502 0 stevel fatal("PPPIO_NEWPPA ioctl failed: %m"); 503 0 stevel } 504 0 stevel ifunit = x; 505 0 stevel if (req_unit >= 0 && ifunit != req_unit) { 506 0 stevel if (plumbed) 507 0 stevel fatal("unable to get requested unit %d", req_unit); 508 0 stevel else 509 0 stevel warn("unable to get requested unit %d", req_unit); 510 0 stevel } 511 0 stevel /* 512 0 stevel * Enable packet time-stamping when idle option is specified. Note 513 0 stevel * that we need to only do this on the control stream. Subsequent 514 0 stevel * streams attached to this control stream (ppa) will inherit 515 0 stevel * the time-stamp bit. 516 0 stevel */ 517 0 stevel if (idle_time_limit > 0) { 518 0 stevel if (strioctl(pppfd, PPPIO_USETIMESTAMP, NULL, 0, 0) < 0) { 519 0 stevel warn("PPPIO_USETIMESTAMP ioctl failed: %m"); 520 0 stevel } 521 0 stevel } 522 0 stevel if (plumbed) { 523 0 stevel sys_ifname(); 524 0 stevel read_interface(0); 525 0 stevel } 526 0 stevel } 527 0 stevel 528 0 stevel int 529 0 stevel sys_extra_fd(void) 530 0 stevel { 531 0 stevel int fd; 532 0 stevel 533 0 stevel fd = extra_dev_fd; 534 0 stevel extra_dev_fd = -1; 535 0 stevel return (fd); 536 0 stevel } 537 0 stevel 538 0 stevel static int 539 0 stevel open_udpfd(void) 540 0 stevel { 541 0 stevel int udpfd; 542 0 stevel 543 0 stevel udpfd = open(UDP_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 544 0 stevel if (udpfd < 0) { 545 0 stevel error("Couldn't open UDP device (%s): %m", UDP_DEV_NAME); 546 0 stevel } 547 0 stevel return (udpfd); 548 0 stevel } 549 0 stevel 550 0 stevel /* 551 0 stevel * plumb_ipif() 552 0 stevel * 553 0 stevel * Perform IP interface plumbing. 554 0 stevel */ 555 0 stevel /*ARGSUSED*/ 556 0 stevel static int 557 0 stevel plumb_ipif(int unit) 558 0 stevel { 559 0 stevel int udpfd = -1, tmpfd; 560 0 stevel uint32_t x; 561 0 stevel struct ifreq ifr; 562 0 stevel 563 0 stevel if (!IPCP_ENABLED || (ifunit == -1) || (pppfd == -1)) { 564 0 stevel return (0); 565 0 stevel } 566 0 stevel if (plumbed) 567 0 stevel return (1); 568 0 stevel if (ipfd == -1 && open_ipfd() == -1) 569 0 stevel return (0); 570 0 stevel if (use_plink && (udpfd = open_udpfd()) == -1) 571 0 stevel return (0); 572 0 stevel tmpfd = open(drvnam, O_RDWR | O_NONBLOCK, 0); 573 0 stevel if (tmpfd < 0) { 574 0 stevel error("Couldn't open PPP device (%s): %m", drvnam); 575 0 stevel if (udpfd != -1) 576 0 stevel (void) close(udpfd); 577 0 stevel return (0); 578 0 stevel } 579 0 stevel if (kdebugflag & 1) { 580 0 stevel x = PPPDBG_LOG + PPPDBG_DRIVER; 581 0 stevel if (strioctl(tmpfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 582 0 stevel warn("PPPIO_DEBUG ioctl for mux failed: %m"); 583 0 stevel } 584 0 stevel } 585 0 stevel if (myioctl(tmpfd, I_PUSH, IP_MOD_NAME) < 0) { 586 0 stevel error("Couldn't push IP module (%s): %m", IP_MOD_NAME); 587 0 stevel goto err_ret; 588 0 stevel } 589 0 stevel /* 590 0 stevel * Assign ppa according to the unit number returned by ppp device 591 0 stevel * after plumbing is completed above. Without setting the ppa, ip 592 0 stevel * module will return EINVAL upon setting the interface UP 593 0 stevel * (SIOCSxIFFLAGS). This is because ip module in 2.8 expects two 594 0 stevel * DLPI_INFO_REQ to be sent down to the driver (below ip) before 595 0 stevel * IFF_UP bit can be set. Plumbing the device causes one DLPI_INFO_REQ 596 0 stevel * to be sent down, and the second DLPI_INFO_REQ is sent upon receiving 597 0 stevel * IF_UNITSEL (old) or SIOCSLIFNAME (new) ioctls. Such setting of the 598 0 stevel * ppa is required because the ppp DLPI provider advertises itself as 599 0 stevel * a DLPI style 2 type, which requires a point of attachment to be 600 0 stevel * specified. The only way the user can specify a point of attachment 601 0 stevel * is via SIOCSLIFNAME or IF_UNITSEL. Such changes in the behavior of 602 0 stevel * ip module was made to meet new or evolving standards requirements. 603 0 stevel */ 604 0 stevel if (myioctl(tmpfd, IF_UNITSEL, &ifunit) < 0) { 605 0 stevel error("Couldn't set ppa for unit %d: %m", ifunit); 606 0 stevel goto err_ret; 607 0 stevel } 608 0 stevel if (use_plink) { 609 0 stevel ipmuxid = myioctl(udpfd, I_PLINK, (void *)tmpfd); 610 0 stevel if (ipmuxid < 0) { 611 0 stevel error("Can't I_PLINK PPP device to IP: %m"); 612 0 stevel goto err_ret; 613 0 stevel } 614 0 stevel } else { 615 0 stevel ipmuxid = myioctl(ipfd, I_LINK, (void *)tmpfd); 616 0 stevel if (ipmuxid < 0) { 617 0 stevel error("Can't I_LINK PPP device to IP: %m"); 618 0 stevel goto err_ret; 619 0 stevel } 620 0 stevel } 621 0 stevel BZERO(&ifr, sizeof (ifr)); 622 0 stevel (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 623 0 stevel ifr.ifr_ip_muxid = ipmuxid; 624 0 stevel ifr.ifr_arp_muxid = -1; 625 0 stevel if (myioctl(ipfd, SIOCSIFMUXID, (caddr_t)&ifr) < 0) { 626 0 stevel error("Can't set mux ID SIOCSIFMUXID on %s: %m", ifname); 627 0 stevel goto err_ret; 628 0 stevel } 629 0 stevel if (udpfd != -1) 630 0 stevel (void) close(udpfd); 631 0 stevel (void) close(tmpfd); 632 0 stevel return (1); 633 0 stevel err_ret: 634 0 stevel if (udpfd != -1) 635 0 stevel (void) close(udpfd); 636 0 stevel (void) close(tmpfd); 637 0 stevel return (0); 638 0 stevel } 639 0 stevel 640 0 stevel /* 641 0 stevel * unplumb_ipif() 642 0 stevel * 643 0 stevel * Perform IP interface unplumbing. Possibly called from die(), so there 644 0 stevel * shouldn't be any call to die() or fatal() here. 645 0 stevel */ 646 0 stevel static int 647 0 stevel unplumb_ipif(int unit) 648 0 stevel { 649 0 stevel int udpfd = -1, fd = -1; 650 0 stevel int id; 651 0 stevel struct lifreq lifr; 652 0 stevel 653 0 stevel if (!IPCP_ENABLED || (ifunit == -1)) { 654 0 stevel return (0); 655 0 stevel } 656 0 stevel if (!plumbed && (ipmuxid == -1 || (ipfd == -1 && !use_plink))) 657 0 stevel return (1); 658 0 stevel id = ipmuxid; 659 0 stevel if (!plumbed && use_plink) { 660 0 stevel if ((udpfd = open_udpfd()) == -1) 661 0 stevel return (0); 662 0 stevel /* 663 0 stevel * Note: must re-get mux ID, since any intervening 664 0 stevel * ifconfigs will change this. 665 0 stevel */ 666 0 stevel BZERO(&lifr, sizeof (lifr)); 667 0 stevel (void) strlcpy(lifr.lifr_name, ifname, 668 0 stevel sizeof (lifr.lifr_name)); 669 0 stevel if (myioctl(ipfd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) { 670 0 stevel warn("Can't get mux fd: SIOCGLIFMUXID: %m"); 671 0 stevel } else { 672 0 stevel id = lifr.lifr_ip_muxid; 673 0 stevel fd = myioctl(udpfd, _I_MUXID2FD, (void *)id); 674 0 stevel if (fd < 0) { 675 0 stevel warn("Can't get mux fd: _I_MUXID2FD: %m"); 676 0 stevel } 677 0 stevel } 678 0 stevel } 679 0 stevel /* 680 0 stevel * Mark down and unlink the ip interface. 681 0 stevel */ 682 0 stevel (void) sifdown(unit); 683 0 stevel if (default_route_gateway != 0) { 684 0 stevel (void) cifdefaultroute(0, default_route_gateway, 685 0 stevel default_route_gateway); 686 0 stevel } 687 0 stevel if (proxy_arp_addr != 0) { 688 0 stevel (void) cifproxyarp(0, proxy_arp_addr); 689 0 stevel } 690 0 stevel ipmuxid = -1; 691 0 stevel if (plumbed) 692 0 stevel return (1); 693 0 stevel if (use_plink) { 694 0 stevel if (myioctl(udpfd, I_PUNLINK, (void *)id) < 0) { 695 0 stevel error("Can't I_PUNLINK PPP from IP: %m"); 696 0 stevel if (fd != -1) 697 0 stevel (void) close(fd); 698 0 stevel (void) close(udpfd); 699 0 stevel return (0); 700 0 stevel } 701 0 stevel if (fd != -1) 702 0 stevel (void) close(fd); 703 0 stevel (void) close(udpfd); 704 0 stevel } else { 705 0 stevel if (myioctl(ipfd, I_UNLINK, (void *)id) < 0) { 706 0 stevel error("Can't I_UNLINK PPP from IP: %m"); 707 0 stevel return (0); 708 0 stevel } 709 0 stevel } 710 0 stevel return (1); 711 0 stevel } 712 0 stevel 713 0 stevel /* 714 0 stevel * sys_cleanup() 715 0 stevel * 716 0 stevel * Restore any system state we modified before exiting: mark the 717 0 stevel * interface down, delete default route and/or proxy arp entry. This 718 0 stevel * should not call die() because it's called from die(). 719 0 stevel */ 720 0 stevel void 721 0 stevel sys_cleanup() 722 0 stevel { 723 0 stevel (void) unplumb_ipif(0); 724 0 stevel #ifdef INET6 725 0 stevel (void) unplumb_ip6if(0); 726 0 stevel #endif /* INET6 */ 727 0 stevel } 728 0 stevel 729 0 stevel /* 730 0 stevel * get_first_hwaddr() 731 0 stevel * 732 0 stevel * Stores the first hardware interface address found in the system 733 0 stevel * into addr and return 1 upon success, or 0 if none is found. This 734 0 stevel * is also called from the multilink code. 735 0 stevel */ 736 0 stevel int 737 0 stevel get_first_hwaddr(addr, msize) 738 0 stevel uchar_t *addr; 739 0 stevel int msize; 740 0 stevel { 741 0 stevel struct ifconf ifc; 742 0 stevel register struct ifreq *pifreq; 743 0 stevel struct ifreq ifr; 744 0 stevel int fd, num_ifs, i; 745 0 stevel uint_t fl, req_size; 746 0 stevel char *req; 747 0 stevel boolean_t found; 748 0 stevel 749 0 stevel if (addr == NULL) { 750 0 stevel return (0); 751 0 stevel } 752 0 stevel fd = socket(AF_INET, SOCK_DGRAM, 0); 753 0 stevel if (fd < 0) { 754 0 stevel error("get_first_hwaddr: error opening IP socket: %m"); 755 0 stevel return (0); 756 0 stevel } 757 0 stevel /* 758 0 stevel * Find out how many interfaces are running 759 0 stevel */ 760 0 stevel if (myioctl(fd, SIOCGIFNUM, (caddr_t)&num_ifs) < 0) { 761 0 stevel num_ifs = MAXIFS; 762 0 stevel } 763 0 stevel req_size = num_ifs * sizeof (struct ifreq); 764 0 stevel req = malloc(req_size); 765 0 stevel if (req == NULL) { 766 0 stevel novm("interface request structure."); 767 0 stevel } 768 0 stevel /* 769 0 stevel * Get interface configuration info for all interfaces 770 0 stevel */ 771 0 stevel ifc.ifc_len = req_size; 772 0 stevel ifc.ifc_buf = req; 773 0 stevel if (myioctl(fd, SIOCGIFCONF, &ifc) < 0) { 774 0 stevel error("SIOCGIFCONF: %m"); 775 0 stevel (void) close(fd); 776 0 stevel free(req); 777 0 stevel return (0); 778 0 stevel } 779 0 stevel /* 780 0 stevel * And traverse each interface to look specifically for the first 781 0 stevel * occurence of an Ethernet interface which has been marked up 782 0 stevel */ 783 0 stevel pifreq = ifc.ifc_req; 784 0 stevel found = 0; 785 0 stevel for (i = ifc.ifc_len / sizeof (struct ifreq); i > 0; i--, pifreq++) { 786 0 stevel 787 0 stevel if (strchr(pifreq->ifr_name, ':') != NULL) { 788 0 stevel continue; 789 0 stevel } 790 0 stevel BZERO(&ifr, sizeof (ifr)); 791 0 stevel (void) strncpy(ifr.ifr_name, pifreq->ifr_name, 792 0 stevel sizeof (ifr.ifr_name)); 793 0 stevel if (myioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { 794 0 stevel continue; 795 0 stevel } 796 0 stevel fl = ifr.ifr_flags; 797 0 stevel if ((fl & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK)) 798 0 stevel != (IFF_UP | IFF_BROADCAST)) { 799 0 stevel continue; 800 0 stevel } 801 0 stevel if (get_if_hwaddr(addr, msize, ifr.ifr_name) <= 0) { 802 0 stevel continue; 803 0 stevel } 804 0 stevel found = 1; 805 0 stevel break; 806 0 stevel } 807 0 stevel free(req); 808 0 stevel (void) close(fd); 809 0 stevel 810 0 stevel return (found); 811 0 stevel } 812 0 stevel 813 0 stevel /* 814 0 stevel * get_if_hwaddr() 815 0 stevel * 816 0 stevel * Get the hardware address for the specified network interface device. 817 0 stevel * Return the length of the MAC address (in bytes) or -1 if error. 818 0 stevel */ 819 0 stevel int 820 6631 ss150715 get_if_hwaddr(uchar_t *addrp, int msize, char *linkname) 821 0 stevel { 822 6631 ss150715 dlpi_handle_t dh; 823 6631 ss150715 uchar_t physaddr[DLPI_PHYSADDR_MAX]; 824 6631 ss150715 size_t physaddrlen = sizeof (physaddr); 825 6631 ss150715 int retv; 826 0 stevel 827 6631 ss150715 if ((addrp == NULL) || (linkname == NULL)) 828 0 stevel return (-1); 829 6631 ss150715 830 0 stevel /* 831 6631 ss150715 * Open the link and ask for hardware address. 832 0 stevel */ 833 6631 ss150715 if ((retv = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) { 834 6631 ss150715 error("Could not open %s: %s", linkname, dlpi_strerror(retv)); 835 0 stevel return (-1); 836 0 stevel } 837 0 stevel 838 6631 ss150715 retv = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, 839 6631 ss150715 physaddr, &physaddrlen); 840 6631 ss150715 dlpi_close(dh); 841 6631 ss150715 if (retv != DLPI_SUCCESS) { 842 6631 ss150715 error("Could not get physical address on %s: %s", linkname, 843 6631 ss150715 dlpi_strerror(retv)); 844 0 stevel return (-1); 845 0 stevel } 846 0 stevel 847 0 stevel /* 848 0 stevel * Check if we have enough space to copy the address to. 849 0 stevel */ 850 6631 ss150715 if (physaddrlen > msize) 851 0 stevel return (-1); 852 6631 ss150715 (void) memcpy(addrp, physaddr, physaddrlen); 853 6631 ss150715 return (physaddrlen); 854 0 stevel } 855 0 stevel 856 0 stevel /* 857 0 stevel * giflags() 858 0 stevel */ 859 0 stevel static int 860 0 stevel giflags(u_int32_t flag, bool *retval) 861 0 stevel { 862 0 stevel struct ifreq ifr; 863 0 stevel int fd; 864 0 stevel 865 0 stevel *retval = 0; 866 0 stevel fd = socket(AF_INET, SOCK_DGRAM, 0); 867 0 stevel if (fd < 0) { 868 0 stevel error("giflags: error opening IP socket: %m"); 869 0 stevel return (errno); 870 0 stevel } 871 0 stevel 872 0 stevel BZERO(&ifr, sizeof (ifr)); 873 0 stevel (void) strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 874 0 stevel if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { 875 0 stevel (void) close(fd); 876 0 stevel return (errno); 877 0 stevel } 878 0 stevel 879 0 stevel *retval = ((ifr.ifr_flags & flag) != 0); 880 0 stevel (void) close(fd); 881 0 stevel return (errno); 882 0 stevel } 883 0 stevel 884 0 stevel /* 885 0 stevel * sys_close() 886 0 stevel * 887 0 stevel * Clean up in a child process before exec-ing. 888 0 stevel */ 889 0 stevel void 890 0 stevel sys_close() 891 0 stevel { 892 0 stevel if (ipfd != -1) { 893 0 stevel (void) close(ipfd); 894 0 stevel ipfd = -1; 895 0 stevel } 896 0 stevel #ifdef INET6 897 0 stevel if (ip6fd != -1) { 898 0 stevel (void) close(ip6fd); 899 0 stevel ip6fd = -1; 900 0 stevel } 901 0 stevel #endif /* INET6 */ 902 0 stevel if (pppfd != -1) { 903 0 stevel (void) close(pppfd); 904 0 stevel pppfd = -1; 905 0 stevel } 906 0 stevel } 907 0 stevel 908 0 stevel /* 909 0 stevel * any_compressions() 910 0 stevel * 911 0 stevel * Check if compression is enabled or not. In the STREAMS implementation of 912 0 stevel * kernel-portion pppd, the comp STREAMS module performs the ACFC, PFC, as 913 0 stevel * well CCP and VJ compressions. However, if the user has explicitly declare 914 0 stevel * to not enable them from the command line, there is no point of having the 915 0 stevel * comp module be pushed on the stream. 916 0 stevel */ 917 0 stevel static int 918 0 stevel any_compressions(void) 919 0 stevel { 920 0 stevel if ((!lcp_wantoptions[0].neg_accompression) && 921 0 stevel (!lcp_wantoptions[0].neg_pcompression) && 922 0 stevel (!ccp_protent.enabled_flag) && 923 0 stevel (!ipcp_wantoptions[0].neg_vj)) { 924 0 stevel return (0); 925 0 stevel } 926 0 stevel return (1); 927 0 stevel } 928 0 stevel 929 0 stevel /* 930 0 stevel * modpush() 931 0 stevel * 932 0 stevel * Push a module on the stream. 933 0 stevel */ 934 0 stevel static int 935 0 stevel modpush(int fd, const char *modname, const char *text) 936 0 stevel { 937 0 stevel if (myioctl(fd, I_PUSH, (void *)modname) < 0) { 938 0 stevel error("Couldn't push %s module: %m", text); 939 0 stevel return (-1); 940 0 stevel } 941 0 stevel if (++tty_npushed == 1 && !already_ppp) { 942 0 stevel if (strioctl(fd, PPPIO_LASTMOD, NULL, 0, 0) < 0) { 943 0 stevel warn("unable to set LASTMOD on %s: %m", text); 944 0 stevel } 945 0 stevel } 946 0 stevel return (0); 947 0 stevel } 948 0 stevel 949 0 stevel /* 950 0 stevel * establish_ppp() 951 0 stevel * 952 0 stevel * Turn the serial port into a ppp interface. 953 0 stevel */ 954 0 stevel int 955 0 stevel establish_ppp(fd) 956 0 stevel int fd; 957 0 stevel { 958 0 stevel int i; 959 0 stevel uint32_t x; 960 0 stevel 961 0 stevel if (default_device && !notty) { 962 0 stevel tty_sid = getsid((pid_t)0); 963 0 stevel } 964 0 stevel 965 0 stevel if (integrated_driver) 966 0 stevel return (pppfd); 967 0 stevel 968 0 stevel /* 969 0 stevel * Pop any existing modules off the tty stream 970 0 stevel */ 971 0 stevel for (i = 0; ; ++i) { 972 0 stevel if ((myioctl(fd, I_LOOK, tty_modules[i]) < 0) || 973 0 stevel (strcmp(tty_modules[i], "ptem") == 0) || 974 0 stevel (myioctl(fd, I_POP, (void *)0) < 0)) { 975 0 stevel break; 976 0 stevel } 977 0 stevel } 978 0 stevel tty_nmodules = i; 979 0 stevel /* 980 0 stevel * Push the async hdlc module and the compressor module 981 0 stevel */ 982 0 stevel tty_npushed = 0; 983 0 stevel if (!sync_serial && !already_ppp && 984 0 stevel modpush(fd, AHDLC_MOD_NAME, "PPP async HDLC") < 0) { 985 0 stevel return (-1); 986 0 stevel } 987 0 stevel /* 988 0 stevel * There's no need to push comp module if we don't intend 989 0 stevel * to compress anything 990 0 stevel */ 991 0 stevel if (any_compressions()) { 992 0 stevel (void) modpush(fd, COMP_MOD_NAME, "PPP compression"); 993 0 stevel } 994 0 stevel 995 0 stevel /* 996 0 stevel * Link the serial port under the PPP multiplexor 997 0 stevel */ 998 0 stevel if ((fdmuxid = myioctl(pppfd, I_LINK, (void *)fd)) < 0) { 999 0 stevel error("Can't link tty to PPP mux: %m"); 1000 0 stevel return (-1); 1001 0 stevel } 1002 0 stevel if (tty_npushed == 0 && !already_ppp) { 1003 0 stevel if (strioctl(pppfd, PPPIO_LASTMOD, NULL, 0, 0) < 0) { 1004 0 stevel warn("unable to set LASTMOD on PPP mux: %m"); 1005 0 stevel } 1006 0 stevel } 1007 0 stevel /* 1008 0 stevel * Debug configuration must occur *after* I_LINK. 1009 0 stevel */ 1010 0 stevel if (kdebugflag & 4) { 1011 0 stevel x = PPPDBG_LOG + PPPDBG_AHDLC; 1012 0 stevel if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 1013 0 stevel warn("PPPIO_DEBUG ioctl for ahdlc module failed: %m"); 1014 0 stevel } 1015 0 stevel } 1016 0 stevel if (any_compressions() && (kdebugflag & 2)) { 1017 0 stevel x = PPPDBG_LOG + PPPDBG_COMP; 1018 0 stevel if (strioctl(pppfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 1019 0 stevel warn("PPPIO_DEBUG ioctl for comp module failed: %m"); 1020 0 stevel } 1021 0 stevel } 1022 0 stevel return (pppfd); 1023 0 stevel } 1024 0 stevel 1025 0 stevel /* 1026 0 stevel * restore_loop() 1027 0 stevel * 1028 0 stevel * Reattach the ppp unit to the loopback. This doesn't need to do anything 1029 0 stevel * because disestablish_ppp does it 1030 0 stevel */ 1031 0 stevel void 1032 0 stevel restore_loop() 1033 0 stevel { 1034 0 stevel } 1035 0 stevel 1036 0 stevel /* 1037 0 stevel * disestablish_ppp() 1038 0 stevel * 1039 0 stevel * Restore the serial port to normal operation. It attempts to reconstruct 1040 0 stevel * the stream with the previously popped modules. This shouldn't call die() 1041 0 stevel * because it's called from die(). Stream reconstruction is needed in case 1042 0 stevel * pppd is used for dial-in on /dev/tty and there's an option error. 1043 0 stevel */ 1044 0 stevel void 1045 0 stevel disestablish_ppp(fd) 1046 0 stevel int fd; 1047 0 stevel { 1048 0 stevel int i; 1049 0 stevel 1050 0 stevel if (fdmuxid == -1 || integrated_driver) { 1051 0 stevel return; 1052 0 stevel } 1053 0 stevel if (myioctl(pppfd, I_UNLINK, (void *)fdmuxid) < 0) { 1054 0 stevel if (!hungup) { 1055 0 stevel error("Can't unlink tty from PPP mux: %m"); 1056 0 stevel } 1057 0 stevel } 1058 0 stevel fdmuxid = -1; 1059 0 stevel if (!hungup) { 1060 0 stevel while (tty_npushed > 0 && myioctl(fd, I_POP, (void *)0) >= 0) { 1061 0 stevel --tty_npushed; 1062 0 stevel } 1063 0 stevel for (i = tty_nmodules - 1; i >= 0; --i) { 1064 0 stevel if (myioctl(fd, I_PUSH, tty_modules[i]) < 0) { 1065 0 stevel error("Couldn't restore tty module %s: %m", 1066 0 stevel tty_modules[i]); 1067 0 stevel } 1068 0 stevel } 1069 0 stevel } 1070 0 stevel if (hungup && default_device && tty_sid > 0) { 1071 0 stevel /* 1072 0 stevel * If we have received a hangup, we need to send a 1073 0 stevel * SIGHUP to the terminal's controlling process. 1074 0 stevel * The reason is that the original stream head for 1075 0 stevel * the terminal hasn't seen the M_HANGUP message 1076 0 stevel * (it went up through the ppp driver to the stream 1077 0 stevel * head for our fd to /dev/ppp). 1078 0 stevel */ 1079 0 stevel (void) kill(tty_sid, SIGHUP); 1080 0 stevel } 1081 0 stevel } 1082 0 stevel 1083 0 stevel /* 1084 0 stevel * clean_check() 1085 0 stevel * 1086 0 stevel * Check whether the link seems not to be 8-bit clean 1087 0 stevel */ 1088 0 stevel void 1089 0 stevel clean_check() 1090 0 stevel { 1091 0 stevel uint32_t x; 1092 0 stevel char *s = NULL; 1093 0 stevel 1094 0 stevel /* 1095 0 stevel * Skip this is synchronous link is used, since spppasyn won't 1096 0 stevel * be anywhere in the stream below to handle the ioctl. 1097 0 stevel */ 1098 0 stevel if (sync_serial) { 1099 0 stevel return; 1100 0 stevel } 1101 0 stevel 1102 0 stevel if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof (x)) < 0) { 1103 0 stevel warn("unable to obtain serial link status: %m"); 1104 0 stevel return; 1105 0 stevel } 1106 0 stevel switch (~x) { 1107 0 stevel case RCV_B7_0: 1108 0 stevel s = "bit 7 set to 1"; 1109 0 stevel break; 1110 0 stevel case RCV_B7_1: 1111 0 stevel s = "bit 7 set to 0"; 1112 0 stevel break; 1113 0 stevel case RCV_EVNP: 1114 0 stevel s = "odd parity"; 1115 0 stevel break; 1116 0 stevel case RCV_ODDP: 1117 0 stevel s = "even parity"; 1118 0 stevel break; 1119 0 stevel } 1120 0 stevel if (s != NULL) { 1121 0 stevel warn("Serial link is not 8-bit clean:"); 1122 0 stevel warn("All received characters had %s", s); 1123 0 stevel } 1124 0 stevel } 1125 0 stevel 1126 0 stevel /* 1127 0 stevel * List of valid speeds. 1128 0 stevel */ 1129 0 stevel struct speed { 1130 0 stevel int speed_int; 1131 0 stevel int speed_val; 1132 0 stevel } speeds [] = { 1133 0 stevel #ifdef B50 1134 0 stevel { 50, B50 }, 1135 0 stevel #endif 1136 0 stevel #ifdef B75 1137 0 stevel { 75, B75 }, 1138 0 stevel #endif 1139 0 stevel #ifdef B110 1140 0 stevel { 110, B110 }, 1141 0 stevel #endif 1142 0 stevel #ifdef B134 1143 0 stevel { 134, B134 }, 1144 0 stevel #endif 1145 0 stevel #ifdef B150 1146 0 stevel { 150, B150 }, 1147 0 stevel #endif 1148 0 stevel #ifdef B200 1149 0 stevel { 200, B200 }, 1150 0 stevel #endif 1151 0 stevel #ifdef B300 1152 0 stevel { 300, B300 }, 1153 0 stevel #endif 1154 0 stevel #ifdef B600 1155 0 stevel { 600, B600 }, 1156 0 stevel #endif 1157 0 stevel #ifdef B1200 1158 0 stevel { 1200, B1200 }, 1159 0 stevel #endif 1160 0 stevel #ifdef B1800 1161 0 stevel { 1800, B1800 }, 1162 0 stevel #endif 1163 0 stevel #ifdef B2000 1164 0 stevel { 2000, B2000 }, 1165 0 stevel #endif 1166 0 stevel #ifdef B2400 1167 0 stevel { 2400, B2400 }, 1168 0 stevel #endif 1169 0 stevel #ifdef B3600 1170 0 stevel { 3600, B3600 }, 1171 0 stevel #endif 1172 0 stevel #ifdef B4800 1173 0 stevel { 4800, B4800 }, 1174 0 stevel #endif 1175 0 stevel #ifdef B7200 1176 0 stevel { 7200, B7200 }, 1177 0 stevel #endif 1178 0 stevel #ifdef B9600 1179 0 stevel { 9600, B9600 }, 1180 0 stevel #endif 1181 0 stevel #ifdef B19200 1182 0 stevel { 19200, B19200 }, 1183 0 stevel #endif 1184 0 stevel #ifdef B38400 1185 0 stevel { 38400, B38400 }, 1186 0 stevel #endif 1187 0 stevel #ifdef EXTA 1188 0 stevel { 19200, EXTA }, 1189 0 stevel #endif 1190 0 stevel #ifdef EXTB 1191 0 stevel { 38400, EXTB }, 1192 0 stevel #endif 1193 0 stevel #ifdef B57600 1194 0 stevel { 57600, B57600 }, 1195 0 stevel #endif 1196 0 stevel #ifdef B76800 1197 0 stevel { 76800, B76800 }, 1198 0 stevel #endif 1199 0 stevel #ifdef B115200 1200 0 stevel { 115200, B115200 }, 1201 0 stevel #endif 1202 0 stevel #ifdef B153600 1203 0 stevel { 153600, B153600 }, 1204 0 stevel #endif 1205 0 stevel #ifdef B230400 1206 0 stevel { 230400, B230400 }, 1207 0 stevel #endif 1208 0 stevel #ifdef B307200 1209 0 stevel { 307200, B307200 }, 1210 0 stevel #endif 1211 0 stevel #ifdef B460800 1212 0 stevel { 460800, B460800 }, 1213 9354 Tim #endif 1214 9354 Tim #ifdef B921600 1215 9354 Tim { 921600, B921600 }, 1216 0 stevel #endif 1217 0 stevel { 0, 0 } 1218 0 stevel }; 1219 0 stevel 1220 0 stevel /* 1221 0 stevel * translate_speed() 1222 0 stevel * 1223 0 stevel * Translate from bits/second to a speed_t 1224 0 stevel */ 1225 0 stevel static int 1226 0 stevel translate_speed(int bps) 1227 0 stevel { 1228 0 stevel struct speed *speedp; 1229 0 stevel 1230 0 stevel if (bps == 0) { 1231 0 stevel return (0); 1232 0 stevel } 1233 0 stevel for (speedp = speeds; speedp->speed_int; speedp++) { 1234 0 stevel if (bps == speedp->speed_int) { 1235 0 stevel return (speedp->speed_val); 1236 0 stevel } 1237 0 stevel } 1238 0 stevel set_source(&speed_info); 1239 0 stevel option_error("speed %d not supported", bps); 1240 0 stevel return (0); 1241 0 stevel } 1242 0 stevel 1243 0 stevel /* 1244 0 stevel * baud_rate_of() 1245 0 stevel * 1246 0 stevel * Translate from a speed_t to bits/second 1247 0 stevel */ 1248 0 stevel static int 1249 0 stevel baud_rate_of(int speed) 1250 0 stevel { 1251 0 stevel struct speed *speedp; 1252 0 stevel 1253 0 stevel if (speed == 0) { 1254 0 stevel return (0); 1255 0 stevel } 1256 0 stevel for (speedp = speeds; speedp->speed_int; speedp++) { 1257 0 stevel if (speed == speedp->speed_val) { 1258 0 stevel return (speedp->speed_int); 1259 0 stevel } 1260 0 stevel } 1261 0 stevel return (0); 1262 0 stevel } 1263 0 stevel 1264 0 stevel /* 1265 0 stevel * set_up_tty() 1266 0 stevel * 1267 0 stevel * Set up the serial port on `fd' for 8 bits, no parity, at the requested 1268 0 stevel * speed, etc. If `local' is true, set CLOCAL regardless of whether the 1269 0 stevel * modem option was specified. 1270 0 stevel */ 1271 0 stevel void 1272 0 stevel set_up_tty(fd, local) 1273 0 stevel int fd, local; 1274 0 stevel { 1275 0 stevel int speed; 1276 0 stevel struct termios tios; 1277 0 stevel struct scc_mode sm; 1278 0 stevel 1279 0 stevel if (already_ppp) 1280 0 stevel return; 1281 0 stevel 1282 0 stevel if (sync_serial) { 1283 0 stevel restore_term = 0; 1284 0 stevel speed = B0; 1285 0 stevel baud_rate = 0; 1286 0 stevel 1287 0 stevel if (strioctl(fd, S_IOCGETMODE, &sm, sizeof (sm), 1288 0 stevel sizeof (sm)) < 0) { 1289 0 stevel return; 1290 0 stevel } 1291 0 stevel 1292 0 stevel baud_rate = sm.sm_baudrate; 1293 0 stevel dbglog("synchronous speed appears to be %d bps", baud_rate); 1294 0 stevel } else { 1295 0 stevel if (tcgetattr(fd, &tios) < 0) { 1296 0 stevel fatal("tcgetattr: %m"); 1297 0 stevel } 1298 0 stevel if (!restore_term) { 1299 0 stevel inittermios = tios; 1300 0 stevel if (myioctl(fd, TIOCGWINSZ, &wsinfo) < 0) { 1301 0 stevel if (errno == EINVAL) { 1302 0 stevel /* 1303 0 stevel * ptem returns EINVAL if all zeroes. 1304 0 stevel * Strange and unfixable code. 1305 0 stevel */ 1306 0 stevel bzero(&wsinfo, sizeof (wsinfo)); 1307 0 stevel } else { 1308 0 stevel warn("unable to get TTY window " 1309 0 stevel "size: %m"); 1310 0 stevel } 1311 0 stevel } 1312 0 stevel } 1313 0 stevel tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); 1314 0 stevel if (crtscts > 0) { 1315 0 stevel tios.c_cflag |= CRTSCTS | CRTSXOFF; 1316 0 stevel } else if (crtscts < 0) { 1317 0 stevel tios.c_cflag &= ~CRTSCTS & ~CRTSXOFF; 1318 0 stevel } 1319 0 stevel tios.c_cflag |= CS8 | CREAD | HUPCL; 1320 0 stevel if (local || !modem) { 1321 0 stevel tios.c_cflag |= CLOCAL; 1322 0 stevel } 1323 0 stevel tios.c_iflag = IGNBRK | IGNPAR; 1324 0 stevel tios.c_oflag = 0; 1325 0 stevel tios.c_lflag = 0; 1326 0 stevel tios.c_cc[VMIN] = 1; 1327 0 stevel tios.c_cc[VTIME] = 0; 1328 0 stevel 1329 0 stevel if (crtscts == -2) { 1330 0 stevel tios.c_iflag |= IXON | IXOFF; 1331 0 stevel tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ 1332 0 stevel tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ 1333 0 stevel } 1334 0 stevel speed = translate_speed(inspeed); 1335 0 stevel if (speed) { 1336 0 stevel (void) cfsetospeed(&tios, speed); 1337 0 stevel (void) cfsetispeed(&tios, speed); 1338 0 stevel } else { 1339 0 stevel speed = cfgetospeed(&tios); 1340 0 stevel /* 1341 0 stevel * We can't proceed if the serial port speed is 0, 1342 0 stevel * since that implies that the serial port is disabled. 1343 0 stevel */ 1344 0 stevel if (speed == B0) { 1345 0 stevel fatal("Baud rate for %s is 0; need explicit " 1346 0 stevel "baud rate", devnam); 1347 0 stevel } 1348 0 stevel } 1349 0 stevel if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { 1350 0 stevel fatal("tcsetattr: %m"); 1351 0 stevel } 1352 0 stevel baud_rate = baud_rate_of(speed); 1353 0 stevel dbglog("%s speed set to %d bps", 1354 0 stevel fd == pty_slave ? "pty" : "serial", baud_rate); 1355 0 stevel restore_term = 1; 1356 0 stevel } 1357 0 stevel } 1358 0 stevel 1359 0 stevel /* 1360 0 stevel * restore_tty() 1361 0 stevel * 1362 0 stevel * Restore the terminal to the saved settings. 1363 0 stevel */ 1364 0 stevel void 1365 0 stevel restore_tty(fd) 1366 0 stevel int fd; 1367 0 stevel { 1368 0 stevel if (restore_term == 0) { 1369 0 stevel return; 1370 0 stevel } 1371 0 stevel if (!default_device) { 1372 0 stevel /* 1373 0 stevel * Turn off echoing, because otherwise we can get into 1374 0 stevel * a loop with the tty and the modem echoing to each 1375 0 stevel * other. We presume we are the sole user of this tty 1376 0 stevel * device, so when we close it, it will revert to its 1377 0 stevel * defaults anyway. 1378 0 stevel */ 1379 0 stevel inittermios.c_lflag &= ~(ECHO | ECHONL); 1380 0 stevel } 1381 0 stevel if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) { 1382 0 stevel if (!hungup && errno != ENXIO) { 1383 0 stevel warn("tcsetattr: %m"); 1384 0 stevel } 1385 0 stevel } 1386 0 stevel if (wsinfo.ws_row != 0 || wsinfo.ws_col != 0 || 1387 0 stevel wsinfo.ws_xpixel != 0 || wsinfo.ws_ypixel != 0) { 1388 0 stevel if (myioctl(fd, TIOCSWINSZ, &wsinfo) < 0) { 1389 0 stevel warn("unable to set TTY window size: %m"); 1390 0 stevel } 1391 0 stevel } 1392 0 stevel restore_term = 0; 1393 0 stevel } 1394 0 stevel 1395 0 stevel /* 1396 0 stevel * setdtr() 1397 0 stevel * 1398 0 stevel * Control the DTR line on the serial port. This is called from die(), so it 1399 0 stevel * shouldn't call die() 1400 0 stevel */ 1401 0 stevel void 1402 0 stevel setdtr(fd, on) 1403 0 stevel int fd, on; 1404 0 stevel { 1405 0 stevel int modembits = TIOCM_DTR; 1406 0 stevel if (!already_ppp && 1407 0 stevel myioctl(fd, (on ? TIOCMBIS : TIOCMBIC), &modembits) < 0) { 1408 0 stevel warn("unable to set DTR line %s: %m", (on ? "ON" : "OFF")); 1409 0 stevel } 1410 0 stevel } 1411 0 stevel 1412 0 stevel /* 1413 0 stevel * open_loopback() 1414 0 stevel * 1415 0 stevel * Open the device we use for getting packets in demand mode. Under Solaris 2, 1416 0 stevel * we use our existing fd to the ppp driver. 1417 0 stevel */ 1418 0 stevel int 1419 0 stevel open_ppp_loopback() 1420 0 stevel { 1421 0 stevel /* 1422 0 stevel * Plumb the interface. 1423 0 stevel */ 1424 0 stevel if (IPCP_ENABLED && (plumb_ipif(0) == 0)) { 1425 0 stevel fatal("Unable to initialize IP interface for demand dial."); 1426 0 stevel } 1427 0 stevel #ifdef INET6 1428 0 stevel if (IPV6CP_ENABLED && (plumb_ip6if(0) == 0)) { 1429 0 stevel fatal("Unable to initialize IPv6 interface for demand dial."); 1430 0 stevel } 1431 0 stevel #endif /* INET6 */ 1432 0 stevel 1433 0 stevel return (pppfd); 1434 0 stevel } 1435 0 stevel 1436 0 stevel /* 1437 0 stevel * output() 1438 0 stevel * 1439 0 stevel * Output PPP packet downstream 1440 0 stevel */ 1441 0 stevel /*ARGSUSED*/ 1442 0 stevel void 1443 0 stevel output(unit, p, len) 1444 0 stevel int unit; 1445 0 stevel uchar_t *p; 1446 0 stevel int len; 1447 0 stevel { 1448 0 stevel struct strbuf data; 1449 0 stevel struct pollfd pfd; 1450 0 stevel int retries, n; 1451 0 stevel bool sent_ok = 1; 1452 0 stevel 1453 0 stevel data.len = len; 1454 0 stevel data.buf = (caddr_t)p; 1455 0 stevel retries = 4; 1456 0 stevel 1457 0 stevel while (putmsg(pppfd, NULL, &data, 0) < 0) { 1458 0 stevel if (errno == EINTR) 1459 0 stevel continue; 1460 0 stevel if (--retries < 0 || 1461 0 stevel (errno != EWOULDBLOCK && errno != EAGAIN)) { 1462 0 stevel if (errno != ENXIO) { 1463 0 stevel error("Couldn't send packet: %m"); 1464 0 stevel sent_ok = 0; 1465 0 stevel } 1466 0 stevel break; 1467 0 stevel } 1468 0 stevel pfd.fd = pppfd; 1469 0 stevel pfd.events = POLLOUT; 1470 0 stevel do { 1471 0 stevel /* wait for up to 0.25 seconds */ 1472 0 stevel n = poll(&pfd, 1, 250); 1473 0 stevel } while ((n == -1) && (errno == EINTR)); 1474 0 stevel } 1475 0 stevel if (debug && sent_ok) { 1476 0 stevel dbglog("sent %P", p, len); 1477 0 stevel } 1478 0 stevel } 1479 0 stevel 1480 0 stevel /* 1481 0 stevel * wait_input() 1482 0 stevel * 1483 0 stevel * Wait until there is data available, for the length of time specified by 1484 0 stevel * timo (indefinite if timo is NULL). 1485 0 stevel */ 1486 0 stevel void 1487 0 stevel wait_input(timo) 1488 0 stevel struct timeval *timo; 1489 0 stevel { 1490 0 stevel int t; 1491 0 stevel 1492 0 stevel t = (timo == NULL ? -1 : (timo->tv_sec * 1000 + timo->tv_usec / 1000)); 1493 0 stevel if ((poll(pollfds, n_pollfds, t) < 0) && (errno != EINTR)) { 1494 0 stevel fatal("poll: %m"); 1495 0 stevel } 1496 0 stevel } 1497 0 stevel 1498 0 stevel /* 1499 0 stevel * add_fd() 1500 0 stevel * 1501 0 stevel * Add an fd to the set that wait_input waits for. 1502 0 stevel */ 1503 0 stevel void 1504 0 stevel add_fd(fd) 1505 0 stevel int fd; 1506 0 stevel { 1507 0 stevel int n; 1508 0 stevel 1509 0 stevel if (fd < 0) { 1510 0 stevel return; 1511 0 stevel } 1512 0 stevel for (n = 0; n < n_pollfds; ++n) { 1513 0 stevel if (pollfds[n].fd == fd) { 1514 0 stevel return; 1515 0 stevel } 1516 0 stevel } 1517 0 stevel if (n_pollfds < MAX_POLLFDS) { 1518 0 stevel pollfds[n_pollfds].fd = fd; 1519 0 stevel pollfds[n_pollfds].events = POLLIN | POLLPRI | POLLHUP; 1520 0 stevel ++n_pollfds; 1521 0 stevel } else { 1522 0 stevel fatal("add_fd: too many inputs!"); 1523 0 stevel } 1524 0 stevel } 1525 0 stevel 1526 0 stevel /* 1527 0 stevel * remove_fd() 1528 0 stevel * 1529 0 stevel * Remove an fd from the set that wait_input waits for. 1530 0 stevel */ 1531 0 stevel void 1532 0 stevel remove_fd(fd) 1533 0 stevel int fd; 1534 0 stevel { 1535 0 stevel int n; 1536 0 stevel 1537 0 stevel for (n = 0; n < n_pollfds; ++n) { 1538 0 stevel if (pollfds[n].fd == fd) { 1539 0 stevel while (++n < n_pollfds) { 1540 0 stevel pollfds[n-1] = pollfds[n]; 1541 0 stevel } 1542 0 stevel --n_pollfds; 1543 0 stevel break; 1544 0 stevel } 1545 0 stevel } 1546 0 stevel } 1547 0 stevel 1548 0 stevel static void 1549 0 stevel dump_packet(uchar_t *buf, int len) 1550 0 stevel { 1551 0 stevel uchar_t *bp; 1552 0 stevel int proto, offs; 1553 0 stevel const char *cp; 1554 0 stevel char sbuf[32]; 1555 0 stevel uint32_t src, dst; 1556 0 stevel struct protoent *pep; 1557 9751 james struct in6_addr addr; 1558 9751 james char fromstr[INET6_ADDRSTRLEN]; 1559 9751 james char tostr[INET6_ADDRSTRLEN]; 1560 0 stevel 1561 0 stevel if (len < 4) { 1562 9751 james notice("strange link activity: %.*B", len, buf); 1563 0 stevel return; 1564 0 stevel } 1565 0 stevel bp = buf; 1566 0 stevel if (bp[0] == 0xFF && bp[1] == 0x03) 1567 0 stevel bp += 2; 1568 0 stevel proto = *bp++; 1569 0 stevel if (!(proto & 1)) 1570 0 stevel proto = (proto << 8) + *bp++; 1571 0 stevel len -= bp-buf; 1572 9751 james switch (proto) { 1573 9751 james case PPP_IP: 1574 9751 james if (len < IP_HDRLEN || get_ipv(bp) != 4 || get_iphl(bp) < 5) { 1575 9751 james notice("strange IP packet activity: %16.*B", len, buf); 1576 0 stevel return; 1577 0 stevel } 1578 0 stevel src = get_ipsrc(bp); 1579 0 stevel dst = get_ipdst(bp); 1580 0 stevel proto = get_ipproto(bp); 1581 0 stevel if ((pep = getprotobynumber(proto)) != NULL) { 1582 0 stevel cp = pep->p_name; 1583 0 stevel } else { 1584 0 stevel (void) slprintf(sbuf, sizeof (sbuf), "IP proto %d", 1585 0 stevel proto); 1586 0 stevel cp = sbuf; 1587 0 stevel } 1588 0 stevel if ((get_ipoff(bp) & IP_OFFMASK) != 0) { 1589 0 stevel len -= get_iphl(bp) * 4; 1590 0 stevel bp += get_iphl(bp) * 4; 1591 9751 james notice("%s fragment from %I->%I: %8.*B", cp, src, dst, 1592 0 stevel len, bp); 1593 0 stevel } else { 1594 0 stevel if (len > get_iplen(bp)) 1595 0 stevel len = get_iplen(bp); 1596 0 stevel len -= get_iphl(bp) * 4; 1597 0 stevel bp += get_iphl(bp) * 4; 1598 0 stevel offs = proto == IPPROTO_TCP ? (get_tcpoff(bp)*4) : 8; 1599 0 stevel if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) 1600 9751 james notice("%s data:%d %s%I:%d->%I:%d: %8.*B", cp, 1601 9751 james len-offs, 1602 9751 james proto == IPPROTO_TCP ? 1603 9751 james tcp_flag_decode(get_tcpflags(bp)) : "", 1604 9751 james src, get_sport(bp), dst, get_dport(bp), 1605 9751 james len-offs, bp+offs); 1606 0 stevel else 1607 9751 james notice("%s %d bytes %I->%I: %8.*B", cp, len, 1608 0 stevel src, dst, len, bp); 1609 0 stevel } 1610 9751 james return; 1611 9751 james 1612 9751 james case PPP_IPV6: 1613 9751 james if (len < IP6_HDRLEN) { 1614 9751 james notice("strange IPv6 activity: %16.*B", len, buf); 1615 9751 james return; 1616 9751 james } 1617 9751 james (void) BCOPY(get_ip6src(bp), &addr, sizeof (addr)); 1618 9751 james (void) inet_ntop(AF_INET6, &addr, fromstr, sizeof (fromstr)); 1619 9751 james (void) BCOPY(get_ip6dst(bp), &addr, sizeof (addr)); 1620 9751 james (void) inet_ntop(AF_INET6, &addr, tostr, sizeof (tostr)); 1621 9751 james proto = get_ip6nh(bp); 1622 9751 james if (proto == IPPROTO_FRAGMENT) { 1623 9751 james notice("IPv6 fragment from %s->%s", fromstr, 1624 9751 james tostr); 1625 9751 james return; 1626 9751 james } 1627 9751 james if ((pep = getprotobynumber(proto)) != NULL) { 1628 9751 james cp = pep->p_name; 1629 9751 james } else { 1630 9751 james (void) slprintf(sbuf, sizeof (sbuf), "IPv6 proto %d", 1631 9751 james proto); 1632 9751 james cp = sbuf; 1633 9751 james } 1634 9751 james len -= IP6_HDRLEN; 1635 9751 james bp += IP6_HDRLEN; 1636 9751 james offs = proto == IPPROTO_TCP ? (get_tcpoff(bp)*4) : 8; 1637 9751 james if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) 1638 9751 james notice("%s data:%d %s[%s]%d->[%s]%d: %8.*B", cp, 1639 9751 james len-offs, 1640 9751 james proto == IPPROTO_TCP ? 1641 9751 james tcp_flag_decode(get_tcpflags(bp)) : "", 1642 9751 james fromstr, get_sport(bp), tostr, get_dport(bp), 1643 9751 james len-offs, bp+offs); 1644 9751 james else 1645 9751 james notice("%s %d bytes %s->%s: %8.*B", cp, len, 1646 9751 james fromstr, tostr, len, bp); 1647 0 stevel return; 1648 0 stevel } 1649 0 stevel if ((cp = protocol_name(proto)) == NULL) { 1650 0 stevel (void) slprintf(sbuf, sizeof (sbuf), "0x#X", proto); 1651 0 stevel cp = (const char *)sbuf; 1652 0 stevel } 1653 9751 james notice("link activity: %s %16.*B", cp, len, bp); 1654 0 stevel } 1655 0 stevel 1656 0 stevel /* 1657 0 stevel * handle_bind() 1658 0 stevel */ 1659 0 stevel static void 1660 0 stevel handle_bind(u_int32_t reason) 1661 0 stevel { 1662 0 stevel /* 1663 0 stevel * Here we might, in the future, handle DL_BIND_REQ notifications 1664 0 stevel * in order to close and re-open a NCP when certain interface 1665 0 stevel * parameters (addresses, etc.) are changed via external mechanisms 1666 0 stevel * such as through the "ifconfig" program. 1667 0 stevel */ 1668 0 stevel switch (reason) { 1669 0 stevel case PPP_LINKSTAT_IPV4_BOUND: 1670 0 stevel break; 1671 0 stevel #ifdef INET6 1672 0 stevel case PPP_LINKSTAT_IPV6_BOUND: 1673 0 stevel break; 1674 0 stevel #endif 1675 0 stevel default: 1676 0 stevel error("handle_bind: unrecognized reason"); 1677 0 stevel break; 1678 0 stevel } 1679 0 stevel } 1680 0 stevel 1681 0 stevel /* 1682 0 stevel * handle_unbind() 1683 0 stevel */ 1684 0 stevel static void 1685 0 stevel handle_unbind(u_int32_t reason) 1686 0 stevel { 1687 0 stevel bool iff_up_isset; 1688 0 stevel int rc; 1689 0 stevel static const char *unplumb_str = "unplumbed"; 1690 0 stevel static const char *down_str = "downed"; 1691 0 stevel 1692 0 stevel /* 1693 0 stevel * Since the kernel driver (sppp) notifies this daemon of the 1694 0 stevel * DLPI bind/unbind activities (for the purpose of bringing down 1695 0 stevel * a NCP), we need to explicitly test the "actual" status of 1696 0 stevel * the interface instance for which the notification is destined 1697 0 stevel * from. This is because /dev/ip performs multiple DLPI attach- 1698 0 stevel * bind-unbind-detach during the early life of the interface, 1699 0 stevel * and when certain interface parameters change. A DL_UNBIND_REQ 1700 0 stevel * coming down to the sppp driver from /dev/ip (which results in 1701 0 stevel * our receiving of the PPP_LINKSTAT_*_UNBOUND link status message) 1702 0 stevel * is not enough to conclude that the interface has been marked 1703 0 stevel * DOWN (its IFF_UP bit is cleared) or is going away. Therefore, 1704 0 stevel * we should query /dev/ip directly, upon receiving such *_UNBOUND 1705 0 stevel * notification, to determine whether the interface is DOWN 1706 0 stevel * for real, and only take the necessary actions when IFF_UP 1707 0 stevel * bit for the interface instance is actually cleared. 1708 0 stevel */ 1709 0 stevel switch (reason) { 1710 0 stevel case PPP_LINKSTAT_IPV4_UNBOUND: 1711 0 stevel (void) sleep(1); 1712 0 stevel rc = giflags(IFF_UP, &iff_up_isset); 1713 0 stevel if (!iff_up_isset) { 1714 0 stevel if_is_up = 0; 1715 0 stevel ipmuxid = -1; 1716 0 stevel info("IPv4 interface %s by administrator", 1717 0 stevel ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str)); 1718 0 stevel fsm_close(&ipcp_fsm[0], 1719 0 stevel "administratively disconnected"); 1720 0 stevel } 1721 0 stevel break; 1722 0 stevel #ifdef INET6 1723 0 stevel case PPP_LINKSTAT_IPV6_UNBOUND: 1724 0 stevel (void) sleep(1); 1725 0 stevel rc = giflags(IFF_UP, &iff_up_isset); 1726 0 stevel if (!iff_up_isset) { 1727 0 stevel if6_is_up = 0; 1728 0 stevel ip6muxid = -1; 1729 0 stevel info("IPv6 interface %s by administrator", 1730 0 stevel ((rc < 0 && rc == ENXIO) ? unplumb_str : down_str)); 1731 0 stevel fsm_close(&ipv6cp_fsm[0], 1732 0 stevel "administratively disconnected"); 1733 0 stevel } 1734 0 stevel break; 1735 0 stevel #endif 1736 0 stevel default: 1737 0 stevel error("handle_unbind: unrecognized reason"); 1738 0 stevel break; 1739 0 stevel } 1740 0 stevel } 1741 0 stevel 1742 0 stevel /* 1743 0 stevel * read_packet() 1744 0 stevel * 1745 0 stevel * Get a PPP packet from the serial device. 1746 0 stevel */ 1747 0 stevel int 1748 0 stevel read_packet(buf) 1749 0 stevel uchar_t *buf; 1750 0 stevel { 1751 0 stevel struct strbuf ctrl; 1752 0 stevel struct strbuf data; 1753 0 stevel int flags; 1754 0 stevel int len; 1755 0 stevel int rc; 1756 0 stevel struct ppp_ls *plp; 1757 0 stevel uint32_t ctrlbuf[1536 / sizeof (uint32_t)]; 1758 0 stevel bool flushmode; 1759 0 stevel 1760 0 stevel flushmode = 0; 1761 0 stevel for (;;) { 1762 0 stevel 1763 0 stevel data.maxlen = PPP_MRU + PPP_HDRLEN; 1764 0 stevel data.buf = (caddr_t)buf; 1765 0 stevel 1766 0 stevel ctrl.maxlen = sizeof (ctrlbuf); 1767 0 stevel ctrl.buf = (caddr_t)ctrlbuf; 1768 0 stevel 1769 0 stevel flags = 0; 1770 0 stevel rc = len = getmsg(pppfd, &ctrl, &data, &flags); 1771 0 stevel if (sys_read_packet_hook != NULL) { 1772 0 stevel rc = len = (*sys_read_packet_hook)(len, &ctrl, &data, 1773 0 stevel flags); 1774 0 stevel } 1775 0 stevel if (len < 0) { 1776 0 stevel if (errno == EAGAIN || errno == EINTR) { 1777 0 stevel return (-1); 1778 0 stevel } 1779 0 stevel fatal("Error reading packet: %m"); 1780 0 stevel } 1781 0 stevel if ((data.len > 0) && (ctrl.len < 0)) { 1782 0 stevel /* 1783 0 stevel * If there's more data on stream head, keep reading 1784 0 stevel * but discard, since the stream is now corrupt. 1785 0 stevel */ 1786 0 stevel if (rc & MOREDATA) { 1787 0 stevel dbglog("More data; input packet garbled"); 1788 0 stevel flushmode = 1; 1789 0 stevel continue; 1790 0 stevel } 1791 0 stevel if (flushmode) 1792 0 stevel return (-1); 1793 0 stevel return (data.len); 1794 0 stevel 1795 0 stevel } else if (ctrl.len > 0) { 1796 0 stevel /* 1797 0 stevel * If there's more ctl on stream head, keep reading, 1798 0 stevel * but start discarding. We can't deal with fragmented 1799 0 stevel * messages at all. 1800 0 stevel */ 1801 0 stevel if (rc & MORECTL) { 1802 0 stevel dbglog("More control; stream garbled"); 1803 0 stevel flushmode = 1; 1804 0 stevel continue; 1805 0 stevel } 1806 0 stevel if (flushmode) 1807 0 stevel return (-1); 1808 0 stevel if (ctrl.len < sizeof (struct ppp_ls)) { 1809 0 stevel warn("read_packet: ctl.len %d < " 1810 0 stevel "sizeof ppp_ls %d", 1811 0 stevel ctrl.len, sizeof (struct ppp_ls)); 1812 0 stevel return (-1); 1813 0 stevel } 1814 0 stevel plp = (struct ppp_ls *)ctrlbuf; 1815 0 stevel if (plp->magic != PPPLSMAGIC) { 1816 0 stevel /* Skip, as we don't understand it */ 1817 0 stevel dbglog("read_packet: unrecognized control %lX", 1818 0 stevel plp->magic); 1819 0 stevel return (-1); 1820 0 stevel } 1821 0 stevel 1822 0 stevel lastlink_status = plp->ppp_message; 1823 0 stevel 1824 0 stevel switch (plp->ppp_message) { 1825 0 stevel case PPP_LINKSTAT_HANGUP: 1826 0 stevel return (0); /* Hangup */ 1827 0 stevel /* For use by integrated drivers. */ 1828 0 stevel case PPP_LINKSTAT_UP: 1829 0 stevel lcp_lowerdown(0); 1830 0 stevel lcp_lowerup(0); 1831 0 stevel return (0); 1832 0 stevel case PPP_LINKSTAT_NEEDUP: 1833 9751 james if (data.len > 0) 1834 0 stevel dump_packet(buf, data.len); 1835 0 stevel return (-1); /* Demand dial */ 1836 0 stevel case PPP_LINKSTAT_IPV4_UNBOUND: 1837 0 stevel (void) handle_unbind(plp->ppp_message); 1838 0 stevel return (-1); 1839 0 stevel case PPP_LINKSTAT_IPV4_BOUND: 1840 0 stevel (void) handle_bind(plp->ppp_message); 1841 0 stevel return (-1); 1842 0 stevel #ifdef INET6 1843 0 stevel case PPP_LINKSTAT_IPV6_UNBOUND: 1844 0 stevel (void) handle_unbind(plp->ppp_message); 1845 0 stevel return (-1); 1846 0 stevel case PPP_LINKSTAT_IPV6_BOUND: 1847 0 stevel (void) handle_bind(plp->ppp_message); 1848 0 stevel return (-1); 1849 0 stevel #endif 1850 0 stevel default: 1851 0 stevel warn("read_packet: unknown link status type!"); 1852 0 stevel return (-1); 1853 0 stevel } 1854 0 stevel } else { 1855 0 stevel /* 1856 0 stevel * We get here on zero length data or control. 1857 0 stevel */ 1858 0 stevel return (-1); 1859 0 stevel } 1860 0 stevel } 1861 0 stevel } 1862 0 stevel 1863 0 stevel /* 1864 0 stevel * get_loop_output() 1865 0 stevel * 1866 0 stevel * Get outgoing packets from the ppp device, and detect when we want to bring 1867 0 stevel * the real link up. Return value is 1 if we need to bring up the link, or 0 1868 0 stevel * otherwise. 1869 0 stevel */ 1870 0 stevel int 1871 0 stevel get_loop_output() 1872 0 stevel { 1873 0 stevel int loops; 1874 0 stevel 1875 0 stevel /* 1876 0 stevel * In the Solaris 2.x kernel-level portion implementation, packets 1877 0 stevel * which are received on a demand-dial interface are immediately 1878 0 stevel * discarded, and a notification message is sent up the control 1879 0 stevel * stream to the pppd process. Therefore, the call to read_packet() 1880 0 stevel * below is merely there to wait for such message. 1881 0 stevel */ 1882 0 stevel lastlink_status = 0; 1883 0 stevel loops = 0; 1884 0 stevel while (read_packet(inpacket_buf) > 0) { 1885 0 stevel if (++loops > 10) 1886 0 stevel break; 1887 0 stevel } 1888 0 stevel return (lastlink_status == PPP_LINKSTAT_NEEDUP); 1889 0 stevel } 1890 0 stevel 1891 0 stevel #ifdef MUX_FRAME 1892 0 stevel /*ARGSUSED*/ 1893 0 stevel void 1894 0 stevel ppp_send_muxoption(unit, muxflag) 1895 0 stevel int unit; 1896 0 stevel u_int32_t muxflag; 1897 0 stevel { 1898 0 stevel uint32_t cf[2]; 1899 0 stevel 1900 0 stevel /* 1901 0 stevel * Since muxed frame feature is implemented in the async module, 1902 0 stevel * don't send down the ioctl in the synchronous case. 1903 0 stevel */ 1904 0 stevel if (!sync_serial && fdmuxid >= 0 && pppfd != -1) { 1905 0 stevel cf[0] = muxflag; 1906 0 stevel cf[1] = X_MUXMASK; 1907 0 stevel 1908 0 stevel if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) { 1909 0 stevel error("Couldn't set mux option: %m"); 1910 0 stevel } 1911 0 stevel } 1912 0 stevel } 1913 0 stevel 1914 0 stevel /*ARGSUSED*/ 1915 0 stevel void 1916 0 stevel ppp_recv_muxoption(unit, muxflag) 1917 0 stevel int unit; 1918 0 stevel u_int32_t muxflag; 1919 0 stevel { 1920 0 stevel uint32_t cf[2]; 1921 0 stevel 1922 0 stevel /* 1923 0 stevel * Since muxed frame feature is implemented in the async module, 1924 0 stevel * don't send down the ioctl in the synchronous case. 1925 0 stevel */ 1926 0 stevel if (!sync_serial && fdmuxid >= 0 && pppfd != -1) { 1927 0 stevel cf[0] = muxflag; 1928 0 stevel cf[1] = R_MUXMASK; 1929 0 stevel 1930 0 stevel if (strioctl(pppfd, PPPIO_MUX, cf, sizeof (cf), 0) < 0) { 1931 0 stevel error("Couldn't set receive mux option: %m"); 1932 0 stevel } 1933 0 stevel } 1934 0 stevel } 1935 0 stevel #endif 1936 0 stevel 1937 0 stevel /* 1938 0 stevel * ppp_send_config() 1939 0 stevel * 1940 0 stevel * Configure the transmit characteristics of the ppp interface. 1941 0 stevel */ 1942 0 stevel /*ARGSUSED*/ 1943 0 stevel void 1944 0 stevel ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) 1945 0 stevel int unit; 1946 0 stevel int mtu; 1947 0 stevel u_int32_t asyncmap; 1948 0 stevel int pcomp; 1949 0 stevel int accomp; 1950 0 stevel { 1951 0 stevel uint32_t cf[2]; 1952 0 stevel 1953 0 stevel if (pppfd == -1) { 1954 0 stevel error("ppp_send_config called with invalid device handle"); 1955 0 stevel return; 1956 0 stevel } 1957 0 stevel cf[0] = link_mtu = mtu; 1958 0 stevel if (strioctl(pppfd, PPPIO_MTU, cf, sizeof (cf[0]), 0) < 0) { 1959 0 stevel if (hungup && errno == ENXIO) { 1960 0 stevel return; 1961 0 stevel } 1962 0 stevel error("Couldn't set MTU: %m"); 1963 0 stevel } 1964 0 stevel if (fdmuxid != -1) { 1965 0 stevel if (!sync_serial) { 1966 0 stevel if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, 1967 0 stevel sizeof (asyncmap), 0) < 0) { 1968 0 stevel error("Couldn't set transmit ACCM: %m"); 1969 0 stevel } 1970 0 stevel } 1971 0 stevel cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0); 1972 0 stevel cf[1] = COMP_PROT | COMP_AC; 1973 0 stevel 1974 0 stevel if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf, 1975 0 stevel sizeof (cf), sizeof (cf[0])) < 0) { 1976 0 stevel error("Couldn't set prot/AC compression: %m"); 1977 0 stevel } 1978 0 stevel } 1979 0 stevel } 1980 0 stevel 1981 0 stevel /* 1982 0 stevel * ppp_set_xaccm() 1983 0 stevel * 1984 0 stevel * Set the extended transmit ACCM for the interface. 1985 0 stevel */ 1986 0 stevel /*ARGSUSED*/ 1987 0 stevel void 1988 0 stevel ppp_set_xaccm(unit, accm) 1989 0 stevel int unit; 1990 0 stevel ext_accm accm; 1991 0 stevel { 1992 0 stevel if (sync_serial) { 1993 0 stevel return; 1994 0 stevel } 1995 0 stevel if (fdmuxid != -1 && strioctl(pppfd, PPPIO_XACCM, accm, 1996 0 stevel sizeof (ext_accm), 0) < 0) { 1997 0 stevel if (!hungup || errno != ENXIO) { 1998 0 stevel warn("Couldn't set extended ACCM: %m"); 1999 0 stevel } 2000 0 stevel } 2001 0 stevel } 2002 0 stevel 2003 0 stevel /* 2004 0 stevel * ppp_recv_config() 2005 0 stevel * 2006 0 stevel * Configure the receive-side characteristics of the ppp interface. 2007 0 stevel */ 2008 0 stevel /*ARGSUSED*/ 2009 0 stevel void 2010 0 stevel ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) 2011 0 stevel int unit; 2012 0 stevel int mru; 2013 0 stevel u_int32_t asyncmap; 2014 0 stevel int pcomp; 2015 0 stevel int accomp; 2016 0 stevel { 2017 0 stevel uint32_t cf[2]; 2018 0 stevel 2019 0 stevel if (pppfd == -1) { 2020 0 stevel error("ppp_recv_config called with invalid device handle"); 2021 0 stevel return; 2022 0 stevel } 2023 0 stevel cf[0] = mru; 2024 0 stevel if (strioctl(pppfd, PPPIO_MRU, cf, sizeof (cf[0]), 0) < 0) { 2025 0 stevel if (hungup && errno == ENXIO) { 2026 0 stevel return; 2027 0 stevel } 2028 0 stevel error("Couldn't set MRU: %m"); 2029 0 stevel } 2030 0 stevel if (fdmuxid != -1) { 2031 0 stevel if (!sync_serial) { 2032 0 stevel if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, 2033 0 stevel sizeof (asyncmap), 0) < 0) { 2034 0 stevel error("Couldn't set receive ACCM: %m"); 2035 0 stevel } 2036 0 stevel } 2037 0 stevel cf[0] = (pcomp ? DECOMP_PROT : 0) + (accomp ? DECOMP_AC : 0); 2038 0 stevel cf[1] = DECOMP_PROT | DECOMP_AC; 2039 0 stevel 2040 0 stevel if (any_compressions() && strioctl(pppfd, PPPIO_CFLAGS, cf, 2041 0 stevel sizeof (cf), sizeof (cf[0])) < 0) { 2042 0 stevel error("Couldn't set prot/AC decompression: %m"); 2043 0 stevel } 2044 0 stevel } 2045 0 stevel } 2046 0 stevel 2047 0 stevel #ifdef NEGOTIATE_FCS 2048 0 stevel /* 2049 0 stevel * ppp_send_fcs() 2050 0 stevel * 2051 0 stevel * Configure the sender-side FCS. 2052 0 stevel */ 2053 0 stevel /*ARGSUSED*/ 2054 0 stevel void 2055 0 stevel ppp_send_fcs(unit, fcstype) 2056 0 stevel int unit, fcstype; 2057 0 stevel { 2058 0 stevel uint32_t fcs; 2059 0 stevel 2060 0 stevel if (sync_serial) { 2061 0 stevel return; 2062 0 stevel } 2063 0 stevel 2064 0 stevel if (fcstype & FCSALT_32) { 2065 0 stevel fcs = PPPFCS_32; 2066 0 stevel } else if (fcstype & FCSALT_NULL) { 2067 0 stevel fcs = PPPFCS_NONE; 2068 0 stevel } else { 2069 0 stevel fcs = PPPFCS_16; 2070 0 stevel } 2071 0 stevel if (strioctl(pppfd, PPPIO_XFCS, &fcs, sizeof (fcs), 0) < 0) { 2072 0 stevel warn("Couldn't set transmit FCS: %m"); 2073 0 stevel } 2074 0 stevel } 2075 0 stevel 2076 0 stevel /* 2077 0 stevel * ppp_recv_fcs() 2078 0 stevel * 2079 0 stevel * Configure the receiver-side FCS. 2080 0 stevel */ 2081 0 stevel /*ARGSUSED*/ 2082 0 stevel void 2083 0 stevel ppp_recv_fcs(unit, fcstype) 2084 0 stevel int unit, fcstype; 2085 0 stevel { 2086 0 stevel uint32_t fcs; 2087 0 stevel 2088 0 stevel if (sync_serial) { 2089 0 stevel return; 2090 0 stevel } 2091 0 stevel 2092 0 stevel if (fcstype & FCSALT_32) { 2093 0 stevel fcs = PPPFCS_32; 2094 0 stevel } else if (fcstype & FCSALT_NULL) { 2095 0 stevel fcs = PPPFCS_NONE; 2096 0 stevel } else { 2097 0 stevel fcs = PPPFCS_16; 2098 0 stevel } 2099 0 stevel if (strioctl(pppfd, PPPIO_RFCS, &fcs, sizeof (fcs), 0) < 0) { 2100 0 stevel warn("Couldn't set receive FCS: %m"); 2101 0 stevel } 2102 0 stevel } 2103 0 stevel #endif 2104 0 stevel 2105 0 stevel /* 2106 0 stevel * ccp_test() 2107 0 stevel * 2108 0 stevel * Ask kernel whether a given compression method is acceptable for use. 2109 0 stevel */ 2110 0 stevel /*ARGSUSED*/ 2111 0 stevel int 2112 0 stevel ccp_test(unit, opt_ptr, opt_len, for_transmit) 2113 0 stevel int unit; 2114 0 stevel uchar_t *opt_ptr; 2115 0 stevel int opt_len; 2116 0 stevel int for_transmit; 2117 0 stevel { 2118 0 stevel if (strioctl(pppfd, (for_transmit ? PPPIO_XCOMP : PPPIO_RCOMP), 2119 0 stevel opt_ptr, opt_len, 0) >= 0) { 2120 0 stevel return (1); 2121 0 stevel } 2122 0 stevel warn("Error in %s ioctl: %m", 2123 0 stevel (for_transmit ? "PPPIO_XCOMP" : "PPPIO_RCOMP")); 2124 0 stevel return ((errno == ENOSR) ? 0 : -1); 2125 0 stevel } 2126 0 stevel 2127 0 stevel #ifdef COMP_TUNE 2128 0 stevel /* 2129 0 stevel * ccp_tune() 2130 0 stevel * 2131 0 stevel * Tune compression effort level. 2132 0 stevel */ 2133 0 stevel /*ARGSUSED*/ 2134 0 stevel void 2135 0 stevel ccp_tune(unit, effort) 2136 0 stevel int unit, effort; 2137 0 stevel { 2138 0 stevel uint32_t x; 2139 0 stevel 2140 0 stevel x = effort; 2141 0 stevel if (strioctl(pppfd, PPPIO_COMPLEV, &x, sizeof (x), 0) < 0) { 2142 0 stevel warn("unable to set compression effort level: %m"); 2143 0 stevel } 2144 0 stevel } 2145 0 stevel #endif 2146 0 stevel 2147 0 stevel /* 2148 0 stevel * ccp_flags_set() 2149 0 stevel * 2150 0 stevel * Inform kernel about the current state of CCP. 2151 0 stevel */ 2152 0 stevel /*ARGSUSED*/ 2153 0 stevel void 2154 0 stevel ccp_flags_set(unit, isopen, isup) 2155 0 stevel int unit, isopen, isup; 2156 0 stevel { 2157 0 stevel uint32_t cf[2]; 2158 0 stevel 2159 0 stevel cf[0] = (isopen ? CCP_ISOPEN : 0) + (isup ? CCP_ISUP : 0); 2160 0 stevel cf[1] = CCP_ISOPEN | CCP_ISUP | CCP_ERROR | CCP_FATALERROR; 2161 0 stevel 2162 0 stevel if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 2163 0 stevel < 0) { 2164 0 stevel if (!hungup || errno != ENXIO) { 2165 0 stevel error("Couldn't set kernel CCP state: %m"); 2166 0 stevel } 2167 0 stevel } 2168 0 stevel } 2169 0 stevel 2170 0 stevel /* 2171 0 stevel * get_idle_time() 2172 0 stevel * 2173 0 stevel * Return how long the link has been idle. 2174 0 stevel */ 2175 0 stevel /*ARGSUSED*/ 2176 0 stevel int 2177 0 stevel get_idle_time(u, pids) 2178 0 stevel int u; 2179 0 stevel struct ppp_idle *pids; 2180 0 stevel { 2181 0 stevel int rc; 2182 0 stevel 2183 0 stevel rc = strioctl(pppfd, PPPIO_GIDLE, pids, 0, sizeof (struct ppp_idle)); 2184 0 stevel if (rc < 0) { 2185 0 stevel warn("unable to obtain idle time: %m"); 2186 0 stevel } 2187 0 stevel return ((rc == 0) ? 1 : 0); 2188 0 stevel } 2189 0 stevel 2190 0 stevel /* 2191 0 stevel * get_ppp_stats() 2192 0 stevel * 2193 0 stevel * Return statistics for the link. 2194 0 stevel */ 2195 0 stevel /*ARGSUSED*/ 2196 0 stevel int 2197 0 stevel get_ppp_stats(u, stats) 2198 0 stevel int u; 2199 0 stevel struct pppd_stats *stats; 2200 0 stevel { 2201 0 stevel struct ppp_stats64 s64; 2202 0 stevel struct ppp_stats s; 2203 0 stevel 2204 0 stevel /* Try first to get these from the 64-bit interface */ 2205 0 stevel if (strioctl(pppfd, PPPIO_GETSTAT64, &s64, 0, sizeof (s64)) >= 0) { 2206 0 stevel stats->bytes_in = s64.p.ppp_ibytes; 2207 0 stevel stats->bytes_out = s64.p.ppp_obytes; 2208 0 stevel stats->pkts_in = s64.p.ppp_ipackets; 2209 0 stevel stats->pkts_out = s64.p.ppp_opackets; 2210 0 stevel return (1); 2211 0 stevel } 2212 0 stevel 2213 0 stevel if (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof (s)) < 0) { 2214 0 stevel error("Couldn't get link statistics: %m"); 2215 0 stevel return (0); 2216 0 stevel } 2217 0 stevel stats->bytes_in = s.p.ppp_ibytes; 2218 0 stevel stats->bytes_out = s.p.ppp_obytes; 2219 0 stevel stats->pkts_in = s.p.ppp_ipackets; 2220 0 stevel stats->pkts_out = s.p.ppp_opackets; 2221 0 stevel return (1); 2222 0 stevel } 2223 0 stevel 2224 0 stevel #if defined(FILTER_PACKETS) 2225 0 stevel /* 2226 0 stevel * set_filters() 2227 0 stevel * 2228 0 stevel * Transfer the pass and active filters to the kernel. 2229 0 stevel */ 2230 0 stevel int 2231 0 stevel set_filters(pass, active) 2232 0 stevel struct bpf_program *pass; 2233 0 stevel struct bpf_program *active; 2234 0 stevel { 2235 0 stevel int ret = 1; 2236 0 stevel 2237 0 stevel if (pass->bf_len > 0) { 2238 0 stevel if (strioctl(pppfd, PPPIO_PASSFILT, pass, 2239 0 stevel sizeof (struct bpf_program), 0) < 0) { 2240 0 stevel error("Couldn't set pass-filter in kernel: %m"); 2241 0 stevel ret = 0; 2242 0 stevel } 2243 0 stevel } 2244 0 stevel if (active->bf_len > 0) { 2245 0 stevel if (strioctl(pppfd, PPPIO_ACTIVEFILT, active, 2246 0 stevel sizeof (struct bpf_program), 0) < 0) { 2247 0 stevel error("Couldn't set active-filter in kernel: %m"); 2248 0 stevel ret = 0; 2249 0 stevel } 2250 0 stevel } 2251 0 stevel return (ret); 2252 0 stevel } 2253 0 stevel #endif /* FILTER_PACKETS */ 2254 0 stevel 2255 0 stevel /* 2256 0 stevel * ccp_fatal_error() 2257 0 stevel * 2258 0 stevel * Returns 1 if decompression was disabled as a result of an error detected 2259 0 stevel * after decompression of a packet, 0 otherwise. This is necessary because 2260 0 stevel * of patent nonsense. 2261 0 stevel */ 2262 0 stevel /*ARGSUSED*/ 2263 0 stevel int 2264 0 stevel ccp_fatal_error(unit) 2265 0 stevel int unit; 2266 0 stevel { 2267 0 stevel uint32_t cf[2]; 2268 0 stevel 2269 0 stevel cf[0] = cf[1] = 0; 2270 0 stevel if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 2271 0 stevel < 0) { 2272 0 stevel if (errno != ENXIO && errno != EINVAL) { 2273 0 stevel error("Couldn't get compression flags: %m"); 2274 0 stevel } 2275 0 stevel return (0); 2276 0 stevel } 2277 0 stevel return (cf[0] & CCP_FATALERROR); 2278 0 stevel } 2279 0 stevel 2280 0 stevel /* 2281 0 stevel * sifvjcomp() 2282 0 stevel * 2283 0 stevel * Config TCP header compression. 2284 0 stevel */ 2285 0 stevel /*ARGSUSED*/ 2286 0 stevel int 2287 0 stevel sifvjcomp(u, vjcomp, xcidcomp, xmaxcid) 2288 0 stevel int u, vjcomp, xcidcomp, xmaxcid; 2289 0 stevel { 2290 0 stevel uint32_t cf[2]; 2291 0 stevel uchar_t maxcid[2]; 2292 0 stevel 2293 0 stevel /* 2294 0 stevel * Since VJ compression code is in the comp module, there's no 2295 0 stevel * point of sending down any ioctls pertaining to VJ compression 2296 0 stevel * when the module isn't pushed on the stream. 2297 0 stevel */ 2298 0 stevel if (!any_compressions()) { 2299 0 stevel return (1); 2300 0 stevel } 2301 0 stevel 2302 0 stevel if (vjcomp) { 2303 0 stevel maxcid[0] = xcidcomp; 2304 0 stevel maxcid[1] = 15; /* XXX should be rmaxcid */ 2305 0 stevel 2306 0 stevel if (strioctl(pppfd, PPPIO_VJINIT, maxcid, 2307 0 stevel sizeof (maxcid), 0) < 0) { 2308 0 stevel error("Couldn't initialize VJ compression: %m"); 2309 0 stevel return (0); 2310 0 stevel } 2311 0 stevel } 2312 0 stevel 2313 0 stevel cf[0] = (vjcomp ? COMP_VJC + DECOMP_VJC : 0) /* XXX this is wrong */ 2314 0 stevel + (xcidcomp? COMP_VJCCID + DECOMP_VJCCID: 0); 2315 0 stevel 2316 0 stevel cf[1] = COMP_VJC + DECOMP_VJC + COMP_VJCCID + DECOMP_VJCCID; 2317 0 stevel 2318 0 stevel if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof (cf), sizeof (cf[0])) 2319 0 stevel < 0) { 2320 0 stevel if (vjcomp) { 2321 0 stevel error("Couldn't enable VJ compression: %m"); 2322 0 stevel } else { 2323 0 stevel error("Couldn't disable VJ compression: %m"); 2324 0 stevel } 2325 0 stevel return (0); 2326 0 stevel } 2327 0 stevel return (1); 2328 0 stevel } 2329 0 stevel 2330 0 stevel /* 2331 0 stevel * siflags() 2332 0 stevel * 2333 0 stevel * Set or clear the IP interface flags. 2334 0 stevel */ 2335 0 stevel int 2336 0 stevel siflags(f, set) 2337 0 stevel u_int32_t f; 2338 0 stevel int set; 2339 0 stevel { 2340 0 stevel struct ifreq ifr; 2341 0 stevel 2342 0 stevel if (!IPCP_ENABLED || (ipmuxid == -1)) { 2343 0 stevel return (0); 2344 0 stevel } 2345 0 stevel if (ipfd == -1 && open_ipfd() == -1) 2346 0 stevel return (0); 2347 0 stevel BZERO(&ifr, sizeof (ifr)); 2348 0 stevel (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2349 0 stevel if (myioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) { 2350 0 stevel error("Couldn't get IP interface flags: %m"); 2351 0 stevel return (0); 2352 0 stevel } 2353 0 stevel if (set) { 2354 0 stevel ifr.ifr_flags |= f; 2355 0 stevel } else { 2356 0 stevel ifr.ifr_flags &= ~f; 2357 0 stevel } 2358 0 stevel if (myioctl(ipfd, SIOCSIFFLAGS, &ifr) < 0) { 2359 0 stevel error("Couldn't set IP interface flags: %m"); 2360 0 stevel return (0); 2361 0 stevel } 2362 0 stevel return (1); 2363 0 stevel } 2364 0 stevel 2365 0 stevel /* 2366 0 stevel * sifup() 2367 0 stevel * 2368 0 stevel * Config the interface up and enable IP packets to pass. 2369 0 stevel */ 2370 0 stevel /*ARGSUSED*/ 2371 0 stevel int 2372 0 stevel sifup(u) 2373 0 stevel int u; 2374 0 stevel { 2375 0 stevel if (if_is_up) { 2376 0 stevel return (1); 2377 0 stevel } else if (!IPCP_ENABLED) { 2378 0 stevel warn("sifup called when IPCP is disabled"); 2379 0 stevel return (0); 2380 0 stevel } else if (ipmuxid == -1) { 2381 0 stevel warn("sifup called in wrong state"); 2382 0 stevel return (0); 2383 0 stevel } else if (!siflags(IFF_UP, 1)) { 2384 0 stevel error("Unable to mark the IP interface UP"); 2385 0 stevel return (0); 2386 0 stevel } 2387 0 stevel if_is_up = 1; 2388 0 stevel return (1); 2389 0 stevel } 2390 0 stevel 2391 0 stevel /* 2392 0 stevel * sifdown() 2393 0 stevel * 2394 0 stevel * Config the interface down and disable IP. Possibly called from die(), 2395 0 stevel * so there shouldn't be any call to die() here. 2396 0 stevel */ 2397 0 stevel /*ARGSUSED*/ 2398 0 stevel int 2399 0 stevel sifdown(u) 2400 0 stevel int u; 2401 0 stevel { 2402 0 stevel if (!IPCP_ENABLED) { 2403 0 stevel warn("sifdown called when IPCP is disabled"); 2404 0 stevel return (0); 2405 0 stevel } else if (!if_is_up || (ipmuxid == -1)) { 2406 0 stevel return (1); 2407 0 stevel } else if (!siflags(IFF_UP, 0)) { 2408 0 stevel error("Unable to mark the IP interface DOWN"); 2409 0 stevel return (0); 2410 0 stevel } 2411 0 stevel if_is_up = 0; 2412 0 stevel return (1); 2413 0 stevel } 2414 0 stevel 2415 0 stevel /* 2416 0 stevel * sifnpmode() 2417 0 stevel * 2418 0 stevel * Set the mode for handling packets for a given NP. Not worried 2419 0 stevel * about performance here since this is done only rarely. 2420 0 stevel */ 2421 0 stevel /*ARGSUSED*/ 2422 0 stevel int 2423 0 stevel sifnpmode(u, proto, mode) 2424 0 stevel int u; 2425 0 stevel int proto; 2426 0 stevel enum NPmode mode; 2427 0 stevel { 2428 0 stevel uint32_t npi[2]; 2429 0 stevel const char *cp; 2430 0 stevel static const struct npi_entry { 2431 0 stevel enum NPmode ne_value; 2432 0 stevel const char *ne_name; 2433 0 stevel } npi_list[] = { 2434 0 stevel { NPMODE_PASS, "pass" }, 2435 0 stevel { NPMODE_DROP, "drop" }, 2436 0 stevel { NPMODE_ERROR, "error" }, 2437 0 stevel { NPMODE_QUEUE, "queue" }, 2438 0 stevel }; 2439 0 stevel int i; 2440 0 stevel char pname[32], mname[32]; 2441 0 stevel 2442 0 stevel npi[0] = proto; 2443 0 stevel npi[1] = (uint32_t)mode; 2444 0 stevel 2445 0 stevel cp = protocol_name(proto); 2446 0 stevel if (cp == NULL) 2447 0 stevel (void) slprintf(pname, sizeof (pname), "NP %04X", proto); 2448 0 stevel else 2449 0 stevel (void) strlcpy(pname, cp, sizeof (pname)); 2450 0 stevel for (i = 0; i < Dim(npi_list); i++) 2451 0 stevel if (npi_list[i].ne_value == mode) 2452 0 stevel break; 2453 0 stevel if (i >= Dim(npi_list)) 2454 0 stevel (void) slprintf(mname, sizeof (mname), "mode %d", (int)mode); 2455 0 stevel else 2456 0 stevel (void) strlcpy(mname, npi_list[i].ne_name, sizeof (mname)); 2457 0 stevel 2458 0 stevel if ((proto == PPP_IP && !if_is_up) || 2459 0 stevel (proto == PPP_IPV6 && !if6_is_up)) { 2460 0 stevel dbglog("ignoring request to set %s to %s", pname, mname); 2461 0 stevel return (1); 2462 0 stevel } 2463 0 stevel if (strioctl(pppfd, PPPIO_NPMODE, npi, sizeof (npi), 0) < 0) { 2464 0 stevel error("unable to set %s to %s: %m", pname, mname); 2465 0 stevel return (0); 2466 0 stevel } 2467 0 stevel return (1); 2468 0 stevel } 2469 0 stevel 2470 0 stevel /* 2471 0 stevel * sifmtu() 2472 0 stevel * 2473 0 stevel * Config the interface IP MTU. 2474 0 stevel */ 2475 0 stevel int 2476 0 stevel sifmtu(mtu) 2477 0 stevel int mtu; 2478 0 stevel { 2479 0 stevel struct ifreq ifr; 2480 0 stevel 2481 0 stevel if (!IPCP_ENABLED || (ipmuxid == -1)) { 2482 0 stevel return (0); 2483 0 stevel } 2484 0 stevel if (ipfd == -1 && open_ipfd() == -1) 2485 0 stevel return (0); 2486 0 stevel BZERO(&ifr, sizeof (ifr)); 2487 0 stevel (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2488 0 stevel ifr.ifr_metric = mtu; 2489 0 stevel if (myioctl(ipfd, SIOCSIFMTU, &ifr) < 0) { 2490 0 stevel error("Couldn't set IP MTU on %s to %d: %m", ifr.ifr_name, 2491 0 stevel mtu); 2492 0 stevel return (0); 2493 0 stevel } 2494 0 stevel return (1); 2495 0 stevel } 2496 0 stevel 2497 0 stevel /* 2498 0 stevel * sifaddr() 2499 0 stevel * 2500 0 stevel * Config the interface IP addresses and netmask. 2501 0 stevel */ 2502 0 stevel /*ARGSUSED*/ 2503 0 stevel int 2504 0 stevel sifaddr(u, o, h, m) 2505 0 stevel int u; 2506 0 stevel u_int32_t o; 2507 0 stevel u_int32_t h; 2508 0 stevel u_int32_t m; 2509 0 stevel { 2510 0 stevel struct ifreq ifr; 2511 0 stevel struct sockaddr_in sin; 2512 0 stevel 2513 0 stevel if (!IPCP_ENABLED || (ipmuxid == -1 && plumb_ipif(u) == 0)) { 2514 0 stevel return (0); 2515 0 stevel } 2516 0 stevel if (ipfd == -1 && open_ipfd() == -1) 2517 0 stevel return (0); 2518 0 stevel /* 2519 0 stevel * Set the IP interface MTU. 2520 0 stevel */ 2521 0 stevel if (!sifmtu(link_mtu)) { 2522 0 stevel return (0); 2523 0 stevel } 2524 0 stevel /* 2525 0 stevel * Set the IP interface local point-to-point address. 2526 0 stevel */ 2527 0 stevel BZERO(&sin, sizeof (sin)); 2528 0 stevel sin.sin_family = AF_INET; 2529 0 stevel sin.sin_addr.s_addr = o; 2530 0 stevel 2531 0 stevel BZERO(&ifr, sizeof (ifr)); 2532 0 stevel (void) strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); 2533 0 stevel ifr.ifr_addr = *(struct sockaddr *)&sin; 2534 0 stevel if (myioctl(ipfd, SIOCSIFADDR, &ifr) < 0) { 2535 0 stevel error("Couldn't set local IP address (%s): %m", ifr.ifr_name); 2536 0 stevel return (0); 2537 0 stevel } 2538 0 stevel /* 2539 0 stevel * Set the IP interface remote point-to-point address. 2540 0 stevel */ 2541 0 stevel sin.sin_addr.s_addr = h; 2542 0 stevel 2543 0 stevel ifr.ifr_dstaddr = *(struct sockaddr *)&sin; 2544 0 stevel if (myioctl(ipfd, SIOCSIFDSTADDR, &ifr) < 0) { 2545 0 stevel error("Couldn't set remote IP address (%s): %m", ifr.ifr_name); 2546 0 stevel return (0); 2547 0 stevel } 2548 0 stevel remote_addr = h; 2549 0 stevel return (1); 2550 0 stevel } 2551 0 stevel 2552 0 stevel /* 2553 0 stevel * cifaddr() 2554 0 stevel * 2555 0 stevel * Clear the interface IP addresses. 2556 0 stevel */ 2557 0 stevel /*ARGSUSED*/ 2558 0 stevel int 2559 0 stevel cifaddr(u, o, h) 2560 0 stevel int u; 2561 0 stevel u_int32_t o; 2562 0 stevel u_int32_t h; 2563 0 stevel { 2564 0 stevel if (!IPCP_ENABLED) { 2565 0 stevel return (0); 2566 0 stevel } 2567 0 stevel /* 2568 0 stevel * Most of the work is done in sifdown(). 2569 0 stevel */ 2570 0 stevel remote_addr = 0; 2571 0 stevel return (1); 2572 0 stevel } 2573 0 stevel 2574 0 stevel /* 2575 0 stevel * sifroute() 2576 0 stevel * 2577 0 stevel * Add or delete a route. 2578 0 stevel */ 2579 0 stevel /*ARGSUSED*/ 2580 0 stevel static int 2581 0 stevel sifroute(int u, u_int32_t l, u_int32_t g, int add, const char *str) 2582 0 stevel { 2583 0 stevel struct sockaddr_in sin_dst, sin_gtw; 2584 0 stevel struct rtentry rt; 2585 0 stevel 2586 0 stevel if (!IPCP_ENABLED || (ipmuxid == -1)) { 2587 0 stevel error("Can't %s route: IP is not enabled", str); 2588 0 stevel return (0); 2589 0 stevel } 2590 0 stevel if (ipfd == -1 && open_ipfd() == -1) 2591 0 stevel return (0); 2592 0 stevel 2593 0 stevel BZERO(&sin_dst, sizeof (sin_dst)); 2594 0 stevel sin_dst.sin_family = AF_INET; 2595 0 stevel sin_dst.sin_addr.s_addr = l; 2596 0 stevel 2597 0 stevel BZERO(&sin_gtw, sizeof (sin_gtw)); 2598 0 stevel sin_gtw.sin_family = AF_INET; 2599 0 stevel sin_gtw.sin_addr.s_addr = g; 2600 0 stevel 2601 0 stevel BZERO(&rt, sizeof (rt)); 2602 0 stevel rt.rt_dst = *(struct sockaddr *)&sin_dst; 2603 0 stevel rt.rt_gateway = *(struct sockaddr *)&sin_gtw; 2604 0 stevel rt.rt_flags = (RTF_GATEWAY|RTF_STATIC); 2605 0 stevel 2606 0 stevel if (myioctl(ipfd, (add ? SIOCADDRT : SIOCDELRT), &rt) < 0) { 2607 0 stevel error("Can't %s route: %m", str); 2608 0 stevel return (0); 2609 0 stevel } 2610 0 stevel return (1); 2611 0 stevel } 2612 0 stevel 2613 0 stevel /* 2614 0 stevel * sifdefaultroute() 2615 0 stevel * 2616 0 stevel * Assign a default route through the address given. 2617 0 stevel */ 2618 0 stevel /*ARGSUSED*/ 2619 0 stevel int 2620 0 stevel sifdefaultroute(u, l, g) 2621 0 stevel int u; 2622 0 stevel u_int32_t l; 2623 0 stevel u_int32_t g; 2624 0 stevel { 2625 0 stevel if (!sifroute(u, 0, g, 1, "add default")) { 2626 0 stevel return (0); 2627 0 stevel } 2628 0 stevel default_route_gateway = g; 2629 0 stevel return (1); 2630 0 stevel } 2631 0 stevel 2632 0 stevel /* 2633 0 stevel * cifdefaultroute() 2634 0 stevel * 2635 0 stevel * Delete a default route through the address given. 2636 0 stevel */ 2637 0 stevel /*ARGSUSED*/ 2638 0 stevel int 2639 0 stevel cifdefaultroute(u, l, g) 2640 0 stevel int u; 2641 0 stevel u_int32_t l; 2642 0 stevel u_int32_t g; 2643 0 stevel { 2644 0 stevel if (!sifroute(u, 0, g, 0, "delete default")) { 2645 0 stevel return (0); 2646 0 stevel } 2647 0 stevel default_route_gateway = 0; 2648 0 stevel return (1); 2649 0 stevel } 2650 0 stevel 2651 0 stevel /* 2652 0 stevel * sifproxyarp() 2653 0 stevel * 2654 0 stevel * Make a proxy ARP entry for the peer. 2655 0 stevel */ 2656 0 stevel /*ARGSUSED*/ 2657 0 stevel int 2658 0 stevel sifproxyarp(unit, hisaddr, quietflag) 2659 0 stevel int unit; 2660 0 stevel u_int32_t hisaddr; 2661 0 stevel int quietflag; 2662 0 stevel { 2663 0 stevel struct sockaddr_in sin; 2664 0 stevel struct xarpreq arpreq; 2665 0 stevel const uchar_t *cp; 2666 0 stevel char *str = NULL; 2667 0 stevel 2668 0 stevel if (!IPCP_ENABLED || (ipmuxid == -1)) { 2669 0 stevel return (0); 2670 0 stevel } 2671 0 stevel if (ipfd == -1 && open_ipfd() == -1) 2672 0 stevel return (0); 2673 0 stevel 2674 0 stevel BZERO(&sin, sizeof (sin)); 2675 0 stevel sin.sin_family = AF_INET; 2676 0 stevel sin.sin_addr.s_addr = hisaddr; 2677 0 stevel 2678 0 stevel BZERO(&arpreq, sizeof (arpreq)); 2679 0 stevel if (!get_ether_addr(hisaddr, &arpreq.xarp_ha, quietflag)) { 2680 0 stevel return (0); 2681 0 stevel } 2682 0 stevel BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin)); 2683 0 stevel arpreq.xarp_flags = ATF_PERM | ATF_PUBL; 2684 0 stevel arpreq.xarp_ha.sdl_family = AF_LINK; 2685 0 stevel 2686 0 stevel if (myioctl(ipfd, SIOCSXARP, (caddr_t)&arpreq) < 0) { 2687 0 stevel if (!quietflag) 2688 0 stevel error("Couldn't set proxy ARP entry: %m"); 2689 0 stevel return (0); 2690 0 stevel } 2691 0 stevel cp = (const uchar_t *)LLADDR(&arpreq.xarp_ha); 2692 0 stevel str = _link_ntoa(cp, str, arpreq.xarp_ha.sdl_alen, IFT_OTHER); 2693 0 stevel if (str != NULL) { 2694 0 stevel dbglog("established proxy ARP for %I using %s", hisaddr, 2695 0 stevel str); 2696 0 stevel free(str); 2697 0 stevel } 2698 0 stevel proxy_arp_addr = hisaddr; 2699 0 stevel return (1); 2700 0 stevel } 2701 0 stevel 2702 0 stevel /* 2703 0 stevel * cifproxyarp() 2704 0 stevel * 2705 0 stevel * Delete the proxy ARP entry for the peer. 2706 0 stevel */ 2707 0 stevel /*ARGSUSED*/ 2708 0 stevel int 2709 0 stevel cifproxyarp(unit, hisaddr) 2710 0 stevel int unit; 2711 0 stevel u_int32_t hisaddr; 2712 0 stevel { 2713 0 stevel struct sockaddr_in sin; 2714 0 stevel struct xarpreq arpreq; 2715 0 stevel 2716 0 stevel if (!IPCP_ENABLED || (ipmuxid == -1)) { 2717 0 stevel return (0); 2718 0 stevel } 2719 0 stevel if (ipfd == -1 && open_ipfd() == -1) 2720 0 stevel return (0); 2721 0 stevel 2722 0 stevel BZERO(&sin, sizeof (sin)); 2723 0 stevel sin.sin_family = AF_INET; 2724 0 stevel sin.sin_addr.s_addr = hisaddr; 2725 0 stevel 2726 0 stevel BZERO(&arpreq, sizeof (arpreq)); 2727 0 stevel BCOPY(&sin, &arpreq.xarp_pa, sizeof (sin)); 2728 0 stevel arpreq.xarp_ha.sdl_family = AF_LINK; 2729 0 stevel 2730 0 stevel if (myioctl(ipfd, SIOCDXARP, (caddr_t)&arpreq) < 0) { 2731 0 stevel error("Couldn't delete proxy ARP entry: %m"); 2732 0 stevel return (0); 2733 0 stevel } 2734 0 stevel proxy_arp_addr = 0; 2735 0 stevel return (1); 2736 0 stevel } 2737 0 stevel 2738 0 stevel /* 2739 0 stevel * get_ether_addr() 2740 0 stevel * 2741 0 stevel * Get the hardware address of an interface on the the same subnet as 2742 0 stevel * ipaddr. This routine uses old-style interfaces for intentional 2743 0 stevel * backward compatibility -- SIOCGLIF* isn't in older Solaris 2744 0 stevel * releases. 2745 0 stevel */ 2746 0 stevel static int 2747 0 stevel get_ether_addr(u_int32_t ipaddr, struct sockaddr_dl *hwaddr, int quietflag) 2748 0 stevel { 2749 0 stevel struct ifreq *ifr, *ifend, ifreq; 2750 0 stevel int nif, s, retv; 2751 0 stevel struct ifconf ifc; 2752 0 stevel u_int32_t ina, mask; 2753 0 stevel struct xarpreq req; 2754 0 stevel struct sockaddr_in sin; 2755 0 stevel 2756 0 stevel if (ipfd == -1 && open_ipfd() == -1) 2757 0 stevel return (0); 2758 0 stevel 2759 0 stevel /* 2760 0 stevel * Scan through the system's network interfaces. 2761 0 stevel */ 2762 0 stevel if (myioctl(ipfd, SIOCGIFNUM, &nif) < 0) { 2763 0 stevel nif = MAXIFS; 2764 0 stevel } 2765 0 stevel if (nif <= 0) 2766 0 stevel return (0); 2767 0 stevel ifc.ifc_len = nif * sizeof (struct ifreq); 2768 0 stevel ifc.ifc_buf = (caddr_t)malloc(ifc.ifc_len); 2769 0 stevel if (ifc.ifc_buf == NULL) { 2770 0 stevel return (0); 2771 0 stevel } 2772 0 stevel if (myioctl(ipfd, SIOCGIFCONF, &ifc) < 0) { 2773 0 stevel error("Couldn't get system interface list: %m"); 2774 0 stevel free(ifc.ifc_buf); 2775 0 stevel return (0); 2776 0 stevel } 2777 0 stevel /* LINTED */ 2778 0 stevel ifend = (struct ifreq *)(ifc.ifc_buf + ifc.ifc_len); 2779 0 stevel for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) { 2780 0 stevel if (ifr->ifr_addr.sa_family != AF_INET) { 2781 0 stevel continue; 2782 0 stevel } 2783 0 stevel /* 2784 0 stevel * Check that the interface is up, and not 2785 0 stevel * point-to-point or loopback. 2786 0 stevel */ 2787 0 stevel (void) strlcpy(ifreq.ifr_name, ifr->ifr_name, 2788 6631 ss150715 sizeof (ifreq.ifr_name)); 2789 0 stevel if (myioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0) { 2790 0 stevel continue; 2791 0 stevel } 2792 0 stevel if ((ifreq.ifr_flags & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT| 2793 0 stevel IFF_LOOPBACK|IFF_NOARP)) != (IFF_UP|IFF_BROADCAST)) { 2794 0 stevel continue; 2795 0 stevel } 2796 0 stevel /* 2797 0 stevel * Get its netmask and check that it's on the right subnet. 2798 0 stevel */ 2799 0 stevel if (myioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0) { 2800 0 stevel continue; 2801 0 stevel } 2802 0 stevel (void) memcpy(&sin, &ifr->ifr_addr, sizeof (sin)); 2803 0 stevel ina = sin.sin_addr.s_addr; 2804 0 stevel (void) memcpy(&sin, &ifreq.ifr_addr, sizeof (sin)); 2805 0 stevel mask = sin.sin_addr.s_addr; 2806 0 stevel if ((ipaddr & mask) == (ina & mask)) { 2807 0 stevel break; 2808 0 stevel } 2809 0 stevel } 2810 0 stevel if (ifr >= ifend) { 2811 0 stevel if (!quietflag) 2812 0 stevel warn("No suitable interface found for proxy ARP of %I", 2813 0 stevel ipaddr); 2814 0 stevel free(ifc.ifc_buf); 2815 0 stevel return (0); 2816 0 stevel } 2817 0 stevel info("found interface %s for proxy ARP of %I", ifr->ifr_name, ipaddr); 2818 0 stevel 2819 0 stevel /* 2820 0 stevel * New way - get the address by doing an arp request. 2821 0 stevel */ 2822 0 stevel s = socket(AF_INET, SOCK_DGRAM, 0); 2823 0 stevel if (s < 0) { 2824 0 stevel error("get_ether_addr: error opening IP socket: %m"); 2825 0 stevel free(ifc.ifc_buf); 2826 0 stevel return (0); 2827 0 stevel } 2828 0 stevel BZERO(&sin, sizeof (sin)); 2829 0 stevel sin.sin_family = AF_INET; 2830 0 stevel sin.sin_addr.s_addr = ina; 2831 0 stevel 2832 0 stevel BZERO(&req, sizeof (req)); 2833 0 stevel BCOPY(&sin, &req.xarp_pa, sizeof (sin)); 2834 0 stevel req.xarp_ha.sdl_family = AF_LINK; 2835 0 stevel 2836 0 stevel if (myioctl(s, SIOCGXARP, &req) < 0) { 2837 0 stevel error("Couldn't get ARP entry for %I: %m", ina); 2838 0 stevel retv = 0; 2839 0 stevel } else { 2840 0 stevel (void) memcpy(hwaddr, &req.xarp_ha, 2841 0 stevel sizeof (struct sockaddr_dl)); 2842 0 stevel retv = 1; 2843 0 stevel } 2844 0 stevel (void) close(s); 2845 0 stevel free(ifc.ifc_buf); 2846 0 stevel return (retv); 2847 0 stevel } 2848 0 stevel 2849 0 stevel /* 2850 0 stevel * GetMask() 2851 0 stevel * 2852 0 stevel * Return mask (bogus, but needed for compatibility with other platforms). 2853 0 stevel */ 2854 0 stevel /*ARGSUSED*/ 2855 0 stevel u_int32_t 2856 0 stevel GetMask(addr) 2857 0 stevel u_int32_t addr; 2858 0 stevel { 2859 0 stevel return (0xffffffffUL); 2860 0 stevel } 2861 0 stevel 2862 0 stevel /* 2863 0 stevel * logwtmp() 2864 0 stevel * 2865 0 stevel * Write an accounting record to the /var/adm/wtmp file. 2866 0 stevel */ 2867 0 stevel /*ARGSUSED*/ 2868 0 stevel void 2869 0 stevel logwtmp(line, name, host) 2870 0 stevel const char *line; 2871 0 stevel const char *name; 2872 0 stevel const char *host; 2873 0 stevel { 2874 0 stevel static struct utmpx utmpx; 2875 0 stevel 2876 0 stevel if (name[0] != '\0') { 2877 0 stevel /* 2878 0 stevel * logging in 2879 0 stevel */ 2880 0 stevel (void) strncpy(utmpx.ut_user, name, sizeof (utmpx.ut_user)); 2881 0 stevel (void) strncpy(utmpx.ut_id, ifname, sizeof (utmpx.ut_id)); 2882 0 stevel (void) strncpy(utmpx.ut_line, line, sizeof (utmpx.ut_line)); 2883 0 stevel 2884 0 stevel utmpx.ut_pid = getpid(); 2885 0 stevel utmpx.ut_type = USER_PROCESS; 2886 0 stevel } else { 2887 0 stevel utmpx.ut_type = DEAD_PROCESS; 2888 0 stevel } 2889 0 stevel (void) gettimeofday(&utmpx.ut_tv, NULL); 2890 0 stevel updwtmpx("/var/adm/wtmpx", &utmpx); 2891 0 stevel } 2892 0 stevel 2893 0 stevel /* 2894 0 stevel * get_host_seed() 2895 0 stevel * 2896 0 stevel * Return the serial number of this machine. 2897 0 stevel */ 2898 0 stevel int 2899 0 stevel get_host_seed() 2900 0 stevel { 2901 0 stevel char buf[32]; 2902 0 stevel 2903 0 stevel if (sysinfo(SI_HW_SERIAL, buf, sizeof (buf)) < 0) { 2904 0 stevel error("sysinfo: %m"); 2905 0 stevel return (0); 2906 0 stevel } 2907 0 stevel return ((int)strtoul(buf, NULL, 16)); 2908 0 stevel } 2909 0 stevel 2910 0 stevel /* 2911 0 stevel * strioctl() 2912 0 stevel * 2913 0 stevel * Wrapper for STREAMS I_STR ioctl. Masks out EINTR from caller. 2914 0 stevel */ 2915 0 stevel static int 2916 0 stevel strioctl(int fd, int cmd, void *ptr, int ilen, int olen) 2917 0 stevel { 2918 0 stevel struct strioctl str; 2919 0 stevel 2920 0 stevel str.ic_cmd = cmd; 2921 0 stevel str.ic_timout = PPPSTRTIMOUT; 2922 0 stevel str.ic_len = ilen; 2923 0 stevel str.ic_dp = ptr; 2924 0 stevel 2925 0 stevel if (myioctl(fd, I_STR, &str) == -1) { 2926 0 stevel return (-1); 2927 0 stevel } 2928 0 stevel if (str.ic_len != olen) { 2929 0 stevel dbglog("strioctl: expected %d bytes, got %d for cmd %x\n", 2930 0 stevel olen, str.ic_len, cmd); 2931 0 stevel } 2932 0 stevel return (0); 2933 0 stevel } 2934 0 stevel 2935 0 stevel /* 2936 0 stevel * have_route_to() 2937 0 stevel * 2938 0 stevel * Determine if the system has a route to the specified IP address. 2939 0 stevel * Returns 0 if not, 1 if so, -1 if we can't tell. `addr' is in network 2940 0 stevel * byte order. For demand mode to work properly, we have to ignore routes 2941 0 stevel * through our own interface. XXX Would be nice to use routing socket. 2942 0 stevel */ 2943 0 stevel int 2944 0 stevel have_route_to(addr) 2945 0 stevel u_int32_t addr; 2946 0 stevel { 2947 0 stevel int r, flags, i; 2948 0 stevel struct { 2949 0 stevel struct T_optmgmt_req req; 2950 0 stevel struct opthdr hdr; 2951 0 stevel } req; 2952 0 stevel union { 2953 0 stevel struct T_optmgmt_ack ack; 2954 0 stevel unsigned char space[64]; 2955 0 stevel } ack; 2956 0 stevel struct opthdr *rh; 2957 0 stevel struct strbuf cbuf, dbuf; 2958 0 stevel int nroutes; 2959 0 stevel mib2_ipRouteEntry_t routes[8]; 2960 0 stevel mib2_ipRouteEntry_t *rp; 2961 0 stevel 2962 0 stevel if (ipfd == -1 && open_ipfd() == -1) 2963 0 stevel return (0); 2964 0 stevel 2965 0 stevel req.req.PRIM_type = T_OPTMGMT_REQ; 2966 0 stevel req.req.OPT_offset = (caddr_t)&req.hdr - (caddr_t)&req; 2967 0 stevel req.req.OPT_length = sizeof (req.hdr); 2968 0 stevel #ifdef T_CURRENT 2969 0 stevel req.req.MGMT_flags = T_CURRENT; 2970 0 stevel #else 2971 0 stevel /* Old-style */ 2972 0 stevel req.req.MGMT_flags = T_CHECK; 2973 0 stevel #endif 2974 0 stevel 2975 0 stevel req.hdr.level = MIB2_IP; 2976 0 stevel req.hdr.name = 0; 2977 0 stevel req.hdr.len = 0; 2978 0 stevel 2979 0 stevel cbuf.buf = (caddr_t)&req; 2980 0 stevel cbuf.len = sizeof (req); 2981 0 stevel 2982 0 stevel if (putmsg(ipfd, &cbuf, NULL, 0) == -1) { 2983 0 stevel warn("have_route_to: putmsg: %m"); 2984 0 stevel return (-1); 2985 0 stevel } 2986 0 stevel 2987 0 stevel for (;;) { 2988 0 stevel cbuf.buf = (caddr_t)&ack; 2989 0 stevel cbuf.maxlen = sizeof (ack); 2990 0 stevel dbuf.buf = (caddr_t)routes; 2991 0 stevel dbuf.maxlen = sizeof (routes); 2992 0 stevel flags = 0; 2993 0 stevel r = getmsg(ipfd, &cbuf, &dbuf, &flags); 2994 0 stevel if (r == -1) { 2995 0 stevel warn("have_route_to: getmsg: %m"); 2996 0 stevel return (-1); 2997 0 stevel } 2998 0 stevel 2999 0 stevel if (cbuf.len < sizeof (struct T_optmgmt_ack) || 3000 0 stevel ack.ack.PRIM_type != T_OPTMGMT_ACK || 3001 0 stevel ack.ack.MGMT_flags != T_SUCCESS || 3002 0 stevel ack.ack.OPT_length < sizeof (struct opthdr)) { 3003 0 stevel dbglog("have_route_to: bad message len=%d prim=%d", 3004 0 stevel cbuf.len, ack.ack.PRIM_type); 3005 0 stevel return (-1); 3006 0 stevel } 3007 0 stevel /* LINTED */ 3008 0 stevel rh = (struct opthdr *)((caddr_t)&ack + ack.ack.OPT_offset); 3009 0 stevel if (rh->level == 0 && rh->name == 0) { 3010 0 stevel break; 3011 0 stevel } 3012 0 stevel if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) { 3013 0 stevel while (r == MOREDATA) { 3014 0 stevel r = getmsg(ipfd, NULL, &dbuf, &flags); 3015 0 stevel } 3016 0 stevel continue; 3017 0 stevel } 3018 0 stevel 3019 0 stevel /* 3020 0 stevel * Note that we have to skip routes to our own 3021 0 stevel * interface in order for demand dial to work. 3022 0 stevel * 3023 0 stevel * XXX awful hack here. We don't know our own 3024 0 stevel * ifIndex, so we can't check ipRouteIfIndex here. 3025 0 stevel * Instead, we check the next hop address. 3026 0 stevel */ 3027 0 stevel for (;;) { 3028 0 stevel nroutes = dbuf.len / sizeof (mib2_ipRouteEntry_t); 3029 0 stevel for (rp = routes, i = 0; i < nroutes; ++i, ++rp) { 3030 0 stevel if (rp->ipRouteNextHop != remote_addr && 3031 0 stevel ((addr ^ rp->ipRouteDest) & 3032 0 stevel rp->ipRouteMask) == 0) { 3033 0 stevel dbglog("have route to %I/%I via %I", 3034 0 stevel rp->ipRouteDest, 3035 0 stevel rp->ipRouteMask, 3036 0 stevel rp->ipRouteNextHop); 3037 0 stevel return (1); 3038 0 stevel } 3039 0 stevel } 3040 0 stevel if (r == 0) { 3041 0 stevel break; 3042 0 stevel } 3043 0 stevel r = getmsg(ipfd, NULL, &dbuf, &flags); 3044 0 stevel } 3045 0 stevel } 3046 0 stevel return (0); 3047 0 stevel } 3048 0 stevel 3049 0 stevel /* 3050 0 stevel * get_pty() 3051 0 stevel * 3052 0 stevel * Get a pty master/slave pair and chown the slave side to the uid given. 3053 0 stevel * Assumes slave_name points to MAXPATHLEN bytes of space. 3054 0 stevel */ 3055 0 stevel int 3056 0 stevel get_pty(master_fdp, slave_fdp, slave_name, uid) 3057 0 stevel int *master_fdp; 3058 0 stevel int *slave_fdp; 3059 0 stevel char *slave_name; 3060 0 stevel int uid; 3061 0 stevel { 3062 0 stevel int mfd; 3063 0 stevel int sfd; 3064 0 stevel char *pty_name; 3065 0 stevel 3066 0 stevel mfd = open("/dev/ptmx", O_NOCTTY | O_RDWR); 3067 0 stevel if (mfd < 0) { 3068 0 stevel error("Couldn't open pty master: %m"); 3069 0 stevel return (0); 3070 0 stevel } 3071 0 stevel pty_name = ptsname(mfd); 3072 0 stevel if (pty_name == NULL) { 3073 0 stevel dbglog("Didn't get pty slave name on first try; sleeping."); 3074 0 stevel /* In case "grow" operation is in progress; try again. */ 3075 0 stevel (void) sleep(1); 3076 0 stevel pty_name = ptsname(mfd); 3077 0 stevel } 3078 0 stevel if (pty_name == NULL) { 3079 0 stevel error("Couldn't get name of pty slave"); 3080 0 stevel (void) close(mfd); 3081 0 stevel return (0); 3082 0 stevel } 3083 0 stevel if (chown(pty_name, uid, -1) < 0) { 3084 0 stevel warn("Couldn't change owner of pty slave: %m"); 3085 0 stevel } 3086 0 stevel if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0) { 3087 0 stevel warn("Couldn't change permissions on pty slave: %m"); 3088 0 stevel } 3089 0 stevel if (unlockpt(mfd) < 0) { 3090 0 stevel warn("Couldn't unlock pty slave: %m"); 3091 0 stevel } 3092 0 stevel sfd = open(pty_name, O_RDWR); 3093 0 stevel if (sfd < 0) { 3094 0 stevel error("Couldn't open pty slave %s: %m", pty_name); 3095 0 stevel (void) close(mfd); 3096 0 stevel return (0); 3097 0 stevel } 3098 0 stevel if (myioctl(sfd, I_PUSH, "ptem") < 0) { 3099 0 stevel warn("Couldn't push ptem module on pty slave: %m"); 3100 0 stevel } 3101 0 stevel dbglog("Using %s; master fd %d, slave fd %d", pty_name, mfd, sfd); 3102 0 stevel 3103 0 stevel (void) strlcpy(slave_name, pty_name, MAXPATHLEN); 3104 0 stevel 3105 0 stevel *master_fdp = mfd; 3106 0 stevel *slave_fdp = sfd; 3107 0 stevel 3108 0 stevel return (1); 3109 0 stevel } 3110 0 stevel 3111 0 stevel #ifdef INET6 3112 0 stevel static int 3113 0 stevel open_udp6fd(void) 3114 0 stevel { 3115 0 stevel int udp6fd; 3116 0 stevel 3117 0 stevel udp6fd = open(UDP6_DEV_NAME, O_RDWR | O_NONBLOCK, 0); 3118 0 stevel if (udp6fd < 0) { 3119 0 stevel error("Couldn't open UDPv6 device (%s): %m", UDP6_DEV_NAME); 3120 0 stevel } 3121 0 stevel return (udp6fd); 3122 0 stevel } 3123 0 stevel 3124 0 stevel /* 3125 0 stevel * plumb_ip6if() 3126 0 stevel * 3127 0 stevel * Perform IPv6 interface plumbing. 3128 0 stevel */ 3129 0 stevel /*ARGSUSED*/ 3130 0 stevel static int 3131 0 stevel plumb_ip6if(int unit) 3132 0 stevel { 3133 0 stevel int udp6fd = -1, tmpfd; 3134 0 stevel uint32_t x; 3135 0 stevel struct lifreq lifr; 3136 0 stevel 3137 0 stevel if (!IPV6CP_ENABLED || (ifunit == -1) || (pppfd == -1)) { 3138 0 stevel return (0); 3139 0 stevel } 3140 0 stevel if (plumbed) 3141 0 stevel return (1); 3142 0 stevel if (ip6fd == -1 && open_ip6fd() == -1) 3143 0 stevel return (0); 3144 0 stevel if (use_plink && (udp6fd = open_udp6fd()) == -1) 3145 0 stevel return (0); 3146 0 stevel tmpfd = open(drvnam, O_RDWR | O_NONBLOCK, 0); 3147 0 stevel if (tmpfd < 0) { 3148 0 stevel error("Couldn't open PPP device (%s): %m", drvnam); 3149 0 stevel if (udp6fd != -1) 3150 0 stevel (void) close(udp6fd); 3151 0 stevel return (0); 3152 0 stevel } 3153 0 stevel if (kdebugflag & 1) { 3154 0 stevel x = PPPDBG_LOG + PPPDBG_DRIVER; 3155 0 stevel if (strioctl(tmpfd, PPPIO_DEBUG, &x, sizeof (x), 0) < 0) { 3156 0 stevel warn("PPPIO_DEBUG ioctl for mux failed: %m"); 3157 0 stevel } 3158 0 stevel } 3159 0 stevel if (myioctl(tmpfd, I_PUSH, IP_MOD_NAME) < 0) { 3160 0 stevel error("Couldn't push IP module(%s): %m", IP_MOD_NAME); 3161 0 stevel goto err_ret; 3162 0 stevel } 3163 0 stevel /* 3164 0 stevel * Sets interface ppa and flags (refer to comments in plumb_ipif for 3165 0 stevel * the IF_UNITSEL ioctl). In addition, the IFF_IPV6 bit must be set in 3166 0 stevel * order to declare this as an IPv6 interface. 3167 0 stevel */ 3168 0 stevel BZERO(&lifr, sizeof (lifr)); 3169 0 stevel if (myioctl(tmpfd, SIOCGLIFFLAGS, &lifr) < 0) { 3170 0 stevel error("Couldn't get IPv6 interface flags: %m"); 3171 0 stevel goto err_ret; 3172 0 stevel } 3173 0 stevel lifr.lifr_flags |= IFF_IPV6; 3174 0 stevel lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4); 3175 0 stevel lifr.lifr_ppa = ifunit; 3176 0 stevel (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 3177 0 stevel if (myioctl(tmpfd, SIOCSLIFNAME, &lifr) < 0) { 3178 0 stevel error("Can't set ifname for unit %d: %m", ifunit); 3179 0 stevel goto err_ret; 3180 0 stevel } 3181 0 stevel if (use_plink) { 3182 0 stevel ip6muxid = myioctl(udp6fd, I_PLINK, (void *)tmpfd); 3183 0 stevel if (ip6muxid < 0) { 3184 0 stevel error("Can't I_PLINK PPP device to IPv6: %m"); 3185 0 stevel goto err_ret; 3186 0 stevel } 3187 0 stevel } else { 3188 0 stevel ip6muxid = myioctl(ip6fd, I_LINK, (void *)tmpfd); 3189 0 stevel if (ip6muxid < 0) { 3190 0 stevel error("Can't I_LINK PPP device to IPv6: %m"); 3191 0 stevel goto err_ret; 3192 0 stevel } 3193 0 stevel } 3194 0 stevel lifr.lifr_ip_muxid = ip6muxid; 3195 0 stevel lifr.lifr_arp_muxid = -1; 3196 0 stevel if (myioctl(ip6fd, SIOCSLIFMUXID, (caddr_t)&lifr) < 0) { 3197 0 stevel error("Can't set mux ID: SIOCSLIFMUXID: %m"); 3198 0 stevel goto err_ret; 3199 0 stevel } 3200 0 stevel (void) close(tmpfd); 3201 0 stevel if (udp6fd != -1) 3202 0 stevel (void) close(udp6fd); 3203 0 stevel return (1); 3204 0 stevel 3205 0 stevel err_ret: 3206 0 stevel (void) close(tmpfd); 3207 0 stevel if (udp6fd != -1) 3208 0 stevel (void) close(udp6fd); 3209 0 stevel return (0); 3210 0 stevel }