]> git.saurik.com Git - apple/configd.git/blobdiff - scutil.tproj/scutil.c
configd-1109.101.1.tar.gz
[apple/configd.git] / scutil.tproj / scutil.c
index 9776c29aa984df160b68c653263cf48ff7caf60e..8f6e263e49de2fe2dfd516161fcdb4c492dd6fa9 100644 (file)
@@ -1,15 +1,15 @@
 /*
- * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -17,7 +17,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
@@ -45,6 +45,7 @@
  * - initial revision
  */
 
+#include <TargetConditionals.h>
 #include <ctype.h>
 #include <getopt.h>
 #include <stdio.h>
 #include "commands.h"
 #include "dictionary.h"
 #include "net.h"
+#include "nc.h"
 #include "prefs.h"
 #include "session.h"
 #include "tests.h"
 
-#include "SCDynamicStoreInternal.h"
-
-
-#define LINE_LENGTH 256
-
+#define LINE_LENGTH 2048
 
 __private_extern__ AuthorizationRef    authorization   = NULL;
 __private_extern__ InputRef            currentInput    = NULL;
+__private_extern__ Boolean             doDispatch      = FALSE;
 __private_extern__ int                 nesting         = 0;
+__private_extern__ SCPreferencesRef    ni_prefs        = NULL;
 __private_extern__ CFRunLoopRef                notifyRl        = NULL;
 __private_extern__ CFRunLoopSourceRef  notifyRls       = NULL;
 __private_extern__ SCPreferencesRef    prefs           = NULL;
+__private_extern__ char                        *prefsPath      = NULL;
 __private_extern__ SCDynamicStoreRef   store           = NULL;
 __private_extern__ CFPropertyListRef   value           = NULL;
 __private_extern__ CFMutableArrayRef   watchedKeys     = NULL;
@@ -86,22 +87,102 @@ __private_extern__ CFMutableArrayRef       watchedPatterns = NULL;
 
 static const struct option longopts[] = {
 //     { "debug",              no_argument,            NULL,   'd'     },
+//     { "dispatch",           no_argument,            NULL,   'D'     },
 //     { "verbose",            no_argument,            NULL,   'v'     },
 //     { "SPI",                no_argument,            NULL,   'p'     },
 //     { "check-reachability", required_argument,      NULL,   'r'     },
 //     { "timeout",            required_argument,      NULL,   't'     },
 //     { "wait-key",           required_argument,      NULL,   'w'     },
+//     { "watch-reachability", no_argument,            NULL,   'W'     },
+       { "configuration",      no_argument,            NULL,   0       },
        { "dns",                no_argument,            NULL,   0       },
        { "get",                required_argument,      NULL,   0       },
+       { "error",              required_argument,      NULL,   0       },
        { "help",               no_argument,            NULL,   '?'     },
+       { "nc",                 required_argument,      NULL,   0       },
        { "net",                no_argument,            NULL,   0       },
+       { "nwi",                no_argument,            NULL,   0       },
        { "prefs",              no_argument,            NULL,   0       },
        { "proxy",              no_argument,            NULL,   0       },
+       { "renew",              required_argument,      NULL,   0       },
        { "set",                required_argument,      NULL,   0       },
+       { "snapshot",           no_argument,            NULL,   0       },
+       { "user",               required_argument,      NULL,   0       },
+       { "password",           required_argument,      NULL,   0       },
+       { "secret",             required_argument,      NULL,   0       },
+       { "log",                required_argument,      NULL,   0       },
+       { "advisory",           required_argument,      NULL,   0       },
+#if    !TARGET_OS_IPHONE
+       { "allow-new-interfaces", no_argument,          NULL,   0       },
+#endif // !TARGET_OS_IPHONE
+       { "disable-until-needed", no_argument,          NULL,   0       },
        { NULL,                 0,                      NULL,   0       }
 };
 
 
+__private_extern__
+CFStringRef
+_copyStringFromSTDIN(CFStringRef prompt, CFStringRef defaultValue)
+{
+       char            buf[1024];
+       int             i;
+       Boolean         is_user_prompt = (prompt != NULL && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO));
+       int             len;
+       char            *modbuf;
+       int             modlen;
+       CFStringRef     utf8;
+
+       /* Print out a prompt to user that entry is desired */
+       if (is_user_prompt) {
+               if (defaultValue != NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("%@ [%@]: "), prompt, defaultValue);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("%@: "), prompt);
+               }
+       }
+
+       /* Get user input */
+       if (fgets(buf, sizeof(buf), stdin) == NULL) {
+               return NULL;
+       }
+
+       /* Prepare for trim */
+       len = (int)strlen(buf);
+       modbuf = buf;
+       modlen = len;
+
+       /* Trim new-line */
+       if ((modlen > 0) && (modbuf[modlen - 1] == '\n')) {
+               modbuf[modlen - 1] = '\0';
+               modlen--;
+       }
+
+       /* If nothing was entered at the user prompt, set default */
+       if (is_user_prompt && defaultValue != NULL && modlen == 0) {
+               CFRetain(defaultValue);
+               return defaultValue;
+       }
+
+       /* Trim spaces from front */
+       while (modlen > 0 && isspace(modbuf[0])) {
+               modbuf = &modbuf[1];
+               modlen--;
+       }
+
+       /* Trim spaces from back */
+       for (i = modlen - 1; i >= 0; i--) {
+               if (isspace(buf[i])) {
+                       buf[i] = '\0';
+                       modlen--;
+               } else {
+                       break;
+               }
+       }
+
+       utf8 = CFStringCreateWithBytes(NULL, (UInt8 *)modbuf, modlen, kCFStringEncodingUTF8, TRUE);
+       return utf8;
+}
+
 static char *
 getLine(char *buf, int len, InputRef src)
 {
@@ -115,13 +196,13 @@ getLine(char *buf, int len, InputRef src)
                if (line == NULL)
                        return NULL;
 
-               strncpy(buf, line, len);
+               strlcpy(buf, line, len);
        } else {
                if (fgets(buf, len, src->fp) == NULL)
                        return NULL;
        }
 
-       n = strlen(buf);
+       n = (int)strlen(buf);
        if (buf[n-1] == '\n') {
                /* the entire line fit in the buffer, remove the newline */
                buf[n-1] = '\0';
@@ -132,13 +213,12 @@ getLine(char *buf, int len, InputRef src)
                } while ((n != '\n') && (n != EOF));
        }
 
-       if (src->h) {
+       if (src->h && (buf[0] != '\0')) {
                HistEvent       ev;
 
                history(src->h, &ev, H_ENTER, buf);
        }
 
-
        return buf;
 }
 
@@ -249,13 +329,13 @@ usage(const char *command)
        SCPrint(TRUE, stderr, CFSTR("usage: %s\n"), command);
        SCPrint(TRUE, stderr, CFSTR("\tinteractive access to the dynamic store.\n"));
        SCPrint(TRUE, stderr, CFSTR("\n"));
-       SCPrint(TRUE, stderr, CFSTR("   or: %s --prefs\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --prefs [preference-file]\n"), command);
        SCPrint(TRUE, stderr, CFSTR("\tinteractive access to the [raw] stored preferences.\n"));
        SCPrint(TRUE, stderr, CFSTR("\n"));
-       SCPrint(TRUE, stderr, CFSTR("   or: %s -r nodename\n"), command);
-       SCPrint(TRUE, stderr, CFSTR("   or: %s -r address\n"), command);
-       SCPrint(TRUE, stderr, CFSTR("   or: %s -r local-address remote-address\n"), command);
-       SCPrint(TRUE, stderr, CFSTR("\tcheck reachability of node, address, or address pair.\n"));
+       SCPrint(TRUE, stderr, CFSTR("   or: %s [-W] -r nodename\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("   or: %s [-W] -r address\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("   or: %s [-W] -r local-address remote-address\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("\tcheck reachability of node, address, or address pair (-W to \"watch\").\n"));
        SCPrint(TRUE, stderr, CFSTR("\n"));
        SCPrint(TRUE, stderr, CFSTR("   or: %s -w dynamic-store-key [ -t timeout ]\n"), command);
        SCPrint(TRUE, stderr, CFSTR("\t-w\twait for presense of dynamic store key\n"));
@@ -263,6 +343,7 @@ usage(const char *command)
        SCPrint(TRUE, stderr, CFSTR("\n"));
        SCPrint(TRUE, stderr, CFSTR("   or: %s --get pref\n"), command);
        SCPrint(TRUE, stderr, CFSTR("   or: %s --set pref [newval]\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --get filename path key  \n"), command);
        SCPrint(TRUE, stderr, CFSTR("\tpref\tdisplay (or set) the specified preference.  Valid preferences\n"));
        SCPrint(TRUE, stderr, CFSTR("\t\tinclude:\n"));
        SCPrint(TRUE, stderr, CFSTR("\t\t\tComputerName, LocalHostName, HostName\n"));
@@ -274,6 +355,28 @@ usage(const char *command)
        SCPrint(TRUE, stderr, CFSTR("\n"));
        SCPrint(TRUE, stderr, CFSTR("   or: %s --proxy\n"), command);
        SCPrint(TRUE, stderr, CFSTR("\tshow \"proxy\" configuration.\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --nwi\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("\tshow network information\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --nc\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("\tshow VPN network configuration information. Use --nc help for full command list\n"));
+
+       if (_sc_debug) {
+               SCPrint(TRUE, stderr, CFSTR("\n"));
+               SCPrint(TRUE, stderr, CFSTR("   or: %s --log IPMonitor [off|on]\n"), command);
+               SCPrint(TRUE, stderr, CFSTR("\tmanage logging.\n"));
+
+               SCPrint(TRUE, stderr, CFSTR("\n"));
+               SCPrint(TRUE, stderr, CFSTR("   or: %s --disable-until-needed <interfaceName> [on|off ]\n"), command);
+               SCPrint(TRUE, stderr, CFSTR("\tmanage secondary interface demand.\n"));
+       }
+
+#if    !TARGET_OS_IPHONE
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --allow-new-interfaces [off|on]\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("\tmanage new interface creation with screen locked.\n"));
+#endif // !TARGET_OS_IPHONE
 
        if (getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) {
                SCPrint(TRUE, stderr, CFSTR("\n"));
@@ -281,6 +384,10 @@ usage(const char *command)
                SCPrint(TRUE, stderr, CFSTR("\tmanage network configuration.\n"));
        }
 
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --error err#\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("\tdisplay a descriptive message for the given error code\n"));
+
        exit (EX_USAGE);
 }
 
@@ -288,40 +395,62 @@ usage(const char *command)
 static char *
 prompt(EditLine *el)
 {
+#pragma unused(el)
+#if    !TARGET_OS_SIMULATOR
        return "> ";
+#else  // !TARGET_OS_SIMULATOR
+       return "sim> ";
+#endif // !TARGET_OS_SIMULATOR
 }
 
 
 int
 main(int argc, char * const argv[])
 {
-       Boolean                 doDNS   = FALSE;
-       Boolean                 doNet   = FALSE;
-       Boolean                 doPrefs = FALSE;
-       Boolean                 doProxy = FALSE;
-       Boolean                 doReach = FALSE;
-       char                    *get    = NULL;
+       const char *            advisoryInterface       = NULL;
+#if    !TARGET_OS_IPHONE
+       Boolean                 allowNewInterfaces      = FALSE;
+#endif // !TARGET_OS_IPHONE
+       Boolean                 configuration           = FALSE;
+       Boolean                 disableUntilNeeded      = FALSE;
+       Boolean                 doAdvisory              = FALSE;
+       Boolean                 doDNS                   = FALSE;
+       Boolean                 doNet                   = FALSE;
+       Boolean                 doNWI                   = FALSE;
+       Boolean                 doPrefs                 = FALSE;
+       Boolean                 doProxy                 = FALSE;
+       Boolean                 doReach                 = FALSE;
+       Boolean                 doSnap                  = FALSE;
+       char                    *error                  = NULL;
+       char                    *get                    = NULL;
+       char                    *log                    = NULL;
        extern int              optind;
        int                     opt;
        int                     opti;
-       const char              *prog   = argv[0];
-       char                    *set    = NULL;
+       const char              *prog                   = argv[0];
+       char                    *renew                  = NULL;
+       char                    *set                    = NULL;
+       char                    *nc_cmd                 = NULL;
        InputRef                src;
-       int                     timeout = 15;   /* default timeout (in seconds) */
-       char                    *wait   = NULL;
-       int                     xStore  = 0;    /* non dynamic store command line options */
+       int                     timeout                 = 15;   /* default timeout (in seconds) */
+       char                    *wait                   = NULL;
+       Boolean                 watch                   = FALSE;
+       int                     xStore                  = 0;    /* non dynamic store command line options */
 
        /* process any arguments */
 
-       while ((opt = getopt_long(argc, argv, "dvprt:w:", longopts, &opti)) != -1)
+       while ((opt = getopt_long(argc, argv, "dDvprt:w:W", longopts, &opti)) != -1) {
                switch(opt) {
                case 'd':
                        _sc_debug = TRUE;
-                       _sc_log   = FALSE;      /* enable framework logging */
+                       _sc_log   = kSCLogDestinationFile;      /* enable framework logging */
+                       break;
+               case 'D':
+                       doDispatch = TRUE;
                        break;
                case 'v':
                        _sc_verbose = TRUE;
-                       _sc_log     = FALSE;    /* enable framework logging */
+                       _sc_log     = kSCLogDestinationFile;    /* enable framework logging */
                        break;
                case 'p':
                        enablePrivateAPI = TRUE;
@@ -337,31 +466,75 @@ main(int argc, char * const argv[])
                        wait = optarg;
                        xStore++;
                        break;
+               case 'W':
+                       watch = TRUE;
+                       break;
                case 0:
-                       if        (strcmp(longopts[opti].name, "dns") == 0) {
+                       if        (strcmp(longopts[opti].name, "configuration") == 0) {
+                               configuration = TRUE;
+                               xStore++;
+                       } else if (strcmp(longopts[opti].name, "dns") == 0) {
                                doDNS = TRUE;
                                xStore++;
+                       } else if (strcmp(longopts[opti].name, "error") == 0) {
+                               error = optarg;
+                               xStore++;
                        } else if (strcmp(longopts[opti].name, "get") == 0) {
                                get = optarg;
                                xStore++;
+                       } else if (strcmp(longopts[opti].name, "nc") == 0) {
+                               nc_cmd = optarg;
+                               xStore++;
                        } else if (strcmp(longopts[opti].name, "net") == 0) {
                                doNet = TRUE;
                                xStore++;
+                       } else if (strcmp(longopts[opti].name, "nwi") == 0) {
+                               doNWI = TRUE;
+                               xStore++;
                        } else if (strcmp(longopts[opti].name, "prefs") == 0) {
                                doPrefs = TRUE;
                                xStore++;
                        } else if (strcmp(longopts[opti].name, "proxy") == 0) {
                                doProxy = TRUE;
                                xStore++;
+                       } else if (strcmp(longopts[opti].name, "renew") == 0) {
+                               renew = optarg;
+                               xStore++;
                        } else if (strcmp(longopts[opti].name, "set") == 0) {
                                set = optarg;
                                xStore++;
+                       } else if (strcmp(longopts[opti].name, "snapshot") == 0) {
+                               doSnap = TRUE;
+                               xStore++;
+                       } else if (strcmp(longopts[opti].name, "log") == 0) {
+                               log = optarg;
+                               xStore++;
+#if    !TARGET_OS_IPHONE
+                       } else if (strcmp(longopts[opti].name, "allow-new-interfaces") == 0) {
+                               allowNewInterfaces = TRUE;
+                               xStore++;
+#endif // !TARGET_OS_IPHONE
+                       } else if (strcmp(longopts[opti].name, "disable-until-needed") == 0) {
+                               disableUntilNeeded = TRUE;
+                               xStore++;
+                       } else if (strcmp(longopts[opti].name, "user") == 0) {
+                               username = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
+                       } else if (strcmp(longopts[opti].name, "password") == 0) {
+                               password = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
+                       } else if (strcmp(longopts[opti].name, "secret") == 0) {
+                               sharedsecret = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
+                       } else if (strcmp(longopts[opti].name, "advisory") == 0) {
+                               doAdvisory = TRUE;
+                               advisoryInterface = optarg;
+                               xStore++;
                        }
                        break;
                case '?':
                default :
                        usage(prog);
                }
+       }
+
        argc -= optind;
        argv += optind;
 
@@ -370,12 +543,22 @@ main(int argc, char * const argv[])
                usage(prog);
        }
 
-       /* are we checking the reachability of a host/address */
+       /* are we asking for a configuration summary */
+       if (configuration) {
+               do_configuration(argc, (char **)argv);
+               /* NOT REACHED */
+       }
+
+       /* are we checking (or watching) the reachability of a host/address */
        if (doReach) {
-               if ((argc < 1) || (argc > 2)) {
+               if (argc < 1) {
                        usage(prog);
                }
-               do_checkReachability(argc, (char **)argv);
+               if (watch) {
+                       do_watchReachability(argc, (char **)argv);
+               } else {
+                       do_checkReachability(argc, (char **)argv);
+               }
                /* NOT REACHED */
        }
 
@@ -387,15 +570,69 @@ main(int argc, char * const argv[])
 
        /* are we looking up the DNS configuration */
        if (doDNS) {
-               do_showDNSConfiguration(argc, (char **)argv);
+               if (watch) {
+                       do_watchDNSConfiguration(argc, (char **)argv);
+               } else {
+                       do_showDNSConfiguration(argc, (char **)argv);
+               }
+               /* NOT REACHED */
+       }
+
+       if (doNWI) {
+               if (watch) {
+                       do_watchNWI(argc, (char**)argv);
+               } else {
+                       do_showNWI(argc, (char**)argv);
+               }
                /* NOT REACHED */
        }
 
+       if (doSnap) {
+               if (!enablePrivateAPI) {
+                       usage(prog);
+               }
+
+               do_open(0, NULL);       /* open the dynamic store */
+               do_snapshot(argc, (char**)argv);
+               exit(0);
+       }
+
+       if (doAdvisory) {
+               do_advisory(advisoryInterface, watch, argc, (char**)argv);
+               /* NOT REACHED */
+       }
+
+       /* are we translating error #'s to descriptive text */
+       if (error != NULL) {
+               int     sc_status       = atoi(error);
+
+               SCPrint(TRUE, stdout, CFSTR("Error: 0x%08x %d %s\n"),
+                       sc_status,
+                       sc_status,
+                       SCErrorString(sc_status));
+               exit(0);
+       }
+
        /* are we looking up a preference value */
        if (get) {
-               if (findPref(get) < 0) {
+               if (argc == 0) {
+                       if (findPref(get) < 0) {
+                               usage(prog);
+                       }
+               } else if (argc == 2) {
+                       /*
+                        * extended --get
+                        *   i.e. scutil --get <filename> <prefs path> <key>
+                        *
+                        * need to go back one argument to re-use the 1st "--get"
+                        * argument as the prefs path name
+                        */
+                       argc++;
+                       argv--;
+               } else {
                        usage(prog);
                }
+
                do_getPref(get, argc, (char **)argv);
                /* NOT REACHED */
        }
@@ -415,6 +652,38 @@ main(int argc, char * const argv[])
                /* NOT REACHED */
        }
 
+       /* verbose log */
+       if (log != NULL) {
+               if (strcasecmp(log, "IPMonitor")) {
+                       usage(prog);
+               }
+               do_log(log, argc, (char * *)argv);
+               /* NOT REACHED */
+       }
+
+#if    !TARGET_OS_IPHONE
+       /* allowNewInterfaces */
+       if (allowNewInterfaces) {
+               do_ifnamer("allow-new-interfaces", argc, (char * *)argv);
+               /* NOT REACHED */
+       }
+#endif // !TARGET_OS_IPHONE
+
+       /* disableUntilNeeded */
+       if (disableUntilNeeded) {
+               do_disable_until_needed(argc, (char * *)argv);
+               /* NOT REACHED */
+       }
+
+       /* network connection commands */
+       if (nc_cmd) {
+               if (find_nc_cmd(nc_cmd) < 0) {
+                       usage(prog);
+               }
+               do_nc_cmd(nc_cmd, argc, (char **)argv, watch);
+               /* NOT REACHED */
+       }
+
        if (doNet) {
                /* if we are going to be managing the network configuration */
                commands  = (cmdInfo *)commands_net;
@@ -424,16 +693,16 @@ main(int argc, char * const argv[])
                        usage(prog);
                }
 
-               do_net_init();          /* initialization */
-               do_net_open(0, NULL);   /* open default prefs */
+               do_net_init();                          /* initialization */
+               do_net_open(argc, (char **)argv);       /* open prefs */
        } else if (doPrefs) {
                /* if we are going to be managing the network configuration */
                commands  = (cmdInfo *)commands_prefs;
                nCommands = nCommands_prefs;
 
-               do_dictInit(0, NULL);   /* start with an empty dictionary */
-               do_prefs_init();        /* initialization */
-               do_prefs_open(0, NULL); /* open default prefs */
+               do_dictInit(0, NULL);                   /* start with an empty dictionary */
+               do_prefs_init();                        /* initialization */
+               do_prefs_open(argc, (char **)argv);     /* open prefs */
        } else {
                /* if we are going to be managing the dynamic store */
                commands  = (cmdInfo *)commands_store;
@@ -443,6 +712,12 @@ main(int argc, char * const argv[])
                do_open(0, NULL);       /* open the dynamic store */
        }
 
+       /* are we trying to renew a DHCP lease */
+       if (renew != NULL) {
+               do_renew(renew);
+               /* NOT REACHED */
+       }
+
        /* allocate command input stream */
        src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0);
        src->fp = stdin;
@@ -484,9 +759,13 @@ main(int argc, char * const argv[])
                }
        }
 
-       while (process_line(src) == TRUE) {
-              /* debug information, diagnostics */
-               __showMachPortStatus();
+       while (TRUE) {
+               Boolean ok;
+
+               ok = process_line(src);
+               if (!ok) {
+                       break;
+               }
        }
 
        /* close the socket, free resources */