diff options
-rw-r--r-- | sys/netatalk/at_control.c | 1200 |
1 files changed, 594 insertions, 606 deletions
diff --git a/sys/netatalk/at_control.c b/sys/netatalk/at_control.c index 064ae04..5151628 100644 --- a/sys/netatalk/at_control.c +++ b/sys/netatalk/at_control.c @@ -42,270 +42,268 @@ static int aa_claim_addr(struct ifaddr *ifa, struct sockaddr *gw); (a)->sat_addr.s_node == (b)->sat_addr.s_node) int -at_control(struct socket *so, u_long cmd, caddr_t data, - struct ifnet *ifp, struct thread *td) +at_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, + struct thread *td) { - struct ifreq *ifr = (struct ifreq *)data; - struct sockaddr_at *sat; - struct netrange *nr; - struct at_aliasreq *ifra = (struct at_aliasreq *)data; - struct at_ifaddr *aa0; - struct at_ifaddr *aa = NULL; - struct ifaddr *ifa, *ifa0; - - /* - * If we have an ifp, then find the matching at_ifaddr if it exists - */ - if (ifp != NULL) { - for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { - if (aa->aa_ifp == ifp) break; - } - } - - /* - * In this first switch table we are basically getting ready for - * the second one, by getting the atalk-specific things set up - * so that they start to look more similar to other protocols etc. - */ + struct ifreq *ifr = (struct ifreq *)data; + struct sockaddr_at *sat; + struct netrange *nr; + struct at_aliasreq *ifra = (struct at_aliasreq *)data; + struct at_ifaddr *aa0; + struct at_ifaddr *aa = NULL; + struct ifaddr *ifa, *ifa0; - switch (cmd) { - case SIOCAIFADDR: - case SIOCDIFADDR: /* - * If we have an appletalk sockaddr, scan forward of where - * we are now on the at_ifaddr list to find one with a matching - * address on this interface. - * This may leave aa pointing to the first address on the - * NEXT interface! + * If we have an ifp, then find the matching at_ifaddr if it exists */ - if (ifra->ifra_addr.sat_family == AF_APPLETALK) { - for (; aa; aa = aa->aa_next) { - if (aa->aa_ifp == ifp && - sateqaddr(&aa->aa_addr, &ifra->ifra_addr)) { - break; + if (ifp != NULL) { + for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { + if (aa->aa_ifp == ifp) + break; } - } - } - /* - * If we a retrying to delete an addres but didn't find such, - * then rewurn with an error - */ - if (cmd == SIOCDIFADDR && aa == NULL) { - return (EADDRNOTAVAIL); } - /*FALLTHROUGH*/ - case SIOCSIFADDR: - /* - * If we are not superuser, then we don't get to do these ops. + /* + * In this first switch table we are basically getting ready for + * the second one, by getting the atalk-specific things set up + * so that they start to look more similar to other protocols etc. */ - if (suser(td)) { - return (EPERM); - } - sat = satosat(&ifr->ifr_addr); - nr = (struct netrange *)sat->sat_zero; - if (nr->nr_phase == 1) { - /* - * Look for a phase 1 address on this interface. - * This may leave aa pointing to the first address on the - * NEXT interface! - */ - for (; aa; aa = aa->aa_next) { - if (aa->aa_ifp == ifp && - (aa->aa_flags & AFA_PHASE2) == 0) { - break; + switch (cmd) { + case SIOCAIFADDR: + case SIOCDIFADDR: + /* + * If we have an appletalk sockaddr, scan forward of where we + * are now on the at_ifaddr list to find one with a matching + * address on this interface. This may leave aa pointing to + * the first address on the NEXT interface! + */ + if (ifra->ifra_addr.sat_family == AF_APPLETALK) { + for (; aa; aa = aa->aa_next) { + if (aa->aa_ifp == ifp && + sateqaddr(&aa->aa_addr, &ifra->ifra_addr)) + break; + } } - } - } else { /* default to phase 2 */ - /* - * Look for a phase 2 address on this interface. - * This may leave aa pointing to the first address on the - * NEXT interface! - */ - for (; aa; aa = aa->aa_next) { - if (aa->aa_ifp == ifp && (aa->aa_flags & AFA_PHASE2)) { - break; + /* + * If we a retrying to delete an addres but didn't find such, + * then rewurn with an error + */ + if (cmd == SIOCDIFADDR && aa == NULL) + return (EADDRNOTAVAIL); + /*FALLTHROUGH*/ + + case SIOCSIFADDR: + /* + * If we are not superuser, then we don't get to do these ops. + */ + if (suser(td)) + return (EPERM); + + sat = satosat(&ifr->ifr_addr); + nr = (struct netrange *)sat->sat_zero; + if (nr->nr_phase == 1) { + /* + * Look for a phase 1 address on this interface. + * This may leave aa pointing to the first address on + * the NEXT interface! + */ + for (; aa; aa = aa->aa_next) { + if (aa->aa_ifp == ifp && + (aa->aa_flags & AFA_PHASE2) == 0) + break; + } + } else { /* default to phase 2 */ + /* + * Look for a phase 2 address on this interface. + * This may leave aa pointing to the first address on + * the NEXT interface! + */ + for (; aa; aa = aa->aa_next) { + if (aa->aa_ifp == ifp && (aa->aa_flags & + AFA_PHASE2)) + break; + } } - } - } - if (ifp == NULL) - panic("at_control"); + if (ifp == NULL) + panic("at_control"); - /* - * If we failed to find an existing at_ifaddr entry, then we - * allocate a fresh one. - */ - if (aa == NULL) { - aa0 = malloc(sizeof(struct at_ifaddr), M_IFADDR, M_WAITOK | M_ZERO); - if ((aa = at_ifaddr_list) != NULL) { /* - * Don't let the loopback be first, since the first - * address is the machine's default address for - * binding. - * If it is, stick ourself in front, otherwise - * go to the back of the list. + * If we failed to find an existing at_ifaddr entry, then we + * allocate a fresh one. */ - if (at_ifaddr_list->aa_ifp->if_flags & IFF_LOOPBACK) { - aa = aa0; - aa->aa_next = at_ifaddr_list; - at_ifaddr_list = aa; + if (aa == NULL) { + aa0 = malloc(sizeof(struct at_ifaddr), M_IFADDR, + M_WAITOK | M_ZERO); + if ((aa = at_ifaddr_list) != NULL) { + /* + * Don't let the loopback be first, since the + * first address is the machine's default + * address for binding. If it is, stick + * ourself in front, otherwise go to the back + * of the list. + */ + if (at_ifaddr_list->aa_ifp->if_flags & + IFF_LOOPBACK) { + aa = aa0; + aa->aa_next = at_ifaddr_list; + at_ifaddr_list = aa; + } else { + for (; aa->aa_next; aa = aa->aa_next) + ; + aa->aa_next = aa0; + } + } else + at_ifaddr_list = aa0; + aa = aa0; + + /* + * Find the end of the interface's addresses + * and link our new one on the end + */ + ifa = (struct ifaddr *)aa; + IFA_LOCK_INIT(ifa); + ifa->ifa_refcnt = 1; + TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link); + + /* + * As the at_ifaddr contains the actual sockaddrs, + * and the ifaddr itself, link them al together + * correctly. + */ + ifa->ifa_addr = (struct sockaddr *)&aa->aa_addr; + ifa->ifa_dstaddr = (struct sockaddr *)&aa->aa_addr; + ifa->ifa_netmask = (struct sockaddr *)&aa->aa_netmask; + + /* + * Set/clear the phase 2 bit. + */ + if (nr->nr_phase == 1) + aa->aa_flags &= ~AFA_PHASE2; + else + aa->aa_flags |= AFA_PHASE2; + + /* + * and link it all together + */ + aa->aa_ifp = ifp; } else { - for (; aa->aa_next; aa = aa->aa_next) - ; - aa->aa_next = aa0; - } - } else { - at_ifaddr_list = aa0; - } - aa = aa0; - - /* - * Find the end of the interface's addresses - * and link our new one on the end - */ - ifa = (struct ifaddr *)aa; - IFA_LOCK_INIT(ifa); - ifa->ifa_refcnt = 1; - TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link); - - /* - * As the at_ifaddr contains the actual sockaddrs, - * and the ifaddr itself, link them al together correctly. - */ - ifa->ifa_addr = (struct sockaddr *)&aa->aa_addr; - ifa->ifa_dstaddr = (struct sockaddr *)&aa->aa_addr; - ifa->ifa_netmask = (struct sockaddr *)&aa->aa_netmask; - - /* - * Set/clear the phase 2 bit. - */ - if (nr->nr_phase == 1) { - aa->aa_flags &= ~AFA_PHASE2; - } else { - aa->aa_flags |= AFA_PHASE2; - } - - /* - * and link it all together - */ - aa->aa_ifp = ifp; - } else { - /* - * If we DID find one then we clobber any routes dependent on it.. - */ - at_scrub(ifp, aa); - } - break; - - case SIOCGIFADDR : - sat = satosat(&ifr->ifr_addr); - nr = (struct netrange *)sat->sat_zero; - if (nr->nr_phase == 1) { - /* - * If the request is specifying phase 1, then - * only look at a phase one address - */ - for (; aa; aa = aa->aa_next) { - if (aa->aa_ifp == ifp && - (aa->aa_flags & AFA_PHASE2) == 0) { - break; - } - } - } else { - /* - * default to phase 2 - */ - for (; aa; aa = aa->aa_next) { - if (aa->aa_ifp == ifp && (aa->aa_flags & AFA_PHASE2)) { - break; + /* + * If we DID find one then we clobber any routes + * dependent on it.. + */ + at_scrub(ifp, aa); } - } - } + break; - if (aa == NULL) - return (EADDRNOTAVAIL); - break; - } + case SIOCGIFADDR : + sat = satosat(&ifr->ifr_addr); + nr = (struct netrange *)sat->sat_zero; + if (nr->nr_phase == 1) { + /* + * If the request is specifying phase 1, then + * only look at a phase one address + */ + for (; aa; aa = aa->aa_next) { + if (aa->aa_ifp == ifp && + (aa->aa_flags & AFA_PHASE2) == 0) + break; + } + } else { + /* + * default to phase 2 + */ + for (; aa; aa = aa->aa_next) { + if (aa->aa_ifp == ifp && (aa->aa_flags & + AFA_PHASE2)) + break; + } + } - /* - * By the time this switch is run we should be able to assume that - * the "aa" pointer is valid when needed. - */ - switch (cmd) { - case SIOCGIFADDR: + if (aa == NULL) + return (EADDRNOTAVAIL); + break; + } /* - * copy the contents of the sockaddr blindly. + * By the time this switch is run we should be able to assume that + * the "aa" pointer is valid when needed. */ - sat = (struct sockaddr_at *)&ifr->ifr_addr; - *sat = aa->aa_addr; + switch (cmd) { + case SIOCGIFADDR: - /* - * and do some cleanups - */ - ((struct netrange *)&sat->sat_zero)->nr_phase - = (aa->aa_flags & AFA_PHASE2) ? 2 : 1; - ((struct netrange *)&sat->sat_zero)->nr_firstnet = aa->aa_firstnet; - ((struct netrange *)&sat->sat_zero)->nr_lastnet = aa->aa_lastnet; - break; - - case SIOCSIFADDR: - return (at_ifinit(ifp, aa, (struct sockaddr_at *)&ifr->ifr_addr)); - - case SIOCAIFADDR: - if (sateqaddr(&ifra->ifra_addr, &aa->aa_addr)) { - return (0); - } - return (at_ifinit(ifp, aa, (struct sockaddr_at *)&ifr->ifr_addr)); + /* + * copy the contents of the sockaddr blindly. + */ + sat = (struct sockaddr_at *)&ifr->ifr_addr; + *sat = aa->aa_addr; - case SIOCDIFADDR: - /* - * scrub all routes.. didn't we just DO this? XXX yes, del it - */ - at_scrub(ifp, aa); + /* + * and do some cleanups + */ + ((struct netrange *)&sat->sat_zero)->nr_phase + = (aa->aa_flags & AFA_PHASE2) ? 2 : 1; + ((struct netrange *)&sat->sat_zero)->nr_firstnet = + aa->aa_firstnet; + ((struct netrange *)&sat->sat_zero)->nr_lastnet = + aa->aa_lastnet; + break; - /* - * remove the ifaddr from the interface - */ - ifa0 = (struct ifaddr *)aa; - TAILQ_REMOVE(&ifp->if_addrhead, ifa0, ifa_link); + case SIOCSIFADDR: + return (at_ifinit(ifp, aa, + (struct sockaddr_at *)&ifr->ifr_addr)); - /* - * Now remove the at_ifaddr from the parallel structure - * as well, or we'd be in deep trouble - */ - aa0 = aa; - if (aa0 == (aa = at_ifaddr_list)) { - at_ifaddr_list = aa->aa_next; - } else { - while (aa->aa_next && (aa->aa_next != aa0)) { - aa = aa->aa_next; - } - - /* - * if we found it, remove it, otherwise we screwed up. - */ - if (aa->aa_next) { - aa->aa_next = aa0->aa_next; - } else { - panic("at_control"); - } - } + case SIOCAIFADDR: + if (sateqaddr(&ifra->ifra_addr, &aa->aa_addr)) + return (0); + return (at_ifinit(ifp, aa, + (struct sockaddr_at *)&ifr->ifr_addr)); - /* - * Now reclaim the reference. - */ - IFAFREE(ifa0); - break; - - default: - if (ifp == NULL || ifp->if_ioctl == NULL) - return (EOPNOTSUPP); - return ((*ifp->if_ioctl)(ifp, cmd, data)); - } - return (0); + case SIOCDIFADDR: + /* + * scrub all routes.. didn't we just DO this? XXX yes, del it + */ + at_scrub(ifp, aa); + + /* + * remove the ifaddr from the interface + */ + ifa0 = (struct ifaddr *)aa; + TAILQ_REMOVE(&ifp->if_addrhead, ifa0, ifa_link); + + /* + * Now remove the at_ifaddr from the parallel structure + * as well, or we'd be in deep trouble + */ + aa0 = aa; + if (aa0 == (aa = at_ifaddr_list)) { + at_ifaddr_list = aa->aa_next; + } else { + while (aa->aa_next && (aa->aa_next != aa0)) + aa = aa->aa_next; + + /* + * if we found it, remove it, otherwise we screwed up. + */ + if (aa->aa_next) + aa->aa_next = aa0->aa_next; + else + panic("at_control"); + } + + /* + * Now reclaim the reference. + */ + IFAFREE(ifa0); + break; + + default: + if (ifp == NULL || ifp->if_ioctl == NULL) + return (EOPNOTSUPP); + return ((*ifp->if_ioctl)(ifp, cmd, data)); + } + return (0); } /* @@ -315,32 +313,29 @@ at_control(struct socket *so, u_long cmd, caddr_t data, * as aa->at_ifaddr.ifa_ifp should be the same. */ static int -at_scrub(ifp, aa) - struct ifnet *ifp; - struct at_ifaddr *aa; +at_scrub(struct ifnet *ifp, struct at_ifaddr *aa) { - int error; + int error; - if (aa->aa_flags & AFA_ROUTE) { - if (ifp->if_flags & IFF_LOOPBACK) { - if ((error = aa_delsingleroute(&aa->aa_ifa, - &aa->aa_addr.sat_addr, - &aa->aa_netmask.sat_addr)) != 0) { - return (error); + if (aa->aa_flags & AFA_ROUTE) { + if (ifp->if_flags & IFF_LOOPBACK) { + if ((error = aa_delsingleroute(&aa->aa_ifa, + &aa->aa_addr.sat_addr, &aa->aa_netmask.sat_addr)) + != 0) + return (error); + } else if (ifp->if_flags & IFF_POINTOPOINT) { + if ((error = rtinit(&aa->aa_ifa, RTM_DELETE, + RTF_HOST)) != 0) + return (error); + } else if (ifp->if_flags & IFF_BROADCAST) { + error = aa_dorangeroute(&aa->aa_ifa, + ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), + RTM_DELETE); } - } else if (ifp->if_flags & IFF_POINTOPOINT) { - if ((error = rtinit(&aa->aa_ifa, RTM_DELETE, RTF_HOST)) != 0) - return (error); - } else if (ifp->if_flags & IFF_BROADCAST) { - error = aa_dorangeroute(&aa->aa_ifa, - ntohs(aa->aa_firstnet), - ntohs(aa->aa_lastnet), - RTM_DELETE); + aa->aa_ifa.ifa_flags &= ~IFA_ROUTE; + aa->aa_flags &= ~AFA_ROUTE; } - aa->aa_ifa.ifa_flags &= ~IFA_ROUTE; - aa->aa_flags &= ~AFA_ROUTE; - } - return (0); + return (0); } /* @@ -348,330 +343,326 @@ at_scrub(ifp, aa) * bang them all together at high speed and see what happens */ static int -at_ifinit(ifp, aa, sat) - struct ifnet *ifp; - struct at_ifaddr *aa; - struct sockaddr_at *sat; +at_ifinit(struct ifnet *ifp, struct at_ifaddr *aa, struct sockaddr_at *sat) { - struct netrange nr, onr; - struct sockaddr_at oldaddr; - int error = 0, i, j; - int netinc, nodeinc, nnets; - u_short net; - - /* - * save the old addresses in the at_ifaddr just in case we need them. - */ - oldaddr = aa->aa_addr; - onr.nr_firstnet = aa->aa_firstnet; - onr.nr_lastnet = aa->aa_lastnet; - - /* - * take the address supplied as an argument, and add it to the - * at_ifnet (also given). Remember ing to update - * those parts of the at_ifaddr that need special processing - */ - bzero(AA_SAT(aa), sizeof(struct sockaddr_at)); - bcopy(sat->sat_zero, &nr, sizeof(struct netrange)); - bcopy(sat->sat_zero, AA_SAT(aa)->sat_zero, sizeof(struct netrange)); - nnets = ntohs(nr.nr_lastnet) - ntohs(nr.nr_firstnet) + 1; - aa->aa_firstnet = nr.nr_firstnet; - aa->aa_lastnet = nr.nr_lastnet; + struct netrange nr, onr; + struct sockaddr_at oldaddr; + int error = 0, i, j; + int netinc, nodeinc, nnets; + u_short net; + + /* + * save the old addresses in the at_ifaddr just in case we need them. + */ + oldaddr = aa->aa_addr; + onr.nr_firstnet = aa->aa_firstnet; + onr.nr_lastnet = aa->aa_lastnet; + + /* + * take the address supplied as an argument, and add it to the + * at_ifnet (also given). Remember ing to update + * those parts of the at_ifaddr that need special processing + */ + bzero(AA_SAT(aa), sizeof(struct sockaddr_at)); + bcopy(sat->sat_zero, &nr, sizeof(struct netrange)); + bcopy(sat->sat_zero, AA_SAT(aa)->sat_zero, sizeof(struct netrange)); + nnets = ntohs(nr.nr_lastnet) - ntohs(nr.nr_firstnet) + 1; + aa->aa_firstnet = nr.nr_firstnet; + aa->aa_lastnet = nr.nr_lastnet; /* XXX ALC */ #if 0 - printf("at_ifinit: %s: %u.%u range %u-%u phase %d\n", - ifp->if_name, - ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, - ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), - (aa->aa_flags & AFA_PHASE2) ? 2 : 1); + printf("at_ifinit: %s: %u.%u range %u-%u phase %d\n", + ifp->if_name, + ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, + ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), + (aa->aa_flags & AFA_PHASE2) ? 2 : 1); #endif - /* - * We could eliminate the need for a second phase 1 probe (post - * autoconf) if we check whether we're resetting the node. Note - * that phase 1 probes use only nodes, not net.node pairs. Under - * phase 2, both the net and node must be the same. - */ - if (ifp->if_flags & IFF_LOOPBACK) { - AA_SAT(aa)->sat_len = sat->sat_len; - AA_SAT(aa)->sat_family = AF_APPLETALK; - AA_SAT(aa)->sat_addr.s_net = sat->sat_addr.s_net; - AA_SAT(aa)->sat_addr.s_node = sat->sat_addr.s_node; -#if 0 - } else if (fp->if_flags & IFF_POINTOPOINT) { - /* unimplemented */ /* - * we'd have to copy the dstaddr field over from the sat - * but it's not clear that it would contain the right info.. + * We could eliminate the need for a second phase 1 probe (post + * autoconf) if we check whether we're resetting the node. Note + * that phase 1 probes use only nodes, not net.node pairs. Under + * phase 2, both the net and node must be the same. */ + if (ifp->if_flags & IFF_LOOPBACK) { + AA_SAT(aa)->sat_len = sat->sat_len; + AA_SAT(aa)->sat_family = AF_APPLETALK; + AA_SAT(aa)->sat_addr.s_net = sat->sat_addr.s_net; + AA_SAT(aa)->sat_addr.s_node = sat->sat_addr.s_node; +#if 0 + } else if (fp->if_flags & IFF_POINTOPOINT) { + /* unimplemented */ + /* + * we'd have to copy the dstaddr field over from the sat + * but it's not clear that it would contain the right info.. + */ #endif - } else { - /* - * We are a normal (probably ethernet) interface. - * apply the new address to the interface structures etc. - * We will probe this address on the net first, before - * applying it to ensure that it is free.. If it is not, then - * we will try a number of other randomly generated addresses - * in this net and then increment the net. etc.etc. until - * we find an unused address. - */ - aa->aa_flags |= AFA_PROBING; /* if not loopback we Must probe? */ - AA_SAT(aa)->sat_len = sizeof(struct sockaddr_at); - AA_SAT(aa)->sat_family = AF_APPLETALK; - if (aa->aa_flags & AFA_PHASE2) { - if (sat->sat_addr.s_net == ATADDR_ANYNET) { + } else { /* - * If we are phase 2, and the net was not specified - * then we select a random net within the supplied netrange. - * XXX use /dev/random? + * We are a normal (probably ethernet) interface. + * apply the new address to the interface structures etc. + * We will probe this address on the net first, before + * applying it to ensure that it is free.. If it is not, then + * we will try a number of other randomly generated addresses + * in this net and then increment the net. etc.etc. until + * we find an unused address. */ - if (nnets != 1) { - net = ntohs(nr.nr_firstnet) + time_second % (nnets - 1); + aa->aa_flags |= AFA_PROBING; /* not loopback we Must probe? */ + AA_SAT(aa)->sat_len = sizeof(struct sockaddr_at); + AA_SAT(aa)->sat_family = AF_APPLETALK; + if (aa->aa_flags & AFA_PHASE2) { + if (sat->sat_addr.s_net == ATADDR_ANYNET) { + /* + * If we are phase 2, and the net was not + * specified then we select a random net + * within the supplied netrange. + * XXX use /dev/random? + */ + if (nnets != 1) + net = ntohs(nr.nr_firstnet) + + time_second % (nnets - 1); + else + net = ntohs(nr.nr_firstnet); + } else { + /* + * if a net was supplied, then check that it + * is within the netrange. If it is not then + * replace the old values and return an error + */ + if (ntohs(sat->sat_addr.s_net) < + ntohs(nr.nr_firstnet) || + ntohs(sat->sat_addr.s_net) > + ntohs(nr.nr_lastnet)) { + aa->aa_addr = oldaddr; + aa->aa_firstnet = onr.nr_firstnet; + aa->aa_lastnet = onr.nr_lastnet; + return (EINVAL); + } + /* + * otherwise just use the new net number.. + */ + net = ntohs(sat->sat_addr.s_net); + } } else { - net = ntohs(nr.nr_firstnet); + /* + * we must be phase one, so just use whatever we were + * given. I guess it really isn't going to be + * used... RIGHT? + */ + net = ntohs(sat->sat_addr.s_net); } - } else { - /* - * if a net was supplied, then check that it is within - * the netrange. If it is not then replace the old values - * and return an error + + /* + * set the node part of the address into the ifaddr. + * If it's not specified, be random about it... + * XXX use /dev/random? */ - if (ntohs(sat->sat_addr.s_net) < ntohs(nr.nr_firstnet) || - ntohs(sat->sat_addr.s_net) > ntohs(nr.nr_lastnet)) { - aa->aa_addr = oldaddr; - aa->aa_firstnet = onr.nr_firstnet; - aa->aa_lastnet = onr.nr_lastnet; - return (EINVAL); + if (sat->sat_addr.s_node == ATADDR_ANYNODE) + AA_SAT(aa)->sat_addr.s_node = time_second; + else + AA_SAT(aa)->sat_addr.s_node = sat->sat_addr.s_node; + + /* + * Copy the phase. + */ + AA_SAT(aa)->sat_range.r_netrange.nr_phase = + ((aa->aa_flags & AFA_PHASE2) ? 2:1); + + /* + * step through the nets in the range + * starting at the (possibly random) start point. + */ + for (i = nnets, netinc = 1; i > 0; net = + ntohs(nr.nr_firstnet) + ((net - ntohs(nr.nr_firstnet) + + netinc) % nnets), i--) { + AA_SAT(aa)->sat_addr.s_net = htons(net); + + /* + * using a rather strange stepping method, + * stagger through the possible node addresses + * Once again, starting at the (possibly random) + * initial node address. + */ + for (j = 0, nodeinc = time_second | 1; j < 256; + j++, AA_SAT(aa)->sat_addr.s_node += nodeinc) { + if (AA_SAT(aa)->sat_addr.s_node > 253 || + AA_SAT(aa)->sat_addr.s_node < 1) + continue; + aa->aa_probcnt = 10; + + /* + * start off the probes as an asynchronous + * activity. though why wait 200mSec? + */ + aa->aa_ch = timeout(aarpprobe, (caddr_t)ifp, + hz / 5); + if (tsleep(aa, PPAUSE|PCATCH, "at_ifinit", + 0)) { + /* + * theoretically we shouldn't time + * out here so if we returned with an + * error.. + */ + printf("at_ifinit: why did this " + "happen?!\n"); + aa->aa_addr = oldaddr; + aa->aa_firstnet = onr.nr_firstnet; + aa->aa_lastnet = onr.nr_lastnet; + return (EINTR); + } + + /* + * The async activity should have woken us + * up. We need to see if it was successful + * in finding a free spot, or if we need to + * iterate to the next address to try. + */ + if ((aa->aa_flags & AFA_PROBING) == 0) + break; + } + + /* + * of course we need to break out through two loops... + */ + if ((aa->aa_flags & AFA_PROBING) == 0) + break; + /* reset node for next network */ + AA_SAT(aa)->sat_addr.s_node = time_second; } + /* - * otherwise just use the new net number.. + * if we are still trying to probe, then we have finished all + * the possible addresses, so we need to give up */ - net = ntohs(sat->sat_addr.s_net); - } - } else { - /* - * we must be phase one, so just use whatever we were given. - * I guess it really isn't going to be used... RIGHT? - */ - net = ntohs(sat->sat_addr.s_net); + if (aa->aa_flags & AFA_PROBING) { + aa->aa_addr = oldaddr; + aa->aa_firstnet = onr.nr_firstnet; + aa->aa_lastnet = onr.nr_lastnet; + return (EADDRINUSE); + } } /* - * set the node part of the address into the ifaddr. - * If it's not specified, be random about it... - * XXX use /dev/random? + * Now that we have selected an address, we need to tell the interface + * about it, just in case it needs to adjust something. */ - if (sat->sat_addr.s_node == ATADDR_ANYNODE) { - AA_SAT(aa)->sat_addr.s_node = time_second; - } else { - AA_SAT(aa)->sat_addr.s_node = sat->sat_addr.s_node; + if (ifp->if_ioctl != NULL && + (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)aa))) { + /* + * of course this could mean that it objects violently + * so if it does, we back out again.. + */ + aa->aa_addr = oldaddr; + aa->aa_firstnet = onr.nr_firstnet; + aa->aa_lastnet = onr.nr_lastnet; + return (error); } /* - * Copy the phase. + * set up the netmask part of the at_ifaddr + * and point the appropriate pointer in the ifaddr to it. + * probably pointless, but what the heck.. XXX */ - AA_SAT(aa)->sat_range.r_netrange.nr_phase - = ((aa->aa_flags & AFA_PHASE2) ? 2:1); + bzero(&aa->aa_netmask, sizeof(aa->aa_netmask)); + aa->aa_netmask.sat_len = sizeof(struct sockaddr_at); + aa->aa_netmask.sat_family = AF_APPLETALK; + aa->aa_netmask.sat_addr.s_net = 0xffff; + aa->aa_netmask.sat_addr.s_node = 0; + aa->aa_ifa.ifa_netmask =(struct sockaddr *) &(aa->aa_netmask); /* XXX */ - /* - * step through the nets in the range - * starting at the (possibly random) start point. + /* + * Initialize broadcast (or remote p2p) address */ - for (i = nnets, netinc = 1; i > 0; net = ntohs(nr.nr_firstnet) + - ((net - ntohs(nr.nr_firstnet) + netinc) % nnets), i--) { - AA_SAT(aa)->sat_addr.s_net = htons(net); - - /* - * using a rather strange stepping method, - * stagger through the possible node addresses - * Once again, starting at the (possibly random) - * initial node address. - */ - for (j = 0, nodeinc = time_second | 1; j < 256; - j++, AA_SAT(aa)->sat_addr.s_node += nodeinc) { - if (AA_SAT(aa)->sat_addr.s_node > 253 || - AA_SAT(aa)->sat_addr.s_node < 1) { - continue; - } - aa->aa_probcnt = 10; - - /* - * start off the probes as an asynchronous activity. - * though why wait 200mSec? - */ - aa->aa_ch = timeout(aarpprobe, (caddr_t)ifp, hz / 5); - if (tsleep(aa, PPAUSE|PCATCH, "at_ifinit", 0)) { - /* - * theoretically we shouldn't time out here - * so if we returned with an error.. - */ - printf("at_ifinit: why did this happen?!\n"); - aa->aa_addr = oldaddr; - aa->aa_firstnet = onr.nr_firstnet; - aa->aa_lastnet = onr.nr_lastnet; - return (EINTR); - } - - /* - * The async activity should have woken us up. - * We need to see if it was successful in finding - * a free spot, or if we need to iterate to the next - * address to try. - */ - if ((aa->aa_flags & AFA_PROBING) == 0) { - break; - } - } - - /* - * of course we need to break out through two loops... - */ - if ((aa->aa_flags & AFA_PROBING) == 0) { - break; - } - /* reset node for next network */ - AA_SAT(aa)->sat_addr.s_node = time_second; + bzero(&aa->aa_broadaddr, sizeof(aa->aa_broadaddr)); + aa->aa_broadaddr.sat_len = sizeof(struct sockaddr_at); + aa->aa_broadaddr.sat_family = AF_APPLETALK; + + aa->aa_ifa.ifa_metric = ifp->if_metric; + if (ifp->if_flags & IFF_BROADCAST) { + aa->aa_broadaddr.sat_addr.s_net = htons(0); + aa->aa_broadaddr.sat_addr.s_node = 0xff; + aa->aa_ifa.ifa_broadaddr = (struct sockaddr *) + &aa->aa_broadaddr; + /* add the range of routes needed */ + error = aa_dorangeroute(&aa->aa_ifa, ntohs(aa->aa_firstnet), + ntohs(aa->aa_lastnet), RTM_ADD); + } else if (ifp->if_flags & IFF_POINTOPOINT) { + struct at_addr rtaddr, rtmask; + + bzero(&rtaddr, sizeof(rtaddr)); + bzero(&rtmask, sizeof(rtmask)); + /* fill in the far end if we know it here XXX */ + aa->aa_ifa.ifa_dstaddr = (struct sockaddr *) &aa->aa_dstaddr; + error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask); + } else if (ifp->if_flags & IFF_LOOPBACK) { + struct at_addr rtaddr, rtmask; + + bzero(&rtaddr, sizeof(rtaddr)); + bzero(&rtmask, sizeof(rtmask)); + rtaddr.s_net = AA_SAT(aa)->sat_addr.s_net; + rtaddr.s_node = AA_SAT(aa)->sat_addr.s_node; + rtmask.s_net = 0xffff; + /* XXX should not be so.. should be HOST route */ + rtmask.s_node = 0x0; + error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask); } /* - * if we are still trying to probe, then we have finished all - * the possible addresses, so we need to give up + * set the address of our "check if this addr is ours" routine. */ + aa->aa_ifa.ifa_claim_addr = aa_claim_addr; - if (aa->aa_flags & AFA_PROBING) { - aa->aa_addr = oldaddr; - aa->aa_firstnet = onr.nr_firstnet; - aa->aa_lastnet = onr.nr_lastnet; - return (EADDRINUSE); + /* + * of course if we can't add these routes we back out, but it's + * getting risky by now XXX + */ + if (error) { + at_scrub(ifp, aa); + aa->aa_addr = oldaddr; + aa->aa_firstnet = onr.nr_firstnet; + aa->aa_lastnet = onr.nr_lastnet; + return (error); } - } - /* - * Now that we have selected an address, we need to tell the interface - * about it, just in case it needs to adjust something. - */ - if (ifp->if_ioctl != NULL&& - (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)aa))) { /* - * of course this could mean that it objects violently - * so if it does, we back out again.. + * note that the address has a route associated with it.... */ - aa->aa_addr = oldaddr; - aa->aa_firstnet = onr.nr_firstnet; - aa->aa_lastnet = onr.nr_lastnet; - return (error); - } - - /* - * set up the netmask part of the at_ifaddr - * and point the appropriate pointer in the ifaddr to it. - * probably pointless, but what the heck.. XXX - */ - bzero(&aa->aa_netmask, sizeof(aa->aa_netmask)); - aa->aa_netmask.sat_len = sizeof(struct sockaddr_at); - aa->aa_netmask.sat_family = AF_APPLETALK; - aa->aa_netmask.sat_addr.s_net = 0xffff; - aa->aa_netmask.sat_addr.s_node = 0; - aa->aa_ifa.ifa_netmask =(struct sockaddr *) &(aa->aa_netmask); /* XXX */ - - /* - * Initialize broadcast (or remote p2p) address - */ - bzero(&aa->aa_broadaddr, sizeof(aa->aa_broadaddr)); - aa->aa_broadaddr.sat_len = sizeof(struct sockaddr_at); - aa->aa_broadaddr.sat_family = AF_APPLETALK; - - aa->aa_ifa.ifa_metric = ifp->if_metric; - if (ifp->if_flags & IFF_BROADCAST) { - aa->aa_broadaddr.sat_addr.s_net = htons(0); - aa->aa_broadaddr.sat_addr.s_node = 0xff; - aa->aa_ifa.ifa_broadaddr = (struct sockaddr *) &aa->aa_broadaddr; - /* add the range of routes needed */ - error = aa_dorangeroute(&aa->aa_ifa, - ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), RTM_ADD); - } - else if (ifp->if_flags & IFF_POINTOPOINT) { - struct at_addr rtaddr, rtmask; - - bzero(&rtaddr, sizeof(rtaddr)); - bzero(&rtmask, sizeof(rtmask)); - /* fill in the far end if we know it here XXX */ - aa->aa_ifa.ifa_dstaddr = (struct sockaddr *) &aa->aa_dstaddr; - error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask); - } - else if (ifp->if_flags & IFF_LOOPBACK) { - struct at_addr rtaddr, rtmask; - - bzero(&rtaddr, sizeof(rtaddr)); - bzero(&rtmask, sizeof(rtmask)); - rtaddr.s_net = AA_SAT(aa)->sat_addr.s_net; - rtaddr.s_node = AA_SAT(aa)->sat_addr.s_node; - rtmask.s_net = 0xffff; - rtmask.s_node = 0x0; /* XXX should not be so.. should be HOST route */ - error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask); - } - - - /* - * set the address of our "check if this addr is ours" routine. - */ - aa->aa_ifa.ifa_claim_addr = aa_claim_addr; - - /* - * of course if we can't add these routes we back out, but it's getting - * risky by now XXX - */ - if (error) { - at_scrub(ifp, aa); - aa->aa_addr = oldaddr; - aa->aa_firstnet = onr.nr_firstnet; - aa->aa_lastnet = onr.nr_lastnet; - return (error); - } - - /* - * note that the address has a route associated with it.... - */ - aa->aa_ifa.ifa_flags |= IFA_ROUTE; - aa->aa_flags |= AFA_ROUTE; - return (0); + aa->aa_ifa.ifa_flags |= IFA_ROUTE; + aa->aa_flags |= AFA_ROUTE; + return (0); } /* * check whether a given address is a broadcast address for us.. */ int -at_broadcast(sat) - struct sockaddr_at *sat; +at_broadcast(struct sockaddr_at *sat) { - struct at_ifaddr *aa; + struct at_ifaddr *aa; - /* - * If the node is not right, it can't be a broadcast - */ - if (sat->sat_addr.s_node != ATADDR_BCAST) { - return (0); - } - - /* - * If the node was right then if the net is right, it's a broadcast - */ - if (sat->sat_addr.s_net == ATADDR_ANYNET) { - return (1); - } - - /* - * failing that, if the net is one we have, it's a broadcast as well. - */ - for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { - if ((aa->aa_ifp->if_flags & IFF_BROADCAST) - && (ntohs(sat->sat_addr.s_net) >= ntohs(aa->aa_firstnet) - && ntohs(sat->sat_addr.s_net) <= ntohs(aa->aa_lastnet))) { + /* + * If the node is not right, it can't be a broadcast + */ + if (sat->sat_addr.s_node != ATADDR_BCAST) + return (0); + + /* + * If the node was right then if the net is right, it's a broadcast + */ + if (sat->sat_addr.s_net == ATADDR_ANYNET) + return (1); + + /* + * failing that, if the net is one we have, it's a broadcast as well. + */ + for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) { + if ((aa->aa_ifp->if_flags & IFF_BROADCAST) + && (ntohs(sat->sat_addr.s_net) >= ntohs(aa->aa_firstnet) + && ntohs(sat->sat_addr.s_net) <= ntohs(aa->aa_lastnet))) return (1); } - } - return (0); + return (0); } /* @@ -711,79 +702,77 @@ aa_dorangeroute(struct ifaddr *ifa, u_int bot, u_int top, int cmd) while (bot <= top) { mask1 = 1; - while (((bot & ~mask1) >= bot) - && ((bot | mask1) <= top)) { + while (((bot & ~mask1) >= bot) && ((bot | mask1) <= top)) { mask1 <<= 1; mask1 |= 1; } mask1 >>= 1; mask.s_net = htons(~mask1); addr.s_net = htons(bot); - if(cmd == RTM_ADD) { - error = aa_addsingleroute(ifa,&addr,&mask); + if (cmd == RTM_ADD) { + error = aa_addsingleroute(ifa,&addr,&mask); if (error) { /* XXX clean up? */ return (error); } - } else { + } else error = aa_delsingleroute(ifa,&addr,&mask); - } bot = (bot | mask1) + 1; } return (0); } static int -aa_addsingleroute(struct ifaddr *ifa, - struct at_addr *addr, struct at_addr *mask) +aa_addsingleroute(struct ifaddr *ifa, struct at_addr *addr, + struct at_addr *mask) { - int error; + int error; #if 0 - printf("aa_addsingleroute: %x.%x mask %x.%x ...\n", - ntohs(addr->s_net), addr->s_node, - ntohs(mask->s_net), mask->s_node); + printf("aa_addsingleroute: %x.%x mask %x.%x ...\n", + ntohs(addr->s_net), addr->s_node, ntohs(mask->s_net), + mask->s_node); #endif - error = aa_dosingleroute(ifa, addr, mask, RTM_ADD, RTF_UP); - if (error) - printf("aa_addsingleroute: error %d\n", error); - return (error); + error = aa_dosingleroute(ifa, addr, mask, RTM_ADD, RTF_UP); + if (error) + printf("aa_addsingleroute: error %d\n", error); + return (error); } static int -aa_delsingleroute(struct ifaddr *ifa, - struct at_addr *addr, struct at_addr *mask) +aa_delsingleroute(struct ifaddr *ifa, struct at_addr *addr, + struct at_addr *mask) { - int error; + int error; - error = aa_dosingleroute(ifa, addr, mask, RTM_DELETE, 0); - if (error) - printf("aa_delsingleroute: error %d\n", error); - return (error); + error = aa_dosingleroute(ifa, addr, mask, RTM_DELETE, 0); + if (error) + printf("aa_delsingleroute: error %d\n", error); + return (error); } static int -aa_dosingleroute(struct ifaddr *ifa, - struct at_addr *at_addr, struct at_addr *at_mask, int cmd, int flags) +aa_dosingleroute(struct ifaddr *ifa, struct at_addr *at_addr, + struct at_addr *at_mask, int cmd, int flags) { - struct sockaddr_at addr, mask; - - bzero(&addr, sizeof(addr)); - bzero(&mask, sizeof(mask)); - addr.sat_family = AF_APPLETALK; - addr.sat_len = sizeof(struct sockaddr_at); - addr.sat_addr.s_net = at_addr->s_net; - addr.sat_addr.s_node = at_addr->s_node; - mask.sat_family = AF_APPLETALK; - mask.sat_len = sizeof(struct sockaddr_at); - mask.sat_addr.s_net = at_mask->s_net; - mask.sat_addr.s_node = at_mask->s_node; - if (at_mask->s_node) - flags |= RTF_HOST; - return (rtrequest(cmd, (struct sockaddr *) &addr, - (flags & RTF_HOST)?(ifa->ifa_dstaddr):(ifa->ifa_addr), - (struct sockaddr *) &mask, flags, NULL)); + struct sockaddr_at addr, mask; + + bzero(&addr, sizeof(addr)); + bzero(&mask, sizeof(mask)); + addr.sat_family = AF_APPLETALK; + addr.sat_len = sizeof(struct sockaddr_at); + addr.sat_addr.s_net = at_addr->s_net; + addr.sat_addr.s_node = at_addr->s_node; + mask.sat_family = AF_APPLETALK; + mask.sat_len = sizeof(struct sockaddr_at); + mask.sat_addr.s_net = at_mask->s_net; + mask.sat_addr.s_node = at_mask->s_node; + if (at_mask->s_node) + flags |= RTF_HOST; + return (rtrequest(cmd, (struct sockaddr *) &addr, + (flags & RTF_HOST)?(ifa->ifa_dstaddr):(ifa->ifa_addr), + (struct sockaddr *) &mask, flags, NULL)); } #if 0 @@ -791,28 +780,27 @@ aa_dosingleroute(struct ifaddr *ifa, static void aa_clean(void) { - struct at_ifaddr *aa; - struct ifaddr *ifa; - struct ifnet *ifp; - - while ((aa = at_ifaddr_list) != NULL) { - ifp = aa->aa_ifp; - at_scrub(ifp, aa); - at_ifaddr_list = aa->aa_next; - if ((ifa = ifp->if_addrlist) == (struct ifaddr *)aa) { - ifp->if_addrlist = ifa->ifa_next; - } else { - while (ifa->ifa_next && - (ifa->ifa_next != (struct ifaddr *)aa)) { - ifa = ifa->ifa_next; - } - if (ifa->ifa_next) { - ifa->ifa_next = ((struct ifaddr *)aa)->ifa_next; - } else { - panic("at_entry"); - } + struct at_ifaddr *aa; + struct ifaddr *ifa; + struct ifnet *ifp; + + while ((aa = at_ifaddr_list) != NULL) { + ifp = aa->aa_ifp; + at_scrub(ifp, aa); + at_ifaddr_list = aa->aa_next; + if ((ifa = ifp->if_addrlist) == (struct ifaddr *)aa) + ifp->if_addrlist = ifa->ifa_next; + else { + while (ifa->ifa_next && + (ifa->ifa_next != (struct ifaddr *)aa)) + ifa = ifa->ifa_next; + if (ifa->ifa_next) + ifa->ifa_next = + ((struct ifaddr *)aa)->ifa_next; + else + panic("at_entry"); + } } - } } #endif @@ -827,6 +815,7 @@ aa_claim_addr(struct ifaddr *ifa, struct sockaddr *gw0) case 1: if(addr->sat_range.r_netrange.nr_phase == 1) return (1); + case 0: case 2: /* @@ -835,13 +824,12 @@ aa_claim_addr(struct ifaddr *ifa, struct sockaddr *gw0) * then it's ours. */ if ((addr->sat_addr.s_net == gw->sat_addr.s_net) - || ((addr->sat_range.r_netrange.nr_lastnet) - && (ntohs(gw->sat_addr.s_net) - >= ntohs(addr->sat_range.r_netrange.nr_firstnet)) - && (ntohs(gw->sat_addr.s_net) - <= ntohs(addr->sat_range.r_netrange.nr_lastnet)))) { + || ((addr->sat_range.r_netrange.nr_lastnet) + && (ntohs(gw->sat_addr.s_net) >= + ntohs(addr->sat_range.r_netrange.nr_firstnet)) + && (ntohs(gw->sat_addr.s_net) <= + ntohs(addr->sat_range.r_netrange.nr_lastnet)))) return (1); - } break; default: printf("atalk: bad phase\n"); |