~ubuntu-branches/ubuntu/wily/dhcpcd5/wily-proposed

« back to all changes in this revision

Viewing changes to platform-bsd.c

  • Committer: Package Import Robot
  • Author(s): Roy Marples
  • Date: 2013-08-04 08:00:44 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20130804080044-36wi725sqa9658eq
Tags: 6.0.5-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
 
1
/*
2
2
 * dhcpcd - DHCP client daemon
3
 
 * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
 
3
 * Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
4
4
 * All rights reserved
5
5
 
6
6
 * Redistribution and use in source and binary forms, with or without
25
25
 * SUCH DAMAGE.
26
26
 */
27
27
 
 
28
#include <sys/ioctl.h>
28
29
#include <sys/param.h>
29
30
#include <sys/socket.h>
30
31
#include <sys/sysctl.h>
31
32
#include <sys/utsname.h>
 
33
 
 
34
#include <net/if.h>
 
35
#ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */
 
36
#  include <net/if_var.h>
 
37
#endif
32
38
#include <netinet/in.h>
 
39
#include <netinet6/in6_var.h>
33
40
 
 
41
#include <errno.h>
 
42
#include <stdlib.h>
 
43
#include <string.h>
34
44
#include <syslog.h>
 
45
#include <unistd.h>
35
46
 
 
47
#include "dhcpcd.h"
 
48
#include "if-options.h"
36
49
#include "platform.h"
37
50
 
38
51
#ifndef SYS_NMLN        /* OSX */
53
66
        return march;
54
67
}
55
68
 
 
69
#ifdef INET6
 
70
#define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0)
 
71
#define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1)
56
72
static int
57
 
inet6_sysctl(int code)
 
73
inet6_sysctl(int code, int val, int action)
58
74
{
59
75
        int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
60
 
        int val;
61
76
        size_t size;
62
77
 
63
78
        mib[3] = code;
64
79
        size = sizeof(val);
 
80
        if (action) {
 
81
                if (sysctl(mib, sizeof(mib)/sizeof(mib[0]),
 
82
                    NULL, 0, &val, size) == -1)
 
83
                        return -1;
 
84
                return 0;
 
85
        }
65
86
        if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &val, &size, NULL, 0) == -1)
66
87
                return -1;
67
88
        return val;
68
89
}
69
90
 
 
91
static void
 
92
restore_kernel_ra(void)
 
93
{
 
94
 
 
95
        if (options & DHCPCD_FORKED)
 
96
                return;
 
97
        syslog(LOG_INFO, "restoring Kernel IPv6 RA support");
 
98
        if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 1) == -1)
 
99
                syslog(LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m");
 
100
}
 
101
 
 
102
static int
 
103
ipv6_ra_flush(void)
 
104
{
 
105
        int s;
 
106
        char dummy[IFNAMSIZ + 8];
 
107
 
 
108
        s = socket(AF_INET6, SOCK_DGRAM, 0);
 
109
        if (s == -1)
 
110
                return -1;
 
111
        strcpy(dummy, "lo0");
 
112
        if (ioctl(s, SIOCSRTRFLUSH_IN6, (caddr_t)&dummy) == -1)
 
113
                syslog(LOG_ERR, "SIOSRTRFLUSH_IN6: %m");
 
114
//      if (ioctl(s, SIOCSPFXFLUSH_IN6, (caddr_t)&dummy) == -1)
 
115
//              syslog(LOG_ERR, "SIOSPFXFLUSH_IN6: %m");
 
116
        close(s);
 
117
        return 0;
 
118
}
 
119
 
70
120
int
71
 
check_ipv6(const char *ifname)
 
121
check_ipv6(const char *ifname, int own)
72
122
{
 
123
        static int set_restore = 0, forward_warned = 0, global_ra = 0;
 
124
        int ra, forward;
73
125
 
74
 
        /* BSD doesn't support these values per iface, so just reutrn 1 */
 
126
        /* BSD doesn't support these values per iface, so just return
 
127
         * the global ra setting */
75
128
        if (ifname)
76
 
                return 1;
77
 
 
78
 
        if (inet6_sysctl(IPV6CTL_ACCEPT_RTADV) != 1) {
79
 
                syslog(LOG_WARNING,
80
 
                    "Kernel is not configured to accept IPv6 RAs");
81
 
                return 0;
82
 
        }
83
 
        if (inet6_sysctl(IPV6CTL_FORWARDING) != 0) {
84
 
                syslog(LOG_WARNING,
85
 
                    "Kernel is configured as a router, not a host");
86
 
                return 0;
87
 
        }
88
 
        return 1;
89
 
}
 
129
                return global_ra;
 
130
 
 
131
        ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV);
 
132
        if (ra == -1)
 
133
                /* The sysctl probably doesn't exist, but this isn't an
 
134
                 * error as such so just log it and continue */
 
135
                syslog(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
 
136
                    "IPV6CTL_ACCEPT_RTADV: %m");
 
137
        else if (ra != 0 && own) {
 
138
                syslog(LOG_INFO, "disabling Kernel IPv6 RA support");
 
139
                if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) {
 
140
                        syslog(LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m");
 
141
                        return ra;
 
142
                }
 
143
                if (!set_restore) {
 
144
                        set_restore = 1;
 
145
                        atexit(restore_kernel_ra);
 
146
                }
 
147
                ra = 0;
 
148
        }
 
149
        if (ifname == NULL)
 
150
                global_ra = ra;
 
151
 
 
152
        if (!forward_warned) {
 
153
                forward = get_inet6_sysctl(IPV6CTL_FORWARDING);
 
154
                if (forward == -1)
 
155
                        /* The sysctl probably doesn't exist, but this isn't an
 
156
                         * error as such so just log it and continue */
 
157
                        syslog(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
 
158
                            "IPV6CTL_FORWARDING: %m");
 
159
                else if (forward != 0) {
 
160
                        forward_warned = 1;
 
161
                        syslog(LOG_WARNING,
 
162
                            "Kernel is configured as a router, not a host");
 
163
                }
 
164
        }
 
165
 
 
166
        /* Flush the kernel knowledge of advertised routers */
 
167
        ipv6_ra_flush();
 
168
 
 
169
        return ra;
 
170
}
 
171
 
 
172
int
 
173
ipv6_dadtransmits(__unused const char *ifname)
 
174
{
 
175
        int r;
 
176
 
 
177
        r = get_inet6_sysctl(IPV6CTL_DAD_COUNT);
 
178
        return r < 0 ? 0 : r;
 
179
}
 
180
#endif