xref: /csrg-svn/sys/netiso/clnp_arp.c (revision 37536)
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