Remove AppleTalk support

Prepare update to FreeBSD 11.
This commit is contained in:
Sebastian Huber 2016-10-07 07:24:30 +02:00
parent 40f202da4e
commit a9d38f5306
24 changed files with 0 additions and 4469 deletions

View File

@ -209,7 +209,6 @@ def headerPaths():
('freebsd/sys/cam', '*.h', 'cam'),
('freebsd/sys/net', '*.h', 'net'),
('freebsd/sys/net80211', '*.h', 'net80211'),
('freebsd/sys/netatalk', '*.h', 'netatalk'),
('freebsd/sys/netinet', '*.h', 'netinet'),
('freebsd/sys/netinet6', '*.h', 'netinet6'),
('freebsd/sys/netipsec', '*.h', 'netipsec'),

View File

@ -1,192 +0,0 @@
#include <machine/rtems-bsd-user-space.h>
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netatalk/at.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include "ifconfig.h"
static struct netrange at_nr; /* AppleTalk net range */
static struct ifaliasreq at_addreq;
/* XXX FIXME -- should use strtoul for better parsing. */
static void
setatrange(const char *range, int dummy __unused, int s,
const struct afswtch *afp)
{
u_int first = 123, last = 123;
if (sscanf(range, "%u-%u", &first, &last) != 2
|| first == 0 || first > 0xffff
|| last == 0 || last > 0xffff || first > last)
errx(1, "%s: illegal net range: %u-%u", range, first, last);
at_nr.nr_firstnet = htons(first);
at_nr.nr_lastnet = htons(last);
}
static void
setatphase(const char *phase, int dummy __unused, int s,
const struct afswtch *afp)
{
if (!strcmp(phase, "1"))
at_nr.nr_phase = 1;
else if (!strcmp(phase, "2"))
at_nr.nr_phase = 2;
else
errx(1, "%s: illegal phase", phase);
}
static void
at_status(int s __unused, const struct ifaddrs *ifa)
{
struct sockaddr_at *sat, null_sat;
struct netrange *nr;
memset(&null_sat, 0, sizeof(null_sat));
sat = (struct sockaddr_at *)ifa->ifa_addr;
if (sat == NULL)
return;
nr = &sat->sat_range.r_netrange;
printf("\tatalk %d.%d range %d-%d phase %d",
ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
if (ifa->ifa_flags & IFF_POINTOPOINT) {
sat = (struct sockaddr_at *)ifa->ifa_dstaddr;
if (sat == NULL)
sat = &null_sat;
printf("--> %d.%d",
ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
}
if (ifa->ifa_flags & IFF_BROADCAST) {
sat = (struct sockaddr_at *)ifa->ifa_broadaddr;
if (sat != NULL)
printf(" broadcast %d.%d",
ntohs(sat->sat_addr.s_net),
sat->sat_addr.s_node);
}
putchar('\n');
}
static void
at_getaddr(const char *addr, int which)
{
struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr;
u_int net, node;
sat->sat_family = AF_APPLETALK;
sat->sat_len = sizeof(*sat);
if (which == MASK)
errx(1, "AppleTalk does not use netmasks");
if (sscanf(addr, "%u.%u", &net, &node) != 2
|| net > 0xffff || node > 0xfe)
errx(1, "%s: illegal address", addr);
sat->sat_addr.s_net = htons(net);
sat->sat_addr.s_node = node;
}
static void
at_postproc(int s, const struct afswtch *afp)
{
struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr;
if (at_nr.nr_phase == 0)
at_nr.nr_phase = 2; /* Default phase 2 */
if (at_nr.nr_firstnet == 0)
at_nr.nr_firstnet = /* Default range of one */
at_nr.nr_lastnet = sat->sat_addr.s_net;
printf("\tatalk %d.%d range %d-%d phase %d\n",
ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet),
at_nr.nr_phase);
if ((u_short) ntohs(at_nr.nr_firstnet) >
(u_short) ntohs(sat->sat_addr.s_net)
|| (u_short) ntohs(at_nr.nr_lastnet) <
(u_short) ntohs(sat->sat_addr.s_net))
errx(1, "AppleTalk address is not in range");
sat->sat_range.r_netrange = at_nr;
}
static struct cmd atalk_cmds[] = {
DEF_CMD_ARG("range", setatrange),
DEF_CMD_ARG("phase", setatphase),
};
static struct afswtch af_atalk = {
.af_name = "atalk",
.af_af = AF_APPLETALK,
.af_status = at_status,
.af_getaddr = at_getaddr,
.af_postproc = at_postproc,
.af_difaddr = SIOCDIFADDR,
.af_aifaddr = SIOCAIFADDR,
.af_ridreq = &at_addreq,
.af_addreq = &at_addreq,
};
#ifndef __rtems__
static __constructor void
#else /* __rtems__ */
void
#endif /* __rtems__ */
atalk_ctor(void)
{
#ifdef __rtems__
memset(&at_nr, 0, sizeof(at_nr));
memset(&at_addreq, 0, sizeof(at_addreq));
#endif /* __rtems__ */
#define N(a) (sizeof(a) / sizeof(a[0]))
size_t i;
for (i = 0; i < N(atalk_cmds); i++)
cmd_register(&atalk_cmds[i]);
af_register(&af_atalk);
#undef N
}

View File

@ -171,7 +171,6 @@ int rtems_bsd_command_ifconfig(int argc, char *argv[])
ifconfig_ctor();
atalk_ctor();
bridge_ctor();
carp_ctor();
clone_ctor();

View File

@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netatalk/at.h>
#include <arpa/inet.h>
#include <netdb.h>
@ -110,7 +109,6 @@ struct rt_ctx {
#ifdef INET6
struct sockaddr_in6 sin6;
#endif
struct sockaddr_at sat;
struct sockaddr_dl sdl;
struct sockaddr_inarp sinarp;
struct sockaddr_storage ss; /* added to avoid memory overrun */
@ -144,8 +142,6 @@ struct rt_ctx rt_ctx;
typedef union sockunion *sup;
static int atalk_aton(const char *, struct at_addr *);
static char *atalk_ntoa(struct at_addr, char [20]);
static void bprintf(FILE *, int, const char *);
static void flushroutes(struct rt_ctx *, int argc, char *argv[]);
static int flushroutes_fib(struct rt_ctx *, int);
@ -637,7 +633,6 @@ static const char *
routename(struct rt_ctx *c, struct sockaddr *sa)
{
const char *cp;
char atalk_buf[20];
struct hostent *hp;
int n;
@ -714,11 +709,6 @@ routename(struct rt_ctx *c, struct sockaddr *sa)
}
#endif
case AF_APPLETALK:
(void) snprintf(c->rt_line, sizeof(c->rt_line), "atalk %s",
atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr, atalk_buf));
break;
case AF_LINK:
return (link_ntoa((struct sockaddr_dl *)sa));
@ -748,7 +738,6 @@ const char *
netname(struct rt_ctx *c, struct sockaddr *sa)
{
const char *cp = NULL;
char atalk_buf[20];
struct netent *np = NULL;
u_long net, mask;
u_long i;
@ -840,11 +829,6 @@ netname(struct rt_ctx *c, struct sockaddr *sa)
}
#endif
case AF_APPLETALK:
(void) snprintf(c->net_line, sizeof(c->net_line), "atalk %s",
atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr, atalk_buf));
break;
case AF_LINK:
return (link_ntoa((struct sockaddr_dl *)sa));
@ -942,10 +926,6 @@ newroute(struct rt_ctx *c, int argc, char **argv)
c->aflen = sizeof(struct sockaddr_in6);
break;
#endif
case K_ATALK:
c->af = AF_APPLETALK;
c->aflen = sizeof(struct sockaddr_at);
break;
case K_SA:
c->af = PF_ROUTE;
c->aflen = sizeof(union sockunion);
@ -1423,12 +1403,6 @@ getaddr(struct rt_ctx *c, int which, char *str, struct hostent **hpp, int nrflag
}
#endif /* INET6 */
case AF_APPLETALK:
if (!atalk_aton(str, &su->sat.sat_addr))
errx(EX_NOHOST, "bad address: %s", str);
c->rtm_addrs |= RTA_NETMASK;
return(c->forcehost || su->sat.sat_addr.s_node != 0);
case AF_LINK:
link_addr(str, &su->sdl);
return (1);
@ -2034,8 +2008,6 @@ keyword(const char *cp)
static void
sodump(sup su, const char *which)
{
char atalk_buf[20];
switch (su->sa.sa_family) {
case AF_LINK:
(void) printf("%s: link %s; ",
@ -2045,10 +2017,6 @@ sodump(sup su, const char *which)
(void) printf("%s: inet %s; ",
which, inet_ntoa(su->sin.sin_addr));
break;
case AF_APPLETALK:
(void) printf("%s: atalk %s; ",
which, atalk_ntoa(su->sat.sat_addr, atalk_buf));
break;
}
(void) fflush(stdout);
}
@ -2103,23 +2071,3 @@ sockaddr(char *addr, struct sockaddr *sa)
} while (cp < cplim);
sa->sa_len = cp - (char *)sa;
}
static int
atalk_aton(const char *text, struct at_addr *addr)
{
u_int net, node;
if (sscanf(text, "%u.%u", &net, &node) != 2
|| net > 0xffff || node > 0xff)
return(0);
addr->s_net = htons(net);
addr->s_node = node;
return(1);
}
static char *
atalk_ntoa(struct at_addr at, char buf[20])
{
(void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node);
return(buf);
}

View File

@ -1,726 +0,0 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright (c) 2004-2009 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Copyright (c) 1990,1991,1994 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
*
* $FreeBSD$
*/
#include <rtems/bsd/local/opt_atalk.h>
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#undef s_net
#include <netinet/if_ether.h>
#include <netatalk/at.h>
#include <netatalk/at_var.h>
#include <netatalk/aarp.h>
#include <netatalk/phase2.h>
#include <netatalk/at_extern.h>
#include <security/mac/mac_framework.h>
static void aarptfree(struct aarptab *aat);
static void at_aarpinput(struct ifnet *ifp, struct mbuf *m);
#define AARPTAB_BSIZ 9
#define AARPTAB_NB 19
#define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB)
static struct aarptab aarptab[AARPTAB_SIZE];
struct mtx aarptab_mtx;
MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF);
#define AARPTAB_HASH(a) ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB)
#define AARPTAB_LOOK(aat, addr) do { \
int n; \
\
AARPTAB_LOCK_ASSERT(); \
aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
for (n = 0; n < AARPTAB_BSIZ; n++, aat++) { \
if (aat->aat_ataddr.s_net == (addr).s_net && \
aat->aat_ataddr.s_node == (addr).s_node) \
break; \
} \
if (n >= AARPTAB_BSIZ) \
aat = NULL; \
} while (0)
#define AARPT_AGE (60 * 1)
#define AARPT_KILLC 20
#define AARPT_KILLI 3
static const u_char atmulticastaddr[6] = {
0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
};
u_char at_org_code[3] = {
0x08, 0x00, 0x07,
};
const u_char aarp_org_code[3] = {
0x00, 0x00, 0x00,
};
static struct callout_handle aarptimer_ch =
CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
static void
aarptimer(void *ignored)
{
struct aarptab *aat;
int i;
aarptimer_ch = timeout(aarptimer, NULL, AARPT_AGE * hz);
aat = aarptab;
AARPTAB_LOCK();
for (i = 0; i < AARPTAB_SIZE; i++, aat++) {
if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM))
continue;
if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ?
AARPT_KILLC : AARPT_KILLI))
continue;
aarptfree(aat);
}
AARPTAB_UNLOCK();
}
/*
* Search through the network addresses to find one that includes the given
* network. Remember to take netranges into consideration.
*
* The _locked variant relies on the caller holding the at_ifaddr lock; the
* unlocked variant returns a reference that the caller must dispose of.
*/
struct at_ifaddr *
at_ifawithnet_locked(struct sockaddr_at *sat)
{
struct at_ifaddr *aa;
struct sockaddr_at *sat2;
AT_IFADDR_LOCK_ASSERT();
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
sat2 = &(aa->aa_addr);
if (sat2->sat_addr.s_net == sat->sat_addr.s_net)
break;
if ((aa->aa_flags & AFA_PHASE2) &&
(ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net)) &&
(ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net)))
break;
}
return (aa);
}
struct at_ifaddr *
at_ifawithnet(struct sockaddr_at *sat)
{
struct at_ifaddr *aa;
AT_IFADDR_RLOCK();
aa = at_ifawithnet_locked(sat);
if (aa != NULL)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
return (aa);
}
static void
aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat)
{
struct mbuf *m;
struct ether_header *eh;
struct ether_aarp *ea;
struct at_ifaddr *aa;
struct llc *llc;
struct sockaddr sa;
AARPTAB_UNLOCK_ASSERT();
m = m_gethdr(M_DONTWAIT, MT_DATA);
if (m == NULL)
return;
#ifdef MAC
mac_netatalk_aarp_send(ifp, m);
#endif
m->m_len = sizeof(*ea);
m->m_pkthdr.len = sizeof(*ea);
MH_ALIGN(m, sizeof(*ea));
ea = mtod(m, struct ether_aarp *);
bzero((caddr_t)ea, sizeof(*ea));
ea->aarp_hrd = htons(AARPHRD_ETHER);
ea->aarp_pro = htons(ETHERTYPE_AT);
ea->aarp_hln = sizeof(ea->aarp_sha);
ea->aarp_pln = sizeof(ea->aarp_spu);
ea->aarp_op = htons(AARPOP_REQUEST);
bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha));
/*
* We need to check whether the output ethernet type should be phase
* 1 or 2. We have the interface that we'll be sending the aarp out.
* We need to find an AppleTalk network on that interface with the
* same address as we're looking for. If the net is phase 2,
* generate an 802.2 and SNAP header.
*/
aa = at_ifawithnet(sat);
if (aa == NULL) {
m_freem(m);
return;
}
eh = (struct ether_header *)sa.sa_data;
if (aa->aa_flags & AFA_PHASE2) {
bcopy(atmulticastaddr, eh->ether_dhost,
sizeof(eh->ether_dhost));
eh->ether_type = htons(sizeof(struct llc) +
sizeof(struct ether_aarp));
M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
if (m == NULL) {
ifa_free(&aa->aa_ifa);
return;
}
llc = mtod(m, struct llc *);
llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
llc->llc_control = LLC_UI;
bcopy(aarp_org_code, llc->llc_org_code,
sizeof(aarp_org_code));
llc->llc_ether_type = htons(ETHERTYPE_AARP);
bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
sizeof(ea->aarp_spnet));
bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet,
sizeof(ea->aarp_tpnet));
ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node;
ea->aarp_tpnode = sat->sat_addr.s_node;
} else {
bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
sizeof(eh->ether_dhost));
eh->ether_type = htons(ETHERTYPE_AARP);
ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node;
ea->aarp_tpa = sat->sat_addr.s_node;
}
#ifdef NETATALKDEBUG
printf("aarp: sending request for %u.%u\n",
ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node);
#endif /* NETATALKDEBUG */
ifa_free(&aa->aa_ifa);
sa.sa_len = sizeof(struct sockaddr);
sa.sa_family = AF_UNSPEC;
ifp->if_output(ifp, m, &sa, NULL);
}
int
aarpresolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr_at *destsat,
u_char *desten)
{
struct at_ifaddr *aa;
struct aarptab *aat;
AT_IFADDR_RLOCK();
if (at_broadcast(destsat)) {
m->m_flags |= M_BCAST;
if ((aa = at_ifawithnet_locked(destsat)) == NULL) {
AT_IFADDR_RUNLOCK();
m_freem(m);
return (0);
}
if (aa->aa_flags & AFA_PHASE2)
bcopy(atmulticastaddr, (caddr_t)desten,
sizeof(atmulticastaddr));
else
bcopy(ifp->if_broadcastaddr, (caddr_t)desten,
sizeof(ifp->if_addrlen));
AT_IFADDR_RUNLOCK();
return (1);
}
AT_IFADDR_RUNLOCK();
AARPTAB_LOCK();
AARPTAB_LOOK(aat, destsat->sat_addr);
if (aat == NULL) {
/* No entry. */
aat = aarptnew(&destsat->sat_addr);
/* We should fail more gracefully. */
if (aat == NULL)
panic("aarpresolve: no free entry");
goto done;
}
/* Found an entry. */
aat->aat_timer = 0;
if (aat->aat_flags & ATF_COM) {
/* Entry is COMplete. */
bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten,
sizeof(aat->aat_enaddr));
AARPTAB_UNLOCK();
return (1);
}
/* Entry has not completed. */
if (aat->aat_hold)
m_freem(aat->aat_hold);
done:
aat->aat_hold = m;
AARPTAB_UNLOCK();
aarpwhohas(ifp, destsat);
return (0);
}
void
aarpintr(struct mbuf *m)
{
struct arphdr *ar;
struct ifnet *ifp;
ifp = m->m_pkthdr.rcvif;
if (ifp->if_flags & IFF_NOARP)
goto out;
if (m->m_len < sizeof(struct arphdr))
goto out;
ar = mtod(m, struct arphdr *);
if (ntohs(ar->ar_hrd) != AARPHRD_ETHER)
goto out;
if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln +
2 * ar->ar_pln)
goto out;
switch(ntohs(ar->ar_pro)) {
case ETHERTYPE_AT:
at_aarpinput(ifp, m);
return;
default:
break;
}
out:
m_freem(m);
}
static void
at_aarpinput(struct ifnet *ifp, struct mbuf *m)
{
struct ether_aarp *ea;
struct at_ifaddr *aa;
struct aarptab *aat;
struct ether_header *eh;
struct llc *llc;
struct sockaddr_at sat;
struct sockaddr sa;
struct at_addr spa, tpa, ma;
int op;
u_short net;
ea = mtod(m, struct ether_aarp *);
/* Check to see if from my hardware address. */
if (!bcmp((caddr_t)ea->aarp_sha, IF_LLADDR(ifp), ETHER_ADDR_LEN)) {
m_freem(m);
return;
}
/* Don't accept requests from broadcast address. */
if (!bcmp(ea->aarp_sha, ifp->if_broadcastaddr, ifp->if_addrlen)) {
log(LOG_ERR, "aarp: source link address is broadcast\n");
m_freem(m);
return;
}
op = ntohs(ea->aarp_op);
bcopy(ea->aarp_tpnet, &net, sizeof(net));
if (net != 0) {
/* Should be ATADDR_ANYNET? */
sat.sat_len = sizeof(struct sockaddr_at);
sat.sat_family = AF_APPLETALK;
sat.sat_addr.s_net = net;
aa = at_ifawithnet(&sat);
if (aa == NULL) {
m_freem(m);
return;
}
bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net));
bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net));
} else {
/*
* Since we don't know the net, we just look for the first
* phase 1 address on the interface.
*/
IF_ADDR_RLOCK(ifp);
for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead);
aa;
aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
(aa->aa_flags & AFA_PHASE2) == 0) {
break;
}
}
if (aa == NULL) {
IF_ADDR_RUNLOCK(ifp);
m_freem(m);
return;
}
ifa_ref(&aa->aa_ifa);
IF_ADDR_RUNLOCK(ifp);
tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
}
spa.s_node = ea->aarp_spnode;
tpa.s_node = ea->aarp_tpnode;
ma.s_net = AA_SAT(aa)->sat_addr.s_net;
ma.s_node = AA_SAT(aa)->sat_addr.s_node;
/*
* This looks like it's from us.
*/
if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
if (aa->aa_flags & AFA_PROBING) {
/*
* We're probing, someone either responded to our
* probe, or probed for the same address we'd like to
* use. Change the address we're probing for.
*/
callout_stop(&aa->aa_callout);
wakeup(aa);
ifa_free(&aa->aa_ifa);
m_freem(m);
return;
} else if (op != AARPOP_PROBE) {
/*
* This is not a probe, and we're not probing. This
* means that someone's saying they have the same
* source address as the one we're using. Get upset.
*/
ifa_free(&aa->aa_ifa);
log(LOG_ERR,
"aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
ea->aarp_sha[0], ea->aarp_sha[1],
ea->aarp_sha[2], ea->aarp_sha[3],
ea->aarp_sha[4], ea->aarp_sha[5]);
m_freem(m);
return;
}
}
AARPTAB_LOCK();
AARPTAB_LOOK(aat, spa);
if (aat != NULL) {
if (op == AARPOP_PROBE) {
/*
* Someone's probing for spa, dealocate the one we've
* got, so that if the prober keeps the address,
* we'll be able to arp for him.
*/
aarptfree(aat);
AARPTAB_UNLOCK();
ifa_free(&aa->aa_ifa);
m_freem(m);
return;
}
bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
sizeof(ea->aarp_sha));
aat->aat_flags |= ATF_COM;
if (aat->aat_hold) {
struct mbuf *mhold = aat->aat_hold;
aat->aat_hold = NULL;
AARPTAB_UNLOCK();
sat.sat_len = sizeof(struct sockaddr_at);
sat.sat_family = AF_APPLETALK;
sat.sat_addr = spa;
(*ifp->if_output)(ifp, mhold,
(struct sockaddr *)&sat, NULL); /* XXX */
} else
AARPTAB_UNLOCK();
} else if ((tpa.s_net == ma.s_net) && (tpa.s_node == ma.s_node)
&& (op != AARPOP_PROBE) && ((aat = aarptnew(&spa)) != NULL)) {
bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
sizeof(ea->aarp_sha));
aat->aat_flags |= ATF_COM;
AARPTAB_UNLOCK();
} else
AARPTAB_UNLOCK();
/*
* Don't respond to responses, and never respond if we're still
* probing.
*/
if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
ifa_free(&aa->aa_ifa);
m_freem(m);
return;
}
bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha,
sizeof(ea->aarp_sha));
bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha, sizeof(ea->aarp_sha));
/* XXX */
eh = (struct ether_header *)sa.sa_data;
bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost,
sizeof(eh->ether_dhost));
if (aa->aa_flags & AFA_PHASE2) {
eh->ether_type = htons(sizeof(struct llc) +
sizeof(struct ether_aarp));
M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
if (m == NULL) {
ifa_free(&aa->aa_ifa);
return;
}
llc = mtod(m, struct llc *);
llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
llc->llc_control = LLC_UI;
bcopy(aarp_org_code, llc->llc_org_code,
sizeof(aarp_org_code));
llc->llc_ether_type = htons(ETHERTYPE_AARP);
bcopy(ea->aarp_spnet, ea->aarp_tpnet,
sizeof(ea->aarp_tpnet));
bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet));
} else
eh->ether_type = htons(ETHERTYPE_AARP);
ifa_free(&aa->aa_ifa);
ea->aarp_tpnode = ea->aarp_spnode;
ea->aarp_spnode = ma.s_node;
ea->aarp_op = htons(AARPOP_RESPONSE);
sa.sa_len = sizeof(struct sockaddr);
sa.sa_family = AF_UNSPEC;
(*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
return;
}
static void
aarptfree(struct aarptab *aat)
{
AARPTAB_LOCK_ASSERT();
if (aat->aat_hold)
m_freem(aat->aat_hold);
aat->aat_hold = NULL;
aat->aat_timer = aat->aat_flags = 0;
aat->aat_ataddr.s_net = 0;
aat->aat_ataddr.s_node = 0;
}
struct aarptab *
aarptnew(struct at_addr *addr)
{
int n;
int oldest = -1;
struct aarptab *aat, *aato = NULL;
static int first = 1;
AARPTAB_LOCK_ASSERT();
if (first) {
first = 0;
aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz);
}
aat = &aarptab[AARPTAB_HASH(*addr) * AARPTAB_BSIZ];
for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
if (aat->aat_flags == 0)
goto out;
if (aat->aat_flags & ATF_PERM)
continue;
if ((int) aat->aat_timer > oldest) {
oldest = aat->aat_timer;
aato = aat;
}
}
if (aato == NULL)
return (NULL);
aat = aato;
aarptfree(aat);
out:
aat->aat_ataddr = *addr;
aat->aat_flags = ATF_INUSE;
return (aat);
}
void
aarpprobe(void *arg)
{
struct ifnet *ifp = arg;
struct mbuf *m;
struct ether_header *eh;
struct ether_aarp *ea;
struct at_ifaddr *aa;
struct llc *llc;
struct sockaddr sa;
/*
* We need to check whether the output ethernet type should be phase
* 1 or 2. We have the interface that we'll be sending the aarp out.
* We need to find an AppleTalk network on that interface with the
* same address as we're looking for. If the net is phase 2,
* generate an 802.2 and SNAP header.
*/
AARPTAB_LOCK();
for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
(aa->aa_flags & AFA_PROBING))
break;
}
if (aa == NULL) {
/* Serious error XXX. */
AARPTAB_UNLOCK();
printf("aarpprobe why did this happen?!\n");
return;
}
if (aa->aa_probcnt <= 0) {
aa->aa_flags &= ~AFA_PROBING;
wakeup(aa);
AARPTAB_UNLOCK();
return;
} else
callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp);
ifa_ref(&aa->aa_ifa);
AARPTAB_UNLOCK();
m = m_gethdr(M_DONTWAIT, MT_DATA);
if (m == NULL) {
ifa_free(&aa->aa_ifa);
return;
}
#ifdef MAC
mac_netatalk_aarp_send(ifp, m);
#endif
m->m_len = sizeof(*ea);
m->m_pkthdr.len = sizeof(*ea);
MH_ALIGN(m, sizeof(*ea));
ea = mtod(m, struct ether_aarp *);
bzero((caddr_t)ea, sizeof(*ea));
ea->aarp_hrd = htons(AARPHRD_ETHER);
ea->aarp_pro = htons(ETHERTYPE_AT);
ea->aarp_hln = sizeof(ea->aarp_sha);
ea->aarp_pln = sizeof(ea->aarp_spu);
ea->aarp_op = htons(AARPOP_PROBE);
bcopy(IF_LLADDR(ifp), (caddr_t)ea->aarp_sha,
sizeof(ea->aarp_sha));
eh = (struct ether_header *)sa.sa_data;
if (aa->aa_flags & AFA_PHASE2) {
bcopy(atmulticastaddr, eh->ether_dhost,
sizeof(eh->ether_dhost));
eh->ether_type = htons(sizeof(struct llc) +
sizeof(struct ether_aarp));
M_PREPEND(m, sizeof(struct llc), M_WAIT);
llc = mtod(m, struct llc *);
llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
llc->llc_control = LLC_UI;
bcopy(aarp_org_code, llc->llc_org_code,
sizeof(aarp_org_code));
llc->llc_ether_type = htons(ETHERTYPE_AARP);
bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
sizeof(ea->aarp_spnet));
bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet,
sizeof(ea->aarp_tpnet));
ea->aarp_spnode = ea->aarp_tpnode =
AA_SAT(aa)->sat_addr.s_node;
} else {
bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
sizeof(eh->ether_dhost));
eh->ether_type = htons(ETHERTYPE_AARP);
ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node;
}
#ifdef NETATALKDEBUG
printf("aarp: sending probe for %u.%u\n",
ntohs(AA_SAT(aa)->sat_addr.s_net), AA_SAT(aa)->sat_addr.s_node);
#endif /* NETATALKDEBUG */
ifa_free(&aa->aa_ifa);
sa.sa_len = sizeof(struct sockaddr);
sa.sa_family = AF_UNSPEC;
(*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
aa->aa_probcnt--;
}
void
aarp_clean(void)
{
struct aarptab *aat;
int i;
untimeout(aarptimer, 0, aarptimer_ch);
AARPTAB_LOCK();
for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) {
if (aat->aat_hold) {
m_freem(aat->aat_hold);
aat->aat_hold = NULL;
}
}
AARPTAB_UNLOCK();
}

View File

@ -1,86 +0,0 @@
/*-
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
*
* $FreeBSD$
*/
#ifndef _NETATALK_AARP_H_
#define _NETATALK_AARP_H_
/*
* This structure is used for both phase 1 and 2. Under phase 1
* the net is not filled in. It is in phase 2. In both cases, the
* hardware address length is (for some unknown reason) 4. If
* anyone at Apple could program their way out of paper bag, it
* would be 1 and 3 respectively for phase 1 and 2.
*/
union aapa {
u_char ap_pa[4];
struct ap_node {
u_char an_zero;
u_char an_net[2];
u_char an_node;
} __packed ap_node;
};
struct ether_aarp {
struct arphdr eaa_hdr;
u_char aarp_sha[6];
union aapa aarp_spu;
u_char aarp_tha[6];
union aapa aarp_tpu;
} __packed;
#define aarp_hrd eaa_hdr.ar_hrd
#define aarp_pro eaa_hdr.ar_pro
#define aarp_hln eaa_hdr.ar_hln
#define aarp_pln eaa_hdr.ar_pln
#define aarp_op eaa_hdr.ar_op
#define aarp_spa aarp_spu.ap_node.an_node
#define aarp_tpa aarp_tpu.ap_node.an_node
#define aarp_spnet aarp_spu.ap_node.an_net
#define aarp_tpnet aarp_tpu.ap_node.an_net
#define aarp_spnode aarp_spu.ap_node.an_node
#define aarp_tpnode aarp_tpu.ap_node.an_node
struct aarptab {
struct at_addr aat_ataddr;
u_char aat_enaddr[6];
u_char aat_timer;
u_char aat_flags;
struct mbuf *aat_hold;
};
#define AARPHRD_ETHER 0x0001
#define AARPOP_REQUEST 0x01
#define AARPOP_RESPONSE 0x02
#define AARPOP_PROBE 0x03
#ifdef _KERNEL
struct aarptab *aarptnew(struct at_addr *);
#endif
#endif /* _NETATALK_AARP_H_ */

View File

@ -1,86 +0,0 @@
/*-
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Mike Clark
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-763-0525
* netatalk@itd.umich.edu
*
* $FreeBSD$
*/
#ifndef _NETATALK_AT_H_
#define _NETATALK_AT_H_
/*
* Supported protocols
*/
#define ATPROTO_DDP 0
#define ATPROTO_AARP 254
#define DDP_MAXSZ 587
/*
* If ATPORT_FIRST <= Port < ATPORT_RESERVED, the port was created by a
* privileged process.
*
* If ATPORT_RESERVED <= Port < ATPORT_LAST, the port was not necessarily
* created by a privileged process.
*/
#define ATPORT_FIRST 1
#define ATPORT_RESERVED 128
#define ATPORT_LAST 255
/*
* AppleTalk address.
*/
struct at_addr {
u_short s_net;
u_char s_node;
};
#define ATADDR_ANYNET (u_short)0x0000
#define ATADDR_ANYNODE (u_char)0x00
#define ATADDR_ANYPORT (u_char)0x00
#define ATADDR_BCAST (u_char)0xff /* There is no BCAST for NET. */
struct netrange {
u_char nr_phase;
u_short nr_firstnet;
u_short nr_lastnet;
};
/*
* Socket address, AppleTalk style. We keep magic information in the zero
* bytes. There are three types, NONE, CONFIG which has the phase and a net
* range, and IFACE which has the network address of an interface. IFACE may
* be filled in by the client, and is filled in by the kernel.
*/
struct sockaddr_at {
u_char sat_len;
u_char sat_family;
u_char sat_port;
struct at_addr sat_addr;
union {
struct netrange r_netrange;
char r_zero[8]; /* Hide struct netrange here. */
} sat_range;
};
#define sat_zero sat_range.r_zero
#endif /* !_NETATALK_AT_H_ */

View File

@ -1,888 +0,0 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* Copyright (c) 2009 Robert N. M. Watson
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/sockio.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/priv.h>
#include <sys/rwlock.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#undef s_net
#include <netinet/if_ether.h>
#include <netatalk/at.h>
#include <netatalk/at_var.h>
#include <netatalk/at_extern.h>
struct rwlock at_ifaddr_rw;
struct at_ifaddrhead at_ifaddrhead;
RW_SYSINIT(at_ifaddr_rw, &at_ifaddr_rw, "at_ifaddr_rw");
static int aa_dorangeroute(struct ifaddr *ifa, u_int first, u_int last,
int cmd);
static int aa_addsingleroute(struct ifaddr *ifa, struct at_addr *addr,
struct at_addr *mask);
static int aa_delsingleroute(struct ifaddr *ifa, struct at_addr *addr,
struct at_addr *mask);
static int aa_dosingleroute(struct ifaddr *ifa, struct at_addr *addr,
struct at_addr *mask, int cmd, int flags);
static int at_scrub(struct ifnet *ifp, struct at_ifaddr *aa);
static int at_ifinit(struct ifnet *ifp, struct at_ifaddr *aa,
struct sockaddr_at *sat);
static int aa_claim_addr(struct ifaddr *ifa, struct sockaddr *gw);
#define sateqaddr(a,b) \
((a)->sat_len == (b)->sat_len && \
(a)->sat_family == (b)->sat_family && \
(a)->sat_addr.s_net == (b)->sat_addr.s_net && \
(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)
{
struct ifreq *ifr = (struct ifreq *)data;
struct sockaddr_at *sat;
struct netrange *nr;
struct at_aliasreq *ifra = (struct at_aliasreq *)data;
struct at_ifaddr *aa;
struct ifaddr *ifa;
int error;
/*
* If we have an ifp, then find the matching at_ifaddr if it exists
*/
aa = NULL;
AT_IFADDR_RLOCK();
if (ifp != NULL) {
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
if (aa->aa_ifp == ifp)
break;
}
}
if (aa != NULL)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
/*
* 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.
*/
error = 0;
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) {
struct at_ifaddr *oaa;
AT_IFADDR_RLOCK();
for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
if (aa->aa_ifp == ifp &&
sateqaddr(&aa->aa_addr, &ifra->ifra_addr))
break;
}
if (oaa != NULL && oaa != aa)
ifa_free(&oaa->aa_ifa);
if (aa != NULL && oaa != aa)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
}
/*
* If we a retrying to delete an addres but didn't find such,
* then rewurn with an error
*/
if (cmd == SIOCDIFADDR && aa == NULL) {
error = EADDRNOTAVAIL;
goto out;
}
/*FALLTHROUGH*/
case SIOCSIFADDR:
/*
* If we are not superuser, then we don't get to do these ops.
*
* XXXRW: Layering?
*/
if (priv_check(td, PRIV_NET_ADDIFADDR)) {
error = EPERM;
goto out;
}
sat = satosat(&ifr->ifr_addr);
nr = (struct netrange *)sat->sat_zero;
if (nr->nr_phase == 1) {
struct at_ifaddr *oaa;
/*
* Look for a phase 1 address on this interface.
* This may leave aa pointing to the first address on
* the NEXT interface!
*/
AT_IFADDR_RLOCK();
for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
if (aa->aa_ifp == ifp &&
(aa->aa_flags & AFA_PHASE2) == 0)
break;
}
if (oaa != NULL && oaa != aa)
ifa_free(&oaa->aa_ifa);
if (aa != NULL && oaa != aa)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
} else { /* default to phase 2 */
struct at_ifaddr *oaa;
/*
* Look for a phase 2 address on this interface.
* This may leave aa pointing to the first address on
* the NEXT interface!
*/
AT_IFADDR_RLOCK();
for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
if (aa->aa_ifp == ifp && (aa->aa_flags &
AFA_PHASE2))
break;
}
if (oaa != NULL && oaa != aa)
ifa_free(&oaa->aa_ifa);
if (aa != NULL && oaa != aa)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
}
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) {
aa = malloc(sizeof(struct at_ifaddr), M_IFADDR,
M_NOWAIT | M_ZERO);
if (aa == NULL) {
error = ENOBUFS;
goto out;
}
callout_init(&aa->aa_callout, CALLOUT_MPSAFE);
ifa = (struct ifaddr *)aa;
ifa_init(ifa);
/*
* As the at_ifaddr contains the actual sockaddrs,
* and the ifaddr itself, link them all 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;
ifa_ref(&aa->aa_ifa); /* at_ifaddrhead */
AT_IFADDR_WLOCK();
if (!TAILQ_EMPTY(&at_ifaddrhead)) {
/*
* 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 (TAILQ_FIRST(&at_ifaddrhead)->aa_ifp->
if_flags & IFF_LOOPBACK)
TAILQ_INSERT_HEAD(&at_ifaddrhead, aa,
aa_link);
else
TAILQ_INSERT_TAIL(&at_ifaddrhead, aa,
aa_link);
} else
TAILQ_INSERT_HEAD(&at_ifaddrhead, aa,
aa_link);
AT_IFADDR_WUNLOCK();
/*
* and link it all together
*/
aa->aa_ifp = ifp;
ifa_ref(&aa->aa_ifa); /* if_addrhead */
IF_ADDR_WLOCK(ifp);
TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
IF_ADDR_WUNLOCK(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) {
struct at_ifaddr *oaa;
/*
* If the request is specifying phase 1, then
* only look at a phase one address
*/
AT_IFADDR_RLOCK();
for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
if (aa->aa_ifp == ifp &&
(aa->aa_flags & AFA_PHASE2) == 0)
break;
}
if (oaa != NULL && oaa != aa)
ifa_free(&oaa->aa_ifa);
if (aa != NULL && oaa != aa)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
} else {
struct at_ifaddr *oaa;
/*
* default to phase 2
*/
AT_IFADDR_RLOCK();
for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
if (aa->aa_ifp == ifp && (aa->aa_flags &
AFA_PHASE2))
break;
}
if (oaa != NULL && oaa != aa)
ifa_free(&oaa->aa_ifa);
if (aa != NULL && oaa != aa)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
}
if (aa == NULL) {
error = EADDRNOTAVAIL;
goto out;
}
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:
/*
* copy the contents of the sockaddr blindly.
*/
sat = (struct sockaddr_at *)&ifr->ifr_addr;
*sat = aa->aa_addr;
/*
* 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:
error = at_ifinit(ifp, aa,
(struct sockaddr_at *)&ifr->ifr_addr);
goto out;
case SIOCAIFADDR:
if (sateqaddr(&ifra->ifra_addr, &aa->aa_addr)) {
error = 0;
goto out;
}
error = at_ifinit(ifp, aa,
(struct sockaddr_at *)&ifr->ifr_addr);
goto out;
case SIOCDIFADDR:
/*
* remove the ifaddr from the interface
*/
ifa = (struct ifaddr *)aa;
IF_ADDR_WLOCK(ifp);
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
IF_ADDR_WUNLOCK(ifp);
ifa_free(ifa); /* if_addrhead */
/*
* Now remove the at_ifaddr from the parallel structure
* as well, or we'd be in deep trouble
*/
AT_IFADDR_WLOCK();
TAILQ_REMOVE(&at_ifaddrhead, aa, aa_link);
AT_IFADDR_WUNLOCK();
ifa_free(ifa); /* at_ifaddrhead */
break;
default:
if (ifp == NULL || ifp->if_ioctl == NULL) {
error = EOPNOTSUPP;
goto out;
}
error = ((*ifp->if_ioctl)(ifp, cmd, data));
}
out:
if (aa != NULL)
ifa_free(&aa->aa_ifa);
return (error);
}
/*
* Given an interface and an at_ifaddr (supposedly on that interface)
* remove any routes that depend on this.
* Why ifp is needed I'm not sure,
* as aa->at_ifaddr.ifa_ifp should be the same.
*/
static int
at_scrub(struct ifnet *ifp, struct at_ifaddr *aa)
{
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);
} 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;
}
return (0);
}
/*
* given an at_ifaddr,a sockaddr_at and an ifp,
* bang them all together at high speed and see what happens
*/
static int
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;
/* 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);
#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..
*/
#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; /* 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 {
/*
* 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);
}
/*
* set the node part of the address into the ifaddr.
* If it's not specified, be random about it...
* XXX use /dev/random?
*/
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?
*/
AARPTAB_LOCK();
callout_reset(&aa->aa_callout, hz / 5,
aarpprobe, ifp);
if (msleep(aa, &aarptab_mtx, PPAUSE|PCATCH,
"at_ifinit", 0)) {
AARPTAB_UNLOCK();
/*
* 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);
}
AARPTAB_UNLOCK();
/*
* 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;
}
/*
* if we are still trying to probe, then we have finished all
* the possible addresses, so we need to give up
*/
if (aa->aa_flags & AFA_PROBING) {
aa->aa_addr = oldaddr;
aa->aa_firstnet = onr.nr_firstnet;
aa->aa_lastnet = onr.nr_lastnet;
return (EADDRINUSE);
}
}
/*
* 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..
*/
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;
/* XXX should not be so.. should be HOST route */
rtmask.s_node = 0x0;
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);
}
/*
* check whether a given address is a broadcast address for us..
*/
int
at_broadcast(struct sockaddr_at *sat)
{
struct at_ifaddr *aa;
AT_IFADDR_LOCK_ASSERT();
/*
* 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.
*/
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
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);
}
/*
* aa_dorangeroute()
*
* Add a route for a range of networks from bot to top - 1.
* Algorithm:
*
* Split the range into two subranges such that the middle
* of the two ranges is the point where the highest bit of difference
* between the two addresses makes its transition.
* Each of the upper and lower ranges might not exist, or might be
* representable by 1 or more netmasks. In addition, if both
* ranges can be represented by the same netmask, then they can be merged
* by using the next higher netmask..
*/
static int
aa_dorangeroute(struct ifaddr *ifa, u_int bot, u_int top, int cmd)
{
u_int mask1;
struct at_addr addr;
struct at_addr mask;
int error;
/*
* slight sanity check
*/
if (bot > top) return (EINVAL);
addr.s_node = 0;
mask.s_node = 0;
/*
* just start out with the lowest boundary
* and keep extending the mask till it's too big.
*/
while (bot <= top) {
mask1 = 1;
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 (error) {
/* XXX clean up? */
return (error);
}
} 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)
{
#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);
#endif
return (aa_dosingleroute(ifa, addr, mask, RTM_ADD, RTF_UP));
}
static int
aa_delsingleroute(struct ifaddr *ifa, struct at_addr *addr,
struct at_addr *mask)
{
return (aa_dosingleroute(ifa, addr, mask, RTM_DELETE, 0));
}
static int
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));
}
static int
aa_claim_addr(struct ifaddr *ifa, struct sockaddr *gw0)
{
struct sockaddr_at *addr = (struct sockaddr_at *)ifa->ifa_addr;
struct sockaddr_at *gw = (struct sockaddr_at *)gw0;
switch (gw->sat_range.r_netrange.nr_phase) {
case 1:
if(addr->sat_range.r_netrange.nr_phase == 1)
return (1);
case 0:
case 2:
/*
* if it's our net (including 0),
* or netranges are valid, and we are in the range,
* 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))))
return (1);
break;
default:
printf("atalk: bad phase\n");
}
return (0);
}

View File

@ -1,67 +0,0 @@
/*-
* Copyright (c) 1990,1994 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
*
* $FreeBSD$
*/
#ifndef _NETATALK_AT_EXTERN_H_
#define _NETATALK_AT_EXTERN_H_
extern struct mtx aarptab_mtx;
#define AARPTAB_LOCK() mtx_lock(&aarptab_mtx)
#define AARPTAB_UNLOCK() mtx_unlock(&aarptab_mtx)
#define AARPTAB_LOCK_ASSERT() mtx_assert(&aarptab_mtx, MA_OWNED)
#define AARPTAB_UNLOCK_ASSERT() mtx_assert(&aarptab_mtx, MA_NOTOWNED)
struct at_ifaddr;
struct ifnet;
struct mbuf;
struct route;
struct thread;
struct sockaddr_at;
struct socket;
void aarpintr(struct mbuf *);
void aarpprobe(void *arg);
int aarpresolve(struct ifnet *, struct mbuf *,
struct sockaddr_at *, u_char *);
void aarp_clean(void);
void at1intr(struct mbuf *);
void at2intr(struct mbuf *);
int at_broadcast(struct sockaddr_at *);
u_short at_cksum(struct mbuf *m, int skip);
int at_control(struct socket *so, u_long cmd, caddr_t data,
struct ifnet *ifp, struct thread *td);
struct at_ifaddr *at_ifawithnet(struct sockaddr_at *);
struct at_ifaddr *at_ifawithnet_locked(struct sockaddr_at *sat);
int at_inithead(void**, int);
void ddp_init(void);
int ddp_output(struct mbuf *m, struct socket *so);
int ddp_route(struct mbuf *m, struct route *ro);
struct ddpcb *ddp_search(struct sockaddr_at *, struct sockaddr_at *,
struct at_ifaddr *);
#endif /* !_NETATALK_AT_EXTERN_H_ */

View File

@ -1,66 +0,0 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright (c) 1990, 1991 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Mike Clark
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-763-0525
* netatalk@itd.umich.edu
*
* $FreeBSD$
*/
#include <rtems/bsd/sys/param.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/socket.h>
#include <sys/kernel.h>
#include <net/route.h>
#include <netatalk/at.h>
#include <netatalk/ddp_var.h>
#include <netatalk/at_extern.h>
static struct domain atalkdomain;
static struct protosw atalksw[] = {
{
/* Identifiers */
.pr_type = SOCK_DGRAM,
.pr_domain = &atalkdomain,
.pr_protocol = ATPROTO_DDP,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_output = ddp_output,
.pr_init = ddp_init,
.pr_usrreqs = &ddp_usrreqs,
},
};
static struct domain atalkdomain = {
.dom_family = AF_APPLETALK,
.dom_name = "appletalk",
.dom_protosw = atalksw,
.dom_protoswNPROTOSW = &atalksw[sizeof(atalksw)/sizeof(atalksw[0])],
.dom_rtattach = at_inithead,
.dom_rtoffset = offsetof(struct sockaddr_at, sat_addr) << 3,
.dom_maxrtkey = sizeof(struct sockaddr_at),
};
DOMAIN_SET(atalk);

View File

@ -1,119 +0,0 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright 1994, 1995 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
* granted, provided that both the above copyright notice and this
* permission notice appear in all copies, that both the above
* copyright notice and this permission notice appear in all
* supporting documentation, and that the name of M.I.T. not be used
* in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission. M.I.T. makes
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* at_rmx.c,v 1.13 1995/05/30 08:09:31 rgrimes Exp
* $FreeBSD$
*/
/* This code generates debugging traces to the radix code. */
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <net/route.h>
int at_inithead(void **head, int off);
#if 0
#define HEXBUF_LEN 256
static const char *
prsockaddr(void *v, char *hexbuf)
{
char *bp = &hexbuf[0];
u_char *cp = v;
if (v != NULL) {
int len = *cp;
u_char *cplim = cp + len;
/* return: "(len) hexdump" */
bp += sprintf(bp, "(%d)", len);
for (cp++; cp < cplim && bp < hexbuf + (HEXBUF_LEN - 4);
cp++) {
*bp++ = "0123456789abcdef"[*cp / 16];
*bp++ = "0123456789abcdef"[*cp % 16];
}
} else
bp+= sprintf(bp, "null");
*bp = '\0';
return (hexbuf);
}
#endif
static struct radix_node *
at_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
struct radix_node *treenodes)
{
return (rn_addroute(v_arg, n_arg, head, treenodes));
}
static struct radix_node *
at_matroute(void *v_arg, struct radix_node_head *head)
{
return (rn_match(v_arg, head));
}
static struct radix_node *
at_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
{
return (rn_lookup(v_arg, m_arg, head));
}
static struct radix_node *
at_delroute(void *v_arg, void *netmask_arg, struct radix_node_head *head)
{
return (rn_delete(v_arg, netmask_arg, head));
}
/*
* Initialize our routing tree with debugging hooks.
*/
int
at_inithead(void **head, int off)
{
struct radix_node_head *rnh;
if (!rn_inithead(head, off))
return (0);
rnh = *head;
rnh->rnh_addaddr = at_addroute;
rnh->rnh_deladdr = at_delroute;
rnh->rnh_matchaddr = at_matroute;
rnh->rnh_lookup = at_lookup;
return (1);
}

View File

@ -1,77 +0,0 @@
/*-
* Copyright (c) 1990, 1991 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Mike Clark
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-763-0525
* netatalk@itd.umich.edu
*
* $FreeBSD$
*/
#ifndef _NETATALK_AT_VAR_H_
#define _NETATALK_AT_VAR_H_
/*
* For phase2, we need to keep not only our address on an interface, but also
* the legal networks on the interface.
*/
struct at_ifaddr {
struct ifaddr aa_ifa;
struct sockaddr_at aa_addr;
struct sockaddr_at aa_broadaddr;
struct sockaddr_at aa_netmask;
int aa_flags;
u_short aa_firstnet;
u_short aa_lastnet;
int aa_probcnt;
struct callout aa_callout;
TAILQ_ENTRY(at_ifaddr) aa_link;
};
#define aa_ifp aa_ifa.ifa_ifp
#define aa_dstaddr aa_broadaddr;
TAILQ_HEAD(at_ifaddrhead, at_ifaddr);
struct at_aliasreq {
char ifra_name[IFNAMSIZ];
struct sockaddr_at ifra_addr;
struct sockaddr_at ifra_broadaddr;
struct sockaddr_at ifra_mask;
};
#define ifra_dstaddr ifra_broadaddr
#define AA_SAT(aa) (&(aa->aa_addr))
#define satosat(sa) ((struct sockaddr_at *)(sa))
#define AFA_ROUTE 0x0001
#define AFA_PROBING 0x0002
#define AFA_PHASE2 0x0004
#ifdef _KERNEL
extern struct rwlock at_ifaddr_rw;
extern struct at_ifaddrhead at_ifaddrhead;
#define AT_IFADDR_LOCK_INIT() rw_init(&at_ifaddr_rw, "at_ifaddr_rw")
#define AT_IFADDR_LOCK_ASSERT() rw_assert(&at_ifaddr_rw, RA_LOCKED)
#define AT_IFADDR_RLOCK() rw_rlock(&at_ifaddr_rw)
#define AT_IFADDR_RUNLOCK() rw_runlock(&at_ifaddr_rw)
#define AT_IFADDR_WLOCK() rw_wlock(&at_ifaddr_rw)
#define AT_IFADDR_WUNLOCK() rw_wunlock(&at_ifaddr_rw)
#endif
#endif /* _NETATALK_AT_VAR_H_ */

View File

@ -1,137 +0,0 @@
/*-
* Copyright (c) 1990, 1991 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Mike Clark
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-763-0525
* netatalk@itd.umich.edu
*
* $FreeBSD$
*/
#ifndef _NETATALK_DDP_H_
#define _NETATALK_DDP_H_
/*-
* <-1byte(8bits) ->
* +---------------+
* | 0 | hopc |len|
* +---------------+
* | len (cont) |
* +---------------+
* | |
* +- DDP csum -+
* | |
* +---------------+
* | |
* +- Dest NET -+
* | |
* +---------------+
* | |
* +- Src NET -+
* | |
* +---------------+
* | Dest NODE |
* +---------------+
* | Src NODE |
* +---------------+
* | Dest PORT |
* +---------------+
* | Src PORT |
* +---------------+
*
* On Apples, there is also a ddp_type field, after src_port. However, under
* this unix implementation, user level processes need to be able to set the
* ddp_type. In later revisions, the ddp_type may only be available in a
* raw_appletalk interface.
*/
struct elaphdr {
u_char el_dnode;
u_char el_snode;
u_char el_type;
} __packed;
#define SZ_ELAPHDR 3
#define ELAP_DDPSHORT 0x01
#define ELAP_DDPEXTEND 0x02
/*
* Extended DDP header. Includes sickness for dealing with arbitrary
* bitfields on a little-endian arch.
*/
struct ddpehdr {
union {
struct {
#if BYTE_ORDER == BIG_ENDIAN
unsigned dub_pad:2;
unsigned dub_hops:4;
unsigned dub_len:10;
unsigned dub_sum:16;
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
unsigned dub_sum:16;
unsigned dub_len:10;
unsigned dub_hops:4;
unsigned dub_pad:2;
#endif
} __packed du_bits;
unsigned du_bytes;
} deh_u;
u_short deh_dnet;
u_short deh_snet;
u_char deh_dnode;
u_char deh_snode;
u_char deh_dport;
u_char deh_sport;
} __packed;
#define deh_pad deh_u.du_bits.dub_pad
#define deh_hops deh_u.du_bits.dub_hops
#define deh_len deh_u.du_bits.dub_len
#define deh_sum deh_u.du_bits.dub_sum
#define deh_bytes deh_u.du_bytes
#define DDP_MAXHOPS 15
struct ddpshdr {
union {
struct {
#if BYTE_ORDER == BIG_ENDIAN
unsigned dub_pad:6;
unsigned dub_len:10;
unsigned dub_dport:8;
unsigned dub_sport:8;
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
unsigned dub_sport:8;
unsigned dub_dport:8;
unsigned dub_len:10;
unsigned dub_pad:6;
#endif
} __packed du_bits;
unsigned du_bytes;
} dsh_u;
} __packed;
#define dsh_pad dsh_u.du_bits.dub_pad
#define dsh_len dsh_u.du_bits.dub_len
#define dsh_dport dsh_u.du_bits.dub_dport
#define dsh_sport dsh_u.du_bits.dub_sport
#define dsh_bytes dsh_u.du_bytes
#endif /* _NETATALK_DDP_H_ */

View File

@ -1,442 +0,0 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright (c) 2004-2009 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Copyright (c) 1990, 1994 Regents of The University of Michigan.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
*
* $FreeBSD$
*/
#include <rtems/bsd/sys/param.h>
#include <sys/kernel.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mbuf.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sx.h>
#include <sys/systm.h>
#include <net/if.h>
#include <net/route.h>
#include <netatalk/at.h>
#include <netatalk/at_var.h>
#include <netatalk/ddp.h>
#include <netatalk/ddp_var.h>
#include <netatalk/ddp_pcb.h>
#include <netatalk/at_extern.h>
#include <security/mac/mac_framework.h>
static volatile int ddp_forward = 1;
static volatile int ddp_firewall = 0;
static struct ddpstat ddpstat;
static struct route forwro;
static void ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int);
/*
* Could probably merge these two code segments a little better...
*/
void
at2intr(struct mbuf *m)
{
/*
* Phase 2 packet handling .
*/
ddp_input(m, m->m_pkthdr.rcvif, NULL, 2);
}
void
at1intr(struct mbuf *m)
{
struct elaphdr *elhp, elh;
/*
* Phase 1 packet handling
*/
if (m->m_len < SZ_ELAPHDR && ((m = m_pullup(m, SZ_ELAPHDR)) ==
NULL)) {
ddpstat.ddps_tooshort++;
return;
}
/*
* This seems a little dubious, but I don't know phase 1 so leave it.
*/
elhp = mtod(m, struct elaphdr *);
m_adj(m, SZ_ELAPHDR);
if (elhp->el_type != ELAP_DDPEXTEND) {
bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR);
ddp_input(m, m->m_pkthdr.rcvif, &elh, 1);
} else
ddp_input(m, m->m_pkthdr.rcvif, NULL, 1);
}
static void
ddp_input(struct mbuf *m, struct ifnet *ifp, struct elaphdr *elh, int phase)
{
struct sockaddr_at from, to;
struct ddpshdr *dsh, ddps;
struct at_ifaddr *aa;
struct ddpehdr *deh = NULL, ddpe;
struct ddpcb *ddp;
int dlen, mlen;
u_short cksum = 0;
bzero((caddr_t)&from, sizeof(struct sockaddr_at));
bzero((caddr_t)&to, sizeof(struct sockaddr_at));
if (elh != NULL) {
/*
* Extract the information in the short header. Network
* information is defaulted to ATADDR_ANYNET and node
* information comes from the elh info. We must be phase 1.
*/
ddpstat.ddps_short++;
if (m->m_len < sizeof(struct ddpshdr) &&
((m = m_pullup(m, sizeof(struct ddpshdr))) == NULL)) {
ddpstat.ddps_tooshort++;
return;
}
dsh = mtod(m, struct ddpshdr *);
bcopy((caddr_t)dsh, (caddr_t)&ddps, sizeof(struct ddpshdr));
ddps.dsh_bytes = ntohl(ddps.dsh_bytes);
dlen = ddps.dsh_len;
to.sat_addr.s_net = ATADDR_ANYNET;
to.sat_addr.s_node = elh->el_dnode;
to.sat_port = ddps.dsh_dport;
from.sat_addr.s_net = ATADDR_ANYNET;
from.sat_addr.s_node = elh->el_snode;
from.sat_port = ddps.dsh_sport;
/*
* Make sure that we point to the phase1 ifaddr info and that
* it's valid for this packet.
*/
AT_IFADDR_RLOCK();
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
if ((aa->aa_ifp == ifp)
&& ((aa->aa_flags & AFA_PHASE2) == 0)
&& ((to.sat_addr.s_node ==
AA_SAT(aa)->sat_addr.s_node) ||
(to.sat_addr.s_node == ATADDR_BCAST)))
break;
}
/*
* maybe we got a broadcast not meant for us.. ditch it.
*/
if (aa == NULL) {
AT_IFADDR_RUNLOCK();
m_freem(m);
return;
}
} else {
/*
* There was no 'elh' passed on. This could still be either
* phase1 or phase2. We have a long header, but we may be
* running on a phase 1 net. Extract out all the info
* regarding this packet's src & dst.
*/
ddpstat.ddps_long++;
if (m->m_len < sizeof(struct ddpehdr) &&
((m = m_pullup(m, sizeof(struct ddpehdr))) == NULL)) {
AT_IFADDR_RUNLOCK();
ddpstat.ddps_tooshort++;
return;
}
deh = mtod(m, struct ddpehdr *);
bcopy((caddr_t)deh, (caddr_t)&ddpe, sizeof(struct ddpehdr));
ddpe.deh_bytes = ntohl(ddpe.deh_bytes);
dlen = ddpe.deh_len;
if ((cksum = ddpe.deh_sum) == 0)
ddpstat.ddps_nosum++;
from.sat_addr.s_net = ddpe.deh_snet;
from.sat_addr.s_node = ddpe.deh_snode;
from.sat_port = ddpe.deh_sport;
to.sat_addr.s_net = ddpe.deh_dnet;
to.sat_addr.s_node = ddpe.deh_dnode;
to.sat_port = ddpe.deh_dport;
AT_IFADDR_RLOCK();
if (to.sat_addr.s_net == ATADDR_ANYNET) {
/*
* The TO address doesn't specify a net, so by
* definition it's for this net. Try find ifaddr
* info with the right phase, the right interface,
* and either to our node, a broadcast, or looped
* back (though that SHOULD be covered in the other
* cases).
*
* XXX If we have multiple interfaces, then the first
* with this node number will match (which may NOT be
* what we want, but it's probably safe in 99.999% of
* cases.
*/
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
if (phase == 1 && (aa->aa_flags &
AFA_PHASE2))
continue;
if (phase == 2 && (aa->aa_flags &
AFA_PHASE2) == 0)
continue;
if ((aa->aa_ifp == ifp) &&
((to.sat_addr.s_node ==
AA_SAT(aa)->sat_addr.s_node) ||
(to.sat_addr.s_node == ATADDR_BCAST) ||
(ifp->if_flags & IFF_LOOPBACK)))
break;
}
} else {
/*
* A destination network was given. We just try to
* find which ifaddr info matches it.
*/
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
/*
* This is a kludge. Accept packets that are
* for any router on a local netrange.
*/
if (to.sat_addr.s_net == aa->aa_firstnet &&
to.sat_addr.s_node == 0)
break;
/*
* Don't use ifaddr info for which we are
* totally outside the netrange, and it's not
* a startup packet. Startup packets are
* always implicitly allowed on to the next
* test.
*/
if (((ntohs(to.sat_addr.s_net) <
ntohs(aa->aa_firstnet)) ||
(ntohs(to.sat_addr.s_net) >
ntohs(aa->aa_lastnet))) &&
((ntohs(to.sat_addr.s_net) < 0xff00) ||
(ntohs(to.sat_addr.s_net) > 0xfffe)))
continue;
/*
* Don't record a match either if we just
* don't have a match in the node address.
* This can have if the interface is in
* promiscuous mode for example.
*/
if ((to.sat_addr.s_node !=
AA_SAT(aa)->sat_addr.s_node) &&
(to.sat_addr.s_node != ATADDR_BCAST))
continue;
break;
}
}
}
if (aa != NULL)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
/*
* Adjust the length, removing any padding that may have been added
* at a link layer. We do this before we attempt to forward a
* packet, possibly on a different media.
*/
mlen = m->m_pkthdr.len;
if (mlen < dlen) {
ddpstat.ddps_toosmall++;
goto out;
}
if (mlen > dlen)
m_adj(m, dlen - mlen);
/*
* If it isn't for a net on any of our interfaces, or it IS for a net
* on a different interface than it came in on, (and it is not looped
* back) then consider if we should forward it. As we are not really
* a router this is a bit cheeky, but it may be useful some day.
*/
if ((aa == NULL) || ((to.sat_addr.s_node == ATADDR_BCAST) &&
(aa->aa_ifp != ifp) && ((ifp->if_flags & IFF_LOOPBACK) == 0))) {
/*
* If we've explicitly disabled it, don't route anything.
*/
if (ddp_forward == 0)
goto out;
/*
* If the cached forwarding route is still valid, use it.
*
* XXXRW: Access to the cached route may not be properly
* synchronized for parallel input handling.
*/
if (forwro.ro_rt &&
(satosat(&forwro.ro_dst)->sat_addr.s_net !=
to.sat_addr.s_net ||
satosat(&forwro.ro_dst)->sat_addr.s_node !=
to.sat_addr.s_node)) {
RTFREE(forwro.ro_rt);
forwro.ro_rt = NULL;
}
/*
* If we don't have a cached one (any more) or it's useless,
* then get a new route.
*
* XXX this could cause a 'route leak'. Check this!
*/
if (forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp == NULL) {
forwro.ro_dst.sa_len = sizeof(struct sockaddr_at);
forwro.ro_dst.sa_family = AF_APPLETALK;
satosat(&forwro.ro_dst)->sat_addr.s_net =
to.sat_addr.s_net;
satosat(&forwro.ro_dst)->sat_addr.s_node =
to.sat_addr.s_node;
rtalloc(&forwro);
}
/*
* If it's not going to get there on this hop, and it's
* already done too many hops, then throw it away.
*/
if ((to.sat_addr.s_net !=
satosat(&forwro.ro_dst)->sat_addr.s_net) &&
(ddpe.deh_hops == DDP_MAXHOPS))
goto out;
/*
* A ddp router might use the same interface to forward the
* packet, which this would not effect. Don't allow packets
* to cross from one interface to another however.
*/
if (ddp_firewall && ((forwro.ro_rt == NULL) ||
(forwro.ro_rt->rt_ifp != ifp)))
goto out;
/*
* Adjust the header. If it was a short header then it would
* have not gotten here, so we can assume there is room to
* drop the header in.
*
* XXX what about promiscuous mode, etc...
*/
ddpe.deh_hops++;
ddpe.deh_bytes = htonl(ddpe.deh_bytes);
/* XXX deh? */
bcopy((caddr_t)&ddpe, (caddr_t)deh, sizeof(u_short));
if (ddp_route(m, &forwro))
ddpstat.ddps_cantforward++;
else
ddpstat.ddps_forward++;
if (aa != NULL)
ifa_free(&aa->aa_ifa);
return;
}
/*
* It was for us, and we have an ifaddr to use with it.
*/
from.sat_len = sizeof(struct sockaddr_at);
from.sat_family = AF_APPLETALK;
/*
* We are no longer interested in the link layer so cut it off.
*/
if (elh == NULL) {
if (ddp_cksum && cksum && cksum !=
at_cksum(m, sizeof(int))) {
ddpstat.ddps_badsum++;
goto out;
}
m_adj(m, sizeof(struct ddpehdr));
} else
m_adj(m, sizeof(struct ddpshdr));
/*
* Search for ddp protocol control blocks that match these addresses.
*/
DDP_LIST_SLOCK();
if ((ddp = ddp_search(&from, &to, aa)) == NULL)
goto out_unlock;
#ifdef MAC
if (mac_socket_check_deliver(ddp->ddp_socket, m) != 0)
goto out_unlock;
#endif
/*
* If we found one, deliver the packet to the socket
*/
SOCKBUF_LOCK(&ddp->ddp_socket->so_rcv);
if (sbappendaddr_locked(&ddp->ddp_socket->so_rcv,
(struct sockaddr *)&from, m, NULL) == 0) {
SOCKBUF_UNLOCK(&ddp->ddp_socket->so_rcv);
/*
* If the socket is full (or similar error) dump the packet.
*/
ddpstat.ddps_nosockspace++;
goto out_unlock;
}
/*
* And wake up whatever might be waiting for it
*/
sorwakeup_locked(ddp->ddp_socket);
m = NULL;
out_unlock:
DDP_LIST_SUNLOCK();
out:
if (aa != NULL)
ifa_free(&aa->aa_ifa);
if (m != NULL)
m_freem(m);
}

View File

@ -1,249 +0,0 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright (c) 1990, 1991 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Mike Clark
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-763-0525
* netatalk@itd.umich.edu
*/
/* $FreeBSD$ */
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/if.h>
#include <net/route.h>
#undef s_net
#include <netatalk/at.h>
#include <netatalk/at_var.h>
#include <netatalk/ddp.h>
#include <netatalk/ddp_var.h>
#include <netatalk/at_extern.h>
#include <security/mac/mac_framework.h>
int ddp_cksum = 1;
int
ddp_output(struct mbuf *m, struct socket *so)
{
struct ddpehdr *deh;
struct ddpcb *ddp = sotoddpcb(so);
#ifdef MAC
mac_socket_create_mbuf(so, m);
#endif
M_PREPEND(m, sizeof(struct ddpehdr), M_DONTWAIT);
if (m == NULL)
return (ENOBUFS);
deh = mtod(m, struct ddpehdr *);
deh->deh_pad = 0;
deh->deh_hops = 0;
deh->deh_len = m->m_pkthdr.len;
deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net;
deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node;
deh->deh_dport = ddp->ddp_fsat.sat_port;
deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net;
deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node;
deh->deh_sport = ddp->ddp_lsat.sat_port;
/*
* The checksum calculation is done after all of the other bytes have
* been filled in.
*/
if (ddp_cksum)
deh->deh_sum = at_cksum(m, sizeof(int));
else
deh->deh_sum = 0;
deh->deh_bytes = htonl(deh->deh_bytes);
#ifdef NETATALK_DEBUG
printf ("ddp_output: from %d.%d:%d to %d.%d:%d\n",
ntohs(deh->deh_snet), deh->deh_snode, deh->deh_sport,
ntohs(deh->deh_dnet), deh->deh_dnode, deh->deh_dport);
#endif
return (ddp_route(m, &ddp->ddp_route));
}
u_short
at_cksum(struct mbuf *m, int skip)
{
u_char *data, *end;
u_long cksum = 0;
for (; m; m = m->m_next) {
for (data = mtod(m, u_char *), end = data + m->m_len;
data < end; data++) {
if (skip) {
skip--;
continue;
}
cksum = (cksum + *data) << 1;
if (cksum & 0x00010000)
cksum++;
cksum &= 0x0000ffff;
}
}
if (cksum == 0)
cksum = 0x0000ffff;
return ((u_short)cksum);
}
int
ddp_route(struct mbuf *m, struct route *ro)
{
struct sockaddr_at gate;
struct elaphdr *elh;
struct mbuf *m0;
struct at_ifaddr *aa = NULL;
struct ifnet *ifp = NULL;
u_short net;
#if 0
/* Check for net zero, node zero ("myself") */
if (satosat(&ro->ro_dst)->sat_addr.s_net == ATADDR_ANYNET
&& satosat(&ro->ro_dst)->sat_addr.s_node == ATADDR_ANYNODE) {
/* Find the loopback interface */
}
#endif
/*
* If we have a route, find the ifa that refers to this route. I.e
* the ifa used to get to the gateway.
*/
if ((ro->ro_rt == NULL) || (ro->ro_rt->rt_ifa == NULL) ||
((ifp = ro->ro_rt->rt_ifa->ifa_ifp) == NULL))
rtalloc(ro);
if ((ro->ro_rt != NULL) && (ro->ro_rt->rt_ifa) &&
(ifp = ro->ro_rt->rt_ifa->ifa_ifp)) {
net = ntohs(satosat(ro->ro_rt->rt_gateway)->sat_addr.s_net);
AT_IFADDR_RLOCK();
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
if (((net == 0) || (aa->aa_ifp == ifp)) &&
net >= ntohs(aa->aa_firstnet) &&
net <= ntohs(aa->aa_lastnet))
break;
}
if (aa != NULL)
ifa_ref(&aa->aa_ifa);
AT_IFADDR_RUNLOCK();
} else {
m_freem(m);
#ifdef NETATALK_DEBUG
if (ro->ro_rt == NULL)
printf ("ddp_route: no ro_rt.\n");
else if (ro->ro_rt->rt_ifa == NULL)
printf ("ddp_route: no ro_rt->rt_ifa\n");
else
printf ("ddp_route: no ro_rt->rt_ifa->ifa_ifp\n");
#endif
return (ENETUNREACH);
}
if (aa == NULL) {
#ifdef NETATALK_DEBUG
printf("ddp_route: no atalk address found for %s\n",
ifp->if_xname);
#endif
m_freem(m);
return (ENETUNREACH);
}
/*
* If the destination address is on a directly attached node use
* that, else use the official gateway.
*/
if (ntohs(satosat(&ro->ro_dst)->sat_addr.s_net) >=
ntohs(aa->aa_firstnet) &&
ntohs(satosat(&ro->ro_dst)->sat_addr.s_net) <=
ntohs(aa->aa_lastnet))
gate = *satosat(&ro->ro_dst);
else
gate = *satosat(ro->ro_rt->rt_gateway);
/*
* There are several places in the kernel where data is added to an
* mbuf without ensuring that the mbuf pointer is aligned. This is
* bad for transition routing, since phase 1 and phase 2 packets end
* up poorly aligned due to the three byte elap header.
*
* XXXRW: kern/4184 suggests that an m_pullup() of (m) should take
* place here to address possible alignment issues.
*
* XXXRW: This appears not to handle M_PKTHDR properly, as it doesn't
* move the existing header from the old packet to the new one.
* Posibly should call M_MOVE_PKTHDR()? This would also allow
* removing mac_mbuf_copy().
*/
if (!(aa->aa_flags & AFA_PHASE2)) {
MGET(m0, M_DONTWAIT, MT_DATA);
if (m0 == NULL) {
ifa_free(&aa->aa_ifa);
m_freem(m);
printf("ddp_route: no buffers\n");
return (ENOBUFS);
}
#ifdef MAC
mac_mbuf_copy(m, m0);
#endif
m0->m_next = m;
/* XXX perhaps we ought to align the header? */
m0->m_len = SZ_ELAPHDR;
m = m0;
elh = mtod(m, struct elaphdr *);
elh->el_snode = satosat(&aa->aa_addr)->sat_addr.s_node;
elh->el_type = ELAP_DDPEXTEND;
elh->el_dnode = gate.sat_addr.s_node;
}
ro->ro_rt->rt_use++;
#ifdef NETATALK_DEBUG
printf ("ddp_route: from %d.%d to %d.%d, via %d.%d (%s)\n",
ntohs(satosat(&aa->aa_addr)->sat_addr.s_net),
satosat(&aa->aa_addr)->sat_addr.s_node,
ntohs(satosat(&ro->ro_dst)->sat_addr.s_net),
satosat(&ro->ro_dst)->sat_addr.s_node,
ntohs(gate.sat_addr.s_net), gate.sat_addr.s_node, ifp->if_xname);
#endif
/* Short-circuit the output if we're sending this to ourself. */
if ((satosat(&aa->aa_addr)->sat_addr.s_net ==
satosat(&ro->ro_dst)->sat_addr.s_net) &&
(satosat(&aa->aa_addr)->sat_addr.s_node ==
satosat(&ro->ro_dst)->sat_addr.s_node)) {
ifa_free(&aa->aa_ifa);
return (if_simloop(ifp, m, gate.sat_family, 0));
}
ifa_free(&aa->aa_ifa);
/* XXX */
return ((*ifp->if_output)(ifp, m, (struct sockaddr *)&gate, NULL));
}

View File

@ -1,418 +0,0 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright (c) 2004-2009 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Copyright (c) 1990, 1994 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
* $FreeBSD$
*/
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/priv.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <net/if.h>
#include <net/route.h>
#include <net/netisr.h>
#include <netatalk/at.h>
#include <netatalk/at_var.h>
#include <netatalk/ddp_var.h>
#include <netatalk/ddp_pcb.h>
#include <netatalk/at_extern.h>
struct mtx ddp_list_mtx;
static struct ddpcb *ddp_ports[ATPORT_LAST];
struct ddpcb *ddpcb_list = NULL;
void
at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr)
{
/*
* Prevent modification of ddp during copy of addr.
*/
DDP_LOCK_ASSERT(ddp);
*addr = sodupsockaddr((struct sockaddr *)&ddp->ddp_lsat, M_NOWAIT);
}
int
at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
{
struct sockaddr_at lsat, *sat;
struct at_ifaddr *aa;
struct ddpcb *ddpp;
/*
* We read and write both the ddp passed in, and also ddp_ports.
*/
DDP_LIST_XLOCK_ASSERT();
DDP_LOCK_ASSERT(ddp);
/*
* Shouldn't be bound.
*/
if (ddp->ddp_lsat.sat_port != ATADDR_ANYPORT)
return (EINVAL);
/*
* Validate passed address.
*/
aa = NULL;
if (addr != NULL) {
sat = (struct sockaddr_at *)addr;
if (sat->sat_family != AF_APPLETALK)
return (EAFNOSUPPORT);
if (sat->sat_addr.s_node != ATADDR_ANYNODE ||
sat->sat_addr.s_net != ATADDR_ANYNET) {
AT_IFADDR_RLOCK();
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
if ((sat->sat_addr.s_net ==
AA_SAT(aa)->sat_addr.s_net) &&
(sat->sat_addr.s_node ==
AA_SAT(aa)->sat_addr.s_node))
break;
}
AT_IFADDR_RUNLOCK();
if (aa == NULL)
return (EADDRNOTAVAIL);
}
if (sat->sat_port != ATADDR_ANYPORT) {
if (sat->sat_port < ATPORT_FIRST ||
sat->sat_port >= ATPORT_LAST)
return (EINVAL);
if (sat->sat_port < ATPORT_RESERVED &&
priv_check(td, PRIV_NETATALK_RESERVEDPORT))
return (EACCES);
}
} else {
bzero((caddr_t)&lsat, sizeof(struct sockaddr_at));
lsat.sat_len = sizeof(struct sockaddr_at);
lsat.sat_addr.s_node = ATADDR_ANYNODE;
lsat.sat_addr.s_net = ATADDR_ANYNET;
lsat.sat_family = AF_APPLETALK;
sat = &lsat;
}
if (sat->sat_addr.s_node == ATADDR_ANYNODE &&
sat->sat_addr.s_net == ATADDR_ANYNET) {
AT_IFADDR_RLOCK();
if (TAILQ_EMPTY(&at_ifaddrhead)) {
AT_IFADDR_RUNLOCK();
return (EADDRNOTAVAIL);
}
sat->sat_addr = AA_SAT(TAILQ_FIRST(&at_ifaddrhead))->sat_addr;
AT_IFADDR_RUNLOCK();
}
ddp->ddp_lsat = *sat;
/*
* Choose port.
*/
if (sat->sat_port == ATADDR_ANYPORT) {
for (sat->sat_port = ATPORT_RESERVED;
sat->sat_port < ATPORT_LAST; sat->sat_port++) {
if (ddp_ports[sat->sat_port - 1] == NULL)
break;
}
if (sat->sat_port == ATPORT_LAST)
return (EADDRNOTAVAIL);
ddp->ddp_lsat.sat_port = sat->sat_port;
ddp_ports[sat->sat_port - 1] = ddp;
} else {
for (ddpp = ddp_ports[sat->sat_port - 1]; ddpp;
ddpp = ddpp->ddp_pnext) {
if (ddpp->ddp_lsat.sat_addr.s_net ==
sat->sat_addr.s_net &&
ddpp->ddp_lsat.sat_addr.s_node ==
sat->sat_addr.s_node)
break;
}
if (ddpp != NULL)
return (EADDRINUSE);
ddp->ddp_pnext = ddp_ports[sat->sat_port - 1];
ddp_ports[sat->sat_port - 1] = ddp;
if (ddp->ddp_pnext != NULL)
ddp->ddp_pnext->ddp_pprev = ddp;
}
return (0);
}
int
at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
{
struct sockaddr_at *sat = (struct sockaddr_at *)addr;
struct route *ro;
struct at_ifaddr *aa = NULL;
struct ifnet *ifp;
u_short hintnet = 0, net;
DDP_LIST_XLOCK_ASSERT();
DDP_LOCK_ASSERT(ddp);
if (sat->sat_family != AF_APPLETALK)
return (EAFNOSUPPORT);
/*
* Under phase 2, network 0 means "the network". We take "the
* network" to mean the network the control block is bound to. If
* the control block is not bound, there is an error.
*/
if (sat->sat_addr.s_net == ATADDR_ANYNET &&
sat->sat_addr.s_node != ATADDR_ANYNODE) {
if (ddp->ddp_lsat.sat_port == ATADDR_ANYPORT)
return (EADDRNOTAVAIL);
hintnet = ddp->ddp_lsat.sat_addr.s_net;
}
ro = &ddp->ddp_route;
/*
* If we've got an old route for this pcb, check that it is valid.
* If we've changed our address, we may have an old "good looking"
* route here. Attempt to detect it.
*/
if (ro->ro_rt) {
if (hintnet)
net = hintnet;
else
net = sat->sat_addr.s_net;
aa = NULL;
AT_IFADDR_RLOCK();
if ((ifp = ro->ro_rt->rt_ifp) != NULL) {
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
if (aa->aa_ifp == ifp &&
ntohs(net) >= ntohs(aa->aa_firstnet) &&
ntohs(net) <= ntohs(aa->aa_lastnet))
break;
}
}
if (aa == NULL || (satosat(&ro->ro_dst)->sat_addr.s_net !=
(hintnet ? hintnet : sat->sat_addr.s_net) ||
satosat(&ro->ro_dst)->sat_addr.s_node !=
sat->sat_addr.s_node)) {
RTFREE(ro->ro_rt);
ro->ro_rt = NULL;
}
AT_IFADDR_RUNLOCK();
}
/*
* If we've got no route for this interface, try to find one.
*/
if (ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL) {
ro->ro_dst.sa_len = sizeof(struct sockaddr_at);
ro->ro_dst.sa_family = AF_APPLETALK;
if (hintnet)
satosat(&ro->ro_dst)->sat_addr.s_net = hintnet;
else
satosat(&ro->ro_dst)->sat_addr.s_net =
sat->sat_addr.s_net;
satosat(&ro->ro_dst)->sat_addr.s_node = sat->sat_addr.s_node;
rtalloc(ro);
}
/*
* Make sure any route that we have has a valid interface.
*/
aa = NULL;
if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp)) {
AT_IFADDR_RLOCK();
TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
if (aa->aa_ifp == ifp)
break;
}
AT_IFADDR_RUNLOCK();
}
if (aa == NULL)
return (ENETUNREACH);
ddp->ddp_fsat = *sat;
if (ddp->ddp_lsat.sat_port == ATADDR_ANYPORT)
return (at_pcbsetaddr(ddp, NULL, td));
return (0);
}
void
at_pcbdisconnect(struct ddpcb *ddp)
{
DDP_LOCK_ASSERT(ddp);
ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
}
int
at_pcballoc(struct socket *so)
{
struct ddpcb *ddp;
DDP_LIST_XLOCK_ASSERT();
ddp = malloc(sizeof *ddp, M_PCB, M_NOWAIT | M_ZERO);
if (ddp == NULL)
return (ENOBUFS);
DDP_LOCK_INIT(ddp);
ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
ddp->ddp_socket = so;
so->so_pcb = (caddr_t)ddp;
ddp->ddp_next = ddpcb_list;
ddp->ddp_prev = NULL;
ddp->ddp_pprev = NULL;
ddp->ddp_pnext = NULL;
if (ddpcb_list != NULL)
ddpcb_list->ddp_prev = ddp;
ddpcb_list = ddp;
return(0);
}
void
at_pcbdetach(struct socket *so, struct ddpcb *ddp)
{
/*
* We modify ddp, ddp_ports, and the global list.
*/
DDP_LIST_XLOCK_ASSERT();
DDP_LOCK_ASSERT(ddp);
KASSERT(so->so_pcb != NULL, ("at_pcbdetach: so_pcb == NULL"));
so->so_pcb = NULL;
/* Remove ddp from ddp_ports list. */
if (ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
ddp_ports[ddp->ddp_lsat.sat_port - 1] != NULL) {
if (ddp->ddp_pprev != NULL)
ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
else
ddp_ports[ddp->ddp_lsat.sat_port - 1] = ddp->ddp_pnext;
if (ddp->ddp_pnext != NULL)
ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
}
if (ddp->ddp_route.ro_rt)
RTFREE(ddp->ddp_route.ro_rt);
if (ddp->ddp_prev)
ddp->ddp_prev->ddp_next = ddp->ddp_next;
else
ddpcb_list = ddp->ddp_next;
if (ddp->ddp_next)
ddp->ddp_next->ddp_prev = ddp->ddp_prev;
DDP_UNLOCK(ddp);
DDP_LOCK_DESTROY(ddp);
free(ddp, M_PCB);
}
/*
* For the moment, this just find the pcb with the correct local address. In
* the future, this will actually do some real searching, so we can use the
* sender's address to do de-multiplexing on a single port to many sockets
* (pcbs).
*/
struct ddpcb *
ddp_search(struct sockaddr_at *from, struct sockaddr_at *to,
struct at_ifaddr *aa)
{
struct ddpcb *ddp;
DDP_LIST_SLOCK_ASSERT();
/*
* Check for bad ports.
*/
if (to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST)
return (NULL);
/*
* Make sure the local address matches the sent address. What about
* the interface?
*/
for (ddp = ddp_ports[to->sat_port - 1]; ddp; ddp = ddp->ddp_pnext) {
DDP_LOCK(ddp);
/* XXX should we handle 0.YY? */
/* XXXX.YY to socket on destination interface */
if (to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node) {
DDP_UNLOCK(ddp);
break;
}
/* 0.255 to socket on receiving interface */
if (to->sat_addr.s_node == ATADDR_BCAST &&
(to->sat_addr.s_net == 0 ||
to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net) &&
ddp->ddp_lsat.sat_addr.s_net ==
AA_SAT(aa)->sat_addr.s_net) {
DDP_UNLOCK(ddp);
break;
}
/* XXXX.0 to socket on destination interface */
if (to->sat_addr.s_net == aa->aa_firstnet &&
to->sat_addr.s_node == 0 &&
ntohs(ddp->ddp_lsat.sat_addr.s_net) >=
ntohs(aa->aa_firstnet) &&
ntohs(ddp->ddp_lsat.sat_addr.s_net) <=
ntohs(aa->aa_lastnet)) {
DDP_UNLOCK(ddp);
break;
}
DDP_UNLOCK(ddp);
}
return (ddp);
}

View File

@ -1,84 +0,0 @@
/*-
* Copyright (c) 2004 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Copyright (c) 1990, 1994 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
*
* $FreeBSD$
*/
#ifndef _NETATALK_DDP_PCB_H_
#define _NETATALK_DDP_PCB_H_
int at_pcballoc(struct socket *so);
int at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr,
struct thread *td);
void at_pcbdetach(struct socket *so, struct ddpcb *ddp);
void at_pcbdisconnect(struct ddpcb *ddp);
int at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr,
struct thread *td);
void at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr);
/* Lock macros for per-pcb locks. */
#define DDP_LOCK_INIT(ddp) mtx_init(&(ddp)->ddp_mtx, "ddp_mtx", \
NULL, MTX_DEF)
#define DDP_LOCK_DESTROY(ddp) mtx_destroy(&(ddp)->ddp_mtx)
#define DDP_LOCK(ddp) mtx_lock(&(ddp)->ddp_mtx)
#define DDP_UNLOCK(ddp) mtx_unlock(&(ddp)->ddp_mtx)
#define DDP_LOCK_ASSERT(ddp) mtx_assert(&(ddp)->ddp_mtx, MA_OWNED)
/* Lock macros for global pcb list lock. */
#define DDP_LIST_LOCK_INIT() mtx_init(&ddp_list_mtx, "ddp_list_mtx", \
NULL, MTX_DEF)
#define DDP_LIST_LOCK_DESTROY() mtx_destroy(&ddp_list_mtx)
#define DDP_LIST_XLOCK() mtx_lock(&ddp_list_mtx)
#define DDP_LIST_XUNLOCK() mtx_unlock(&ddp_list_mtx)
#define DDP_LIST_XLOCK_ASSERT() mtx_assert(&ddp_list_mtx, MA_OWNED)
#define DDP_LIST_SLOCK() mtx_lock(&ddp_list_mtx)
#define DDP_LIST_SUNLOCK() mtx_unlock(&ddp_list_mtx)
#define DDP_LIST_SLOCK_ASSERT() mtx_assert(&ddp_list_mtx, MA_OWNED)
#endif /* !_NETATALK_DDP_PCB_H_ */

View File

@ -1,333 +0,0 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
* Copyright (c) 2004-2009 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Copyright (c) 1990, 1994 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
*
* $FreeBSD$
*/
#include <rtems/bsd/sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <net/if.h>
#include <net/route.h>
#include <net/netisr.h>
#include <netatalk/at.h>
#include <netatalk/at_var.h>
#include <netatalk/ddp_var.h>
#include <netatalk/ddp_pcb.h>
#include <netatalk/at_extern.h>
static u_long ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
static u_long ddp_recvspace = 10 * (587 + sizeof(struct sockaddr_at));
static const struct netisr_handler atalk1_nh = {
.nh_name = "atalk1",
.nh_handler = at1intr,
.nh_proto = NETISR_ATALK1,
.nh_policy = NETISR_POLICY_SOURCE,
};
static const struct netisr_handler atalk2_nh = {
.nh_name = "atalk2",
.nh_handler = at2intr,
.nh_proto = NETISR_ATALK2,
.nh_policy = NETISR_POLICY_SOURCE,
};
static const struct netisr_handler aarp_nh = {
.nh_name = "aarp",
.nh_handler = aarpintr,
.nh_proto = NETISR_AARP,
.nh_policy = NETISR_POLICY_SOURCE,
};
static int
ddp_attach(struct socket *so, int proto, struct thread *td)
{
int error = 0;
KASSERT(sotoddpcb(so) == NULL, ("ddp_attach: ddp != NULL"));
/*
* Allocate socket buffer space first so that it's present
* before first use.
*/
error = soreserve(so, ddp_sendspace, ddp_recvspace);
if (error)
return (error);
DDP_LIST_XLOCK();
error = at_pcballoc(so);
DDP_LIST_XUNLOCK();
return (error);
}
static void
ddp_detach(struct socket *so)
{
struct ddpcb *ddp;
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("ddp_detach: ddp == NULL"));
DDP_LIST_XLOCK();
DDP_LOCK(ddp);
at_pcbdetach(so, ddp);
DDP_LIST_XUNLOCK();
}
static int
ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
{
struct ddpcb *ddp;
int error = 0;
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("ddp_bind: ddp == NULL"));
DDP_LIST_XLOCK();
DDP_LOCK(ddp);
error = at_pcbsetaddr(ddp, nam, td);
DDP_UNLOCK(ddp);
DDP_LIST_XUNLOCK();
return (error);
}
static int
ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
struct ddpcb *ddp;
int error = 0;
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("ddp_connect: ddp == NULL"));
DDP_LIST_XLOCK();
DDP_LOCK(ddp);
if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
DDP_UNLOCK(ddp);
DDP_LIST_XUNLOCK();
return (EISCONN);
}
error = at_pcbconnect( ddp, nam, td );
DDP_UNLOCK(ddp);
DDP_LIST_XUNLOCK();
if (error == 0)
soisconnected(so);
return (error);
}
static int
ddp_disconnect(struct socket *so)
{
struct ddpcb *ddp;
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("ddp_disconnect: ddp == NULL"));
DDP_LOCK(ddp);
if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) {
DDP_UNLOCK(ddp);
return (ENOTCONN);
}
at_pcbdisconnect(ddp);
ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
DDP_UNLOCK(ddp);
soisdisconnected(so);
return (0);
}
static int
ddp_shutdown(struct socket *so)
{
KASSERT(sotoddpcb(so) != NULL, ("ddp_shutdown: ddp == NULL"));
socantsendmore(so);
return (0);
}
static int
ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
struct mbuf *control, struct thread *td)
{
struct ddpcb *ddp;
int error = 0;
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("ddp_send: ddp == NULL"));
if (control && control->m_len)
return (EINVAL);
if (addr != NULL) {
DDP_LIST_XLOCK();
DDP_LOCK(ddp);
if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
error = EISCONN;
goto out;
}
error = at_pcbconnect(ddp, addr, td);
if (error == 0) {
error = ddp_output(m, so);
at_pcbdisconnect(ddp);
}
out:
DDP_UNLOCK(ddp);
DDP_LIST_XUNLOCK();
} else {
DDP_LOCK(ddp);
if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT)
error = ENOTCONN;
else
error = ddp_output(m, so);
DDP_UNLOCK(ddp);
}
return (error);
}
/*
* XXXRW: This is never called because we only invoke abort on stream
* protocols.
*/
static void
ddp_abort(struct socket *so)
{
struct ddpcb *ddp;
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("ddp_abort: ddp == NULL"));
DDP_LOCK(ddp);
at_pcbdisconnect(ddp);
DDP_UNLOCK(ddp);
soisdisconnected(so);
}
static void
ddp_close(struct socket *so)
{
struct ddpcb *ddp;
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("ddp_close: ddp == NULL"));
DDP_LOCK(ddp);
at_pcbdisconnect(ddp);
DDP_UNLOCK(ddp);
soisdisconnected(so);
}
void
ddp_init(void)
{
DDP_LIST_LOCK_INIT();
TAILQ_INIT(&at_ifaddrhead);
netisr_register(&atalk1_nh);
netisr_register(&atalk2_nh);
netisr_register(&aarp_nh);
}
#if 0
static void
ddp_clean(void)
{
struct ddpcp *ddp;
for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next)
at_pcbdetach(ddp->ddp_socket, ddp);
DDP_LIST_LOCK_DESTROY();
}
#endif
static int
at_getpeeraddr(struct socket *so, struct sockaddr **nam)
{
return (EOPNOTSUPP);
}
static int
at_getsockaddr(struct socket *so, struct sockaddr **nam)
{
struct ddpcb *ddp;
ddp = sotoddpcb(so);
KASSERT(ddp != NULL, ("at_getsockaddr: ddp == NULL"));
DDP_LOCK(ddp);
at_sockaddr(ddp, nam);
DDP_UNLOCK(ddp);
return (0);
}
struct pr_usrreqs ddp_usrreqs = {
.pru_abort = ddp_abort,
.pru_attach = ddp_attach,
.pru_bind = ddp_bind,
.pru_connect = ddp_connect,
.pru_control = at_control,
.pru_detach = ddp_detach,
.pru_disconnect = ddp_disconnect,
.pru_peeraddr = at_getpeeraddr,
.pru_send = ddp_send,
.pru_shutdown = ddp_shutdown,
.pru_sockaddr = at_getsockaddr,
.pru_close = ddp_close,
};

View File

@ -1,63 +0,0 @@
/*-
* Copyright (c) 1990, 1994 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
*
* $FreeBSD$
*/
#ifndef _NETATALK_DDP_VAR_H_
#define _NETATALK_DDP_VAR_H_
struct ddpcb {
struct sockaddr_at ddp_fsat, ddp_lsat;
struct route ddp_route;
struct socket *ddp_socket;
struct ddpcb *ddp_prev, *ddp_next;
struct ddpcb *ddp_pprev, *ddp_pnext;
struct mtx ddp_mtx;
};
#define sotoddpcb(so) ((struct ddpcb *)(so)->so_pcb)
struct ddpstat {
long ddps_short; /* short header packets received */
long ddps_long; /* long header packets received */
long ddps_nosum; /* no checksum */
long ddps_badsum; /* bad checksum */
long ddps_tooshort; /* packet too short */
long ddps_toosmall; /* not enough data */
long ddps_forward; /* packets forwarded */
long ddps_encap; /* packets encapsulated */
long ddps_cantforward; /* packets rcvd for unreachable dest */
long ddps_nosockspace; /* no space in sockbuf for packet */
};
#ifdef _KERNEL
extern int ddp_cksum;
extern struct ddpcb *ddpcb_list;
extern struct pr_usrreqs ddp_usrreqs;
extern struct mtx ddp_list_mtx;
#endif
#endif /* _NETATALK_DDP_VAR_H_ */

View File

@ -1,31 +0,0 @@
/*-
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Mike Clark
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-763-0525
* netatalk@itd.umich.edu
*
* $FreeBSD$
*/
#ifndef _ATALK_ENDIAN_H_
#define _ATALK_ENDIAN_H_
#include <machine/endian.h>
#endif /* !_ATALK_ENDIAN_H_ */

View File

@ -1,34 +0,0 @@
/*-
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation, and that the name of The University
* of Michigan not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. This software is supplied as is without expressed or
* implied warranties of any kind.
*
* This product includes software developed by the University of
* California, Berkeley and its contributors.
*
* Research Systems Unix Group
* The University of Michigan
* c/o Wesley Craig
* 535 W. William Street
* Ann Arbor, Michigan
* +1-313-764-2278
* netatalk@umich.edu
* $FreeBSD$
*/
#include <net/if_llc.h>
#define llc_org_code llc_un.type_snap.org_code
#define llc_ether_type llc_un.type_snap.ether_type
#define SIOCPHASE1 _IOW('i', 100, struct ifreq) /* AppleTalk phase 1 */
#define SIOCPHASE2 _IOW('i', 101, struct ifreq) /* AppleTalk phase 2 */

View File

@ -1,287 +0,0 @@
#include <machine/rtems-bsd-user-space.h>
/*-
* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)atalk.c 1.1 (Whistle) 6/6/96";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/bsd/sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <arpa/inet.h>
#include <net/route.h>
#include <netatalk/at.h>
#include <netatalk/ddp_var.h>
#include <errno.h>
#include <nlist.h>
#include <netdb.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "netstat.h"
struct ddpcb ddpcb;
struct socket sockb;
static int first = 1;
/*
* Print a summary of connections related to a Network Systems
* protocol. For XXX, also give state of connection.
* Listening processes (aflag) are suppressed unless the
* -a (all) flag is specified.
*/
static const char *
at_pr_net(struct sockaddr_at *sat, int numeric)
{
static char mybuf[50];
if (!numeric) {
switch(sat->sat_addr.s_net) {
case 0xffff:
return "????";
case ATADDR_ANYNET:
return("*");
}
}
sprintf(mybuf,"%hu",ntohs(sat->sat_addr.s_net));
return mybuf;
}
static const char *
at_pr_host(struct sockaddr_at *sat, int numeric)
{
static char mybuf[50];
if (!numeric) {
switch(sat->sat_addr.s_node) {
case ATADDR_BCAST:
return "bcast";
case ATADDR_ANYNODE:
return("*");
}
}
sprintf(mybuf,"%d",(unsigned int)sat->sat_addr.s_node);
return mybuf;
}
static const char *
at_pr_port(struct sockaddr_at *sat)
{
static char mybuf[50];
struct servent *serv;
switch(sat->sat_port) {
case ATADDR_ANYPORT:
return("*");
case 0xff:
return "????";
default:
if (numeric_port) {
(void)snprintf(mybuf, sizeof(mybuf), "%d",
(unsigned int)sat->sat_port);
} else {
serv = getservbyport(sat->sat_port, "ddp");
if (serv == NULL)
(void)snprintf(mybuf, sizeof(mybuf), "%d",
(unsigned int) sat->sat_port);
else
(void) snprintf(mybuf, sizeof(mybuf), "%s",
serv->s_name);
}
}
return mybuf;
}
static char *
at_pr_range(struct sockaddr_at *sat)
{
static char mybuf[50];
if(sat->sat_range.r_netrange.nr_firstnet
!= sat->sat_range.r_netrange.nr_lastnet) {
sprintf(mybuf,"%d-%d",
ntohs(sat->sat_range.r_netrange.nr_firstnet),
ntohs(sat->sat_range.r_netrange.nr_lastnet));
} else {
sprintf(mybuf,"%d",
ntohs(sat->sat_range.r_netrange.nr_firstnet));
}
return mybuf;
}
/* what == 0 for addr only == 3 */
/* 1 for net */
/* 2 for host */
/* 4 for port */
/* 8 for numeric only */
char *
atalk_print(struct sockaddr *sa, int what)
{
struct sockaddr_at *sat = (struct sockaddr_at *)sa;
static char mybuf[50];
int numeric = (what & 0x08);
mybuf[0] = 0;
switch (what & 0x13) {
case 0:
mybuf[0] = 0;
break;
case 1:
sprintf(mybuf,"%s",at_pr_net(sat, numeric));
break;
case 2:
sprintf(mybuf,"%s",at_pr_host(sat, numeric));
break;
case 3:
sprintf(mybuf,"%s.%s",
at_pr_net(sat, numeric),
at_pr_host(sat, numeric));
break;
case 0x10:
sprintf(mybuf,"%s", at_pr_range(sat));
}
if (what & 4) {
sprintf(mybuf+strlen(mybuf),".%s",at_pr_port(sat));
}
return mybuf;
}
char *
atalk_print2(struct sockaddr *sa, struct sockaddr *mask, int what)
{
int n;
static char buf[100];
struct sockaddr_at *sat1, *sat2;
struct sockaddr_at thesockaddr;
struct sockaddr *sa2;
sat1 = (struct sockaddr_at *)sa;
sat2 = (struct sockaddr_at *)mask;
sa2 = (struct sockaddr *)&thesockaddr;
thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net & sat2->sat_addr.s_net;
snprintf(buf, sizeof(buf), "%s", atalk_print(sa2, 1 |(what & 8)));
if(sat2->sat_addr.s_net != 0xFFFF) {
thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net | ~sat2->sat_addr.s_net;
n = strlen(buf);
snprintf(buf + n, sizeof(buf) - n, "-%s", atalk_print(sa2, 1 |(what & 8)));
}
if(what & 2) {
n = strlen(buf);
snprintf(buf + n, sizeof(buf) - n, ".%s", atalk_print(sa, what & (~1)));
}
return(buf);
}
void
atalkprotopr(u_long off __unused, const char *name, int af1 __unused,
int proto __unused)
{
struct ddpcb *this, *next;
if (off == 0)
return;
kread(off, (char *)&this, sizeof (struct ddpcb *));
for ( ; this != NULL; this = next) {
kread((u_long)this, (char *)&ddpcb, sizeof (ddpcb));
next = ddpcb.ddp_next;
#if 0
if (!aflag && atalk_nullhost(ddpcb.ddp_lsat) ) {
continue;
}
#endif
kread((u_long)ddpcb.ddp_socket, (char *)&sockb, sizeof (sockb));
if (first) {
printf("Active ATALK connections");
if (aflag)
printf(" (including servers)");
putchar('\n');
if (Aflag)
printf("%-8.8s ", "PCB");
printf(Aflag ?
"%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
"%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
"Proto", "Recv-Q", "Send-Q",
"Local Address", "Foreign Address", "(state)");
first = 0;
}
if (Aflag)
printf("%8lx ", (u_long) this);
printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc,
sockb.so_snd.sb_cc);
printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
(struct sockaddr *)&ddpcb.ddp_lsat,7));
printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
(struct sockaddr *)&ddpcb.ddp_fsat,7));
putchar('\n');
}
}
#define ANY(x,y,z) if (x || sflag <= 1) \
printf("\t%lu %s%s%s\n",x,y,plural(x),z)
/*
* Dump DDP statistics structure.
*/
void
ddp_stats(u_long off __unused, const char *name, int af1 __unused,
int proto __unused)
{
struct ddpstat ddpstat;
if (off == 0)
return;
kread(off, (char *)&ddpstat, sizeof (ddpstat));
printf("%s:\n", name);
ANY(ddpstat.ddps_short, "packet", " with short headers ");
ANY(ddpstat.ddps_long, "packet", " with long headers ");
ANY(ddpstat.ddps_nosum, "packet", " with no checksum ");
ANY(ddpstat.ddps_tooshort, "packet", " too short ");
ANY(ddpstat.ddps_badsum, "packet", " with bad checksum ");
ANY(ddpstat.ddps_toosmall, "packet", " with not enough data ");
ANY(ddpstat.ddps_forward, "packet", " forwarded ");
ANY(ddpstat.ddps_encap, "packet", " encapsulated ");
ANY(ddpstat.ddps_cantforward, "packet", " rcvd for unreachable dest ");
ANY(ddpstat.ddps_nosockspace, "packet", " dropped due to no socket space ");
}

View File

@ -877,15 +877,6 @@ def dev_nic(mm):
'sys/sys/kenv.h',
'sys/isa/isavar.h',
'sys/isa/pnpvar.h',
'sys/netatalk/at.h',
'sys/netatalk/endian.h',
'sys/netatalk/aarp.h',
'sys/netatalk/at_extern.h',
'sys/netatalk/at_var.h',
'sys/netatalk/ddp.h',
'sys/netatalk/ddp_pcb.h',
'sys/netatalk/ddp_var.h',
'sys/netatalk/phase2.h',
'sys/sys/buf.h',
'sys/sys/mqueue.h',
'sys/sys/tty.h',
@ -918,14 +909,6 @@ def dev_nic(mm):
'sys/dev/random/harvest.c',
'sys/netinet/tcp_hostcache.c',
'sys/dev/led/led.c',
'sys/netatalk/aarp.c',
'sys/netatalk/at_control.c',
'sys/netatalk/at_rmx.c',
'sys/netatalk/ddp_input.c',
'sys/netatalk/ddp_pcb.c',
'sys/netatalk/ddp_usrreq.c',
'sys/netatalk/at_proto.c',
'sys/netatalk/ddp_output.c',
],
mm.generator['source']()
)
@ -2108,7 +2091,6 @@ def user_space(mm):
'sbin/dhclient/privsep.c',
'sbin/dhclient/tables.c',
'sbin/dhclient/tree.c',
'sbin/ifconfig/af_atalk.c',
'sbin/ifconfig/af_inet6.c',
'sbin/ifconfig/af_inet.c',
'sbin/ifconfig/af_link.c',
@ -2129,7 +2111,6 @@ def user_space(mm):
'sbin/ping/ping.c',
'sbin/route/route.c',
'sbin/sysctl/sysctl.c',
'usr.bin/netstat/atalk.c',
'usr.bin/netstat/bpf.c',
'usr.bin/netstat/if.c',
'usr.bin/netstat/inet6.c',

View File

@ -408,7 +408,6 @@ def build(bld):
'freebsd/sbin/dhclient/privsep.c',
'freebsd/sbin/dhclient/tables.c',
'freebsd/sbin/dhclient/tree.c',
'freebsd/sbin/ifconfig/af_atalk.c',
'freebsd/sbin/ifconfig/af_inet.c',
'freebsd/sbin/ifconfig/af_inet6.c',
'freebsd/sbin/ifconfig/af_link.c',
@ -429,7 +428,6 @@ def build(bld):
'freebsd/sbin/ping6/ping6.c',
'freebsd/sbin/route/route.c',
'freebsd/sbin/sysctl/sysctl.c',
'freebsd/usr.bin/netstat/atalk.c',
'freebsd/usr.bin/netstat/bpf.c',
'freebsd/usr.bin/netstat/if.c',
'freebsd/usr.bin/netstat/inet.c',
@ -896,14 +894,6 @@ def build(bld):
'freebsd/sys/net/route.c',
'freebsd/sys/net/rtsock.c',
'freebsd/sys/net/slcompress.c',
'freebsd/sys/netatalk/aarp.c',
'freebsd/sys/netatalk/at_control.c',
'freebsd/sys/netatalk/at_proto.c',
'freebsd/sys/netatalk/at_rmx.c',
'freebsd/sys/netatalk/ddp_input.c',
'freebsd/sys/netatalk/ddp_output.c',
'freebsd/sys/netatalk/ddp_pcb.c',
'freebsd/sys/netatalk/ddp_usrreq.c',
'freebsd/sys/netinet/accf_data.c',
'freebsd/sys/netinet/accf_dns.c',
'freebsd/sys/netinet/accf_http.c',
@ -1205,7 +1195,6 @@ def build(bld):
('freebsd/sys/cam', '*.h', 'cam'),
('freebsd/sys/net', '*.h', 'net'),
('freebsd/sys/net80211', '*.h', 'net80211'),
('freebsd/sys/netatalk', '*.h', 'netatalk'),
('freebsd/sys/netinet', '*.h', 'netinet'),
('freebsd/sys/netinet6', '*.h', 'netinet6'),
('freebsd/sys/netipsec', '*.h', 'netipsec'),