2 * System-dependent procedures for pppd under Solaris 2.x (SunOS 5.x).
4 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation is hereby granted, provided that the above copyright
9 * notice appears in all copies.
11 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
12 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
13 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
15 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
16 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
18 * Copyright (c) 1994 The Australian National University.
19 * All rights reserved.
21 * Permission to use, copy, modify, and distribute this software and its
22 * documentation is hereby granted, provided that the above copyright
23 * notice appears in all copies. This software is provided without any
24 * warranty, express or implied. The Australian National University
25 * makes no representations about the suitability of this software for
28 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
29 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
30 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
31 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
34 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
35 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
36 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
37 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
38 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
42 #define RCSID "$Id: sys-solaris.c,v 1.2 2000/04/21 01:27:57 masputra Exp $"
58 #include <sys/types.h>
59 #include <sys/ioccom.h>
60 #include <sys/stream.h>
61 #include <sys/stropts.h>
62 #include <sys/socket.h>
63 #include <sys/sockio.h>
64 #include <sys/sysmacros.h>
65 #include <sys/systeminfo.h>
68 #include <net/if_arp.h>
69 #include <net/route.h>
70 #include <net/ppp_defs.h>
71 #include <net/pppio.h>
72 #include <net/if_types.h>
73 #include <net/if_dl.h>
74 #include <netinet/in.h>
75 #include <sys/tihdr.h>
76 #include <inet/mib2.h>
78 #include <sys/ethernet.h>
79 #include <sys/ser_sync.h>
81 #include <arpa/inet.h>
92 #if !defined(lint) && !defined(_lint)
93 static const char rcsid
[] = RCSID
;
96 #define PPPSTRTIMOUT 1 /* Timeout in seconds for ioctl */
97 #define MAX_POLLFDS 32
105 #define _IN6_LLX_FROM_EUI64(l, s, eui64, as, len) \
106 (s->sin6_addr.s6_addr32[0] = htonl(as), \
107 eui64_copy(eui64, s->sin6_addr.s6_addr32[2]), \
108 s->sin6_family = AF_INET6, \
109 l.lifr_addr.ss_family = AF_INET6, \
110 l.lifr_addrlen = len, \
114 * Generate a link-local address with an interface-id based on the given
115 * EUI64 identifier. Note that the len field is unused by SIOCSLIFADDR.
117 #define IN6_LLADDR_FROM_EUI64(l, s, eui64) \
118 _IN6_LLX_FROM_EUI64(l, s, eui64, 0xfe800000, 0)
121 * Generate an EUI64 based interface-id for use by stateless address
122 * autoconfiguration. These are required to be 64 bits long as defined in
123 * the "Interface Identifiers" section of the IPv6 Addressing Architecture
126 #define IN6_LLTOKEN_FROM_EUI64(l, s, eui64) \
127 _IN6_LLX_FROM_EUI64(l, s, eui64, 0, 64)
130 #define IPCP_ENABLED ipcp_protent.enabled_flag
132 #define IPV6CP_ENABLED ipv6cp_protent.enabled_flag
135 /* For plug-in usage. */
136 int (*sys_read_packet_hook
) __P((int retv
, struct strbuf
*ctrl
,
137 struct strbuf
*data
, int flags
)) = NULL
;
138 bool already_ppp
= 0; /* Already in PPP mode */
140 static int pppfd
= -1; /* ppp driver fd */
141 static int fdmuxid
= -1; /* driver mux fd */
142 static int ipfd
= -1; /* IPv4 fd */
143 static int ipmuxid
= -1; /* IPv4 mux fd */
144 static int ip6fd
= -1; /* IPv6 fd */
145 static int ip6muxid
= -1; /* IPv6 mux fd */
146 static bool if6_is_up
= 0; /* IPv6 if marked as up */
147 static bool if_is_up
= 0; /* IPv4 if marked as up */
148 static bool restore_term
= 0; /* Restore TTY after closing link */
149 static struct termios inittermios
; /* TTY settings */
150 static struct winsize wsinfo
; /* Initial window size info */
151 static pid_t tty_sid
; /* original sess ID for term */
152 static struct pollfd pollfds
[MAX_POLLFDS
]; /* array of polled fd */
153 static int n_pollfds
= 0; /* total count of polled fd */
154 static int link_mtu
; /* link Maximum Transmit Unit */
155 static int tty_nmodules
; /* total count of TTY modules used */
156 static char tty_modules
[NMODULES
][FMNAMESZ
+1];
157 /* array of TTY modules used */
158 static int tty_npushed
; /* total count of pushed PPP modules */
159 static u_int32_t remote_addr
; /* IP address of peer */
160 static u_int32_t default_route_gateway
; /* Gateway for default route */
161 static u_int32_t proxy_arp_addr
; /* Addr for proxy arp entry */
162 static u_int32_t lastlink_status
; /* Last link status info */
164 static bool use_plink
= 0; /* Use I_LINK by default */
165 static bool plumbed
= 0; /* Use existing interface */
167 /* Default is to use /dev/sppp as driver. */
168 static const char *drvnam
= PPP_DEV_NAME
;
169 static bool integrated_driver
= 0;
170 static int extra_dev_fd
= -1; /* keep open until ready */
172 static option_t solaris_option_list
[] = {
173 { "plink", o_bool
, &use_plink
, "Use I_PLINK instead of I_LINK",
175 { "noplink", o_bool
, &use_plink
, "Use I_LINK instead of I_PLINK",
177 { "plumbed", o_bool
, &plumbed
, "Use pre-plumbed interface",
183 * Prototypes for procedures local to this file.
185 static int translate_speed
__P((int));
186 static int baud_rate_of
__P((int));
187 static int get_ether_addr
__P((u_int32_t
, struct sockaddr_dl
*, int));
188 static int strioctl
__P((int, int, void *, int, int));
189 static int plumb_ipif
__P((int));
190 static int unplumb_ipif
__P((int));
192 static int plumb_ip6if
__P((int));
193 static int unplumb_ip6if
__P((int));
194 static int open_ip6fd(void);
196 static int open_ipfd(void);
197 static int sifroute
__P((int, u_int32_t
, u_int32_t
, int, const char *));
198 static int giflags
__P((u_int32_t
, bool *));
199 static void handle_unbind
__P((u_int32_t
));
200 static void handle_bind
__P((u_int32_t
));
203 * Wrapper for regular ioctl; masks out EINTR.
206 myioctl(int fd
, int cmd
, void *arg
)
211 while ((retv
= ioctl(fd
, cmd
, arg
)) == -1) {
219 * sys_check_options()
221 * Check the options that the user specified.
224 sys_check_options(void)
238 * Add or remove system-specific options.
243 (void) remove_option("ktune");
244 (void) remove_option("noktune");
245 add_options(solaris_option_list
);
251 * Set ifname[] to contain name of IP interface for this unit.
258 if ((cp
= strrchr(drvnam
, '/')) == NULL
)
262 (void) slprintf(ifname
, sizeof (ifname
), "%s%d", cp
, ifunit
);
268 * Check whether the system has any ppp interfaces.
277 if (stat(PPP_DEV_NAME
, &buf
) >= 0)
281 * Simple check for system using Apollo POS without SUNWpppd
282 * (/dev/sppp) installed. This is intentionally not kept open
283 * here, since the user may not have the same privileges (as
284 * determined later). If Apollo were just shipped with the
285 * full complement of packages, this wouldn't be an issue.
287 if (devnam
[0] == '\0' &&
288 (fd
= open(devnam
, O_RDWR
| O_NONBLOCK
| O_NOCTTY
)) >= 0) {
289 if (strioctl(fd
, PPPIO_GTYPE
, &typ
, 0, sizeof (typ
)) >= 0 &&
302 ipfd
= open(IP_DEV_NAME
, O_RDWR
| O_NONBLOCK
, 0);
304 error("Couldn't open IP device (%s): %m", IP_DEV_NAME
);
310 read_ip_interface(int unit
)
313 struct sockaddr_in sin
;
315 if (ipfd
== -1 && open_ipfd() == -1)
318 BZERO(&ifr
, sizeof (ifr
));
319 (void) strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
321 /* Get the existing MTU */
322 if (myioctl(ipfd
, SIOCGIFMTU
, &ifr
) < 0) {
323 warn("Couldn't get IP MTU on %s: %m", ifr
.ifr_name
);
326 dbglog("got MTU %d from interface", ifr
.ifr_metric
);
327 if (ifr
.ifr_metric
!= 0 &&
328 (lcp_allowoptions
[unit
].mru
== 0 ||
329 lcp_allowoptions
[unit
].mru
> ifr
.ifr_metric
))
330 lcp_allowoptions
[unit
].mru
= ifr
.ifr_metric
;
332 /* Get the local IP address */
333 if (ipcp_wantoptions
[unit
].ouraddr
== 0 ||
334 ipcp_from_hostname
) {
335 if (myioctl(ipfd
, SIOCGIFADDR
, &ifr
) < 0) {
336 warn("Couldn't get local IP address (%s): %m",
340 BCOPY(&ifr
.ifr_addr
, &sin
, sizeof (struct sockaddr_in
));
341 ipcp_wantoptions
[unit
].ouraddr
= sin
.sin_addr
.s_addr
;
342 dbglog("got local address %I from interface",
343 ipcp_wantoptions
[unit
].ouraddr
);
346 /* Get the remote IP address */
347 if (ipcp_wantoptions
[unit
].hisaddr
== 0) {
348 if (myioctl(ipfd
, SIOCGIFDSTADDR
, &ifr
) < 0) {
349 warn("Couldn't get remote IP address (%s): %m",
353 BCOPY(&ifr
.ifr_dstaddr
, &sin
, sizeof (struct sockaddr_in
));
354 ipcp_wantoptions
[unit
].hisaddr
= sin
.sin_addr
.s_addr
;
355 dbglog("got remote address %I from interface",
356 ipcp_wantoptions
[unit
].hisaddr
);
365 ip6fd
= open(IP6_DEV_NAME
, O_RDWR
| O_NONBLOCK
, 0);
367 error("Couldn't open IPv6 device (%s): %m", IP6_DEV_NAME
);
373 read_ipv6_interface(int unit
)
376 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&lifr
.lifr_addr
;
378 if (ip6fd
== -1 && open_ip6fd() == -1)
381 BZERO(&lifr
, sizeof (lifr
));
382 (void) strlcpy(lifr
.lifr_name
, ifname
, sizeof (lifr
.lifr_name
));
384 /* Get the existing MTU */
385 if (myioctl(ip6fd
, SIOCGLIFMTU
, &lifr
) < 0) {
386 warn("Couldn't get IPv6 MTU on %s: %m", lifr
.lifr_name
);
389 if (lifr
.lifr_mtu
!= 0 &&
390 (lcp_allowoptions
[unit
].mru
== 0 ||
391 lcp_allowoptions
[unit
].mru
> lifr
.lifr_mtu
))
392 lcp_allowoptions
[unit
].mru
= lifr
.lifr_mtu
;
394 /* Get the local IPv6 address */
395 if (eui64_iszero(ipv6cp_wantoptions
[unit
].ourid
) ||
396 (ipcp_from_hostname
&& ipv6cp_wantoptions
[unit
].use_ip
)) {
397 if (myioctl(ip6fd
, SIOCGLIFADDR
, &lifr
) < 0) {
398 warn("Couldn't get local IPv6 address (%s): %m",
402 eui64_copy(sin6
->sin6_addr
.s6_addr32
[2],
403 ipv6cp_wantoptions
[unit
].ourid
);
406 /* Get the remote IP address */
407 if (eui64_iszero(ipv6cp_wantoptions
[unit
].hisid
)) {
408 if (myioctl(ip6fd
, SIOCGLIFDSTADDR
, &lifr
) < 0) {
409 warn("Couldn't get remote IPv6 address (%s): %m",
413 eui64_copy(sin6
->sin6_addr
.s6_addr32
[2],
414 ipv6cp_wantoptions
[unit
].hisid
);
421 * Read information on existing interface(s) and configure ourselves
422 * to negotiate appropriately.
425 read_interface(int unit
)
427 dbglog("reading existing interface data; %sip %sipv6",
428 IPCP_ENABLED
? "" : "!",
430 IPV6CP_ENABLED
? "" :
433 if (IPCP_ENABLED
&& !read_ip_interface(unit
))
436 if (IPV6CP_ENABLED
&& !read_ipv6_interface(unit
))
444 * System-dependent initialization.
447 sys_init(bool open_as_user
)
456 if (!direct_tty
&& devnam
[0] != '\0') {
458 * Check for integrated driver-like devices (such as
459 * POS). These identify themselves as "PPP
460 * multiplexor" drivers.
463 (void) seteuid(getuid());
464 pppfd
= open(devnam
, O_RDWR
| O_NONBLOCK
);
468 strioctl(pppfd
, PPPIO_GTYPE
, &typ
, 0, sizeof (typ
)) >= 0 &&
470 integrated_driver
= 1;
476 extra_dev_fd
= pppfd
;
482 * Open Solaris PPP device driver.
485 pppfd
= open(drvnam
, O_RDWR
| O_NONBLOCK
);
487 fatal("Can't open %s: %m", drvnam
);
489 if (kdebugflag
& 1) {
490 x
= PPPDBG_LOG
+ PPPDBG_DRIVER
;
491 if (strioctl(pppfd
, PPPIO_DEBUG
, &x
, sizeof (x
), 0) < 0) {
492 warn("PPPIO_DEBUG ioctl for mux failed: %m");
496 * Assign a new PPA and get its unit number.
499 if (strioctl(pppfd
, PPPIO_NEWPPA
, &x
, sizeof (x
), sizeof (x
)) < 0) {
500 if (errno
== ENXIO
&& plumbed
)
501 fatal("No idle interfaces available for use");
502 fatal("PPPIO_NEWPPA ioctl failed: %m");
505 if (req_unit
>= 0 && ifunit
!= req_unit
) {
507 fatal("unable to get requested unit %d", req_unit
);
509 warn("unable to get requested unit %d", req_unit
);
512 * Enable packet time-stamping when idle option is specified. Note
513 * that we need to only do this on the control stream. Subsequent
514 * streams attached to this control stream (ppa) will inherit
515 * the time-stamp bit.
517 if (idle_time_limit
> 0) {
518 if (strioctl(pppfd
, PPPIO_USETIMESTAMP
, NULL
, 0, 0) < 0) {
519 warn("PPPIO_USETIMESTAMP ioctl failed: %m");
543 udpfd
= open(UDP_DEV_NAME
, O_RDWR
| O_NONBLOCK
, 0);
545 error("Couldn't open UDP device (%s): %m", UDP_DEV_NAME
);
553 * Perform IP interface plumbing.
559 int udpfd
= -1, tmpfd
;
563 if (!IPCP_ENABLED
|| (ifunit
== -1) || (pppfd
== -1)) {
568 if (ipfd
== -1 && open_ipfd() == -1)
570 if (use_plink
&& (udpfd
= open_udpfd()) == -1)
572 tmpfd
= open(drvnam
, O_RDWR
| O_NONBLOCK
, 0);
574 error("Couldn't open PPP device (%s): %m", drvnam
);
579 if (kdebugflag
& 1) {
580 x
= PPPDBG_LOG
+ PPPDBG_DRIVER
;
581 if (strioctl(tmpfd
, PPPIO_DEBUG
, &x
, sizeof (x
), 0) < 0) {
582 warn("PPPIO_DEBUG ioctl for mux failed: %m");
585 if (myioctl(tmpfd
, I_PUSH
, IP_MOD_NAME
) < 0) {
586 error("Couldn't push IP module (%s): %m", IP_MOD_NAME
);
590 * Assign ppa according to the unit number returned by ppp device
591 * after plumbing is completed above. Without setting the ppa, ip
592 * module will return EINVAL upon setting the interface UP
593 * (SIOCSxIFFLAGS). This is because ip module in 2.8 expects two
594 * DLPI_INFO_REQ to be sent down to the driver (below ip) before
595 * IFF_UP bit can be set. Plumbing the device causes one DLPI_INFO_REQ
596 * to be sent down, and the second DLPI_INFO_REQ is sent upon receiving
597 * IF_UNITSEL (old) or SIOCSLIFNAME (new) ioctls. Such setting of the
598 * ppa is required because the ppp DLPI provider advertises itself as
599 * a DLPI style 2 type, which requires a point of attachment to be
600 * specified. The only way the user can specify a point of attachment
601 * is via SIOCSLIFNAME or IF_UNITSEL. Such changes in the behavior of
602 * ip module was made to meet new or evolving standards requirements.
604 if (myioctl(tmpfd
, IF_UNITSEL
, &ifunit
) < 0) {
605 error("Couldn't set ppa for unit %d: %m", ifunit
);
609 ipmuxid
= myioctl(udpfd
, I_PLINK
, (void *)tmpfd
);
611 error("Can't I_PLINK PPP device to IP: %m");
615 ipmuxid
= myioctl(ipfd
, I_LINK
, (void *)tmpfd
);
617 error("Can't I_LINK PPP device to IP: %m");
621 BZERO(&ifr
, sizeof (ifr
));
622 (void) strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
623 ifr
.ifr_ip_muxid
= ipmuxid
;
624 ifr
.ifr_arp_muxid
= -1;
625 if (myioctl(ipfd
, SIOCSIFMUXID
, (caddr_t
)&ifr
) < 0) {
626 error("Can't set mux ID SIOCSIFMUXID on %s: %m", ifname
);
643 * Perform IP interface unplumbing. Possibly called from die(), so there
644 * shouldn't be any call to die() or fatal() here.
647 unplumb_ipif(int unit
)
649 int udpfd
= -1, fd
= -1;
653 if (!IPCP_ENABLED
|| (ifunit
== -1)) {
656 if (!plumbed
&& (ipmuxid
== -1 || (ipfd
== -1 && !use_plink
)))
659 if (!plumbed
&& use_plink
) {
660 if ((udpfd
= open_udpfd()) == -1)
663 * Note: must re-get mux ID, since any intervening
664 * ifconfigs will change this.
666 BZERO(&lifr
, sizeof (lifr
));
667 (void) strlcpy(lifr
.lifr_name
, ifname
,
668 sizeof (lifr
.lifr_name
));
669 if (myioctl(ipfd
, SIOCGLIFMUXID
, (caddr_t
)&lifr
) < 0) {
670 warn("Can't get mux fd: SIOCGLIFMUXID: %m");
672 id
= lifr
.lifr_ip_muxid
;
673 fd
= myioctl(udpfd
, _I_MUXID2FD
, (void *)id
);
675 warn("Can't get mux fd: _I_MUXID2FD: %m");
680 * Mark down and unlink the ip interface.
682 (void) sifdown(unit
);
683 if (default_route_gateway
!= 0) {
684 (void) cifdefaultroute(0, default_route_gateway
,
685 default_route_gateway
);
687 if (proxy_arp_addr
!= 0) {
688 (void) cifproxyarp(0, proxy_arp_addr
);
694 if (myioctl(udpfd
, I_PUNLINK
, (void *)id
) < 0) {
695 error("Can't I_PUNLINK PPP from IP: %m");
705 if (myioctl(ipfd
, I_UNLINK
, (void *)id
) < 0) {
706 error("Can't I_UNLINK PPP from IP: %m");
716 * Restore any system state we modified before exiting: mark the
717 * interface down, delete default route and/or proxy arp entry. This
718 * should not call die() because it's called from die().
723 (void) unplumb_ipif(0);
725 (void) unplumb_ip6if(0);
732 * Stores the first hardware interface address found in the system
733 * into addr and return 1 upon success, or 0 if none is found. This
734 * is also called from the multilink code.
737 get_first_hwaddr(addr
, msize
)
742 register struct ifreq
*pifreq
;
752 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
754 error("get_first_hwaddr: error opening IP socket: %m");
758 * Find out how many interfaces are running
760 if (myioctl(fd
, SIOCGIFNUM
, (caddr_t
)&num_ifs
) < 0) {
763 req_size
= num_ifs
* sizeof (struct ifreq
);
764 req
= malloc(req_size
);
766 novm("interface request structure.");
769 * Get interface configuration info for all interfaces
771 ifc
.ifc_len
= req_size
;
773 if (myioctl(fd
, SIOCGIFCONF
, &ifc
) < 0) {
774 error("SIOCGIFCONF: %m");
780 * And traverse each interface to look specifically for the first
781 * occurence of an Ethernet interface which has been marked up
783 pifreq
= ifc
.ifc_req
;
785 for (i
= ifc
.ifc_len
/ sizeof (struct ifreq
); i
> 0; i
--, pifreq
++) {
787 if (strchr(pifreq
->ifr_name
, ':') != NULL
) {
790 BZERO(&ifr
, sizeof (ifr
));
791 (void) strncpy(ifr
.ifr_name
, pifreq
->ifr_name
,
792 sizeof (ifr
.ifr_name
));
793 if (myioctl(fd
, SIOCGIFFLAGS
, &ifr
) < 0) {
797 if ((fl
& (IFF_UP
|IFF_BROADCAST
|IFF_POINTOPOINT
|IFF_LOOPBACK
))
798 != (IFF_UP
| IFF_BROADCAST
)) {
801 if (get_if_hwaddr(addr
, msize
, ifr
.ifr_name
) <= 0) {
816 * Get the hardware address for the specified network interface device.
817 * Return the length of the MAC address (in bytes) or -1 if error.
820 get_if_hwaddr(uchar_t
*addrp
, int msize
, char *linkname
)
823 uchar_t physaddr
[DLPI_PHYSADDR_MAX
];
824 size_t physaddrlen
= sizeof (physaddr
);
827 if ((addrp
== NULL
) || (linkname
== NULL
))
831 * Open the link and ask for hardware address.
833 if ((retv
= dlpi_open(linkname
, &dh
, 0)) != DLPI_SUCCESS
) {
834 error("Could not open %s: %s", linkname
, dlpi_strerror(retv
));
838 retv
= dlpi_get_physaddr(dh
, DL_CURR_PHYS_ADDR
,
839 physaddr
, &physaddrlen
);
841 if (retv
!= DLPI_SUCCESS
) {
842 error("Could not get physical address on %s: %s", linkname
,
843 dlpi_strerror(retv
));
848 * Check if we have enough space to copy the address to.
850 if (physaddrlen
> msize
)
852 (void) memcpy(addrp
, physaddr
, physaddrlen
);
853 return (physaddrlen
);
860 giflags(u_int32_t flag
, bool *retval
)
866 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
868 error("giflags: error opening IP socket: %m");
872 BZERO(&ifr
, sizeof (ifr
));
873 (void) strncpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
874 if (ioctl(fd
, SIOCGIFFLAGS
, &ifr
) < 0) {
879 *retval
= ((ifr
.ifr_flags
& flag
) != 0);
887 * Clean up in a child process before exec-ing.
911 * Check if compression is enabled or not. In the STREAMS implementation of
912 * kernel-portion pppd, the comp STREAMS module performs the ACFC, PFC, as
913 * well CCP and VJ compressions. However, if the user has explicitly declare
914 * to not enable them from the command line, there is no point of having the
915 * comp module be pushed on the stream.
918 any_compressions(void)
920 if ((!lcp_wantoptions
[0].neg_accompression
) &&
921 (!lcp_wantoptions
[0].neg_pcompression
) &&
922 (!ccp_protent
.enabled_flag
) &&
923 (!ipcp_wantoptions
[0].neg_vj
)) {
932 * Push a module on the stream.
935 modpush(int fd
, const char *modname
, const char *text
)
937 if (myioctl(fd
, I_PUSH
, (void *)modname
) < 0) {
938 error("Couldn't push %s module: %m", text
);
941 if (++tty_npushed
== 1 && !already_ppp
) {
942 if (strioctl(fd
, PPPIO_LASTMOD
, NULL
, 0, 0) < 0) {
943 warn("unable to set LASTMOD on %s: %m", text
);
952 * Turn the serial port into a ppp interface.
961 if (default_device
&& !notty
) {
962 tty_sid
= getsid((pid_t
)0);
965 if (integrated_driver
)
969 * Pop any existing modules off the tty stream
972 if ((myioctl(fd
, I_LOOK
, tty_modules
[i
]) < 0) ||
973 (strcmp(tty_modules
[i
], "ptem") == 0) ||
974 (myioctl(fd
, I_POP
, (void *)0) < 0)) {
980 * Push the async hdlc module and the compressor module
983 if (!sync_serial
&& !already_ppp
&&
984 modpush(fd
, AHDLC_MOD_NAME
, "PPP async HDLC") < 0) {
988 * There's no need to push comp module if we don't intend
989 * to compress anything
991 if (any_compressions()) {
992 (void) modpush(fd
, COMP_MOD_NAME
, "PPP compression");
996 * Link the serial port under the PPP multiplexor
998 if ((fdmuxid
= myioctl(pppfd
, I_LINK
, (void *)fd
)) < 0) {
999 error("Can't link tty to PPP mux: %m");
1002 if (tty_npushed
== 0 && !already_ppp
) {
1003 if (strioctl(pppfd
, PPPIO_LASTMOD
, NULL
, 0, 0) < 0) {
1004 warn("unable to set LASTMOD on PPP mux: %m");
1008 * Debug configuration must occur *after* I_LINK.
1010 if (kdebugflag
& 4) {
1011 x
= PPPDBG_LOG
+ PPPDBG_AHDLC
;
1012 if (strioctl(pppfd
, PPPIO_DEBUG
, &x
, sizeof (x
), 0) < 0) {
1013 warn("PPPIO_DEBUG ioctl for ahdlc module failed: %m");
1016 if (any_compressions() && (kdebugflag
& 2)) {
1017 x
= PPPDBG_LOG
+ PPPDBG_COMP
;
1018 if (strioctl(pppfd
, PPPIO_DEBUG
, &x
, sizeof (x
), 0) < 0) {
1019 warn("PPPIO_DEBUG ioctl for comp module failed: %m");
1028 * Reattach the ppp unit to the loopback. This doesn't need to do anything
1029 * because disestablish_ppp does it
1037 * disestablish_ppp()
1039 * Restore the serial port to normal operation. It attempts to reconstruct
1040 * the stream with the previously popped modules. This shouldn't call die()
1041 * because it's called from die(). Stream reconstruction is needed in case
1042 * pppd is used for dial-in on /dev/tty and there's an option error.
1045 disestablish_ppp(fd
)
1050 if (fdmuxid
== -1 || integrated_driver
) {
1053 if (myioctl(pppfd
, I_UNLINK
, (void *)fdmuxid
) < 0) {
1055 error("Can't unlink tty from PPP mux: %m");
1060 while (tty_npushed
> 0 && myioctl(fd
, I_POP
, (void *)0) >= 0) {
1063 for (i
= tty_nmodules
- 1; i
>= 0; --i
) {
1064 if (myioctl(fd
, I_PUSH
, tty_modules
[i
]) < 0) {
1065 error("Couldn't restore tty module %s: %m",
1070 if (hungup
&& default_device
&& tty_sid
> 0) {
1072 * If we have received a hangup, we need to send a
1073 * SIGHUP to the terminal's controlling process.
1074 * The reason is that the original stream head for
1075 * the terminal hasn't seen the M_HANGUP message
1076 * (it went up through the ppp driver to the stream
1077 * head for our fd to /dev/ppp).
1079 (void) kill(tty_sid
, SIGHUP
);
1086 * Check whether the link seems not to be 8-bit clean
1095 * Skip this is synchronous link is used, since spppasyn won't
1096 * be anywhere in the stream below to handle the ioctl.
1102 if (strioctl(pppfd
, PPPIO_GCLEAN
, &x
, 0, sizeof (x
)) < 0) {
1103 warn("unable to obtain serial link status: %m");
1108 s
= "bit 7 set to 1";
1111 s
= "bit 7 set to 0";
1121 warn("Serial link is not 8-bit clean:");
1122 warn("All received characters had %s", s
);
1127 * List of valid speeds.
1200 { 115200, B115200
},
1203 { 153600, B153600
},
1206 { 230400, B230400
},
1209 { 307200, B307200
},
1212 { 460800, B460800
},
1215 { 921600, B921600
},
1223 * Translate from bits/second to a speed_t
1226 translate_speed(int bps
)
1228 struct speed
*speedp
;
1233 for (speedp
= speeds
; speedp
->speed_int
; speedp
++) {
1234 if (bps
== speedp
->speed_int
) {
1235 return (speedp
->speed_val
);
1238 set_source(&speed_info
);
1239 option_error("speed %d not supported", bps
);
1246 * Translate from a speed_t to bits/second
1249 baud_rate_of(int speed
)
1251 struct speed
*speedp
;
1256 for (speedp
= speeds
; speedp
->speed_int
; speedp
++) {
1257 if (speed
== speedp
->speed_val
) {
1258 return (speedp
->speed_int
);
1267 * Set up the serial port on `fd' for 8 bits, no parity, at the requested
1268 * speed, etc. If `local' is true, set CLOCAL regardless of whether the
1269 * modem option was specified.
1272 set_up_tty(fd
, local
)
1276 struct termios tios
;
1287 if (strioctl(fd
, S_IOCGETMODE
, &sm
, sizeof (sm
),
1292 baud_rate
= sm
.sm_baudrate
;
1293 dbglog("synchronous speed appears to be %d bps", baud_rate
);
1295 if (tcgetattr(fd
, &tios
) < 0) {
1296 fatal("tcgetattr: %m");
1298 if (!restore_term
) {
1300 if (myioctl(fd
, TIOCGWINSZ
, &wsinfo
) < 0) {
1301 if (errno
== EINVAL
) {
1303 * ptem returns EINVAL if all zeroes.
1304 * Strange and unfixable code.
1306 bzero(&wsinfo
, sizeof (wsinfo
));
1308 warn("unable to get TTY window "
1313 tios
.c_cflag
&= ~(CSIZE
| CSTOPB
| PARENB
| CLOCAL
);
1315 tios
.c_cflag
|= CRTSCTS
| CRTSXOFF
;
1316 } else if (crtscts
< 0) {
1317 tios
.c_cflag
&= ~CRTSCTS
& ~CRTSXOFF
;
1319 tios
.c_cflag
|= CS8
| CREAD
| HUPCL
;
1320 if (local
|| !modem
) {
1321 tios
.c_cflag
|= CLOCAL
;
1323 tios
.c_iflag
= IGNBRK
| IGNPAR
;
1326 tios
.c_cc
[VMIN
] = 1;
1327 tios
.c_cc
[VTIME
] = 0;
1329 if (crtscts
== -2) {
1330 tios
.c_iflag
|= IXON
| IXOFF
;
1331 tios
.c_cc
[VSTOP
] = 0x13; /* DC3 = XOFF = ^S */
1332 tios
.c_cc
[VSTART
] = 0x11; /* DC1 = XON = ^Q */
1334 speed
= translate_speed(inspeed
);
1336 (void) cfsetospeed(&tios
, speed
);
1337 (void) cfsetispeed(&tios
, speed
);
1339 speed
= cfgetospeed(&tios
);
1341 * We can't proceed if the serial port speed is 0,
1342 * since that implies that the serial port is disabled.
1345 fatal("Baud rate for %s is 0; need explicit "
1346 "baud rate", devnam
);
1349 if (tcsetattr(fd
, TCSAFLUSH
, &tios
) < 0) {
1350 fatal("tcsetattr: %m");
1352 baud_rate
= baud_rate_of(speed
);
1353 dbglog("%s speed set to %d bps",
1354 fd
== pty_slave
? "pty" : "serial", baud_rate
);
1362 * Restore the terminal to the saved settings.
1368 if (restore_term
== 0) {
1371 if (!default_device
) {
1373 * Turn off echoing, because otherwise we can get into
1374 * a loop with the tty and the modem echoing to each
1375 * other. We presume we are the sole user of this tty
1376 * device, so when we close it, it will revert to its
1379 inittermios
.c_lflag
&= ~(ECHO
| ECHONL
);
1381 if (tcsetattr(fd
, TCSAFLUSH
, &inittermios
) < 0) {
1382 if (!hungup
&& errno
!= ENXIO
) {
1383 warn("tcsetattr: %m");
1386 if (wsinfo
.ws_row
!= 0 || wsinfo
.ws_col
!= 0 ||
1387 wsinfo
.ws_xpixel
!= 0 || wsinfo
.ws_ypixel
!= 0) {
1388 if (myioctl(fd
, TIOCSWINSZ
, &wsinfo
) < 0) {
1389 warn("unable to set TTY window size: %m");
1398 * Control the DTR line on the serial port. This is called from die(), so it
1399 * shouldn't call die()
1405 int modembits
= TIOCM_DTR
;
1407 myioctl(fd
, (on
? TIOCMBIS
: TIOCMBIC
), &modembits
) < 0) {
1408 warn("unable to set DTR line %s: %m", (on
? "ON" : "OFF"));
1415 * Open the device we use for getting packets in demand mode. Under Solaris 2,
1416 * we use our existing fd to the ppp driver.
1422 * Plumb the interface.
1424 if (IPCP_ENABLED
&& (plumb_ipif(0) == 0)) {
1425 fatal("Unable to initialize IP interface for demand dial.");
1428 if (IPV6CP_ENABLED
&& (plumb_ip6if(0) == 0)) {
1429 fatal("Unable to initialize IPv6 interface for demand dial.");
1439 * Output PPP packet downstream
1443 output(unit
, p
, len
)
1454 data
.buf
= (caddr_t
)p
;
1457 while (putmsg(pppfd
, NULL
, &data
, 0) < 0) {
1460 if (--retries
< 0 ||
1461 (errno
!= EWOULDBLOCK
&& errno
!= EAGAIN
)) {
1462 if (errno
!= ENXIO
) {
1463 error("Couldn't send packet: %m");
1469 pfd
.events
= POLLOUT
;
1471 /* wait for up to 0.25 seconds */
1472 n
= poll(&pfd
, 1, 250);
1473 } while ((n
== -1) && (errno
== EINTR
));
1475 if (debug
&& sent_ok
) {
1476 dbglog("sent %P", p
, len
);
1483 * Wait until there is data available, for the length of time specified by
1484 * timo (indefinite if timo is NULL).
1488 struct timeval
*timo
;
1492 t
= (timo
== NULL
? -1 : (timo
->tv_sec
* 1000 + timo
->tv_usec
/ 1000));
1493 if ((poll(pollfds
, n_pollfds
, t
) < 0) && (errno
!= EINTR
)) {
1501 * Add an fd to the set that wait_input waits for.
1512 for (n
= 0; n
< n_pollfds
; ++n
) {
1513 if (pollfds
[n
].fd
== fd
) {
1517 if (n_pollfds
< MAX_POLLFDS
) {
1518 pollfds
[n_pollfds
].fd
= fd
;
1519 pollfds
[n_pollfds
].events
= POLLIN
| POLLPRI
| POLLHUP
;
1522 fatal("add_fd: too many inputs!");
1529 * Remove an fd from the set that wait_input waits for.
1537 for (n
= 0; n
< n_pollfds
; ++n
) {
1538 if (pollfds
[n
].fd
== fd
) {
1539 while (++n
< n_pollfds
) {
1540 pollfds
[n
-1] = pollfds
[n
];
1549 dump_packet(uchar_t
*buf
, int len
)
1556 struct protoent
*pep
;
1557 struct in6_addr addr
;
1558 char fromstr
[INET6_ADDRSTRLEN
];
1559 char tostr
[INET6_ADDRSTRLEN
];
1562 notice("strange link activity: %.*B", len
, buf
);
1566 if (bp
[0] == 0xFF && bp
[1] == 0x03)
1570 proto
= (proto
<< 8) + *bp
++;
1574 if (len
< IP_HDRLEN
|| get_ipv(bp
) != 4 || get_iphl(bp
) < 5) {
1575 notice("strange IP packet activity: %16.*B", len
, buf
);
1578 src
= get_ipsrc(bp
);
1579 dst
= get_ipdst(bp
);
1580 proto
= get_ipproto(bp
);
1581 if ((pep
= getprotobynumber(proto
)) != NULL
) {
1584 (void) slprintf(sbuf
, sizeof (sbuf
), "IP proto %d",
1588 if ((get_ipoff(bp
) & IP_OFFMASK
) != 0) {
1589 len
-= get_iphl(bp
) * 4;
1590 bp
+= get_iphl(bp
) * 4;
1591 notice("%s fragment from %I->%I: %8.*B", cp
, src
, dst
,
1594 if (len
> get_iplen(bp
))
1595 len
= get_iplen(bp
);
1596 len
-= get_iphl(bp
) * 4;
1597 bp
+= get_iphl(bp
) * 4;
1598 offs
= proto
== IPPROTO_TCP
? (get_tcpoff(bp
)*4) : 8;
1599 if (proto
== IPPROTO_TCP
|| proto
== IPPROTO_UDP
)
1600 notice("%s data:%d %s%I:%d->%I:%d: %8.*B", cp
,
1602 proto
== IPPROTO_TCP
?
1603 tcp_flag_decode(get_tcpflags(bp
)) : "",
1604 src
, get_sport(bp
), dst
, get_dport(bp
),
1607 notice("%s %d bytes %I->%I: %8.*B", cp
, len
,
1613 if (len
< IP6_HDRLEN
) {
1614 notice("strange IPv6 activity: %16.*B", len
, buf
);
1617 (void) BCOPY(get_ip6src(bp
), &addr
, sizeof (addr
));
1618 (void) inet_ntop(AF_INET6
, &addr
, fromstr
, sizeof (fromstr
));
1619 (void) BCOPY(get_ip6dst(bp
), &addr
, sizeof (addr
));
1620 (void) inet_ntop(AF_INET6
, &addr
, tostr
, sizeof (tostr
));
1621 proto
= get_ip6nh(bp
);
1622 if (proto
== IPPROTO_FRAGMENT
) {
1623 notice("IPv6 fragment from %s->%s", fromstr
,
1627 if ((pep
= getprotobynumber(proto
)) != NULL
) {
1630 (void) slprintf(sbuf
, sizeof (sbuf
), "IPv6 proto %d",
1636 offs
= proto
== IPPROTO_TCP
? (get_tcpoff(bp
)*4) : 8;
1637 if (proto
== IPPROTO_TCP
|| proto
== IPPROTO_UDP
)
1638 notice("%s data:%d %s[%s]%d->[%s]%d: %8.*B", cp
,
1640 proto
== IPPROTO_TCP
?
1641 tcp_flag_decode(get_tcpflags(bp
)) : "",
1642 fromstr
, get_sport(bp
), tostr
, get_dport(bp
),
1645 notice("%s %d bytes %s->%s: %8.*B", cp
, len
,
1646 fromstr
, tostr
, len
, bp
);
1649 if ((cp
= protocol_name(proto
)) == NULL
) {
1650 (void) slprintf(sbuf
, sizeof (sbuf
), "0x#X", proto
);
1651 cp
= (const char *)sbuf
;
1653 notice("link activity: %s %16.*B", cp
, len
, bp
);
1660 handle_bind(u_int32_t reason
)
1663 * Here we might, in the future, handle DL_BIND_REQ notifications
1664 * in order to close and re-open a NCP when certain interface
1665 * parameters (addresses, etc.) are changed via external mechanisms
1666 * such as through the "ifconfig" program.
1669 case PPP_LINKSTAT_IPV4_BOUND
:
1672 case PPP_LINKSTAT_IPV6_BOUND
:
1676 error("handle_bind: unrecognized reason");
1685 handle_unbind(u_int32_t reason
)
1689 static const char *unplumb_str
= "unplumbed";
1690 static const char *down_str
= "downed";
1693 * Since the kernel driver (sppp) notifies this daemon of the
1694 * DLPI bind/unbind activities (for the purpose of bringing down
1695 * a NCP), we need to explicitly test the "actual" status of
1696 * the interface instance for which the notification is destined
1697 * from. This is because /dev/ip performs multiple DLPI attach-
1698 * bind-unbind-detach during the early life of the interface,
1699 * and when certain interface parameters change. A DL_UNBIND_REQ
1700 * coming down to the sppp driver from /dev/ip (which results in
1701 * our receiving of the PPP_LINKSTAT_*_UNBOUND link status message)
1702 * is not enough to conclude that the interface has been marked
1703 * DOWN (its IFF_UP bit is cleared) or is going away. Therefore,
1704 * we should query /dev/ip directly, upon receiving such *_UNBOUND
1705 * notification, to determine whether the interface is DOWN
1706 * for real, and only take the necessary actions when IFF_UP
1707 * bit for the interface instance is actually cleared.
1710 case PPP_LINKSTAT_IPV4_UNBOUND
:
1712 rc
= giflags(IFF_UP
, &iff_up_isset
);
1713 if (!iff_up_isset
) {
1716 info("IPv4 interface %s by administrator",
1717 ((rc
< 0 && rc
== ENXIO
) ? unplumb_str
: down_str
));
1718 fsm_close(&ipcp_fsm
[0],
1719 "administratively disconnected");
1723 case PPP_LINKSTAT_IPV6_UNBOUND
:
1725 rc
= giflags(IFF_UP
, &iff_up_isset
);
1726 if (!iff_up_isset
) {
1729 info("IPv6 interface %s by administrator",
1730 ((rc
< 0 && rc
== ENXIO
) ? unplumb_str
: down_str
));
1731 fsm_close(&ipv6cp_fsm
[0],
1732 "administratively disconnected");
1737 error("handle_unbind: unrecognized reason");
1745 * Get a PPP packet from the serial device.
1757 uint32_t ctrlbuf
[1536 / sizeof (uint32_t)];
1763 data
.maxlen
= PPP_MRU
+ PPP_HDRLEN
;
1764 data
.buf
= (caddr_t
)buf
;
1766 ctrl
.maxlen
= sizeof (ctrlbuf
);
1767 ctrl
.buf
= (caddr_t
)ctrlbuf
;
1770 rc
= len
= getmsg(pppfd
, &ctrl
, &data
, &flags
);
1771 if (sys_read_packet_hook
!= NULL
) {
1772 rc
= len
= (*sys_read_packet_hook
)(len
, &ctrl
, &data
,
1776 if (errno
== EAGAIN
|| errno
== EINTR
) {
1779 fatal("Error reading packet: %m");
1781 if ((data
.len
> 0) && (ctrl
.len
< 0)) {
1783 * If there's more data on stream head, keep reading
1784 * but discard, since the stream is now corrupt.
1786 if (rc
& MOREDATA
) {
1787 dbglog("More data; input packet garbled");
1795 } else if (ctrl
.len
> 0) {
1797 * If there's more ctl on stream head, keep reading,
1798 * but start discarding. We can't deal with fragmented
1802 dbglog("More control; stream garbled");
1808 if (ctrl
.len
< sizeof (struct ppp_ls
)) {
1809 warn("read_packet: ctl.len %d < "
1811 ctrl
.len
, sizeof (struct ppp_ls
));
1814 plp
= (struct ppp_ls
*)ctrlbuf
;
1815 if (plp
->magic
!= PPPLSMAGIC
) {
1816 /* Skip, as we don't understand it */
1817 dbglog("read_packet: unrecognized control %lX",
1822 lastlink_status
= plp
->ppp_message
;
1824 switch (plp
->ppp_message
) {
1825 case PPP_LINKSTAT_HANGUP
:
1826 return (0); /* Hangup */
1827 /* For use by integrated drivers. */
1828 case PPP_LINKSTAT_UP
:
1832 case PPP_LINKSTAT_NEEDUP
:
1834 dump_packet(buf
, data
.len
);
1835 return (-1); /* Demand dial */
1836 case PPP_LINKSTAT_IPV4_UNBOUND
:
1837 (void) handle_unbind(plp
->ppp_message
);
1839 case PPP_LINKSTAT_IPV4_BOUND
:
1840 (void) handle_bind(plp
->ppp_message
);
1843 case PPP_LINKSTAT_IPV6_UNBOUND
:
1844 (void) handle_unbind(plp
->ppp_message
);
1846 case PPP_LINKSTAT_IPV6_BOUND
:
1847 (void) handle_bind(plp
->ppp_message
);
1851 warn("read_packet: unknown link status type!");
1856 * We get here on zero length data or control.
1866 * Get outgoing packets from the ppp device, and detect when we want to bring
1867 * the real link up. Return value is 1 if we need to bring up the link, or 0
1876 * In the Solaris 2.x kernel-level portion implementation, packets
1877 * which are received on a demand-dial interface are immediately
1878 * discarded, and a notification message is sent up the control
1879 * stream to the pppd process. Therefore, the call to read_packet()
1880 * below is merely there to wait for such message.
1882 lastlink_status
= 0;
1884 while (read_packet(inpacket_buf
) > 0) {
1888 return (lastlink_status
== PPP_LINKSTAT_NEEDUP
);
1894 ppp_send_muxoption(unit
, muxflag
)
1901 * Since muxed frame feature is implemented in the async module,
1902 * don't send down the ioctl in the synchronous case.
1904 if (!sync_serial
&& fdmuxid
>= 0 && pppfd
!= -1) {
1908 if (strioctl(pppfd
, PPPIO_MUX
, cf
, sizeof (cf
), 0) < 0) {
1909 error("Couldn't set mux option: %m");
1916 ppp_recv_muxoption(unit
, muxflag
)
1923 * Since muxed frame feature is implemented in the async module,
1924 * don't send down the ioctl in the synchronous case.
1926 if (!sync_serial
&& fdmuxid
>= 0 && pppfd
!= -1) {
1930 if (strioctl(pppfd
, PPPIO_MUX
, cf
, sizeof (cf
), 0) < 0) {
1931 error("Couldn't set receive mux option: %m");
1940 * Configure the transmit characteristics of the ppp interface.
1944 ppp_send_config(unit
, mtu
, asyncmap
, pcomp
, accomp
)
1954 error("ppp_send_config called with invalid device handle");
1957 cf
[0] = link_mtu
= mtu
;
1958 if (strioctl(pppfd
, PPPIO_MTU
, cf
, sizeof (cf
[0]), 0) < 0) {
1959 if (hungup
&& errno
== ENXIO
) {
1962 error("Couldn't set MTU: %m");
1964 if (fdmuxid
!= -1) {
1966 if (strioctl(pppfd
, PPPIO_XACCM
, &asyncmap
,
1967 sizeof (asyncmap
), 0) < 0) {
1968 error("Couldn't set transmit ACCM: %m");
1971 cf
[0] = (pcomp
? COMP_PROT
: 0) + (accomp
? COMP_AC
: 0);
1972 cf
[1] = COMP_PROT
| COMP_AC
;
1974 if (any_compressions() && strioctl(pppfd
, PPPIO_CFLAGS
, cf
,
1975 sizeof (cf
), sizeof (cf
[0])) < 0) {
1976 error("Couldn't set prot/AC compression: %m");
1984 * Set the extended transmit ACCM for the interface.
1988 ppp_set_xaccm(unit
, accm
)
1995 if (fdmuxid
!= -1 && strioctl(pppfd
, PPPIO_XACCM
, accm
,
1996 sizeof (ext_accm
), 0) < 0) {
1997 if (!hungup
|| errno
!= ENXIO
) {
1998 warn("Couldn't set extended ACCM: %m");
2006 * Configure the receive-side characteristics of the ppp interface.
2010 ppp_recv_config(unit
, mru
, asyncmap
, pcomp
, accomp
)
2020 error("ppp_recv_config called with invalid device handle");
2024 if (strioctl(pppfd
, PPPIO_MRU
, cf
, sizeof (cf
[0]), 0) < 0) {
2025 if (hungup
&& errno
== ENXIO
) {
2028 error("Couldn't set MRU: %m");
2030 if (fdmuxid
!= -1) {
2032 if (strioctl(pppfd
, PPPIO_RACCM
, &asyncmap
,
2033 sizeof (asyncmap
), 0) < 0) {
2034 error("Couldn't set receive ACCM: %m");
2037 cf
[0] = (pcomp
? DECOMP_PROT
: 0) + (accomp
? DECOMP_AC
: 0);
2038 cf
[1] = DECOMP_PROT
| DECOMP_AC
;
2040 if (any_compressions() && strioctl(pppfd
, PPPIO_CFLAGS
, cf
,
2041 sizeof (cf
), sizeof (cf
[0])) < 0) {
2042 error("Couldn't set prot/AC decompression: %m");
2047 #ifdef NEGOTIATE_FCS
2051 * Configure the sender-side FCS.
2055 ppp_send_fcs(unit
, fcstype
)
2064 if (fcstype
& FCSALT_32
) {
2066 } else if (fcstype
& FCSALT_NULL
) {
2071 if (strioctl(pppfd
, PPPIO_XFCS
, &fcs
, sizeof (fcs
), 0) < 0) {
2072 warn("Couldn't set transmit FCS: %m");
2079 * Configure the receiver-side FCS.
2083 ppp_recv_fcs(unit
, fcstype
)
2092 if (fcstype
& FCSALT_32
) {
2094 } else if (fcstype
& FCSALT_NULL
) {
2099 if (strioctl(pppfd
, PPPIO_RFCS
, &fcs
, sizeof (fcs
), 0) < 0) {
2100 warn("Couldn't set receive FCS: %m");
2108 * Ask kernel whether a given compression method is acceptable for use.
2112 ccp_test(unit
, opt_ptr
, opt_len
, for_transmit
)
2118 if (strioctl(pppfd
, (for_transmit
? PPPIO_XCOMP
: PPPIO_RCOMP
),
2119 opt_ptr
, opt_len
, 0) >= 0) {
2122 warn("Error in %s ioctl: %m",
2123 (for_transmit
? "PPPIO_XCOMP" : "PPPIO_RCOMP"));
2124 return ((errno
== ENOSR
) ? 0 : -1);
2131 * Tune compression effort level.
2135 ccp_tune(unit
, effort
)
2141 if (strioctl(pppfd
, PPPIO_COMPLEV
, &x
, sizeof (x
), 0) < 0) {
2142 warn("unable to set compression effort level: %m");
2150 * Inform kernel about the current state of CCP.
2154 ccp_flags_set(unit
, isopen
, isup
)
2155 int unit
, isopen
, isup
;
2159 cf
[0] = (isopen
? CCP_ISOPEN
: 0) + (isup
? CCP_ISUP
: 0);
2160 cf
[1] = CCP_ISOPEN
| CCP_ISUP
| CCP_ERROR
| CCP_FATALERROR
;
2162 if (strioctl(pppfd
, PPPIO_CFLAGS
, cf
, sizeof (cf
), sizeof (cf
[0]))
2164 if (!hungup
|| errno
!= ENXIO
) {
2165 error("Couldn't set kernel CCP state: %m");
2173 * Return how long the link has been idle.
2177 get_idle_time(u
, pids
)
2179 struct ppp_idle
*pids
;
2183 rc
= strioctl(pppfd
, PPPIO_GIDLE
, pids
, 0, sizeof (struct ppp_idle
));
2185 warn("unable to obtain idle time: %m");
2187 return ((rc
== 0) ? 1 : 0);
2193 * Return statistics for the link.
2197 get_ppp_stats(u
, stats
)
2199 struct pppd_stats
*stats
;
2201 struct ppp_stats64 s64
;
2204 /* Try first to get these from the 64-bit interface */
2205 if (strioctl(pppfd
, PPPIO_GETSTAT64
, &s64
, 0, sizeof (s64
)) >= 0) {
2206 stats
->bytes_in
= s64
.p
.ppp_ibytes
;
2207 stats
->bytes_out
= s64
.p
.ppp_obytes
;
2208 stats
->pkts_in
= s64
.p
.ppp_ipackets
;
2209 stats
->pkts_out
= s64
.p
.ppp_opackets
;
2213 if (strioctl(pppfd
, PPPIO_GETSTAT
, &s
, 0, sizeof (s
)) < 0) {
2214 error("Couldn't get link statistics: %m");
2217 stats
->bytes_in
= s
.p
.ppp_ibytes
;
2218 stats
->bytes_out
= s
.p
.ppp_obytes
;
2219 stats
->pkts_in
= s
.p
.ppp_ipackets
;
2220 stats
->pkts_out
= s
.p
.ppp_opackets
;
2224 #if defined(FILTER_PACKETS)
2228 * Transfer the pass and active filters to the kernel.
2231 set_filters(pass
, active
)
2232 struct bpf_program
*pass
;
2233 struct bpf_program
*active
;
2237 if (pass
->bf_len
> 0) {
2238 if (strioctl(pppfd
, PPPIO_PASSFILT
, pass
,
2239 sizeof (struct bpf_program
), 0) < 0) {
2240 error("Couldn't set pass-filter in kernel: %m");
2244 if (active
->bf_len
> 0) {
2245 if (strioctl(pppfd
, PPPIO_ACTIVEFILT
, active
,
2246 sizeof (struct bpf_program
), 0) < 0) {
2247 error("Couldn't set active-filter in kernel: %m");
2253 #endif /* FILTER_PACKETS */
2258 * Returns 1 if decompression was disabled as a result of an error detected
2259 * after decompression of a packet, 0 otherwise. This is necessary because
2260 * of patent nonsense.
2264 ccp_fatal_error(unit
)
2270 if (strioctl(pppfd
, PPPIO_CFLAGS
, cf
, sizeof (cf
), sizeof (cf
[0]))
2272 if (errno
!= ENXIO
&& errno
!= EINVAL
) {
2273 error("Couldn't get compression flags: %m");
2277 return (cf
[0] & CCP_FATALERROR
);
2283 * Config TCP header compression.
2287 sifvjcomp(u
, vjcomp
, xcidcomp
, xmaxcid
)
2288 int u
, vjcomp
, xcidcomp
, xmaxcid
;
2294 * Since VJ compression code is in the comp module, there's no
2295 * point of sending down any ioctls pertaining to VJ compression
2296 * when the module isn't pushed on the stream.
2298 if (!any_compressions()) {
2303 maxcid
[0] = xcidcomp
;
2304 maxcid
[1] = 15; /* XXX should be rmaxcid */
2306 if (strioctl(pppfd
, PPPIO_VJINIT
, maxcid
,
2307 sizeof (maxcid
), 0) < 0) {
2308 error("Couldn't initialize VJ compression: %m");
2313 cf
[0] = (vjcomp
? COMP_VJC
+ DECOMP_VJC
: 0) /* XXX this is wrong */
2314 + (xcidcomp
? COMP_VJCCID
+ DECOMP_VJCCID
: 0);
2316 cf
[1] = COMP_VJC
+ DECOMP_VJC
+ COMP_VJCCID
+ DECOMP_VJCCID
;
2318 if (strioctl(pppfd
, PPPIO_CFLAGS
, cf
, sizeof (cf
), sizeof (cf
[0]))
2321 error("Couldn't enable VJ compression: %m");
2323 error("Couldn't disable VJ compression: %m");
2333 * Set or clear the IP interface flags.
2342 if (!IPCP_ENABLED
|| (ipmuxid
== -1)) {
2345 if (ipfd
== -1 && open_ipfd() == -1)
2347 BZERO(&ifr
, sizeof (ifr
));
2348 (void) strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
2349 if (myioctl(ipfd
, SIOCGIFFLAGS
, &ifr
) < 0) {
2350 error("Couldn't get IP interface flags: %m");
2356 ifr
.ifr_flags
&= ~f
;
2358 if (myioctl(ipfd
, SIOCSIFFLAGS
, &ifr
) < 0) {
2359 error("Couldn't set IP interface flags: %m");
2368 * Config the interface up and enable IP packets to pass.
2377 } else if (!IPCP_ENABLED
) {
2378 warn("sifup called when IPCP is disabled");
2380 } else if (ipmuxid
== -1) {
2381 warn("sifup called in wrong state");
2383 } else if (!siflags(IFF_UP
, 1)) {
2384 error("Unable to mark the IP interface UP");
2394 * Config the interface down and disable IP. Possibly called from die(),
2395 * so there shouldn't be any call to die() here.
2402 if (!IPCP_ENABLED
) {
2403 warn("sifdown called when IPCP is disabled");
2405 } else if (!if_is_up
|| (ipmuxid
== -1)) {
2407 } else if (!siflags(IFF_UP
, 0)) {
2408 error("Unable to mark the IP interface DOWN");
2418 * Set the mode for handling packets for a given NP. Not worried
2419 * about performance here since this is done only rarely.
2423 sifnpmode(u
, proto
, mode
)
2430 static const struct npi_entry
{
2431 enum NPmode ne_value
;
2432 const char *ne_name
;
2434 { NPMODE_PASS
, "pass" },
2435 { NPMODE_DROP
, "drop" },
2436 { NPMODE_ERROR
, "error" },
2437 { NPMODE_QUEUE
, "queue" },
2440 char pname
[32], mname
[32];
2443 npi
[1] = (uint32_t)mode
;
2445 cp
= protocol_name(proto
);
2447 (void) slprintf(pname
, sizeof (pname
), "NP %04X", proto
);
2449 (void) strlcpy(pname
, cp
, sizeof (pname
));
2450 for (i
= 0; i
< Dim(npi_list
); i
++)
2451 if (npi_list
[i
].ne_value
== mode
)
2453 if (i
>= Dim(npi_list
))
2454 (void) slprintf(mname
, sizeof (mname
), "mode %d", (int)mode
);
2456 (void) strlcpy(mname
, npi_list
[i
].ne_name
, sizeof (mname
));
2458 if ((proto
== PPP_IP
&& !if_is_up
) ||
2459 (proto
== PPP_IPV6
&& !if6_is_up
)) {
2460 dbglog("ignoring request to set %s to %s", pname
, mname
);
2463 if (strioctl(pppfd
, PPPIO_NPMODE
, npi
, sizeof (npi
), 0) < 0) {
2464 error("unable to set %s to %s: %m", pname
, mname
);
2473 * Config the interface IP MTU.
2481 if (!IPCP_ENABLED
|| (ipmuxid
== -1)) {
2484 if (ipfd
== -1 && open_ipfd() == -1)
2486 BZERO(&ifr
, sizeof (ifr
));
2487 (void) strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
2488 ifr
.ifr_metric
= mtu
;
2489 if (myioctl(ipfd
, SIOCSIFMTU
, &ifr
) < 0) {
2490 error("Couldn't set IP MTU on %s to %d: %m", ifr
.ifr_name
,
2500 * Config the interface IP addresses and netmask.
2511 struct sockaddr_in sin
;
2513 if (!IPCP_ENABLED
|| (ipmuxid
== -1 && plumb_ipif(u
) == 0)) {
2516 if (ipfd
== -1 && open_ipfd() == -1)
2519 * Set the IP interface MTU.
2521 if (!sifmtu(link_mtu
)) {
2525 * Set the IP interface local point-to-point address.
2527 BZERO(&sin
, sizeof (sin
));
2528 sin
.sin_family
= AF_INET
;
2529 sin
.sin_addr
.s_addr
= o
;
2531 BZERO(&ifr
, sizeof (ifr
));
2532 (void) strlcpy(ifr
.ifr_name
, ifname
, sizeof (ifr
.ifr_name
));
2533 ifr
.ifr_addr
= *(struct sockaddr
*)&sin
;
2534 if (myioctl(ipfd
, SIOCSIFADDR
, &ifr
) < 0) {
2535 error("Couldn't set local IP address (%s): %m", ifr
.ifr_name
);
2539 * Set the IP interface remote point-to-point address.
2541 sin
.sin_addr
.s_addr
= h
;
2543 ifr
.ifr_dstaddr
= *(struct sockaddr
*)&sin
;
2544 if (myioctl(ipfd
, SIOCSIFDSTADDR
, &ifr
) < 0) {
2545 error("Couldn't set remote IP address (%s): %m", ifr
.ifr_name
);
2555 * Clear the interface IP addresses.
2564 if (!IPCP_ENABLED
) {
2568 * Most of the work is done in sifdown().
2577 * Add or delete a route.
2581 sifroute(int u
, u_int32_t l
, u_int32_t g
, int add
, const char *str
)
2583 struct sockaddr_in sin_dst
, sin_gtw
;
2586 if (!IPCP_ENABLED
|| (ipmuxid
== -1)) {
2587 error("Can't %s route: IP is not enabled", str
);
2590 if (ipfd
== -1 && open_ipfd() == -1)
2593 BZERO(&sin_dst
, sizeof (sin_dst
));
2594 sin_dst
.sin_family
= AF_INET
;
2595 sin_dst
.sin_addr
.s_addr
= l
;
2597 BZERO(&sin_gtw
, sizeof (sin_gtw
));
2598 sin_gtw
.sin_family
= AF_INET
;
2599 sin_gtw
.sin_addr
.s_addr
= g
;
2601 BZERO(&rt
, sizeof (rt
));
2602 rt
.rt_dst
= *(struct sockaddr
*)&sin_dst
;
2603 rt
.rt_gateway
= *(struct sockaddr
*)&sin_gtw
;
2604 rt
.rt_flags
= (RTF_GATEWAY
|RTF_STATIC
);
2606 if (myioctl(ipfd
, (add
? SIOCADDRT
: SIOCDELRT
), &rt
) < 0) {
2607 error("Can't %s route: %m", str
);
2616 * Assign a default route through the address given.
2620 sifdefaultroute(u
, l
, g
)
2625 if (!sifroute(u
, 0, g
, 1, "add default")) {
2628 default_route_gateway
= g
;
2635 * Delete a default route through the address given.
2639 cifdefaultroute(u
, l
, g
)
2644 if (!sifroute(u
, 0, g
, 0, "delete default")) {
2647 default_route_gateway
= 0;
2654 * Make a proxy ARP entry for the peer.
2658 sifproxyarp(unit
, hisaddr
, quietflag
)
2663 struct sockaddr_in sin
;
2664 struct xarpreq arpreq
;
2668 if (!IPCP_ENABLED
|| (ipmuxid
== -1)) {
2671 if (ipfd
== -1 && open_ipfd() == -1)
2674 BZERO(&sin
, sizeof (sin
));
2675 sin
.sin_family
= AF_INET
;
2676 sin
.sin_addr
.s_addr
= hisaddr
;
2678 BZERO(&arpreq
, sizeof (arpreq
));
2679 if (!get_ether_addr(hisaddr
, &arpreq
.xarp_ha
, quietflag
)) {
2682 BCOPY(&sin
, &arpreq
.xarp_pa
, sizeof (sin
));
2683 arpreq
.xarp_flags
= ATF_PERM
| ATF_PUBL
;
2684 arpreq
.xarp_ha
.sdl_family
= AF_LINK
;
2686 if (myioctl(ipfd
, SIOCSXARP
, (caddr_t
)&arpreq
) < 0) {
2688 error("Couldn't set proxy ARP entry: %m");
2691 cp
= (const uchar_t
*)LLADDR(&arpreq
.xarp_ha
);
2692 str
= _link_ntoa(cp
, str
, arpreq
.xarp_ha
.sdl_alen
, IFT_OTHER
);
2694 dbglog("established proxy ARP for %I using %s", hisaddr
,
2698 proxy_arp_addr
= hisaddr
;
2705 * Delete the proxy ARP entry for the peer.
2709 cifproxyarp(unit
, hisaddr
)
2713 struct sockaddr_in sin
;
2714 struct xarpreq arpreq
;
2716 if (!IPCP_ENABLED
|| (ipmuxid
== -1)) {
2719 if (ipfd
== -1 && open_ipfd() == -1)
2722 BZERO(&sin
, sizeof (sin
));
2723 sin
.sin_family
= AF_INET
;
2724 sin
.sin_addr
.s_addr
= hisaddr
;
2726 BZERO(&arpreq
, sizeof (arpreq
));
2727 BCOPY(&sin
, &arpreq
.xarp_pa
, sizeof (sin
));
2728 arpreq
.xarp_ha
.sdl_family
= AF_LINK
;
2730 if (myioctl(ipfd
, SIOCDXARP
, (caddr_t
)&arpreq
) < 0) {
2731 error("Couldn't delete proxy ARP entry: %m");
2741 * Get the hardware address of an interface on the the same subnet as
2742 * ipaddr. This routine uses old-style interfaces for intentional
2743 * backward compatibility -- SIOCGLIF* isn't in older Solaris
2747 get_ether_addr(u_int32_t ipaddr
, struct sockaddr_dl
*hwaddr
, int quietflag
)
2749 struct ifreq
*ifr
, *ifend
, ifreq
;
2752 u_int32_t ina
, mask
;
2754 struct sockaddr_in sin
;
2756 if (ipfd
== -1 && open_ipfd() == -1)
2760 * Scan through the system's network interfaces.
2762 if (myioctl(ipfd
, SIOCGIFNUM
, &nif
) < 0) {
2767 ifc
.ifc_len
= nif
* sizeof (struct ifreq
);
2768 ifc
.ifc_buf
= (caddr_t
)malloc(ifc
.ifc_len
);
2769 if (ifc
.ifc_buf
== NULL
) {
2772 if (myioctl(ipfd
, SIOCGIFCONF
, &ifc
) < 0) {
2773 error("Couldn't get system interface list: %m");
2778 ifend
= (struct ifreq
*)(ifc
.ifc_buf
+ ifc
.ifc_len
);
2779 for (ifr
= ifc
.ifc_req
; ifr
< ifend
; ++ifr
) {
2780 if (ifr
->ifr_addr
.sa_family
!= AF_INET
) {
2784 * Check that the interface is up, and not
2785 * point-to-point or loopback.
2787 (void) strlcpy(ifreq
.ifr_name
, ifr
->ifr_name
,
2788 sizeof (ifreq
.ifr_name
));
2789 if (myioctl(ipfd
, SIOCGIFFLAGS
, &ifreq
) < 0) {
2792 if ((ifreq
.ifr_flags
& (IFF_UP
|IFF_BROADCAST
|IFF_POINTOPOINT
|
2793 IFF_LOOPBACK
|IFF_NOARP
)) != (IFF_UP
|IFF_BROADCAST
)) {
2797 * Get its netmask and check that it's on the right subnet.
2799 if (myioctl(ipfd
, SIOCGIFNETMASK
, &ifreq
) < 0) {
2802 (void) memcpy(&sin
, &ifr
->ifr_addr
, sizeof (sin
));
2803 ina
= sin
.sin_addr
.s_addr
;
2804 (void) memcpy(&sin
, &ifreq
.ifr_addr
, sizeof (sin
));
2805 mask
= sin
.sin_addr
.s_addr
;
2806 if ((ipaddr
& mask
) == (ina
& mask
)) {
2812 warn("No suitable interface found for proxy ARP of %I",
2817 info("found interface %s for proxy ARP of %I", ifr
->ifr_name
, ipaddr
);
2820 * New way - get the address by doing an arp request.
2822 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
2824 error("get_ether_addr: error opening IP socket: %m");
2828 BZERO(&sin
, sizeof (sin
));
2829 sin
.sin_family
= AF_INET
;
2830 sin
.sin_addr
.s_addr
= ina
;
2832 BZERO(&req
, sizeof (req
));
2833 BCOPY(&sin
, &req
.xarp_pa
, sizeof (sin
));
2834 req
.xarp_ha
.sdl_family
= AF_LINK
;
2836 if (myioctl(s
, SIOCGXARP
, &req
) < 0) {
2837 error("Couldn't get ARP entry for %I: %m", ina
);
2840 (void) memcpy(hwaddr
, &req
.xarp_ha
,
2841 sizeof (struct sockaddr_dl
));
2852 * Return mask (bogus, but needed for compatibility with other platforms).
2859 return (0xffffffffUL
);
2865 * Write an accounting record to the /var/adm/wtmp file.
2869 logwtmp(line
, name
, host
)
2874 static struct utmpx utmpx
;
2876 if (name
[0] != '\0') {
2880 (void) strncpy(utmpx
.ut_user
, name
, sizeof (utmpx
.ut_user
));
2881 (void) strncpy(utmpx
.ut_id
, ifname
, sizeof (utmpx
.ut_id
));
2882 (void) strncpy(utmpx
.ut_line
, line
, sizeof (utmpx
.ut_line
));
2884 utmpx
.ut_pid
= getpid();
2885 utmpx
.ut_type
= USER_PROCESS
;
2887 utmpx
.ut_type
= DEAD_PROCESS
;
2889 (void) gettimeofday(&utmpx
.ut_tv
, NULL
);
2890 updwtmpx("/var/adm/wtmpx", &utmpx
);
2896 * Return the serial number of this machine.
2903 if (sysinfo(SI_HW_SERIAL
, buf
, sizeof (buf
)) < 0) {
2904 error("sysinfo: %m");
2907 return ((int)strtoul(buf
, NULL
, 16));
2913 * Wrapper for STREAMS I_STR ioctl. Masks out EINTR from caller.
2916 strioctl(int fd
, int cmd
, void *ptr
, int ilen
, int olen
)
2918 struct strioctl str
;
2921 str
.ic_timout
= PPPSTRTIMOUT
;
2925 if (myioctl(fd
, I_STR
, &str
) == -1) {
2928 if (str
.ic_len
!= olen
) {
2929 dbglog("strioctl: expected %d bytes, got %d for cmd %x\n",
2930 olen
, str
.ic_len
, cmd
);
2938 * Determine if the system has a route to the specified IP address.
2939 * Returns 0 if not, 1 if so, -1 if we can't tell. `addr' is in network
2940 * byte order. For demand mode to work properly, we have to ignore routes
2941 * through our own interface. XXX Would be nice to use routing socket.
2949 struct T_optmgmt_req req
;
2953 struct T_optmgmt_ack ack
;
2954 unsigned char space
[64];
2957 struct strbuf cbuf
, dbuf
;
2959 mib2_ipRouteEntry_t routes
[8];
2960 mib2_ipRouteEntry_t
*rp
;
2962 if (ipfd
== -1 && open_ipfd() == -1)
2965 req
.req
.PRIM_type
= T_OPTMGMT_REQ
;
2966 req
.req
.OPT_offset
= (caddr_t
)&req
.hdr
- (caddr_t
)&req
;
2967 req
.req
.OPT_length
= sizeof (req
.hdr
);
2969 req
.req
.MGMT_flags
= T_CURRENT
;
2972 req
.req
.MGMT_flags
= T_CHECK
;
2975 req
.hdr
.level
= MIB2_IP
;
2979 cbuf
.buf
= (caddr_t
)&req
;
2980 cbuf
.len
= sizeof (req
);
2982 if (putmsg(ipfd
, &cbuf
, NULL
, 0) == -1) {
2983 warn("have_route_to: putmsg: %m");
2988 cbuf
.buf
= (caddr_t
)&ack
;
2989 cbuf
.maxlen
= sizeof (ack
);
2990 dbuf
.buf
= (caddr_t
)routes
;
2991 dbuf
.maxlen
= sizeof (routes
);
2993 r
= getmsg(ipfd
, &cbuf
, &dbuf
, &flags
);
2995 warn("have_route_to: getmsg: %m");
2999 if (cbuf
.len
< sizeof (struct T_optmgmt_ack
) ||
3000 ack
.ack
.PRIM_type
!= T_OPTMGMT_ACK
||
3001 ack
.ack
.MGMT_flags
!= T_SUCCESS
||
3002 ack
.ack
.OPT_length
< sizeof (struct opthdr
)) {
3003 dbglog("have_route_to: bad message len=%d prim=%d",
3004 cbuf
.len
, ack
.ack
.PRIM_type
);
3008 rh
= (struct opthdr
*)((caddr_t
)&ack
+ ack
.ack
.OPT_offset
);
3009 if (rh
->level
== 0 && rh
->name
== 0) {
3012 if (rh
->level
!= MIB2_IP
|| rh
->name
!= MIB2_IP_21
) {
3013 while (r
== MOREDATA
) {
3014 r
= getmsg(ipfd
, NULL
, &dbuf
, &flags
);
3020 * Note that we have to skip routes to our own
3021 * interface in order for demand dial to work.
3023 * XXX awful hack here. We don't know our own
3024 * ifIndex, so we can't check ipRouteIfIndex here.
3025 * Instead, we check the next hop address.
3028 nroutes
= dbuf
.len
/ sizeof (mib2_ipRouteEntry_t
);
3029 for (rp
= routes
, i
= 0; i
< nroutes
; ++i
, ++rp
) {
3030 if (rp
->ipRouteNextHop
!= remote_addr
&&
3031 ((addr
^ rp
->ipRouteDest
) &
3032 rp
->ipRouteMask
) == 0) {
3033 dbglog("have route to %I/%I via %I",
3036 rp
->ipRouteNextHop
);
3043 r
= getmsg(ipfd
, NULL
, &dbuf
, &flags
);
3052 * Get a pty master/slave pair and chown the slave side to the uid given.
3053 * Assumes slave_name points to MAXPATHLEN bytes of space.
3056 get_pty(master_fdp
, slave_fdp
, slave_name
, uid
)
3066 mfd
= open("/dev/ptmx", O_NOCTTY
| O_RDWR
);
3068 error("Couldn't open pty master: %m");
3071 pty_name
= ptsname(mfd
);
3072 if (pty_name
== NULL
) {
3073 dbglog("Didn't get pty slave name on first try; sleeping.");
3074 /* In case "grow" operation is in progress; try again. */
3076 pty_name
= ptsname(mfd
);
3078 if (pty_name
== NULL
) {
3079 error("Couldn't get name of pty slave");
3083 if (chown(pty_name
, uid
, -1) < 0) {
3084 warn("Couldn't change owner of pty slave: %m");
3086 if (chmod(pty_name
, S_IRUSR
| S_IWUSR
) < 0) {
3087 warn("Couldn't change permissions on pty slave: %m");
3089 if (unlockpt(mfd
) < 0) {
3090 warn("Couldn't unlock pty slave: %m");
3092 sfd
= open(pty_name
, O_RDWR
);
3094 error("Couldn't open pty slave %s: %m", pty_name
);
3098 if (myioctl(sfd
, I_PUSH
, "ptem") < 0) {
3099 warn("Couldn't push ptem module on pty slave: %m");
3101 dbglog("Using %s; master fd %d, slave fd %d", pty_name
, mfd
, sfd
);
3103 (void) strlcpy(slave_name
, pty_name
, MAXPATHLEN
);
3117 udp6fd
= open(UDP6_DEV_NAME
, O_RDWR
| O_NONBLOCK
, 0);
3119 error("Couldn't open UDPv6 device (%s): %m", UDP6_DEV_NAME
);
3127 * Perform IPv6 interface plumbing.
3131 plumb_ip6if(int unit
)
3133 int udp6fd
= -1, tmpfd
;
3137 if (!IPV6CP_ENABLED
|| (ifunit
== -1) || (pppfd
== -1)) {
3142 if (ip6fd
== -1 && open_ip6fd() == -1)
3144 if (use_plink
&& (udp6fd
= open_udp6fd()) == -1)
3146 tmpfd
= open(drvnam
, O_RDWR
| O_NONBLOCK
, 0);
3148 error("Couldn't open PPP device (%s): %m", drvnam
);
3150 (void) close(udp6fd
);
3153 if (kdebugflag
& 1) {
3154 x
= PPPDBG_LOG
+ PPPDBG_DRIVER
;
3155 if (strioctl(tmpfd
, PPPIO_DEBUG
, &x
, sizeof (x
), 0) < 0) {
3156 warn("PPPIO_DEBUG ioctl for mux failed: %m");
3159 if (myioctl(tmpfd
, I_PUSH
, IP_MOD_NAME
) < 0) {
3160 error("Couldn't push IP module(%s): %m", IP_MOD_NAME
);
3164 * Sets interface ppa and flags (refer to comments in plumb_ipif for
3165 * the IF_UNITSEL ioctl). In addition, the IFF_IPV6 bit must be set in
3166 * order to declare this as an IPv6 interface.
3168 BZERO(&lifr
, sizeof (lifr
));
3169 if (myioctl(tmpfd
, SIOCGLIFFLAGS
, &lifr
) < 0) {
3170 error("Couldn't get IPv6 interface flags: %m");
3173 lifr
.lifr_flags
|= IFF_IPV6
;
3174 lifr
.lifr_flags
&= ~(IFF_BROADCAST
| IFF_IPV4
);
3175 lifr
.lifr_ppa
= ifunit
;
3176 (void) strlcpy(lifr
.lifr_name
, ifname
, sizeof (lifr
.lifr_name
));
3177 if (myioctl(tmpfd
, SIOCSLIFNAME
, &lifr
) < 0) {
3178 error("Can't set ifname for unit %d: %m", ifunit
);
3182 ip6muxid
= myioctl(udp6fd
, I_PLINK
, (void *)tmpfd
);
3184 error("Can't I_PLINK PPP device to IPv6: %m");
3188 ip6muxid
= myioctl(ip6fd
, I_LINK
, (void *)tmpfd
);
3190 error("Can't I_LINK PPP device to IPv6: %m");
3194 lifr
.lifr_ip_muxid
= ip6muxid
;
3195 lifr
.lifr_arp_muxid
= -1;
3196 if (myioctl(ip6fd
, SIOCSLIFMUXID
, (caddr_t
)&lifr
) < 0) {
3197 error("Can't set mux ID: SIOCSLIFMUXID: %m");
3200 (void) close(tmpfd
);
3202 (void) close(udp6fd
);
3206 (void) close(tmpfd
);
3208 (void) close(udp6fd
);
3215 * Perform IPv6 interface unplumbing. Possibly called from die(), so there
3216 * shouldn't be any call to die() here.
3219 unplumb_ip6if(int unit
)
3221 int udp6fd
= -1, fd
= -1;
3225 if (!IPV6CP_ENABLED
|| ifunit
== -1) {
3228 if (!plumbed
&& (ip6muxid
== -1 || (ip6fd
== -1 && !use_plink
))) {
3232 if (!plumbed
&& use_plink
) {
3233 if ((udp6fd
= open_udp6fd()) == -1)
3236 * Note: must re-get mux ID, since any intervening
3237 * ifconfigs will change this.
3239 BZERO(&lifr
, sizeof (lifr
));
3240 (void) strlcpy(lifr
.lifr_name
, ifname
,
3241 sizeof (lifr
.lifr_name
));
3242 if (myioctl(ip6fd
, SIOCGLIFMUXID
, (caddr_t
)&lifr
) < 0) {
3243 warn("Can't get mux fd: SIOCGLIFMUXID: %m");
3245 id
= lifr
.lifr_ip_muxid
;
3246 fd
= myioctl(udp6fd
, _I_MUXID2FD
, (void *)id
);
3248 warn("Can't get mux fd: _I_MUXID2FD: %m");
3253 * Mark down and unlink the IPv6 interface.
3255 (void) sif6down(unit
);
3260 if ((fd
= myioctl(udp6fd
, _I_MUXID2FD
, (void *)id
)) < 0) {
3261 error("Can't recapture mux fd: _I_MUXID2FD: %m");
3262 (void) close(udp6fd
);
3265 if (myioctl(udp6fd
, I_PUNLINK
, (void *)id
) < 0) {
3266 error("Can't I_PUNLINK PPP from IPv6: %m");
3268 (void) close(udp6fd
);
3272 (void) close(udp6fd
);
3274 if (myioctl(ip6fd
, I_UNLINK
, (void *)id
) < 0) {
3275 error("Can't I_UNLINK PPP from IPv6: %m");
3285 * Set or clear the IPv6 interface flags.
3295 if (!IPV6CP_ENABLED
|| (ip6muxid
== -1)) {
3298 fd
= socket(AF_INET6
, SOCK_DGRAM
, 0);
3300 error("sif6flags: error opening IPv6 socket: %m");
3303 BZERO(&lifr
, sizeof (lifr
));
3304 (void) strlcpy(lifr
.lifr_name
, ifname
, sizeof (lifr
.lifr_name
));
3305 if (myioctl(fd
, SIOCGLIFFLAGS
, &lifr
) < 0) {
3306 error("Couldn't get IPv6 interface flags: %m");
3311 lifr
.lifr_flags
|= f
;
3313 lifr
.lifr_flags
&= ~f
;
3315 (void) strlcpy(lifr
.lifr_name
, ifname
, sizeof (lifr
.lifr_name
));
3316 if (myioctl(fd
, SIOCSLIFFLAGS
, &lifr
) < 0) {
3317 error("Couldn't set IPv6 interface flags: %m");
3328 * Config the IPv6 interface up and enable IPv6 packets to pass.
3337 } else if (!IPV6CP_ENABLED
) {
3338 warn("sif6up called when IPV6CP is disabled");
3340 } else if (ip6muxid
== -1) {
3341 warn("sif6up called in wrong state");
3343 } else if (!sif6flags(IFF_UP
, 1)) {
3344 error("Unable to mark the IPv6 interface UP");
3354 * Config the IPv6 interface down and disable IPv6. Possibly called from
3355 * die(), so there shouldn't be any call to die() here.
3362 if (!IPV6CP_ENABLED
) {
3363 warn("sif6down called when IPV6CP is disabled");
3365 } else if (!if6_is_up
|| (ip6muxid
== -1)) {
3367 } else if (!sif6flags(IFF_UP
, 0)) {
3368 error("Unable to mark the IPv6 interface DOWN");
3378 * Config the IPv6 interface MTU.
3387 if (!IPV6CP_ENABLED
|| (ip6muxid
== -1)) {
3390 s
= socket(AF_INET6
, SOCK_DGRAM
, 0);
3392 error("sif6mtu: error opening IPv6 socket: %m");
3395 BZERO(&lifr
, sizeof (lifr
));
3396 (void) strlcpy(lifr
.lifr_name
, ifname
, sizeof (lifr
.lifr_name
));
3397 lifr
.lifr_mtu
= mtu
;
3398 if (myioctl(s
, SIOCSLIFMTU
, &lifr
) < 0) {
3399 error("Couldn't set IPv6 MTU (%s): %m", lifr
.lifr_name
);
3410 * Config the interface with an IPv6 link-local address.
3414 sif6addr(unit
, ourid
, hisid
)
3420 struct sockaddr_storage laddr
;
3421 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&laddr
;
3424 if (!IPV6CP_ENABLED
|| (ip6muxid
== -1 && plumb_ip6if(unit
) == 0)) {
3427 fd
= socket(AF_INET6
, SOCK_DGRAM
, 0);
3429 error("sif6addr: error opening IPv6 socket: %m");
3433 * Set the IPv6 interface MTU.
3435 if (!sif6mtu(link_mtu
)) {
3440 * Set the interface address token. Do this because /dev/ppp responds
3441 * to DL_PHYS_ADDR_REQ with zero values, hence the interface token
3442 * came to be zero too, and without this, in.ndpd will complain.
3444 BZERO(&lifr
, sizeof (lifr
));
3445 (void) strlcpy(lifr
.lifr_name
, ifname
, sizeof (lifr
.lifr_name
));
3446 BZERO(sin6
, sizeof (struct sockaddr_in6
));
3447 IN6_LLTOKEN_FROM_EUI64(lifr
, sin6
, ourid
);
3448 if (myioctl(fd
, SIOCSLIFTOKEN
, &lifr
) < 0) {
3449 error("Couldn't set IPv6 token (%s): %m", lifr
.lifr_name
);
3454 * Set the IPv6 interface local point-to-point address.
3456 IN6_LLADDR_FROM_EUI64(lifr
, sin6
, ourid
);
3457 if (myioctl(fd
, SIOCSLIFADDR
, &lifr
) < 0) {
3458 error("Couldn't set local IPv6 address (%s): %m",
3464 * Set the IPv6 interface local point-to-point address.
3466 BZERO(&lifr
, sizeof (lifr
));
3467 (void) strlcpy(lifr
.lifr_name
, ifname
, sizeof (lifr
.lifr_name
));
3468 IN6_LLADDR_FROM_EUI64(lifr
, sin6
, hisid
);
3469 if (myioctl(fd
, SIOCSLIFDSTADDR
, &lifr
) < 0) {
3470 error("Couldn't set remote IPv6 address (%s): %m",
3489 if (!IPV6CP_ENABLED
) {
3493 * Do nothing here, as everything has been done in sif6down().
3501 * Convert 48-bit Ethernet address into 64-bit EUI. Walks the list of valid
3502 * ethernet interfaces, and convert the first found 48-bit MAC address into
3503 * EUI 64. caller also assumes that the system has a properly configured
3504 * Ethernet interface for this function to return non-zero.
3507 ether_to_eui64(p_eui64
)
3510 struct ether_addr eth_addr
;
3512 if (p_eui64
== NULL
) {
3515 if (!get_first_hwaddr(eth_addr
.ether_addr_octet
,
3516 sizeof (eth_addr
.ether_addr_octet
))) {
3520 * And convert the EUI-48 into EUI-64, per RFC 2472 [sec 4.1]
3522 p_eui64
->e8
[0] = (eth_addr
.ether_addr_octet
[0] & 0xFF) | 0x02;
3523 p_eui64
->e8
[1] = (eth_addr
.ether_addr_octet
[1] & 0xFF);
3524 p_eui64
->e8
[2] = (eth_addr
.ether_addr_octet
[2] & 0xFF);
3525 p_eui64
->e8
[3] = 0xFF;
3526 p_eui64
->e8
[4] = 0xFE;
3527 p_eui64
->e8
[5] = (eth_addr
.ether_addr_octet
[3] & 0xFF);
3528 p_eui64
->e8
[6] = (eth_addr
.ether_addr_octet
[4] & 0xFF);
3529 p_eui64
->e8
[7] = (eth_addr
.ether_addr_octet
[5] & 0xFF);
3539 /* see sbuf[] below if you change this list */
3540 static struct bit_ent bit_list
[] = {
3541 { TIOCM_DTR
, "dtr", "DTR" },
3542 { TIOCM_RTS
, "rts", "RTS" },
3543 { TIOCM_CTS
, "cts", "CTS" },
3544 { TIOCM_CD
, "dcd", "DCD" },
3545 { TIOCM_RI
, "ri", "RI" },
3546 { TIOCM_DSR
, "dsr", "DSR" },
3548 { TIOCM_LE
, "disabled", "ENABLED" },
3549 { TIOCM_ST
, NULL
, "2nd-XMIT" },
3550 { TIOCM_SR
, NULL
, "2nd-RECV" },
3556 getbits(int fd
, char *name
, FILE *strptr
)
3559 struct str_list strlist
;
3562 char sbuf
[50]; /* sum of string lengths in bit_list */
3565 nmods
= ioctl(fd
, I_LIST
, NULL
);
3567 error("unable to get module count: %m");
3569 strlist
.sl_nmods
= nmods
;
3570 strlist
.sl_modlist
= malloc(sizeof (struct str_mlist
) * nmods
);
3571 if (strlist
.sl_modlist
== NULL
)
3572 novm("module list");
3573 if (ioctl(fd
, I_LIST
, (caddr_t
)&strlist
) < 0) {
3574 error("unable to get module names: %m");
3576 for (i
= 0; i
< strlist
.sl_nmods
; i
++)
3577 (void) flprintf(strptr
, "%d: %s", i
,
3578 strlist
.sl_modlist
[i
].l_name
);
3579 free(strlist
.sl_modlist
);
3582 if (ioctl(fd
, TIOCMGET
, &mstate
) < 0) {
3583 error("unable to get modem state: %m");
3586 for (be
= bit_list
; be
->val
!= 0; be
++) {
3587 str
= (be
->val
& mstate
) ? be
->on
: be
->off
;
3589 if (sbuf
[0] != '\0')
3590 (void) strcat(sbuf
, " ");
3591 (void) strcat(sbuf
, str
);
3594 (void) flprintf(strptr
, "%s: %s\n", name
, sbuf
);
3599 * Print state of serial link. The stream might be linked under the
3600 * /dev/sppp driver. If it is, then it's necessary to unlink it first
3601 * and relink it when done. Otherwise, it's not possible to use
3602 * ioctl() on the stream.
3605 sys_print_state(FILE *strptr
)
3612 (void) flprintf(strptr
, "serial link is not active");
3615 was_linked
= fdmuxid
!= -1;
3616 if (was_linked
&& ioctl(pppfd
, I_UNLINK
, fdmuxid
) == -1) {
3617 error("I_UNLINK: %m");
3620 getbits(ttyfd
, devnam
, strptr
);
3622 (fdmuxid
= ioctl(pppfd
, I_LINK
, (void *)ttyfd
)) == -1)
3623 fatal("I_LINK: %m");
3628 * send ioctl to driver asking it to block packets with network protocol
3629 * proto in the control queue until the queue for proto is plumbed.
3632 sys_block_proto(uint16_t proto
)
3634 if (proto
> 0x7fff) {
3635 warn("cannot block: not a network proto 0x%lx\n", proto
);
3638 if (strioctl(pppfd
, PPPIO_BLOCKNP
, &proto
, sizeof (proto
), 0) < 0) {
3639 warn("PPPIO_BLOCKNP ioctl failed %m");
3643 * send ioctl to driver asking it to release packets with network protocol
3644 * proto from control queue to the protocol specific queue.
3647 sys_unblock_proto(uint16_t proto
)
3649 if (proto
> 0x7fff) {
3650 warn("cannot unblock: not a network proto 0x%lx\n", proto
);
3653 if (strioctl(pppfd
, PPPIO_UNBLOCKNP
, &proto
, sizeof (proto
), 0) < 0) {
3654 warn("PPPIO_UNBLOCKNP ioctl failed %m");