source: rtems-libbsd/freebsd-userspace/commands/sbin/ifconfig/af_nd6.c @ ebbe3cc

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since ebbe3cc was ebbe3cc, checked in by Jennifer Averett <jennifer.averett@…>, on 09/07/12 at 18:16:22

Added the ifconfig command.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2009 Hiroki Sato.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#ifndef lint
27static const char rcsid[] =
28  "$FreeBSD$";
29#endif /* not lint */
30
31#include <sys/param.h>
32#include <sys/ioctl.h>
33#include <sys/socket.h>
34#include <sys/sysctl.h>
35#include <net/if.h>
36#include <net/route.h>
37
38#include <err.h>
39#include <errno.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44#include <ifaddrs.h>
45
46#include <arpa/inet.h>
47
48#include <netinet/in.h>
49#ifdef __rtems__
50#include <freebsd/net/if_var.h>
51#include <freebsd/netinet/in_var.h>
52#else
53#include <net/if_var.h>
54#include <netinet/in_var.h>
55#endif
56#include <arpa/inet.h>
57#include <netdb.h>
58
59#ifdef __rtems__
60#include <freebsd/netinet6/nd6.h>
61#else
62#include <netinet6/nd6.h>
63#endif
64
65#include "ifconfig.h"
66
67#define MAX_SYSCTL_TRY  5
68#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
69                "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
70                "\020DEFAULTIF"
71
72static int isnd6defif(int);
73void setnd6flags(const char *, int, int, const struct afswtch *);
74void setnd6defif(const char *, int, int, const struct afswtch *);
75
76void
77setnd6flags(const char *dummyaddr __unused,
78        int d, int s,
79        const struct afswtch *afp)
80{
81        struct in6_ndireq nd;
82        int error;
83
84        memset(&nd, 0, sizeof(nd));
85        strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
86        error = ioctl(s, SIOCGIFINFO_IN6, &nd);
87        if (error) {
88                warn("ioctl(SIOCGIFINFO_IN6)");
89                return;
90        }
91        if (d < 0)
92                nd.ndi.flags &= ~(-d);
93        else
94                nd.ndi.flags |= d;
95        error = ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd);
96        if (error)
97                warn("ioctl(SIOCSIFINFO_IN6)");
98}
99
100void
101setnd6defif(const char *dummyaddr __unused,
102        int d, int s,
103        const struct afswtch *afp)
104{
105        struct in6_ndifreq ndifreq;
106        int ifindex;
107        int error;
108
109        memset(&ndifreq, 0, sizeof(ndifreq));
110        strncpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
111
112        if (d < 0) {
113                if (isnd6defif(s)) {
114                        /* ifindex = 0 means to remove default if */
115                        ifindex = 0;
116                } else
117                        return;
118        } else if ((ifindex = if_nametoindex(ndifreq.ifname)) == 0) {
119                warn("if_nametoindex(%s)", ndifreq.ifname);
120                return;
121        }
122
123        ndifreq.ifindex = ifindex;
124        error = ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq);
125        if (error)
126                warn("ioctl(SIOCSDEFIFACE_IN6)");
127}
128
129static int
130isnd6defif(int s)
131{
132        struct in6_ndifreq ndifreq;
133        unsigned int ifindex;
134        int error;
135
136        memset(&ndifreq, 0, sizeof(ndifreq));
137        strncpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
138
139        ifindex = if_nametoindex(ndifreq.ifname);
140        error = ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq);
141        if (error) {
142                warn("ioctl(SIOCGDEFIFACE_IN6)");
143                return (error);
144        }
145        return (ndifreq.ifindex == ifindex);
146}
147
148static void
149nd6_status(int s)
150{
151        struct in6_ndireq nd;
152        struct rt_msghdr *rtm;
153        size_t needed;
154        char *buf, *next;
155        int mib[6], ntry;
156        int s6;
157        int error;
158        int isinet6, isdefif;
159
160        /* Check if the interface has at least one IPv6 address. */
161        mib[0] = CTL_NET;
162        mib[1] = PF_ROUTE;
163        mib[2] = 0;
164        mib[3] = AF_INET6;
165        mib[4] = NET_RT_IFLIST;
166        mib[5] = if_nametoindex(ifr.ifr_name);
167
168        /* Try to prevent a race between two sysctls. */
169        ntry = 0;
170        do {
171                error = sysctl(mib, 6, NULL, &needed, NULL, 0);
172                if (error) {
173                        warn("sysctl(NET_RT_IFLIST)/estimate");
174                        return;
175                }
176                buf = malloc(needed);
177                if (buf == NULL) {
178                        warn("malloc for sysctl(NET_RT_IFLIST) failed");
179                        return;
180                }
181                if ((error = sysctl(mib, 6, buf, &needed, NULL, 0)) < 0) {
182                        if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
183                                warn("sysctl(NET_RT_IFLIST)/get");
184                                free(buf);
185                                return;
186                        }
187                        free(buf);
188                        buf = NULL;
189                }
190        } while (buf == NULL);
191       
192        isinet6 = 0;
193        for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
194                rtm = (struct rt_msghdr *)next;
195
196                if (rtm->rtm_version != RTM_VERSION)
197                        continue;
198                if (rtm->rtm_type == RTM_NEWADDR) {
199                        isinet6 = 1;
200                        break;
201                }
202        }
203        free(buf);
204        if (!isinet6)
205                return;
206
207        memset(&nd, 0, sizeof(nd));
208        strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
209        if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
210                warn("socket(AF_INET6, SOCK_DGRAM)");
211                return;
212        }
213        error = ioctl(s6, SIOCGIFINFO_IN6, &nd);
214        if (error) {
215                warn("ioctl(SIOCGIFINFO_IN6)");
216                close(s6);
217                return;
218        }
219        isdefif = isnd6defif(s6);
220        close(s6);
221        if (nd.ndi.flags == 0 && !isdefif)
222                return;
223        printb("\tnd6 options",
224            (unsigned int)(nd.ndi.flags | (isdefif << 15)), ND6BITS);
225        putchar('\n');
226}
227
228static struct afswtch af_nd6 = {
229        .af_name        = "nd6",
230        .af_af          = AF_LOCAL,
231        .af_other_status= nd6_status,
232};
233
234static __constructor void
235nd6_ctor(void)
236{
237        af_register(&af_nd6);
238}
Note: See TracBrowser for help on using the repository browser.