1 /* $NetBSD: af_inetany.c,v 1.17 2012/12/30 22:52:35 christos Exp $ */
4 * Copyright (c) 2008 David Young. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: af_inetany.c,v 1.17 2012/12/30 22:52:35 christos Exp $");
33 #include <sys/param.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <netinet/in_var.h>
40 #include <netinet6/nd6.h>
42 #include <arpa/inet.h>
56 #include "af_inetany.h"
60 loadbuf(const struct apbuf
*b
, const struct paddr_prefix
*pfx
)
62 return memcpy(b
->buf
, &pfx
->pfx_addr
,
63 MIN(b
->buflen
, pfx
->pfx_addr
.sa_len
));
67 commit_address(prop_dictionary_t env
, prop_dictionary_t oenv
,
68 const struct afparam
*param
)
72 bool alias
, delete, replace
;
74 const struct paddr_prefix
*addr
, *brd
, *dst
, *mask
;
77 if ((af
= getaf(env
)) == -1)
80 if ((s
= getsock(af
)) == -1)
81 err(EXIT_FAILURE
, "%s: getsock", __func__
);
83 if ((ifname
= getifname(env
)) == NULL
)
84 err(EXIT_FAILURE
, "%s: getifname", __func__
);
86 strlcpy(param
->name
[0].buf
, ifname
, param
->name
[0].buflen
);
87 strlcpy(param
->name
[1].buf
, ifname
, param
->name
[1].buflen
);
89 if ((d
= (prop_data_t
)prop_dictionary_get(env
, "address")) != NULL
)
90 addr
= prop_data_data_nocopy(d
);
91 else if (!prop_dictionary_get_bool(env
, "alias", &alias
) || alias
||
92 param
->gifaddr
.cmd
== 0)
94 else if (prog_ioctl(s
, param
->gifaddr
.cmd
, param
->dgreq
.buf
) == -1)
95 err(EXIT_FAILURE
, "%s", param
->gifaddr
.desc
);
96 else if (prog_ioctl(s
, param
->difaddr
.cmd
, param
->dgreq
.buf
) == -1)
97 err(EXIT_FAILURE
, "%s", param
->difaddr
.desc
);
101 if ((d
= (prop_data_t
)prop_dictionary_get(env
, "dst")) != NULL
)
102 dst
= prop_data_data_nocopy(d
);
106 if ((d
= (prop_data_t
)prop_dictionary_get(env
, "netmask")) != NULL
)
107 mask
= prop_data_data_nocopy(d
);
111 if ((d
= (prop_data_t
)prop_dictionary_get(env
, "broadcast")) != NULL
)
112 brd
= prop_data_data_nocopy(d
);
116 if (!prop_dictionary_get_bool(env
, "alias", &alias
)) {
118 replace
= (param
->gifaddr
.cmd
!= 0);
124 loadbuf(¶m
->addr
, addr
);
126 /* TBD: read matching ifaddr from kernel, use the netmask as default
127 * TBD: handle preference
129 if (getifflags(env
, oenv
, &flags
) == -1)
130 err(EXIT_FAILURE
, "%s: getifflags", __func__
);
132 switch (flags
& (IFF_BROADCAST
|IFF_POINTOPOINT
)) {
135 loadbuf(¶m
->brd
, brd
);
139 case IFF_POINTOPOINT
:
141 errx(EXIT_FAILURE
, "%s is not a broadcast interface",
145 loadbuf(¶m
->dst
, dst
);
147 case IFF_BROADCAST
|IFF_POINTOPOINT
:
148 errx(EXIT_FAILURE
, "unsupported interface flags");
150 if (param
->mask
.buf
== NULL
) {
152 errx(EXIT_FAILURE
, "netmask not supported");
153 } else if (mask
!= NULL
)
154 loadbuf(¶m
->mask
, mask
);
155 else if (param
->defmask
.buf
!= NULL
) {
156 memcpy(param
->mask
.buf
, param
->defmask
.buf
,
157 MIN(param
->mask
.buflen
, param
->defmask
.buflen
));
160 if (prog_ioctl(s
, param
->gifaddr
.cmd
, param
->dgreq
.buf
) == 0) {
161 rc
= prog_ioctl(s
, param
->difaddr
.cmd
, param
->dgreq
.buf
);
163 err(EXIT_FAILURE
, "%s", param
->difaddr
.desc
);
164 } else if (errno
== EADDRNOTAVAIL
)
165 ; /* No address was assigned yet. */
167 err(EXIT_FAILURE
, "%s", param
->gifaddr
.desc
);
169 loadbuf(¶m
->dgaddr
, addr
);
170 if (prog_ioctl(s
, param
->difaddr
.cmd
, param
->dgreq
.buf
) == -1)
171 err(EXIT_FAILURE
, "%s", param
->difaddr
.desc
);
174 if (param
->pre_aifaddr
!= NULL
&&
175 (*param
->pre_aifaddr
)(env
, param
) == -1)
176 err(EXIT_FAILURE
, "pre-%s", param
->aifaddr
.desc
);
177 if (prog_ioctl(s
, param
->aifaddr
.cmd
, param
->req
.buf
) == -1)
178 err(EXIT_FAILURE
, "%s", param
->aifaddr
.desc
);