
#ifndef _CONFIGTHREADS_COMMON_H_
#define _CONFIGTHREADS_COMMON_H_
/*
 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * The contents of this file constitute Original Code as defined in and
 * are subject to the Apple Public Source License Version 1.1 (the
 * "License").  You may not use this file except in compliance with the
 * License.  Please obtain a copy of the License at
 * http://www.apple.com/publicsource and read it before using this file.
 *
 * This 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,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * @APPLE_LICENSE_HEADER_END@
 */

/*
 * configthreads_common.h
 * - definitions required by the configuration threads
 */

#include <SystemConfiguration/SystemConfiguration.h>

#include "interfaces.h"
#include "configthreads_types.h"


/*
 * Typedefs and Structures
 */
typedef struct ServiceState Service_t;
typedef dynarray_t IFStateList_t;
typedef struct IFState IFState_t;
typedef struct {
    CFStringRef				serviceID;
    ip6config_method_t		method;
    ip6config_method_data_t *	method_data;
} ServiceConfig_t;

typedef enum {
    IFEventID_start_e = 0,		/* start the configuration method */
    IFEventID_stop_e, 			/* stop/clean-up */
    IFEventID_timeout_e,
    IFEventID_media_e,			/* e.g. link status change */
    IFEventID_data_e,			/* data to process */
    IFEventID_change_e,			/* ask config method to change */
    IFEventID_state_change_e,		/* state address data has changed */
    IFEventID_ipv4_primary_change_e, /* primary ipv4 service has changed */
    IFEventID_last_e,
} IFEventID_t;

typedef ip6config_status_t (ip6config_func_t)(Service_t * service_p,
					    IFEventID_t evid, void * evdata);

typedef struct {
    boolean_t			valid;
    boolean_t			active;
} link_status_t;

typedef struct {
    ip6config_method_data_t *	data;
} config_data_t;

typedef struct {
    config_data_t		config;
} start_event_data_t;

typedef struct {
    config_data_t		config;
    boolean_t			needs_stop;
} change_event_data_t;

struct ServiceState {
    IFState_t *			ifstate;
    ip6config_method_t	method;
    void *				serviceID;
    void *				user_notification;
    void *				user_rls;
    inet6_addrinfo_t	info;
    void * 			private;
};

struct IFState {
    interface_t *		if_p;
    void *				ifname;
    link_status_t		link;
    dynarray_t			services;
    Service_t *			llocal_service;
};

/*
 * Inlines
 */
static __inline__ boolean_t
ip6config_method_is_dynamic(ip6config_method_t method)
{
    if (method == ip6config_method_automatic_e
		|| method == ip6config_method_rtadv_e
        || method == ip6config_method_6to4_e) {
		return (TRUE);
    }
    return (FALSE);
}

static __inline__ boolean_t
ip6config_method_is_manual(ip6config_method_t method)
{
    if (method == ip6config_method_manual_e) {
		return (TRUE);
    }

    return (FALSE);
}

static __inline__ IFState_t *
service_ifstate(Service_t * service_p)
{
    return (service_p->ifstate);
}

static __inline__ interface_t *
service_interface(Service_t * service_p)
{
    return (service_p->ifstate->if_p);
}

static __inline__ link_status_t *
service_link_status(Service_t * service_p)
{
    return (&service_p->ifstate->link);
}

static __inline__ const unsigned char *
IFEventID_names(IFEventID_t evid)
{
    static const unsigned char * names[] = {
	"START",
	"STOP",
	"TIMEOUT",
	"MEDIA",
	"DATA",
	"CHANGE",
    "STATE_CHANGE",
    "IPV4_PRIMARY_CHANGE"
    };
    if (evid < IFEventID_start_e || evid >= IFEventID_last_e)
        return ("<unknown event>");
    return (names[evid]);
}


/*
 * IFState related (IFState.c)
 */

Service_t *		IFState_service_with_ID(IFState_t * ifstate, CFStringRef serviceID);
Service_t *		IFState_service_with_ip(IFState_t * ifstate, struct in6_addr * iaddr);
void			IFState_services_free(IFState_t * ifstate);
void			IFState_service_free(IFState_t * ifstate, CFStringRef serviceID);
ip6config_status_t	IFState_service_add(IFState_t * ifstate, CFStringRef serviceID,
                            ip6config_method_t method, void * method_data);
void			IFState_update_media_status(IFState_t * ifstate);
void			IFState_free(void * arg);
IFState_t *		IFStateList_ifstate_with_name(IFStateList_t * list, char * ifname, int * where);
IFState_t *		IFStateList_ifstate_create(IFStateList_t * list, interface_t * if_p);
void			IFStateList_ifstate_free(IFStateList_t * list, char * ifname);
IFState_t *		IFStateList_service_with_ID(IFStateList_t * list, CFStringRef serviceID,
					Service_t * * ret_service);
IFState_t *		IFStateList_service_with_ip(IFStateList_t * list, struct in6_addr * iaddr,
					Service_t * * ret_service);


#define PROP_SERVICEID		CFSTR("ServiceID")

/* LINK_INACTIVE_WAIT_SECS: Time to wait after the link goes
 *   inactive before unpublishing the interface state information
 */
#define LINK_INACTIVE_WAIT_SECS	4

/*
 * service related (service.c)
 */

CFDictionaryRef	my_SCDynamicStoreCopyValue(SCDynamicStoreRef session, CFStringRef key);

int		service_set_address(Service_t * service_p, struct in6_addr * addr, int prefixLen);
int		service_remove_address(Service_t * service_p);

void		service_publish_success(Service_t * service_p);

void            service_publish_clear(Service_t * service_p);
void		service_publish_failure(Service_t * service_p, ip6config_status_t status, char * msg);

ip6config_status_t service_set_service(IFState_t * ifstate, ServiceConfig_t * config);
void		service_free_inactive_services(char * ifname, ServiceConfig_t * config_list,
		    int count);

void		service_config_list_free(ServiceConfig_t * * list_p_p, int count);
ServiceConfig_t * service_config_list_lookup_method(ServiceConfig_t * config_list, 
                    int count, ip6config_method_t method, 
                    ip6config_method_data_t * method_data);
ServiceConfig_t * service_config_list_init(SCDynamicStoreRef session, CFArrayRef all_ipv6, 
                    char * ifname, int * count_p);

void		Service_free(void * arg);
Service_t *	Service_init(IFState_t * ifstate, CFStringRef serviceID,
		    ip6config_method_t method,
		    void * method_data, ip6config_status_t * status_p);
void		service_report_conflict(Service_t * service_p, struct in6_addr * ip6);


/*
 * interface configuration "threads"
 */
ip6config_status_t
manual_thread(Service_t * service_p, IFEventID_t evid, void * evdata);

ip6config_status_t
rtadv_thread(Service_t * service_p, IFEventID_t evid, void * evdata);

ip6config_status_t
stf_thread(Service_t * service_p, IFEventID_t evid, void * evdata);

ip6config_status_t
linklocal_thread(Service_t * llocal_service, IFEventID_t evid, void * event_data);

#endif _CONFIGTHREADS_COMMON_H_
