is@ pointed out that I set the phase and range of a sockaddr_at

without subsequently doing anything with it, so commit_address()
works with an address with phase == 0.  phase == 0 is not allowed,
hence

random84# ifconfig nfe0 atalk 3.14
ifconfig: SIOCAIFADDR: Invalid argument

Solution: copy the new sockaddr_at to a temporary input environment,
and pass that environment to commit_address().  I may as well copy
the new sockaddr_at to the output environment, while I am at it.
This commit is contained in:
dyoung 2008-08-01 22:44:17 +00:00
parent 10b425b514
commit 83dfe33e66

View File

@ -1,4 +1,4 @@
/* $NetBSD: af_atalk.c,v 1.14 2008/07/15 21:27:58 dyoung Exp $ */
/* $NetBSD: af_atalk.c,v 1.15 2008/08/01 22:44:17 dyoung Exp $ */
/*
* Copyright (c) 1983, 1993
@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: af_atalk.c,v 1.14 2008/07/15 21:27:58 dyoung Exp $");
__RCSID("$NetBSD: af_atalk.c,v 1.15 2008/08/01 22:44:17 dyoung Exp $");
#endif /* not lint */
#include <sys/param.h>
@ -45,6 +45,7 @@ __RCSID("$NetBSD: af_atalk.c,v 1.14 2008/07/15 21:27:58 dyoung Exp $");
#include <err.h>
#include <errno.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <util.h>
@ -126,30 +127,53 @@ at_commit_address(prop_dictionary_t env, prop_dictionary_t oenv)
, .defmask = {.buf = NULL, .buflen = 0}
};
struct netrange nr = {.nr_phase = 2}; /* AppleTalk net range */
prop_data_t d;
const struct paddr_prefix *addr;
struct sockaddr_at sat;
prop_data_t d, d0;
prop_dictionary_t ienv;
struct paddr_prefix *addr;
struct sockaddr_at *sat;
if ((d = (prop_data_t)prop_dictionary_get(env, "address")) == NULL)
if ((d0 = (prop_data_t)prop_dictionary_get(env, "address")) == NULL)
return;
addr = prop_data_data_nocopy(d);
addr = prop_data_data(d0);
memcpy(&sat, &addr->pfx_addr, MIN(sizeof(sat), addr->pfx_addr.sa_len));
sat = (struct sockaddr_at *)&addr->pfx_addr;
(void)prop_dictionary_get_uint8(env, "phase", &nr.nr_phase);
/* Default range of one */
nr.nr_firstnet = nr.nr_lastnet = sat.sat_addr.s_net;
nr.nr_firstnet = nr.nr_lastnet = sat->sat_addr.s_net;
setatrange_impl(env, oenv, &nr);
if (ntohs(nr.nr_firstnet) > ntohs(sat.sat_addr.s_net) ||
ntohs(nr.nr_lastnet) < ntohs(sat.sat_addr.s_net))
if (ntohs(nr.nr_firstnet) > ntohs(sat->sat_addr.s_net) ||
ntohs(nr.nr_lastnet) < ntohs(sat->sat_addr.s_net))
errx(EXIT_FAILURE, "AppleTalk address is not in range");
*((struct netrange *)&sat.sat_zero) = nr;
*((struct netrange *)&sat->sat_zero) = nr;
/* Copy the new address to a temporary input environment */
d = prop_data_create_data_nocopy(addr, paddr_prefix_size(addr));
ienv = prop_dictionary_copy_mutable(env);
if (d == NULL)
err(EXIT_FAILURE, "%s: prop_data_create_data", __func__);
if (ienv == NULL)
err(EXIT_FAILURE, "%s: prop_dictionary_copy_mutable", __func__);
if (!prop_dictionary_set(ienv, "address", (prop_object_t)d))
err(EXIT_FAILURE, "%s: prop_dictionary_set", __func__);
/* copy to output environment for good measure */
if (!prop_dictionary_set(oenv, "address", (prop_object_t)d))
err(EXIT_FAILURE, "%s: prop_dictionary_set", __func__);
prop_object_release((prop_object_t)d);
memset(&ifr, 0, sizeof(ifr));
memset(&ifra, 0, sizeof(ifra));
commit_address(env, oenv, &atparam);
commit_address(ienv, oenv, &atparam);
/* release temporary input environment */
prop_object_release((prop_object_t)ienv);
}
static void