1 /* $NetBSD: af_inetany.c,v 1.11 2008/06/03 04:59:30 dyoung 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.11 2008/06/03 04:59:30 dyoung 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"
59 loadbuf(const struct apbuf
*b
, const struct paddr_prefix
*pfx
)
61 return memcpy(b
->buf
, &pfx
->pfx_addr
,
62 MIN(b
->buflen
, pfx
->pfx_addr
.sa_len
));
66 commit_address(prop_dictionary_t env
, prop_dictionary_t oenv
,
67 const struct afparam
*param
)
71 bool alias
, delete, replace
;
73 const struct paddr_prefix
*addr
, *brd
, *dst
, *mask
;
76 if ((af
= getaf(env
)) == -1)
79 if ((s
= getsock(af
)) == -1)
80 err(EXIT_FAILURE
, "%s: getsock", __func__
);
82 if ((ifname
= getifinfo(env
, oenv
, &flags
)) == NULL
)
85 strlcpy(param
->name
[0].buf
, ifname
, param
->name
[0].buflen
);
86 strlcpy(param
->name
[1].buf
, ifname
, param
->name
[1].buflen
);
88 if ((d
= (prop_data_t
)prop_dictionary_get(env
, "address")) != NULL
)
89 addr
= prop_data_data_nocopy(d
);
90 else if (!prop_dictionary_get_bool(env
, "alias", &alias
) || alias
||
91 param
->gifaddr
.cmd
== 0)
93 else if (ioctl(s
, param
->gifaddr
.cmd
, param
->dgreq
.buf
) == -1)
94 err(EXIT_FAILURE
, param
->gifaddr
.desc
);
95 else if (ioctl(s
, param
->difaddr
.cmd
, param
->dgreq
.buf
) == -1)
96 err(EXIT_FAILURE
, param
->difaddr
.desc
);
100 if ((d
= (prop_data_t
)prop_dictionary_get(env
, "dst")) != NULL
)
101 dst
= prop_data_data_nocopy(d
);
105 if ((d
= (prop_data_t
)prop_dictionary_get(env
, "netmask")) != NULL
)
106 mask
= prop_data_data_nocopy(d
);
110 if ((d
= (prop_data_t
)prop_dictionary_get(env
, "broadcast")) != NULL
)
111 brd
= prop_data_data_nocopy(d
);
115 if (!prop_dictionary_get_bool(env
, "alias", &alias
)) {
117 replace
= (param
->gifaddr
.cmd
!= 0);
123 loadbuf(¶m
->addr
, addr
);
125 /* TBD: read matching ifaddr from kernel, use the netmask as default
126 * TBD: handle preference
128 switch (flags
& (IFF_BROADCAST
|IFF_POINTOPOINT
)) {
131 loadbuf(¶m
->brd
, brd
);
135 case IFF_POINTOPOINT
:
137 errx(EXIT_FAILURE
, "%s is not a broadcast interface",
141 loadbuf(¶m
->dst
, dst
);
143 case IFF_BROADCAST
|IFF_POINTOPOINT
:
144 errx(EXIT_FAILURE
, "unsupported interface flags");
146 if (param
->mask
.buf
== NULL
) {
148 errx(EXIT_FAILURE
, "netmask not supported");
149 } else if (mask
!= NULL
)
150 loadbuf(¶m
->mask
, mask
);
151 else if (param
->defmask
.buf
!= NULL
) {
152 memcpy(param
->mask
.buf
, param
->defmask
.buf
,
153 MIN(param
->mask
.buflen
, param
->defmask
.buflen
));
156 if (ioctl(s
, param
->gifaddr
.cmd
, param
->dgreq
.buf
) == 0) {
157 rc
= ioctl(s
, param
->difaddr
.cmd
, param
->dgreq
.buf
);
159 err(EXIT_FAILURE
, param
->difaddr
.desc
);
160 } else if (errno
== EADDRNOTAVAIL
)
161 ; /* No address was assigned yet. */
163 err(EXIT_FAILURE
, param
->gifaddr
.desc
);
165 loadbuf(¶m
->dgaddr
, addr
);
166 if (ioctl(s
, param
->difaddr
.cmd
, param
->dgreq
.buf
) == -1)
167 err(EXIT_FAILURE
, param
->difaddr
.desc
);
170 if (param
->pre_aifaddr
!= NULL
&&
171 (*param
->pre_aifaddr
)(env
, param
) == -1)
172 err(EXIT_FAILURE
, "pre-%s", param
->aifaddr
.desc
);
173 if (ioctl(s
, param
->aifaddr
.cmd
, param
->req
.buf
) == -1)
174 err(EXIT_FAILURE
, param
->aifaddr
.desc
);