af_inet.c revision 1.2 1 /* $NetBSD: af_inet.c,v 1.2 2006/06/14 11:05:42 tron Exp $ */
2
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
18 *
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
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: af_inet.c,v 1.2 2006/06/14 11:05:42 tron Exp $");
35 #endif /* not lint */
36
37 #include <sys/param.h>
38 #include <sys/ioctl.h>
39 #include <sys/socket.h>
40
41 #include <net/if.h>
42 #include <netinet/in.h>
43 #include <netinet/in_var.h>
44
45 #include <arpa/inet.h>
46
47 #include <err.h>
48 #include <errno.h>
49 #include <ifaddrs.h>
50 #include <netdb.h>
51 #include <string.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54
55 #include "extern.h"
56 #include "af_inet.h"
57
58 struct in_aliasreq in_addreq;
59
60 int setipdst;
61
62 void
63 setifipdst(const char *addr, int d)
64 {
65
66 in_getaddr(addr, DSTADDR);
67 setipdst++;
68 clearaddr = 0;
69 newaddr = 0;
70 }
71
72 void
73 in_alias(struct ifreq *creq)
74 {
75 struct sockaddr_in *iasin;
76 int alias;
77
78 if (lflag)
79 return;
80
81 alias = 1;
82
83 /* Get the non-alias address for this interface. */
84 getsock(AF_INET);
85 if (s < 0) {
86 if (errno == EAFNOSUPPORT)
87 return;
88 err(EXIT_FAILURE, "socket");
89 }
90 (void) memset(&ifr, 0, sizeof(ifr));
91 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
92 if (ioctl(s, SIOCGIFADDR, &ifr) == -1) {
93 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
94 return;
95 } else
96 warn("SIOCGIFADDR");
97 }
98 /* If creq and ifr are the same address, this is not an alias. */
99 if (memcmp(&ifr.ifr_addr, &creq->ifr_addr,
100 sizeof(creq->ifr_addr)) == 0)
101 alias = 0;
102 (void) memset(&in_addreq, 0, sizeof(in_addreq));
103 (void) strncpy(in_addreq.ifra_name, name, sizeof(in_addreq.ifra_name));
104 memcpy(&in_addreq.ifra_addr, &creq->ifr_addr,
105 sizeof(in_addreq.ifra_addr));
106 if (ioctl(s, SIOCGIFALIAS, &in_addreq) == -1) {
107 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
108 return;
109 } else
110 warn("SIOCGIFALIAS");
111 }
112
113 iasin = &in_addreq.ifra_addr;
114 printf("\tinet %s%s", alias ? "alias " : "", inet_ntoa(iasin->sin_addr));
115
116 if (flags & IFF_POINTOPOINT) {
117 iasin = &in_addreq.ifra_dstaddr;
118 printf(" -> %s", inet_ntoa(iasin->sin_addr));
119 }
120
121 iasin = &in_addreq.ifra_mask;
122 printf(" netmask 0x%x", ntohl(iasin->sin_addr.s_addr));
123
124 if (flags & IFF_BROADCAST) {
125 iasin = &in_addreq.ifra_broadaddr;
126 printf(" broadcast %s", inet_ntoa(iasin->sin_addr));
127 }
128 printf("\n");
129 }
130
131 void
132 in_status(int force)
133 {
134 struct ifaddrs *ifap, *ifa;
135 struct ifreq isifr;
136
137 if (getifaddrs(&ifap) != 0)
138 err(EXIT_FAILURE, "getifaddrs");
139 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
140 if (strcmp(name, ifa->ifa_name) != 0)
141 continue;
142 if (ifa->ifa_addr->sa_family != AF_INET)
143 continue;
144 if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len)
145 continue;
146
147 memset(&isifr, 0, sizeof(isifr));
148 strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name));
149 memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
150 in_alias(&isifr);
151 }
152 freeifaddrs(ifap);
153 }
154
155 #define SIN(x) ((struct sockaddr_in *) &(x))
156 struct sockaddr_in *sintab[] = {
157 SIN(ridreq.ifr_addr), SIN(in_addreq.ifra_addr),
158 SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)};
159
160 void
161 in_getaddr(const char *str, int which)
162 {
163 struct sockaddr_in *gasin = sintab[which];
164 struct hostent *hp;
165 struct netent *np;
166
167 gasin->sin_len = sizeof(*gasin);
168 if (which != MASK)
169 gasin->sin_family = AF_INET;
170
171 if (which == ADDR) {
172 char *p = NULL;
173 if ((p = strrchr(str, '/')) != NULL) {
174 *p = '\0';
175 in_getprefix(p + 1, MASK);
176 }
177 }
178
179 if (inet_aton(str, &gasin->sin_addr) == 0) {
180 if ((hp = gethostbyname(str)) != NULL)
181 (void) memcpy(&gasin->sin_addr, hp->h_addr, hp->h_length);
182 else if ((np = getnetbyname(str)) != NULL)
183 gasin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
184 else
185 errx(EXIT_FAILURE, "%s: bad value", str);
186 }
187 }
188
189 void
190 in_getprefix(const char *plen, int which)
191 {
192 struct sockaddr_in *igsin = sintab[which];
193 u_char *cp;
194 int len = strtol(plen, (char **)NULL, 10);
195
196 if ((len < 0) || (len > 32))
197 errx(EXIT_FAILURE, "%s: bad value", plen);
198 igsin->sin_len = sizeof(*igsin);
199 if (which != MASK)
200 igsin->sin_family = AF_INET;
201 if ((len == 0) || (len == 32)) {
202 memset(&igsin->sin_addr, 0xff, sizeof(struct in_addr));
203 return;
204 }
205 memset((void *)&igsin->sin_addr, 0x00, sizeof(igsin->sin_addr));
206 for (cp = (u_char *)&igsin->sin_addr; len > 7; len -= 8)
207 *cp++ = 0xff;
208 if (len)
209 *cp = 0xff << (8 - len);
210 }
211