Example #1
0
static void MyNetworkConnectionCallBack(
    SCNetworkConnectionRef          connection,
    SCNetworkConnectionStatus       status,
    void                            *info
)
    // Our network connection callback.  Called out of the runloop 
    // when there's a change in the status of the network connection.
    // It can be called as part of both a connection attempt and a 
    // disconnection attempt.
    //
    // In response to this callback we do two things:
    //
    // 1. Print the current connection status.
    // 2. Once the [dis]connection attempt is resolved (the status 
    //    hits either 'connected' or 'disconnected'), we stop 
    //    the runloop.  This has the effect of breaking the "main" 
    //    function out of its called to CFRunLoopRun, after which 
    //    it can examine the results of the connection.
    //
    // The "info" parameter is a pointer to our per-connection data. 
    // In this case we use this as a pointer to a CallbackParams 
    // structure.  We use this to track the previous state of the 
    // connection so that we don't print redundant status changes.
{
    CallbackParams *                params;
    SCNetworkConnectionPPPStatus    minorStatus;
    time_t                          now;
    struct tm                       nowLocal;
    char                            nowLocalStr[30];
    Boolean                         printMinorStatus;
    
    assert(connection != NULL);
    assert(info != NULL);
    params = (CallbackParams *) info;
    assert(params->magic = kCallbackParamsMagic);

    // Get a string that represents the current time.
    
    (void) time(&now);
    (void) localtime_r(&now, &nowLocal);
    (void) strftime(nowLocalStr, sizeof(nowLocalStr), "%X", &nowLocal);

    // Due to a bug <rdar://problem/3725976>, it's best to get the major status via 
    // SCNetworkConnectionGetStatus than rely on the value being passed into 
    // the callback.

    status = SCNetworkConnectionGetStatus(connection);
    
    // Get the minor status from the extended status associated with 
    // the connection.
    
    minorStatus = GetMinorStatus(connection);
    
    // Print any status changes.
    
    printMinorStatus = (params->lastMinorStatus != minorStatus);
    if (  (params->forcePrintStatus) 
       || (params->lastMajorStatus != status) 
       ) {
        fprintf(
            stderr, 
            "%s %s (%ld)\n", 
            nowLocalStr, 
            StatusToString(status), 
            (long) status
        );
        printMinorStatus = true;
        params->forcePrintStatus = false;
    }
    if (printMinorStatus) {
        fprintf(
            stderr, 
            "%s     %s (%ld)\n", 
            nowLocalStr, 
            MinorStatusToString(minorStatus), 
            (long) minorStatus
        );
    }

    // If we hit either the connected or disconnected state, 
    // we signal the runloop to stop so that the main function 
    // can process the result of the [dis]connection attempt.
    
    if (  (  minorStatus == kSCNetworkConnectionPPPDisconnected ) 
       || (  minorStatus == kSCNetworkConnectionPPPConnected    ) 
       ) {
        CFRunLoopStop(CFRunLoopGetCurrent());
    }

    // Record the new status.
    
    params->lastMajorStatus = status;
    params->lastMinorStatus = minorStatus;
}
Example #2
-1
static void
nc_watch(int argc, char **argv)
{
	SCNetworkConnectionStatus	status;

	nc_create_connection(argc, argv, TRUE);

	status = SCNetworkConnectionGetStatus(connection);

	// report initial status
	n_callback = 0;
	nc_callback(connection, status, &n_callback);

	// setup watcher
	if (doDispatch) {
		if (!SCNetworkConnectionSetDispatchQueue(connection, dispatch_get_main_queue())) {
			SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
			exit(1);
		}
	} else {
		if (!SCNetworkConnectionScheduleWithRunLoop(connection, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
			SCPrint(TRUE, stderr, CFSTR("Unable to schedule watch process: %s\n"), SCErrorString(SCError()));
			exit(1);
		}
	}

	// wait for changes
	CFRunLoopRun();

	nc_release_connection();
	exit(0);
}
Example #3
-1
/* -----------------------------------------------------------------------------
----------------------------------------------------------------------------- */
static void
nc_status(int argc, char **argv)
{
	SCNetworkConnectionStatus	status;

	nc_create_connection(argc, argv, TRUE);

	status = SCNetworkConnectionGetStatus(connection);
	nc_callback(connection, status, NULL);

	nc_release_connection();
	exit(0);
}
Example #4
-1
CFStringRef
copy_VPN_status(SCNetworkServiceRef service)
{
	CFStringRef output = NULL;
	SCNetworkConnectionStatus status = kSCNetworkConnectionInvalid;
	SCNetworkConnectionRef service_connection = NULL;

	/* Only calculate status is the service is enabled. Default is invalid. */
	if (SCNetworkServiceGetEnabled(service)) {
		service_connection = SCNetworkConnectionCreateWithService(NULL, service, NULL, NULL);
		if (service_connection == NULL) goto done;
		status = SCNetworkConnectionGetStatus(service_connection);
	}

	output = CFStringCreateWithCString(NULL, nc_status_string(status), kCFStringEncodingUTF8);

done:
	my_CFRelease(&service_connection);
	return output;
}
Example #5
-1
int main (int argc, const char * argv[])
    // This program finds the first PPP connection service in the 
    // current network configuration and then connects and 
    // disconnects that service.
{
    int                     err;
    Boolean                 ok;
    CFStringRef             serviceToDial;
    CFDictionaryRef         optionsForDial;
    SCNetworkConnectionRef  connection;
    CallbackParams          params;
    
    serviceToDial  = NULL;
    optionsForDial = NULL;
    connection     = NULL;
    
    // If we're run without an argument, just print the usage.
    
    err = 0;
    if (argc != 1) {
        const char *programName;
        
        programName = strrchr(argv[0], '/');
        if (programName == NULL) {
            programName = argv[0];
        } else {
            programName += 1;
        }
        fprintf(stderr, "Usage: %s\n", programName);
        err = ECANCELED;
    }

    // Find the serviceID of the PPP service to dial and the user's 
    // preferred dialling options.  This routine picks up the last 
    // service dialled using Internet Connect (and the associated 
    // options) or, if Internet Connect has not been used, returns 
    // the first PPP service listed in the Network preferences pane.
    
    if (err == 0) {
        ok = SCNetworkConnectionCopyUserPreferences(
            NULL, 
            &serviceToDial,
            &optionsForDial
        );
        if ( ! ok ) {
            err = SCError();
        }
    }
    
    // Create a SCNetworkConnectionRef for it.
    
    if (err == 0) {
        SCNetworkConnectionContext context;

        // Set up the parameters to our callback function.
        
        params.magic            = kCallbackParamsMagic;
        params.forcePrintStatus = true;
        params.lastMinorStatus  = kSCNetworkConnectionDisconnected;
        params.lastMinorStatus  = kSCNetworkConnectionPPPDisconnected;
        
        // Set up the context to reference those parameters.
        
        context.version         = 0;
        context.info            = (void *) &params;
        context.retain          = NULL;
        context.release         = NULL;
        context.copyDescription = NULL;
        
        connection = SCNetworkConnectionCreateWithServiceID(
            NULL,
            serviceToDial, 
            MyNetworkConnectionCallBack,
            &context
        );
        if (connection == NULL) {
            err = SCError();
        }
    }

    // Schedule our callback with the runloop.
    
    if (err == 0) {
        ok = SCNetworkConnectionScheduleWithRunLoop(
            connection,
            CFRunLoopGetCurrent(),
            kCFRunLoopDefaultMode
        );
        if ( ! ok ) {
            err = SCError();
        }
    }
    
    // Check the status.  If we're already connected tell the user. 
    // If we're not connected, initiate the connection.
    
    if (err == 0) {
        err = ECANCELED;    // Most cases involve us bailing out, 
                            // so set the error here.
        
        switch ( SCNetworkConnectionGetStatus(connection) ) {
            case kSCNetworkConnectionDisconnected:
                err = 0;
                break;
            case kSCNetworkConnectionConnecting:
                fprintf(stderr, "Service is already connecting.\n");
                break;
            case kSCNetworkConnectionDisconnecting:
                fprintf(stderr, "Service is disconnecting.\n");
                break;
            case kSCNetworkConnectionConnected:
                fprintf(stderr, "Service is already connected.\n");
                break;
            case kSCNetworkConnectionInvalid:
                fprintf(stderr, "Service is invalid.  Weird.\n");
                break;
            default:
                fprintf(stderr, "Unexpected status.\n");
                break;
        }
    }
    
    // Initiate the connection.
    
    if (err == 0) {
        fprintf(stderr, "Connecting...\n");

        ok = SCNetworkConnectionStart(
            connection,
            optionsForDial,
            false
        );
        if ( ! ok ) {
            err = SCError();
        }
    }
    
    // Run the runloop and wait for our connection attempt to be resolved. 
    // Once that happens, print the result.
    
    if (err == 0) {
        CFRunLoopRun();
        
        switch (params.lastMinorStatus) {
            case kSCNetworkConnectionPPPConnected:
                fprintf(stderr, "Connection succeeded\n");
                break;
            case kSCNetworkConnectionPPPDisconnected:
                fprintf(stderr, "Connection failed\n");
                err = ECANCELED;
                break;
            default:
                fprintf(
                    stderr, 
                    "Bad params.lastMinorStatus (%ld)\n", 
                    (long) params.lastMinorStatus
                );
                err = EINVAL;
                break;
        }
    }
    
    // Wait for a few seconds.
    
    if (err == 0) {
        fprintf(stderr, "Waiting for a few seconds...\n");
        
        (void) sleep(5);
    
    // Initiate a disconnect.

        params.forcePrintStatus = true;

        fprintf(stderr, "Disconnecting...\n");

        ok = SCNetworkConnectionStop(
            connection,
            true
        );
        if ( ! ok ) {
            err = SCError();
        }
    }
    
    // Run the runloop and wait for our disconnection attempt to be 
    // resolved.  Once that happens, print the result.

    if (err == 0) {
        CFRunLoopRun();
        
        switch (params.lastMinorStatus) {
            case kSCNetworkConnectionPPPDisconnected:
                fprintf(stderr, "Disconnection succeeded\n");
                break;
            case kSCNetworkConnectionPPPConnected:
                fprintf(stderr, "Disconnection failed\n");
                err = ECANCELED;
                break;
            default:
                fprintf(
                    stderr, 
                    "Bad params.lastMinorStatus (%ld)\n", 
                    (long) params.lastMinorStatus
                );
                err = EINVAL;
                break;
        }
    }

    // Clean up.
    
    if (serviceToDial != NULL) {
        CFRelease(serviceToDial);
    }
    if (optionsForDial != NULL) {
        CFRelease(optionsForDial);
    }
    if (connection != NULL) {
        (void) SCNetworkConnectionUnscheduleFromRunLoop(
            connection,
            CFRunLoopGetCurrent(),
            kCFRunLoopDefaultMode
        );
        CFRelease(connection);
    }
    
    if (err == 0) {
        return EXIT_SUCCESS;
    } else {
        if (err != ECANCELED) {
            fprintf(stderr, "Failed with error %d\n.", err);
        }
        return EXIT_FAILURE;
    }
}