Deleted Added
full compact
iface.c (78410) iface.c (81634)
1/*-
2 * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/usr.sbin/ppp/iface.c 78410 2001-06-18 14:59:36Z brian $
26 * $FreeBSD: head/usr.sbin/ppp/iface.c 81634 2001-08-14 16:05:52Z brian $
27 */
28
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <net/if.h>
33#include <net/if_dl.h>
27 */
28
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <net/if.h>
33#include <net/if_dl.h>
34#include <net/if_var.h>
34#include <net/route.h>
35#include <arpa/inet.h>
36#include <netinet/in_systm.h>
35#include <net/route.h>
36#include <arpa/inet.h>
37#include <netinet/in_systm.h>
38#include <netinet/in_var.h>
37#include <netinet/ip.h>
39#include <netinet/ip.h>
40#ifndef NOINET6
41#include <netinet6/nd6.h>
42#endif
38#include <sys/un.h>
39
40#include <errno.h>
41#include <string.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <sys/ioctl.h>
45#include <sys/sysctl.h>

--- 9 unchanged lines hidden (view full) ---

55#include "timer.h"
56#include "fsm.h"
57#include "iplist.h"
58#include "lqr.h"
59#include "hdlc.h"
60#include "throughput.h"
61#include "slcompress.h"
62#include "descriptor.h"
43#include <sys/un.h>
44
45#include <errno.h>
46#include <string.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <sys/ioctl.h>
50#include <sys/sysctl.h>

--- 9 unchanged lines hidden (view full) ---

60#include "timer.h"
61#include "fsm.h"
62#include "iplist.h"
63#include "lqr.h"
64#include "hdlc.h"
65#include "throughput.h"
66#include "slcompress.h"
67#include "descriptor.h"
68#include "ncpaddr.h"
69#include "ip.h"
63#include "ipcp.h"
64#include "filter.h"
65#include "lcp.h"
66#include "ccp.h"
67#include "link.h"
68#include "mp.h"
69#ifndef NORADIUS
70#include "radius.h"
71#endif
70#include "ipcp.h"
71#include "filter.h"
72#include "lcp.h"
73#include "ccp.h"
74#include "link.h"
75#include "mp.h"
76#ifndef NORADIUS
77#include "radius.h"
78#endif
79#include "ipv6cp.h"
80#include "ncp.h"
72#include "bundle.h"
73#include "prompt.h"
74#include "iface.h"
75
76
81#include "bundle.h"
82#include "prompt.h"
83#include "iface.h"
84
85
77static int
78bitsinmask(struct in_addr mask)
79{
80 u_int32_t bitmask, maskaddr;
81 int bits;
82
83 bitmask = 0xffffffff;
84 maskaddr = ntohl(mask.s_addr);
85 for (bits = 32; bits >= 0; bits--) {
86 if (maskaddr == bitmask)
87 break;
88 bitmask &= ~(1 << (32 - bits));
89 }
90
91 return bits;
92}
93
94struct iface *
95iface_Create(const char *name)
96{
86struct iface *
87iface_Create(const char *name)
88{
97 int mib[6], s, maxtries, err;
89 int mib[6], maxtries, err;
98 size_t needed, namelen;
99 char *buf, *ptr, *end;
100 struct if_msghdr *ifm;
101 struct ifa_msghdr *ifam;
102 struct sockaddr_dl *dl;
103 struct sockaddr *sa[RTAX_MAX];
104 struct iface *iface;
105 struct iface_addr *addr;
106
90 size_t needed, namelen;
91 char *buf, *ptr, *end;
92 struct if_msghdr *ifm;
93 struct ifa_msghdr *ifam;
94 struct sockaddr_dl *dl;
95 struct sockaddr *sa[RTAX_MAX];
96 struct iface *iface;
97 struct iface_addr *addr;
98
107 s = socket(AF_INET, SOCK_DGRAM, 0);
108 if (s < 0) {
109 fprintf(stderr, "iface_Create: socket(): %s\n", strerror(errno));
110 return NULL;
111 }
112
113 mib[0] = CTL_NET;
114 mib[1] = PF_ROUTE;
115 mib[2] = 0;
116 mib[3] = 0;
117 mib[4] = NET_RT_IFLIST;
118 mib[5] = 0;
119
120 maxtries = 20;
121 err = 0;
122 do {
123 if (maxtries-- == 0 || (err && err != ENOMEM)) {
124 fprintf(stderr, "iface_Create: sysctl: %s\n", strerror(err));
99 mib[0] = CTL_NET;
100 mib[1] = PF_ROUTE;
101 mib[2] = 0;
102 mib[3] = 0;
103 mib[4] = NET_RT_IFLIST;
104 mib[5] = 0;
105
106 maxtries = 20;
107 err = 0;
108 do {
109 if (maxtries-- == 0 || (err && err != ENOMEM)) {
110 fprintf(stderr, "iface_Create: sysctl: %s\n", strerror(err));
125 close(s);
126 return NULL;
127 }
128
129 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
130 fprintf(stderr, "iface_Create: sysctl: estimate: %s\n",
131 strerror(errno));
111 return NULL;
112 }
113
114 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
115 fprintf(stderr, "iface_Create: sysctl: estimate: %s\n",
116 strerror(errno));
132 close(s);
133 return NULL;
134 }
135
136 if ((buf = (char *)malloc(needed)) == NULL) {
137 fprintf(stderr, "iface_Create: malloc failed: %s\n", strerror(errno));
117 return NULL;
118 }
119
120 if ((buf = (char *)malloc(needed)) == NULL) {
121 fprintf(stderr, "iface_Create: malloc failed: %s\n", strerror(errno));
138 close(s);
139 return NULL;
140 }
141
142 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
143 err = errno;
144 free(buf);
145 buf = NULL;
146 }

--- 14 unchanged lines hidden (view full) ---

161 if (iface == NULL) {
162 fprintf(stderr, "iface_Create: malloc: %s\n", strerror(errno));
163 return NULL;
164 }
165 iface->name = strdup(name);
166 iface->index = ifm->ifm_index;
167 iface->flags = ifm->ifm_flags;
168 iface->mtu = 0;
122 return NULL;
123 }
124
125 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
126 err = errno;
127 free(buf);
128 buf = NULL;
129 }

--- 14 unchanged lines hidden (view full) ---

144 if (iface == NULL) {
145 fprintf(stderr, "iface_Create: malloc: %s\n", strerror(errno));
146 return NULL;
147 }
148 iface->name = strdup(name);
149 iface->index = ifm->ifm_index;
150 iface->flags = ifm->ifm_flags;
151 iface->mtu = 0;
169 iface->in_addrs = 0;
170 iface->in_addr = NULL;
152 iface->addrs = 0;
153 iface->addr = NULL;
171 }
172 ptr += ifm->ifm_msglen; /* First ifa_msghdr */
173 for (; ptr < end; ptr += ifam->ifam_msglen) {
174 ifam = (struct ifa_msghdr *)ptr; /* Next if address */
175
176 if (ifam->ifam_type != RTM_NEWADDR) /* finished this if */
177 break;
178
179 if (iface != NULL && ifam->ifam_addrs & RTA_IFA) {
180 /* Found a configured interface ! */
181 iface_ParseHdr(ifam, sa);
182
154 }
155 ptr += ifm->ifm_msglen; /* First ifa_msghdr */
156 for (; ptr < end; ptr += ifam->ifam_msglen) {
157 ifam = (struct ifa_msghdr *)ptr; /* Next if address */
158
159 if (ifam->ifam_type != RTM_NEWADDR) /* finished this if */
160 break;
161
162 if (iface != NULL && ifam->ifam_addrs & RTA_IFA) {
163 /* Found a configured interface ! */
164 iface_ParseHdr(ifam, sa);
165
183 if (sa[RTAX_IFA] && sa[RTAX_IFA]->sa_family == AF_INET) {
166 if (sa[RTAX_IFA] && (sa[RTAX_IFA]->sa_family == AF_INET
167#ifndef NOINET6
168 || sa[RTAX_IFA]->sa_family == AF_INET6
169#endif
170 )) {
184 /* Record the address */
185
171 /* Record the address */
172
186 addr = (struct iface_addr *)realloc
187 (iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
173 addr = (struct iface_addr *)
174 realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
188 if (addr == NULL)
189 break;
175 if (addr == NULL)
176 break;
190 iface->in_addr = addr;
177 iface->addr = addr;
191
178
192 addr += iface->in_addrs;
193 iface->in_addrs++;
179 addr += iface->addrs;
180 iface->addrs++;
194
181
195 addr->ifa = ((struct sockaddr_in *)sa[RTAX_IFA])->sin_addr;
196
182 ncprange_setsa(&addr->ifa, sa[RTAX_IFA], sa[RTAX_NETMASK]);
197 if (sa[RTAX_BRD])
183 if (sa[RTAX_BRD])
198 addr->brd = ((struct sockaddr_in *)sa[RTAX_BRD])->sin_addr;
184 ncpaddr_setsa(&addr->peer, sa[RTAX_BRD]);
199 else
185 else
200 addr->brd.s_addr = INADDR_ANY;
201
202 if (sa[RTAX_NETMASK])
203 addr->mask = ((struct sockaddr_in *)sa[RTAX_NETMASK])->sin_addr;
204 else
205 addr->mask.s_addr = INADDR_ANY;
206
207 addr->bits = bitsinmask(addr->mask);
186 ncpaddr_init(&addr->peer);
208 }
209 }
210 }
211 }
212
213 free(buf);
187 }
188 }
189 }
190 }
191
192 free(buf);
214 close(s);
215
216 return iface;
217}
218
193
194 return iface;
195}
196
197static int
198iface_addr_Zap(const char *name, struct iface_addr *addr, int s)
199{
200 struct ifaliasreq ifra;
201#ifndef NOINET6
202 struct in6_aliasreq ifra6;
203#endif
204 struct sockaddr_in *me4, *msk4, *peer4;
205 struct sockaddr_storage ssme, sspeer, ssmsk;
206 int res;
207
208 ncprange_getsa(&addr->ifa, &ssme, &ssmsk);
209 ncpaddr_getsa(&addr->peer, &sspeer);
210 res = 0;
211
212 switch (ncprange_family(&addr->ifa)) {
213 case AF_INET:
214 memset(&ifra, '\0', sizeof ifra);
215 strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
216
217 me4 = (struct sockaddr_in *)&ifra.ifra_addr;
218 memcpy(me4, &ssme, sizeof *me4);
219
220 msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
221 memcpy(msk4, &ssmsk, sizeof *msk4);
222
223 peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
224 if (ncpaddr_family(&addr->peer) == AF_UNSPEC) {
225 peer4->sin_family = AF_INET;
226 peer4->sin_len = sizeof(*peer4);
227 peer4->sin_addr.s_addr = INADDR_NONE;
228 } else
229 memcpy(peer4, &sspeer, sizeof *peer4);
230
231 res = ID0ioctl(s, SIOCDIFADDR, &ifra);
232 break;
233
234#ifndef NOINET6
235 case AF_INET6:
236 memset(&ifra6, '\0', sizeof ifra6);
237 strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1);
238
239 memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr);
240 memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask);
241 ifra6.ifra_prefixmask.sin6_family = AF_UNSPEC;
242 if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
243 ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
244 else
245 memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr);
246 ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
247 ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
248
249 res = ID0ioctl(s, SIOCDIFADDR_IN6, &ifra6);
250 break;
251#endif
252 }
253
254 if (res == -1) {
255 char dst[40];
256 const char *end =
257#ifndef NOINET6
258 ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
259#endif
260 "";
261
262 if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
263 log_Printf(LogWARN, "iface rm: ioctl(SIOCDIFADDR%s, %s): %s\n",
264 end, ncprange_ntoa(&addr->ifa), strerror(errno));
265 else {
266 snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
267 log_Printf(LogWARN, "iface rm: ioctl(SIOCDIFADDR%s, %s -> %s): %s\n",
268 end, ncprange_ntoa(&addr->ifa), dst, strerror(errno));
269 }
270 }
271
272 return res != -1;
273}
274
219static void
275static void
220iface_addr_Zap(const char *name, struct iface_addr *addr)
276iface_addr_Add(const char *name, struct iface_addr *addr, int s)
221{
222 struct ifaliasreq ifra;
277{
278 struct ifaliasreq ifra;
223 struct sockaddr_in *me, *peer;
224 int s;
279#ifndef NOINET6
280 struct in6_aliasreq ifra6;
281#endif
282 struct sockaddr_in *me4, *msk4, *peer4;
283 struct sockaddr_storage ssme, sspeer, ssmsk;
284 int res;
225
285
226 s = ID0socket(AF_INET, SOCK_DGRAM, 0);
227 if (s < 0)
228 log_Printf(LogERROR, "iface_addr_Zap: socket(): %s\n", strerror(errno));
229 else {
286 ncprange_getsa(&addr->ifa, &ssme, &ssmsk);
287 ncpaddr_getsa(&addr->peer, &sspeer);
288 res = 0;
289
290 switch (ncprange_family(&addr->ifa)) {
291 case AF_INET:
230 memset(&ifra, '\0', sizeof ifra);
231 strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
292 memset(&ifra, '\0', sizeof ifra);
293 strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
232 me = (struct sockaddr_in *)&ifra.ifra_addr;
233 peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
234 me->sin_family = peer->sin_family = AF_INET;
235 me->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
236 me->sin_addr = addr->ifa;
237 peer->sin_addr = addr->brd;
238 log_Printf(LogDEBUG, "Delete %s\n", inet_ntoa(addr->ifa));
239 if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0)
240 log_Printf(LogWARN, "iface_addr_Zap: ioctl(SIOCDIFADDR, %s): %s\n",
241 inet_ntoa(addr->ifa), strerror(errno));
242 close(s);
294
295 me4 = (struct sockaddr_in *)&ifra.ifra_addr;
296 memcpy(me4, &ssme, sizeof *me4);
297
298 msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
299 memcpy(msk4, &ssmsk, sizeof *msk4);
300
301 peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
302 if (ncpaddr_family(&addr->peer) == AF_UNSPEC) {
303 peer4->sin_family = AF_INET;
304 peer4->sin_len = sizeof(*peer4);
305 peer4->sin_addr.s_addr = INADDR_NONE;
306 } else
307 memcpy(peer4, &sspeer, sizeof *peer4);
308
309 res = ID0ioctl(s, SIOCAIFADDR, &ifra);
310 break;
311
312#ifndef NOINET6
313 case AF_INET6:
314 memset(&ifra6, '\0', sizeof ifra6);
315 strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1);
316
317 memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr);
318 memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask);
319 if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
320 ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
321 else
322 memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr);
323 ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
324 ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
325
326 res = ID0ioctl(s, SIOCAIFADDR_IN6, &ifra6);
327 break;
328#endif
243 }
329 }
330
331 if (res == -1) {
332 char dst[40];
333 const char *end =
334#ifndef NOINET6
335 ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
336#endif
337 "";
338
339 if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
340 log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s): %s\n",
341 end, ncprange_ntoa(&addr->ifa), strerror(errno));
342 else {
343 snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
344 log_Printf(LogWARN, "iface add: ioctl(SIOCDIFADDR%s, %s -> %s): %s\n",
345 end, ncprange_ntoa(&addr->ifa), dst, strerror(errno));
346 }
347 }
244}
245
348}
349
350
246void
351void
247iface_inClear(struct iface *iface, int how)
352iface_Clear(struct iface *iface, struct ncp *ncp, int family, int how)
248{
353{
249 int n, addrs;
354 int addrs, af, inskip, in6skip, n, s4 = -1, s6 = -1, *s;
250
355
251 if (iface->in_addrs) {
252 addrs = n = how == IFACE_CLEAR_ALL ? 0 : 1;
253 for (; n < iface->in_addrs; n++)
254 iface_addr_Zap(iface->name, iface->in_addr + n);
356 if (iface->addrs) {
357 inskip = in6skip = how == IFACE_CLEAR_ALL ? 0 : 1;
358 addrs = 0;
255
359
256 iface->in_addrs = addrs;
360 for (n = 0; n < iface->addrs; n++) {
361 af = ncprange_family(&iface->addr[n].ifa);
362 if (family == 0 || family == af) {
363 if (!iface->addr[n].system && (how & IFACE_SYSTEM))
364 continue;
365 switch (af) {
366 case AF_INET:
367 if (inskip) {
368 inskip = 0;
369 continue;
370 }
371 s = &s4;
372 break;
373
374#ifndef NOINET6
375 case AF_INET6:
376 if (in6skip) {
377 in6skip = 0;
378 continue;
379 }
380 s = &s6;
381 break;
382#endif
383 }
384
385 if (*s == -1 && (*s = ID0socket(af, SOCK_DGRAM, 0)) == -1)
386 log_Printf(LogERROR, "iface_Clear: socket(): %s\n", strerror(errno));
387 else if (iface_addr_Zap(iface->name, iface->addr + n, *s)) {
388 ncp_IfaceAddrDeleted(ncp, iface->addr + n);
389 bcopy(iface->addr + n + 1, iface->addr + n,
390 (iface->addrs - n - 1) * sizeof *iface->addr);
391 iface->addrs--;
392 n--;
393 }
394 }
395 }
396
257 /* Don't bother realloc()ing - we have little to gain */
397 /* Don't bother realloc()ing - we have little to gain */
398
399 if (s4)
400 close(s4);
401 if (s6)
402 close(s6);
258 }
259}
260
261int
403 }
404}
405
406int
262iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask,
263 struct in_addr brd, int how)
407iface_Add(struct iface *iface, struct ncp *ncp, const struct ncprange *ifa,
408 const struct ncpaddr *peer, int how)
264{
409{
265 int slot, s, chg, nochange;
266 struct ifaliasreq ifra;
267 struct sockaddr_in *me, *peer, *msk;
410 int af, n, s, width;
411 struct ncpaddr ifaddr, ncplocal;
268 struct iface_addr *addr;
269
412 struct iface_addr *addr;
413
270 for (slot = 0; slot < iface->in_addrs; slot++)
271 if (iface->in_addr[slot].ifa.s_addr == ifa.s_addr) {
272 if (how & IFACE_FORCE_ADD)
273 break;
274 else
275 /* errno = EEXIST; */
276 return 0;
277 }
278
279 addr = (struct iface_addr *)realloc
280 (iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
281 if (addr == NULL) {
282 log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
414 af = ncprange_family(ifa);
415 if ((s = ID0socket(af, SOCK_DGRAM, 0)) == -1) {
416 log_Printf(LogERROR, "iface_Add: socket(): %s\n", strerror(errno));
283 return 0;
284 }
417 return 0;
418 }
285 iface->in_addr = addr;
419 ncprange_getaddr(ifa, &ncplocal);
286
420
287 /*
288 * We've gotta be careful here. If we try to add an address with the
289 * same destination as an existing interface, nothing will work.
290 * Instead, we tweak all previous address entries that match the
291 * to-be-added destination to 255.255.255.255 (w/ a similar netmask).
292 * There *may* be more than one - if the user has ``iface add''ed
293 * stuff previously.
294 */
295 nochange = 0;
296 s = -1;
297 for (chg = 0; chg < iface->in_addrs; chg++) {
298 if ((iface->in_addr[chg].brd.s_addr == brd.s_addr &&
299 brd.s_addr != INADDR_BROADCAST) || chg == slot) {
300 /*
301 * If we've found an entry that exactly matches what we want to add,
302 * don't remove it and then add it again. If we do, it's possible
303 * that the kernel will (correctly) ``tidy up'' any routes that use
304 * the IP number as a destination.
305 */
306 if (chg == slot && iface->in_addr[chg].mask.s_addr == mask.s_addr) {
307 if (brd.s_addr == iface->in_addr[slot].brd.s_addr)
308 nochange = 1;
309 /*
310 * If only the destination address has changed, the SIOCAIFADDR
311 * we do after the current loop will change it.
312 */
313 continue;
421 for (n = 0; n < iface->addrs; n++) {
422 if (ncprange_contains(&iface->addr[n].ifa, &ncplocal)) {
423 if (!(how & IFACE_FORCE_ADD)) {
424 close(s);
425 return 0; /* errno = EEXIST; */
314 }
426 }
315 if (s == -1 && (s = ID0socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
316 log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno));
317 return 0;
427
428 if (ncprange_equal(&iface->addr[n].ifa, ifa) &&
429 ncpaddr_equal(&iface->addr[n].peer, peer)) {
430 close(s);
431 return 1; /* Already there */
318 }
319
432 }
433
320 memset(&ifra, '\0', sizeof ifra);
321 strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1);
322 me = (struct sockaddr_in *)&ifra.ifra_addr;
323 msk = (struct sockaddr_in *)&ifra.ifra_mask;
324 peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
325 me->sin_family = msk->sin_family = peer->sin_family = AF_INET;
326 me->sin_len = msk->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
327 me->sin_addr = iface->in_addr[chg].ifa;
328 msk->sin_addr = iface->in_addr[chg].mask;
329 peer->sin_addr = iface->in_addr[chg].brd;
330 log_Printf(LogDEBUG, "Delete %s\n", inet_ntoa(me->sin_addr));
331 ID0ioctl(s, SIOCDIFADDR, &ifra); /* Don't care if it fails... */
332 if (chg != slot) {
333 peer->sin_addr.s_addr = iface->in_addr[chg].brd.s_addr =
334 msk->sin_addr.s_addr = iface->in_addr[chg].mask.s_addr =
335 INADDR_BROADCAST;
336 iface->in_addr[chg].bits = 32;
337 log_Printf(LogDEBUG, "Add %s -> 255.255.255.255\n",
338 inet_ntoa(me->sin_addr));
339 if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && errno != EEXIST) {
340 /* Oops - that's bad(ish) news ! We've lost an alias ! */
341 log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n",
342 inet_ntoa(me->sin_addr), strerror(errno));
343 iface->in_addrs--;
344 bcopy(iface->in_addr + chg + 1, iface->in_addr + chg,
345 (iface->in_addrs - chg) * sizeof iface->in_addr[0]);
346 if (slot > chg)
347 slot--;
348 chg--;
349 }
434 width =
435#ifndef NOINET6
436 (af == AF_INET6) ? 128 :
437#endif
438 32;
439 iface_addr_Zap(iface->name, iface->addr + n, s);
440 ncprange_setwidth(&iface->addr[n].ifa, width);
441 ncprange_getaddr(&iface->addr[n].ifa, &ifaddr);
442 if (ncpaddr_equal(&ifaddr, &ncplocal))
443 ncpaddr_copy(&iface->addr[n].peer, peer);
444 else
445 ncpaddr_init(&iface->addr[n].peer);
446 iface_addr_Add(iface->name, iface->addr + n, s);
447 if (ncpaddr_equal(&ifaddr, &ncplocal)) {
448 close(s);
449 ncp_IfaceAddrAdded(ncp, iface->addr + n);
450 return 1;
350 }
351 }
352 }
353
451 }
452 }
453 }
454
354 if (!nochange) {
355 if (s == -1 && (s = ID0socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
356 log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno));
357 return 0;
358 }
359 memset(&ifra, '\0', sizeof ifra);
360 strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1);
361 me = (struct sockaddr_in *)&ifra.ifra_addr;
362 msk = (struct sockaddr_in *)&ifra.ifra_mask;
363 peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
364 me->sin_family = msk->sin_family = peer->sin_family = AF_INET;
365 me->sin_len = msk->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
366 me->sin_addr = ifa;
367 msk->sin_addr = mask;
368 peer->sin_addr = brd;
369
370 if (log_IsKept(LogDEBUG)) {
371 char buf[16];
372
373 strncpy(buf, inet_ntoa(brd), sizeof buf-1);
374 buf[sizeof buf - 1] = '\0';
375 log_Printf(LogDEBUG, "Add %s -> %s\n", inet_ntoa(ifa), buf);
376 }
377
378 /* An EEXIST failure w/ brd == INADDR_BROADCAST is ok (and works!) */
379 if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 &&
380 (brd.s_addr != INADDR_BROADCAST || errno != EEXIST)) {
381 log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n",
382 inet_ntoa(ifa), strerror(errno));
383 ID0ioctl(s, SIOCDIFADDR, &ifra); /* EEXIST ? */
384 close(s);
385 return 0;
386 }
455 addr = (struct iface_addr *)realloc
456 (iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
457 if (addr == NULL) {
458 log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
459 close(s);
460 return 0;
387 }
461 }
462 iface->addr = addr;
388
463
389 if (s != -1)
390 close(s);
464 if (how & IFACE_ADD_FIRST) {
465 /* Stuff it at the start of our list */
466 n = 0;
467 bcopy(iface->addr, iface->addr + 1, iface->addrs * sizeof *iface->addr);
468 } else
469 n = iface->addrs;
391
470
392 if (slot == iface->in_addrs) {
393 /* We're adding a new interface address */
471 iface->addrs++;
472 ncprange_copy(&iface->addr[n].ifa, ifa);
473 ncpaddr_copy(&iface->addr[n].peer, peer);
474 iface->addr[n].system = !!(how & IFACE_SYSTEM);
475 iface_addr_Add(iface->name, iface->addr + n, s);
394
476
395 if (how & IFACE_ADD_FIRST) {
396 /* Stuff it at the start of our list */
397 slot = 0;
398 bcopy(iface->in_addr, iface->in_addr + 1,
399 iface->in_addrs * sizeof iface->in_addr[0]);
400 }
477 close(s);
478 ncp_IfaceAddrAdded(ncp, iface->addr + n);
401
479
402 iface->in_addrs++;
403 } else if (how & IFACE_ADD_FIRST) {
404 /* Shift it up to the first slot */
405 bcopy(iface->in_addr, iface->in_addr + 1, slot * sizeof iface->in_addr[0]);
406 slot = 0;
407 }
408
409 iface->in_addr[slot].ifa = ifa;
410 iface->in_addr[slot].mask = mask;
411 iface->in_addr[slot].brd = brd;
412 iface->in_addr[slot].bits = bitsinmask(iface->in_addr[slot].mask);
413
414 return 1;
415}
416
417int
480 return 1;
481}
482
483int
418iface_inDelete(struct iface *iface, struct in_addr ip)
484iface_Delete(struct iface *iface, struct ncp *ncp, const struct ncpaddr *del)
419{
485{
420 int n;
486 struct ncpaddr found;
487 int n, res, s;
421
488
422 for (n = 0; n < iface->in_addrs; n++)
423 if (iface->in_addr[n].ifa.s_addr == ip.s_addr) {
424 iface_addr_Zap(iface->name, iface->in_addr + n);
425 bcopy(iface->in_addr + n + 1, iface->in_addr + n,
426 (iface->in_addrs - n - 1) * sizeof iface->in_addr[0]);
427 iface->in_addrs--;
428 return 1;
489 if ((s = ID0socket(ncpaddr_family(del), SOCK_DGRAM, 0)) == -1) {
490 log_Printf(LogERROR, "iface_Delete: socket(): %s\n", strerror(errno));
491 return 0;
492 }
493
494 for (n = res = 0; n < iface->addrs; n++) {
495 ncprange_getaddr(&iface->addr[n].ifa, &found);
496 if (ncpaddr_equal(&found, del)) {
497 iface_addr_Zap(iface->name, iface->addr + n, s);
498 ncp_IfaceAddrDeleted(ncp, iface->addr + n);
499 bcopy(iface->addr + n + 1, iface->addr + n,
500 (iface->addrs - n - 1) * sizeof *iface->addr);
501 iface->addrs--;
502 res = 1;
503 break;
429 }
504 }
505 }
430
506
431 return 0;
507 close(s);
508
509 return res;
432}
433
434#define IFACE_ADDFLAGS 1
435#define IFACE_DELFLAGS 2
436
437static int
438iface_ChangeFlags(const char *ifname, int flags, int how)
439{

--- 50 unchanged lines hidden (view full) ---

490 /*
491 * iface_Clear(iface, IFACE_CLEAR_ALL) must be called manually
492 * if that's what the user wants. It's better to leave the interface
493 * allocated so that existing connections can continue to work.
494 */
495
496 if (iface != NULL) {
497 free(iface->name);
510}
511
512#define IFACE_ADDFLAGS 1
513#define IFACE_DELFLAGS 2
514
515static int
516iface_ChangeFlags(const char *ifname, int flags, int how)
517{

--- 50 unchanged lines hidden (view full) ---

568 /*
569 * iface_Clear(iface, IFACE_CLEAR_ALL) must be called manually
570 * if that's what the user wants. It's better to leave the interface
571 * allocated so that existing connections can continue to work.
572 */
573
574 if (iface != NULL) {
575 free(iface->name);
498 free(iface->in_addr);
576 free(iface->addr);
499 free(iface);
500 }
501}
502
503#define if_entry(x) { IFF_##x, #x }
504
505struct {
506 int flag;

--- 15 unchanged lines hidden (view full) ---

522 if_entry(LINK2),
523 if_entry(MULTICAST),
524 { 0, "???" }
525};
526
527int
528iface_Show(struct cmdargs const *arg)
529{
577 free(iface);
578 }
579}
580
581#define if_entry(x) { IFF_##x, #x }
582
583struct {
584 int flag;

--- 15 unchanged lines hidden (view full) ---

600 if_entry(LINK2),
601 if_entry(MULTICAST),
602 { 0, "???" }
603};
604
605int
606iface_Show(struct cmdargs const *arg)
607{
608 struct ncpaddr ncpaddr;
530 struct iface *iface = arg->bundle->iface, *current;
531 int f, flags;
609 struct iface *iface = arg->bundle->iface, *current;
610 int f, flags;
611#ifndef NOINET6
612 int scopeid, width;
613#endif
614 struct in_addr mask;
532
533 current = iface_Create(iface->name);
534 flags = iface->flags = current->flags;
535 iface_Destroy(current);
536
537 prompt_Printf(arg->prompt, "%s (idx %d) <", iface->name, iface->index);
538 for (f = 0; f < sizeof if_flags / sizeof if_flags[0]; f++)
539 if ((if_flags[f].flag & flags) || (!if_flags[f].flag && flags)) {
540 prompt_Printf(arg->prompt, "%s%s", flags == iface->flags ? "" : ",",
541 if_flags[f].value);
542 flags &= ~if_flags[f].flag;
543 }
544 prompt_Printf(arg->prompt, "> mtu %d has %d address%s:\n", iface->mtu,
615
616 current = iface_Create(iface->name);
617 flags = iface->flags = current->flags;
618 iface_Destroy(current);
619
620 prompt_Printf(arg->prompt, "%s (idx %d) <", iface->name, iface->index);
621 for (f = 0; f < sizeof if_flags / sizeof if_flags[0]; f++)
622 if ((if_flags[f].flag & flags) || (!if_flags[f].flag && flags)) {
623 prompt_Printf(arg->prompt, "%s%s", flags == iface->flags ? "" : ",",
624 if_flags[f].value);
625 flags &= ~if_flags[f].flag;
626 }
627 prompt_Printf(arg->prompt, "> mtu %d has %d address%s:\n", iface->mtu,
545 iface->in_addrs, iface->in_addrs == 1 ? "" : "es");
628 iface->addrs, iface->addrs == 1 ? "" : "es");
546
629
547 for (f = 0; f < iface->in_addrs; f++) {
548 prompt_Printf(arg->prompt, " %s", inet_ntoa(iface->in_addr[f].ifa));
549 if (iface->in_addr[f].bits >= 0)
550 prompt_Printf(arg->prompt, "/%d", iface->in_addr[f].bits);
551 if (iface->flags & IFF_POINTOPOINT)
552 prompt_Printf(arg->prompt, " -> %s", inet_ntoa(iface->in_addr[f].brd));
553 else if (iface->flags & IFF_BROADCAST)
554 prompt_Printf(arg->prompt, " broadcast %s",
555 inet_ntoa(iface->in_addr[f].brd));
556 if (iface->in_addr[f].bits < 0)
557 prompt_Printf(arg->prompt, " (mask %s)",
558 inet_ntoa(iface->in_addr[f].mask));
630 for (f = 0; f < iface->addrs; f++) {
631 ncprange_getaddr(&iface->addr[f].ifa, &ncpaddr);
632 switch (ncprange_family(&iface->addr[f].ifa)) {
633 case AF_INET:
634 prompt_Printf(arg->prompt, " inet %s --> ", ncpaddr_ntoa(&ncpaddr));
635 if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC)
636 prompt_Printf(arg->prompt, "255.255.255.255");
637 else
638 prompt_Printf(arg->prompt, "%s", ncpaddr_ntoa(&iface->addr[f].peer));
639 ncprange_getip4mask(&iface->addr[f].ifa, &mask);
640 prompt_Printf(arg->prompt, " netmask 0x%08lx", (long)ntohl(mask.s_addr));
641 break;
642
643#ifndef NOINET6
644 case AF_INET6:
645 prompt_Printf(arg->prompt, " inet6 %s", ncpaddr_ntoa(&ncpaddr));
646 if (ncpaddr_family(&iface->addr[f].peer) != AF_UNSPEC)
647 prompt_Printf(arg->prompt, " --> %s",
648 ncpaddr_ntoa(&iface->addr[f].peer));
649 ncprange_getwidth(&iface->addr[f].ifa, &width);
650 prompt_Printf(arg->prompt, " prefixlen %d", width);
651 if ((scopeid = ncprange_scopeid(&iface->addr[f].ifa)) != -1)
652 prompt_Printf(arg->prompt, " scopeid 0x%x", (unsigned)scopeid);
653 break;
654#endif
655 }
559 prompt_Printf(arg->prompt, "\n");
560 }
561
562 return 0;
563}
564
565void
566iface_ParseHdr(struct ifa_msghdr *ifam, struct sockaddr *sa[RTAX_MAX])

--- 13 unchanged lines hidden ---
656 prompt_Printf(arg->prompt, "\n");
657 }
658
659 return 0;
660}
661
662void
663iface_ParseHdr(struct ifa_msghdr *ifam, struct sockaddr *sa[RTAX_MAX])

--- 13 unchanged lines hidden ---