1 /* $NetBSD: af_inet.c,v 1.13 2009/08/07 19:35:55 dyoung Exp $ */
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: af_inet.c,v 1.13 2009/08/07 19:35:55 dyoung Exp $");
37 #include <sys/param.h>
38 #include <sys/ioctl.h>
39 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netinet/in_var.h>
45 #include <arpa/inet.h>
59 #include "af_inetany.h"
61 static void in_constructor(void) __attribute__((constructor
));
62 static void in_status(prop_dictionary_t
, prop_dictionary_t
, bool);
63 static void in_commit_address(prop_dictionary_t
, prop_dictionary_t
);
64 static void in_alias(const char *, prop_dictionary_t
, prop_dictionary_t
,
65 struct in_aliasreq
*);
67 static struct afswtch af
= {
68 .af_name
= "inet", .af_af
= AF_INET
, .af_status
= in_status
,
69 .af_addr_commit
= in_commit_address
73 in_alias(const char *ifname
, prop_dictionary_t env
, prop_dictionary_t oenv
,
74 struct in_aliasreq
*creq
)
80 struct in_aliasreq in_addreq
;
81 const struct sockaddr_in
* const asin
= &in_addreq
.ifra_addr
;
82 const struct sockaddr_in
* const dsin
= &in_addreq
.ifra_dstaddr
;
83 const struct sockaddr_in
* const bsin
= &in_addreq
.ifra_broadaddr
;
84 char hbuf
[NI_MAXHOST
];
85 const int niflag
= Nflag
? 0 : NI_NUMERICHOST
;
92 /* Get the non-alias address for this interface. */
93 if ((s
= getsock(AF_INET
)) == -1) {
94 if (errno
== EAFNOSUPPORT
)
96 err(EXIT_FAILURE
, "socket");
98 memset(&ifr
, 0, sizeof(ifr
));
99 estrlcpy(ifr
.ifr_name
, ifname
, sizeof(ifr
.ifr_name
));
100 if (ioctl(s
, SIOCGIFADDR
, &ifr
) == -1) {
101 if (errno
== EADDRNOTAVAIL
|| errno
== EAFNOSUPPORT
)
105 /* If creq and ifr are the same address, this is not an alias. */
106 if (memcmp(&ifr
.ifr_addr
, &creq
->ifra_addr
, sizeof(ifr
.ifr_addr
)) == 0)
109 if (ioctl(s
, SIOCGIFALIAS
, &in_addreq
) == -1) {
110 if (errno
== EADDRNOTAVAIL
|| errno
== EAFNOSUPPORT
) {
113 warn("SIOCGIFALIAS");
116 if (getnameinfo((const struct sockaddr
*)asin
, asin
->sin_len
,
117 hbuf
, sizeof(hbuf
), NULL
, 0, niflag
))
118 strlcpy(hbuf
, "", sizeof(hbuf
)); /* some message? */
119 printf("\tinet %s%s", alias
? "alias " : "", hbuf
);
121 if (getifflags(env
, oenv
, &flags
) == -1)
122 err(EXIT_FAILURE
, "%s: getifflags", __func__
);
124 if (flags
& IFF_POINTOPOINT
) {
125 if (getnameinfo((const struct sockaddr
*)dsin
, dsin
->sin_len
,
126 hbuf
, sizeof(hbuf
), NULL
, 0, niflag
))
127 strlcpy(hbuf
, "", sizeof(hbuf
)); /* some message? */
128 printf(" -> %s", hbuf
);
131 printf(" netmask 0x%x", ntohl(in_addreq
.ifra_mask
.sin_addr
.s_addr
));
133 if (flags
& IFF_BROADCAST
) {
134 if (getnameinfo((const struct sockaddr
*)bsin
, bsin
->sin_len
,
135 hbuf
, sizeof(hbuf
), NULL
, 0, niflag
))
136 strlcpy(hbuf
, "", sizeof(hbuf
)); /* some message? */
137 printf(" broadcast %s", hbuf
);
142 in_status(prop_dictionary_t env
, prop_dictionary_t oenv
, bool force
)
144 struct ifaddrs
*ifap
, *ifa
;
145 struct in_aliasreq ifra
;
146 bool printprefs
= false;
149 if ((ifname
= getifname(env
)) == NULL
)
150 err(EXIT_FAILURE
, "%s: getifname", __func__
);
152 if (getifaddrs(&ifap
) != 0)
153 err(EXIT_FAILURE
, "getifaddrs");
155 printprefs
= ifa_any_preferences(ifname
, ifap
, AF_INET
);
157 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
158 if (strcmp(ifname
, ifa
->ifa_name
) != 0)
160 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
162 if (sizeof(ifra
.ifra_addr
) < ifa
->ifa_addr
->sa_len
)
165 memset(&ifra
, 0, sizeof(ifra
));
166 estrlcpy(ifra
.ifra_name
, ifa
->ifa_name
, sizeof(ifra
.ifra_name
));
167 memcpy(&ifra
.ifra_addr
, ifa
->ifa_addr
, ifa
->ifa_addr
->sa_len
);
168 in_alias(ifa
->ifa_name
, env
, oenv
, &ifra
);
170 ifa_print_preference(ifa
->ifa_name
, ifa
->ifa_addr
);
177 in_commit_address(prop_dictionary_t env
, prop_dictionary_t oenv
)
180 struct in_aliasreq in_ifra
;
181 struct afparam inparam
= {
182 .req
= BUFPARAM(in_ifra
)
183 , .dgreq
= BUFPARAM(in_ifr
)
185 {.buf
= in_ifr
.ifr_name
,
186 .buflen
= sizeof(in_ifr
.ifr_name
)}
187 , {.buf
= in_ifra
.ifra_name
,
188 .buflen
= sizeof(in_ifra
.ifra_name
)}
190 , .dgaddr
= BUFPARAM(in_ifr
.ifr_addr
)
191 , .addr
= BUFPARAM(in_ifra
.ifra_addr
)
192 , .dst
= BUFPARAM(in_ifra
.ifra_dstaddr
)
193 , .brd
= BUFPARAM(in_ifra
.ifra_broadaddr
)
194 , .mask
= BUFPARAM(in_ifra
.ifra_mask
)
195 , .aifaddr
= IFADDR_PARAM(SIOCAIFADDR
)
196 , .difaddr
= IFADDR_PARAM(SIOCDIFADDR
)
197 , .gifaddr
= IFADDR_PARAM(SIOCGIFADDR
)
198 , .defmask
= {.buf
= NULL
, .buflen
= 0}
200 memset(&in_ifr
, 0, sizeof(in_ifr
));
201 memset(&in_ifra
, 0, sizeof(in_ifra
));
202 commit_address(env
, oenv
, &inparam
);
208 register_family(&af
);