136367Ssklower /***********************************************************
236367Ssklower Copyright IBM Corporation 1987
336367Ssklower
436367Ssklower All Rights Reserved
536367Ssklower
636367Ssklower Permission to use, copy, modify, and distribute this software and its
736367Ssklower documentation for any purpose and without fee is hereby granted,
836367Ssklower provided that the above copyright notice appear in all copies and that
936367Ssklower both that copyright notice and this permission notice appear in
1036367Ssklower supporting documentation, and that the name of IBM not be
1136367Ssklower used in advertising or publicity pertaining to distribution of the
1236367Ssklower software without specific, written prior permission.
1336367Ssklower
1436367Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536367Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636367Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736367Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836367Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936367Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036367Ssklower SOFTWARE.
2136367Ssklower
2236367Ssklower ******************************************************************/
2336367Ssklower
2436367Ssklower /*
2536367Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636367Ssklower */
2736367Ssklower /* $Header: clnp_arp.c,v 4.2 88/06/29 14:58:32 hagens Exp $ */
2836367Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_arp.c,v $ */
2936367Ssklower
3036367Ssklower #ifndef lint
3136367Ssklower static char *rcsid = "$Header: clnp_arp.c,v 4.2 88/06/29 14:58:32 hagens Exp $";
3236367Ssklower #endif lint
3336367Ssklower
3436367Ssklower #ifdef ISO
3536367Ssklower
36*37536Smckusick #include "types.h"
37*37536Smckusick #include "param.h"
38*37536Smckusick #include "mbuf.h"
39*37536Smckusick #include "domain.h"
40*37536Smckusick #include "protosw.h"
41*37536Smckusick #include "socket.h"
42*37536Smckusick #include "socketvar.h"
43*37536Smckusick #include "errno.h"
44*37536Smckusick #include "ioctl.h"
4536367Ssklower
4636367Ssklower #include "../net/if.h"
4736367Ssklower #include "../net/route.h"
4836367Ssklower
4937470Ssklower #include "iso.h"
5037470Ssklower #include "iso_var.h"
5137470Ssklower #include "iso_map.h"
5237470Ssklower #include "iso_snpac.h"
5337470Ssklower #include "clnp.h"
5437470Ssklower #include "clnp_stat.h"
5537470Ssklower #include "argo_debug.h"
5636367Ssklower
5736367Ssklower #define MAPTAB_BSIZ 20 /* bucket size */
5836367Ssklower #define MAPTAB_NB 13 /* number of buckets */
5936367Ssklower #define MAPTAB_SIZE (MAPTAB_BSIZ * MAPTAB_NB)
6036367Ssklower struct maptab iso_maptab[MAPTAB_SIZE];
6136367Ssklower int iso_maptab_size = MAPTAB_SIZE; /* for isomap command */
6236367Ssklower
6336367Ssklower #define MAPTAB_HASH(addr) \
6436367Ssklower (((u_long) iso_hashchar(addr, addr->isoa_len)) % MAPTAB_NB)
6536367Ssklower
6636367Ssklower #define MAPTAB_LOOK(at,addr) { \
6736367Ssklower register n; \
6836367Ssklower at = &iso_maptab[MAPTAB_HASH(addr) * MAPTAB_BSIZ]; \
6936367Ssklower for (n = 0 ; n < MAPTAB_BSIZ ; n++,at++) \
7036367Ssklower if ((at->map_valid) && (iso_addrmatch1(&at->map_isoa, addr))) \
7136367Ssklower break; \
7236367Ssklower if (n >= MAPTAB_BSIZ) \
7336367Ssklower at = 0; \
7436367Ssklower }
7536367Ssklower
7636367Ssklower /*
7736367Ssklower * FUNCTION: clnp_arpresolve
7836367Ssklower *
7936367Ssklower * PURPOSE: Resolve a clnp address into hardware ethernet addr.
8036367Ssklower *
8136367Ssklower * RETURNS: 1 if addr is resolved
8236367Ssklower * 0 if addr is unknown
8336367Ssklower *
8436367Ssklower * SIDE EFFECTS:
8536367Ssklower *
8636367Ssklower * NOTES: This is a hack. If the address is local, then
8736367Ssklower * the packet is put on the loopback driver. Otherwise,
8836367Ssklower * if a translation is found, that ethernet address is
8936367Ssklower * returned. Otherwise, the packet is dropped. Thus,
9036367Ssklower * each translation must be placed (by hand) in the
9136367Ssklower * tables (see isomap(8)).
9236367Ssklower * TODO: should this map stuff be a critical section?
9336367Ssklower */
9436367Ssklower clnp_arpresolve(ifp, m, dst, edst)
9536367Ssklower struct ifnet *ifp; /* outgoing interface */
9636367Ssklower struct mbuf *m; /* pkt */
9736367Ssklower struct sockaddr_iso *dst; /* destination */
9836367Ssklower char *edst; /* RESULT: ethernet address */
9936367Ssklower {
10036367Ssklower extern struct ifnet loif; /* loopback interface */
10136367Ssklower struct maptab *at; /* ptr to map table entry */
10236367Ssklower struct iso_addr *destiso; /* destination iso addr */
10336367Ssklower
10436367Ssklower destiso = &dst->siso_addr;
10536367Ssklower
10637470Ssklower if (destiso->isoa_genaddr[0] == AFI_SNA) {
10736367Ssklower /*
10836367Ssklower * This is a subnetwork address. Return it immediately
10936367Ssklower */
11036367Ssklower int sna_len;
11136367Ssklower
11236367Ssklower IFDEBUG(D_ESISOUTPUT)
11336367Ssklower printf("clnp_arpresolve: return SN address\n");
11436367Ssklower ENDDEBUG
11536367Ssklower
11636367Ssklower sna_len = destiso->isoa_len - 1; /* subtract size of AFI */
11736367Ssklower if (sna_len != 6) {
11836367Ssklower IFDEBUG(D_ESISOUTPUT)
11936367Ssklower printf("clnp_arpresolve: SN len is bad (%d)\n", sna_len);
12036367Ssklower ENDDEBUG
12136367Ssklower return(-1);
12236367Ssklower }
12337470Ssklower bcopy((caddr_t)&destiso->isoa_genaddr[1], (caddr_t)edst, sna_len);
12436367Ssklower return (1);
12536367Ssklower }
12636367Ssklower
12736367Ssklower IFDEBUG(D_ETHER)
12836367Ssklower printf("clnp_arpresolve: resolving %s\n", clnp_iso_addrp(destiso));
12936367Ssklower ENDDEBUG
13036367Ssklower
13136367Ssklower /* if for us, use software loopback driver if up */
13236367Ssklower if (clnp_ours(destiso)) {
13336367Ssklower IFDEBUG(D_ETHER)
13436367Ssklower printf("clnp_arpresolve: local destination\n");
13536367Ssklower ENDDEBUG
13636367Ssklower if (loif.if_flags & IFF_UP) {
13736367Ssklower IFDEBUG(D_ETHER)
13836367Ssklower printf("clnp_arpresolve: calling looutput\n");
13936367Ssklower ENDDEBUG
14036367Ssklower (void) looutput(&loif, m, (struct sockaddr *)dst);
14136367Ssklower /*
14236367Ssklower * The packet has already been sent and freed.
14336367Ssklower */
14436367Ssklower return (0);
14536367Ssklower }
14636367Ssklower }
14736367Ssklower
14836367Ssklower IFDEBUG(D_ETHER)
14936367Ssklower printf("clnp_arpresolve: NON-local destination\n");
15036367Ssklower ENDDEBUG
15136367Ssklower
15236367Ssklower /*
15336367Ssklower * packet is not for us, check static map table for an entry
15436367Ssklower * This does not need to be a critical section because the
15536367Ssklower * table is not dynamically updated, except by a call to
15636367Ssklower * isomap(8)
15736367Ssklower */
15836367Ssklower MAPTAB_LOOK(at, destiso);
15936367Ssklower if (at == 0) { /* not found */
16036367Ssklower m_freem(m);
16136367Ssklower return (-1);
16236367Ssklower } else {
16336367Ssklower bcopy((caddr_t)at->map_enaddr, (caddr_t)edst, sizeof(at->map_enaddr));
16436367Ssklower return (1);
16536367Ssklower }
16636367Ssklower }
16736367Ssklower
16836367Ssklower /*
16936367Ssklower * FUNCTION: isomap_new
17036367Ssklower *
17136367Ssklower * PURPOSE: create a new entry in the iso address to ethernet
17236367Ssklower * address table
17336367Ssklower *
17436367Ssklower * RETURNS: pointer to newest entry, or NULL if none can be found
17536367Ssklower *
17636367Ssklower * SIDE EFFECTS:
17736367Ssklower *
17836367Ssklower * NOTES: TODO: timeout old entries
17936367Ssklower */
18036367Ssklower struct maptab *
isomap_new(isoa)18136367Ssklower isomap_new(isoa)
18236367Ssklower struct iso_addr *isoa; /* iso address to enter into table */
18336367Ssklower {
18436367Ssklower register struct maptab *at;
18536367Ssklower register int n;
18636367Ssklower
18736367Ssklower at = &iso_maptab[MAPTAB_HASH(isoa) * MAPTAB_BSIZ];
18836367Ssklower for (n = 0 ; n < MAPTAB_BSIZ ; n++,at++) {
18936367Ssklower
19036367Ssklower IFDEBUG (D_IOCTL)
19136367Ssklower printf("isomap_new: at x%x ", at);
19236367Ssklower
19336367Ssklower if (at->map_valid) {
19436367Ssklower int i;
19536367Ssklower
19636367Ssklower printf("(valid) %s ", clnp_iso_addrp(&at->map_isoa));
19736367Ssklower for (i=0; i<6; i++)
19836367Ssklower printf("%x%c", at->map_enaddr[i], i < 5 ? ':' : '\n');
19936367Ssklower } else {
20036367Ssklower printf("invalid\n");
20136367Ssklower }
20236367Ssklower ENDDEBUG
20336367Ssklower
20436367Ssklower if (!at->map_valid) /* found unused slot */
20536367Ssklower return at;
20636367Ssklower }
20736367Ssklower return NULL;
20836367Ssklower }
20936367Ssklower
21036367Ssklower /*
21136367Ssklower * FUNCTION: isomap_free
21236367Ssklower *
21336367Ssklower * PURPOSE: free an entry in the iso address map table
21436367Ssklower *
21536367Ssklower * RETURNS: nothing
21636367Ssklower *
21736367Ssklower * SIDE EFFECTS:
21836367Ssklower *
21936367Ssklower * NOTES:
22036367Ssklower */
isomap_free(at)22136367Ssklower isomap_free(at)
22236367Ssklower register struct maptab *at; /* entry to free */
22336367Ssklower {
22436367Ssklower at->map_valid = 0;
22536367Ssklower }
22636367Ssklower
22736367Ssklower /*
22836367Ssklower * FUNCTION: isomap_ioctl
22936367Ssklower *
23036367Ssklower * PURPOSE: handle ioctls to change the iso address map
23136367Ssklower *
23236367Ssklower * RETURNS: unix error code
23336367Ssklower *
23436367Ssklower * SIDE EFFECTS: changes the maptab table declared above.
23536367Ssklower *
23636367Ssklower * NOTES:
23736367Ssklower */
isomap_ioctl(cmd,data)23836367Ssklower isomap_ioctl(cmd, data)
23936367Ssklower int cmd; /* ioctl to process */
24036367Ssklower caddr_t data; /* data for the cmd */
24136367Ssklower {
24237470Ssklower register struct arpreq_iso *ar = (struct arpreq_iso *)data;
24336367Ssklower register struct maptab *at;
24436367Ssklower register struct sockaddr_iso *siso;
24536367Ssklower register struct iso_addr *isoa;
24636367Ssklower
24736367Ssklower /*
24836367Ssklower * only process commands for the ISO address family
24936367Ssklower */
25037470Ssklower if (ar->arp_pa.siso_family != AF_ISO)
25136367Ssklower return(EAFNOSUPPORT);
25236367Ssklower
25336367Ssklower /* look up this address in table */
25436367Ssklower siso = (struct sockaddr_iso *)&ar->arp_pa;
25536367Ssklower isoa = &siso->siso_addr;
25636367Ssklower
25736367Ssklower IFDEBUG (D_IOCTL)
25836367Ssklower int i;
25936367Ssklower
26036367Ssklower printf("isomap_ioctl: ");
26136367Ssklower switch(cmd) {
26236367Ssklower case SIOCSISOMAP: printf("set"); break;
26336367Ssklower case SIOCDISOMAP: printf("delete"); break;
26436367Ssklower case SIOCGISOMAP: printf("get"); break;
26536367Ssklower }
26636367Ssklower printf(" %s to ", clnp_iso_addrp(isoa));
26736367Ssklower for (i=0; i<6; i++)
26836367Ssklower printf("%x%c", ar->arp_ha.sa_data[i], i < 5 ? ':' : '\n');
26936367Ssklower ENDDEBUG
27036367Ssklower
27136367Ssklower MAPTAB_LOOK(at, isoa);
27236367Ssklower if (at == NULL) { /* not found */
27336367Ssklower if (cmd != SIOCSISOMAP)
27436367Ssklower return(ENXIO);
27536367Ssklower
27636367Ssklower /* TODO: what if setting and net is not directly attached */
27736367Ssklower }
27836367Ssklower
27936367Ssklower switch(cmd) {
28036367Ssklower case SIOCSISOMAP: /* set entry */
28136367Ssklower if (at == NULL) {
28236367Ssklower at = isomap_new(isoa);
28336367Ssklower if (at == NULL)
28436367Ssklower return(ENOBUFS);
28536367Ssklower }
28636367Ssklower bcopy((caddr_t)isoa, (caddr_t)&at->map_isoa,
28736367Ssklower sizeof (struct iso_addr));
28836367Ssklower bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->map_enaddr,
28936367Ssklower sizeof(at->map_enaddr));
29036367Ssklower at->map_valid++;
29136367Ssklower break;
29236367Ssklower
29336367Ssklower case SIOCDISOMAP: /* delete entry */
29436367Ssklower isomap_free(at);
29536367Ssklower break;
29636367Ssklower
29736367Ssklower case SIOCGISOMAP: /* get entry */
29836367Ssklower bcopy((caddr_t)at->map_enaddr, (caddr_t)ar->arp_ha.sa_data,
29936367Ssklower sizeof(at->map_enaddr));
30036367Ssklower }
30136367Ssklower return(0);
30236367Ssklower }
30336367Ssklower #endif ISO
304