1/*
2 * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * linklocal_v6.c
26 * - this service only gets instantiated if the ConfigMethod is set explicitly
27 *   to LinkLocal
28 * - its only purpose is to act as a placeholder and to publish the
29 *   corresponding IPv6 link-local address for the service
30 * - the rest of linklocal is handled by the service management code in
31 *   ipconfigd.c
32 */
33
34/*
35 * Modification History
36 *
37 * October 6, 2009		Dieter Siegmund (dieter@apple.com)
38 * - created
39 */
40#include <stdlib.h>
41#include <unistd.h>
42#include <string.h>
43#include <sys/types.h>
44
45#include "ipconfigd_threads.h"
46#include "globals.h"
47#include "symbol_scope.h"
48
49STATIC void
50linklocal_v6_address_changed(ServiceRef service_p,
51			     inet6_addrlist_t * addr_list_p)
52{
53    inet6_addrinfo_t *	linklocal_p = NULL;
54
55    linklocal_p = inet6_addrlist_get_linklocal(addr_list_p);
56    if (linklocal_p != NULL) {
57	if ((linklocal_p->addr_flags & IN6_IFF_NOTREADY) != 0) {
58	    linklocal_p = NULL;
59	}
60    }
61    if (linklocal_p == NULL) {
62	service_publish_failure(service_p,
63				ipconfig_status_resource_unavailable_e);
64    }
65    else {
66	ServicePublishSuccessIPv6(service_p, linklocal_p, 1, NULL, 0, NULL,
67				  NULL);
68    }
69    return;
70}
71
72PRIVATE_EXTERN ipconfig_status_t
73linklocal_v6_thread(ServiceRef service_p, IFEventID_t evid, void * event_data)
74{
75    interface_t *	if_p = service_interface(service_p);
76
77    switch (evid) {
78    case IFEventID_start_e: {
79	inet6_addrlist_t	addrs;
80
81	my_log(LOG_DEBUG, "%s %s: START", ServiceGetMethodString(service_p),
82	       if_name(if_p));
83	inet6_addrlist_copy(&addrs, if_link_index(if_p));
84	linklocal_v6_address_changed(service_p, &addrs);
85	inet6_addrlist_free(&addrs);
86	break;
87    }
88    case IFEventID_stop_e:
89	my_log(LOG_DEBUG, "%s %s: STOP", ServiceGetMethodString(service_p),
90	       if_name(if_p));
91	break;
92    case IFEventID_ipv6_address_changed_e:
93	linklocal_v6_address_changed(service_p, event_data);
94	break;
95    default:
96	break;
97    }
98
99    return (ipconfig_status_success_e);
100}
101