xref: /csrg-svn/sys/netiso/clnp_arp.c (revision 36367)
1*36367Ssklower /***********************************************************
2*36367Ssklower 		Copyright IBM Corporation 1987
3*36367Ssklower 
4*36367Ssklower                       All Rights Reserved
5*36367Ssklower 
6*36367Ssklower Permission to use, copy, modify, and distribute this software and its
7*36367Ssklower documentation for any purpose and without fee is hereby granted,
8*36367Ssklower provided that the above copyright notice appear in all copies and that
9*36367Ssklower both that copyright notice and this permission notice appear in
10*36367Ssklower supporting documentation, and that the name of IBM not be
11*36367Ssklower used in advertising or publicity pertaining to distribution of the
12*36367Ssklower software without specific, written prior permission.
13*36367Ssklower 
14*36367Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36367Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36367Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36367Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36367Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36367Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36367Ssklower SOFTWARE.
21*36367Ssklower 
22*36367Ssklower ******************************************************************/
23*36367Ssklower 
24*36367Ssklower /*
25*36367Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36367Ssklower  */
27*36367Ssklower /* $Header: clnp_arp.c,v 4.2 88/06/29 14:58:32 hagens Exp $ */
28*36367Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_arp.c,v $ */
29*36367Ssklower 
30*36367Ssklower #ifndef lint
31*36367Ssklower static char *rcsid = "$Header: clnp_arp.c,v 4.2 88/06/29 14:58:32 hagens Exp $";
32*36367Ssklower #endif lint
33*36367Ssklower 
34*36367Ssklower #ifdef ISO
35*36367Ssklower 
36*36367Ssklower #include "../h/types.h"
37*36367Ssklower #include "../h/param.h"
38*36367Ssklower #include "../h/mbuf.h"
39*36367Ssklower #include "../h/domain.h"
40*36367Ssklower #include "../h/protosw.h"
41*36367Ssklower #include "../h/socket.h"
42*36367Ssklower #include "../h/socketvar.h"
43*36367Ssklower #include "../h/errno.h"
44*36367Ssklower #include "../h/ioctl.h"
45*36367Ssklower 
46*36367Ssklower #include "../net/if.h"
47*36367Ssklower #include "../net/route.h"
48*36367Ssklower 
49*36367Ssklower #include "../netiso/iso.h"
50*36367Ssklower #include "../netiso/iso_var.h"
51*36367Ssklower #include "../netiso/iso_map.h"
52*36367Ssklower #include "../netiso/iso_snpac.h"
53*36367Ssklower #include "../netiso/clnp.h"
54*36367Ssklower #include "../netiso/clnp_stat.h"
55*36367Ssklower #include "../netiso/argo_debug.h"
56*36367Ssklower 
57*36367Ssklower #define	MAPTAB_BSIZ	20		/* bucket size */
58*36367Ssklower #define	MAPTAB_NB	13		/* number of buckets */
59*36367Ssklower #define	MAPTAB_SIZE	(MAPTAB_BSIZ * MAPTAB_NB)
60*36367Ssklower struct	maptab	iso_maptab[MAPTAB_SIZE];
61*36367Ssklower int				iso_maptab_size = MAPTAB_SIZE;	/* for isomap command */
62*36367Ssklower 
63*36367Ssklower #define	MAPTAB_HASH(addr) \
64*36367Ssklower 	(((u_long) iso_hashchar(addr, addr->isoa_len)) % MAPTAB_NB)
65*36367Ssklower 
66*36367Ssklower #define	MAPTAB_LOOK(at,addr) { \
67*36367Ssklower 	register n; \
68*36367Ssklower 	at = &iso_maptab[MAPTAB_HASH(addr) * MAPTAB_BSIZ]; \
69*36367Ssklower 	for (n = 0 ; n < MAPTAB_BSIZ ; n++,at++) \
70*36367Ssklower 		if ((at->map_valid) && (iso_addrmatch1(&at->map_isoa, addr))) \
71*36367Ssklower 			break; \
72*36367Ssklower 	if (n >= MAPTAB_BSIZ) \
73*36367Ssklower 		at = 0; \
74*36367Ssklower }
75*36367Ssklower 
76*36367Ssklower /*
77*36367Ssklower  * FUNCTION:		clnp_arpresolve
78*36367Ssklower  *
79*36367Ssklower  * PURPOSE:			Resolve a clnp address into hardware ethernet addr.
80*36367Ssklower  *
81*36367Ssklower  * RETURNS:			1 if addr is resolved
82*36367Ssklower  *					0 if addr is unknown
83*36367Ssklower  *
84*36367Ssklower  * SIDE EFFECTS:
85*36367Ssklower  *
86*36367Ssklower  * NOTES:			This is a hack. If the address is local, then
87*36367Ssklower  *					the packet is put on the loopback driver. Otherwise,
88*36367Ssklower  *					if a translation is found, that ethernet address is
89*36367Ssklower  *					returned. Otherwise, the packet is dropped. Thus,
90*36367Ssklower  *					each translation must be placed (by hand) in the
91*36367Ssklower  *					tables (see isomap(8)).
92*36367Ssklower  *					TODO: should this map stuff be a critical section?
93*36367Ssklower  */
94*36367Ssklower clnp_arpresolve(ifp, m, dst, edst)
95*36367Ssklower struct ifnet 		*ifp;	/* outgoing interface */
96*36367Ssklower struct mbuf			*m;		/* pkt */
97*36367Ssklower struct sockaddr_iso *dst;	/* destination */
98*36367Ssklower char				*edst;	/* RESULT: ethernet address */
99*36367Ssklower {
100*36367Ssklower 	extern struct ifnet 	loif;		/* loopback interface */
101*36367Ssklower 	struct maptab			*at;		/* ptr to map table entry */
102*36367Ssklower 	struct iso_addr			*destiso;	/* destination iso addr */
103*36367Ssklower 
104*36367Ssklower  	destiso = &dst->siso_addr;
105*36367Ssklower 
106*36367Ssklower 	if (destiso->isoa_afi == AFI_SNA) {
107*36367Ssklower 		/*
108*36367Ssklower 		 *	This is a subnetwork address. Return it immediately
109*36367Ssklower 		 */
110*36367Ssklower 		int	sna_len;
111*36367Ssklower 
112*36367Ssklower 		IFDEBUG(D_ESISOUTPUT)
113*36367Ssklower 			printf("clnp_arpresolve: return SN address\n");
114*36367Ssklower 		ENDDEBUG
115*36367Ssklower 
116*36367Ssklower 		sna_len = destiso->isoa_len - 1;	/* subtract size of AFI */
117*36367Ssklower 		if (sna_len != 6) {
118*36367Ssklower 			IFDEBUG(D_ESISOUTPUT)
119*36367Ssklower 				printf("clnp_arpresolve: SN len is bad (%d)\n", sna_len);
120*36367Ssklower 			ENDDEBUG
121*36367Ssklower 			return(-1);
122*36367Ssklower 		}
123*36367Ssklower 		bcopy((caddr_t) destiso->sna_idi, (caddr_t)edst, sna_len);
124*36367Ssklower 		return (1);
125*36367Ssklower 	}
126*36367Ssklower 
127*36367Ssklower 	IFDEBUG(D_ETHER)
128*36367Ssklower 		printf("clnp_arpresolve: resolving %s\n", clnp_iso_addrp(destiso));
129*36367Ssklower 	ENDDEBUG
130*36367Ssklower 
131*36367Ssklower 	/* if for us, use software loopback driver if up */
132*36367Ssklower 	if (clnp_ours(destiso)) {
133*36367Ssklower 		IFDEBUG(D_ETHER)
134*36367Ssklower 			printf("clnp_arpresolve: local destination\n");
135*36367Ssklower 		ENDDEBUG
136*36367Ssklower 		if (loif.if_flags & IFF_UP) {
137*36367Ssklower 			IFDEBUG(D_ETHER)
138*36367Ssklower 				printf("clnp_arpresolve: calling looutput\n");
139*36367Ssklower 			ENDDEBUG
140*36367Ssklower 			(void) looutput(&loif, m, (struct sockaddr *)dst);
141*36367Ssklower 			/*
142*36367Ssklower 			 * The packet has already been sent and freed.
143*36367Ssklower 			 */
144*36367Ssklower 			return (0);
145*36367Ssklower 		}
146*36367Ssklower 	}
147*36367Ssklower 
148*36367Ssklower 	IFDEBUG(D_ETHER)
149*36367Ssklower 		printf("clnp_arpresolve: NON-local destination\n");
150*36367Ssklower 	ENDDEBUG
151*36367Ssklower 
152*36367Ssklower 	/*
153*36367Ssklower 	 *	packet is not for us, check static map table for an entry
154*36367Ssklower 	 *	This does not need to be a critical section because the
155*36367Ssklower 	 *	table is not dynamically updated, except by a call to
156*36367Ssklower 	 *	isomap(8)
157*36367Ssklower 	 */
158*36367Ssklower 	MAPTAB_LOOK(at, destiso);
159*36367Ssklower 	if (at == 0) {			/* not found */
160*36367Ssklower 		m_freem(m);
161*36367Ssklower 		return (-1);
162*36367Ssklower 	} else {
163*36367Ssklower 		bcopy((caddr_t)at->map_enaddr, (caddr_t)edst, sizeof(at->map_enaddr));
164*36367Ssklower 		return (1);
165*36367Ssklower 	}
166*36367Ssklower }
167*36367Ssklower 
168*36367Ssklower /*
169*36367Ssklower  * FUNCTION:		isomap_new
170*36367Ssklower  *
171*36367Ssklower  * PURPOSE:			create a new entry in the iso address to ethernet
172*36367Ssklower  *					address table
173*36367Ssklower  *
174*36367Ssklower  * RETURNS:			pointer to newest entry, or NULL if none can be found
175*36367Ssklower  *
176*36367Ssklower  * SIDE EFFECTS:
177*36367Ssklower  *
178*36367Ssklower  * NOTES:			TODO: timeout old entries
179*36367Ssklower  */
180*36367Ssklower struct maptab *
181*36367Ssklower isomap_new(isoa)
182*36367Ssklower struct iso_addr *isoa;		/* iso address to enter into table */
183*36367Ssklower {
184*36367Ssklower 	register struct maptab	*at;
185*36367Ssklower 	register int 			n;
186*36367Ssklower 
187*36367Ssklower 	at = &iso_maptab[MAPTAB_HASH(isoa) * MAPTAB_BSIZ];
188*36367Ssklower 	for (n = 0 ; n < MAPTAB_BSIZ ; n++,at++) {
189*36367Ssklower 
190*36367Ssklower 		IFDEBUG (D_IOCTL)
191*36367Ssklower 			printf("isomap_new: at x%x ", at);
192*36367Ssklower 
193*36367Ssklower 			if (at->map_valid) {
194*36367Ssklower 				int i;
195*36367Ssklower 
196*36367Ssklower 				printf("(valid) %s ", clnp_iso_addrp(&at->map_isoa));
197*36367Ssklower 				for (i=0; i<6; i++)
198*36367Ssklower 					printf("%x%c", at->map_enaddr[i], i < 5 ? ':' : '\n');
199*36367Ssklower 			} else {
200*36367Ssklower 				printf("invalid\n");
201*36367Ssklower 			}
202*36367Ssklower 		ENDDEBUG
203*36367Ssklower 
204*36367Ssklower 		if (!at->map_valid) /* found unused slot */
205*36367Ssklower 			return at;
206*36367Ssklower 	}
207*36367Ssklower 	return NULL;
208*36367Ssklower }
209*36367Ssklower 
210*36367Ssklower /*
211*36367Ssklower  * FUNCTION:		isomap_free
212*36367Ssklower  *
213*36367Ssklower  * PURPOSE:			free an entry in the iso address map table
214*36367Ssklower  *
215*36367Ssklower  * RETURNS:			nothing
216*36367Ssklower  *
217*36367Ssklower  * SIDE EFFECTS:
218*36367Ssklower  *
219*36367Ssklower  * NOTES:
220*36367Ssklower  */
221*36367Ssklower isomap_free(at)
222*36367Ssklower register struct maptab *at;		/* entry to free */
223*36367Ssklower {
224*36367Ssklower 	at->map_valid = 0;
225*36367Ssklower }
226*36367Ssklower 
227*36367Ssklower /*
228*36367Ssklower  * FUNCTION:		isomap_ioctl
229*36367Ssklower  *
230*36367Ssklower  * PURPOSE:			handle ioctls to change the iso address map
231*36367Ssklower  *
232*36367Ssklower  * RETURNS:			unix error code
233*36367Ssklower  *
234*36367Ssklower  * SIDE EFFECTS:	changes the maptab table declared above.
235*36367Ssklower  *
236*36367Ssklower  * NOTES:
237*36367Ssklower  */
238*36367Ssklower isomap_ioctl(cmd, data)
239*36367Ssklower int		cmd;		/* ioctl to process */
240*36367Ssklower caddr_t	data;	/* data for the cmd */
241*36367Ssklower {
242*36367Ssklower 	register struct arpreq	*ar = (struct arpreq *)data;
243*36367Ssklower 	register struct maptab	*at;
244*36367Ssklower 	register struct sockaddr_iso	*siso;
245*36367Ssklower 	register struct iso_addr		*isoa;
246*36367Ssklower 
247*36367Ssklower 	/*
248*36367Ssklower 	 *	only process commands for the ISO address family
249*36367Ssklower 	 */
250*36367Ssklower 	if (ar->arp_pa.sa_family != AF_ISO)
251*36367Ssklower 		return(EAFNOSUPPORT);
252*36367Ssklower 
253*36367Ssklower 	/* look up this address in table */
254*36367Ssklower 	siso = (struct sockaddr_iso *)&ar->arp_pa;
255*36367Ssklower 	isoa = &siso->siso_addr;
256*36367Ssklower 
257*36367Ssklower 	IFDEBUG (D_IOCTL)
258*36367Ssklower 		int i;
259*36367Ssklower 
260*36367Ssklower 		printf("isomap_ioctl: ");
261*36367Ssklower 		switch(cmd) {
262*36367Ssklower 			case SIOCSISOMAP: printf("set"); break;
263*36367Ssklower 			case SIOCDISOMAP: printf("delete"); break;
264*36367Ssklower 			case SIOCGISOMAP: printf("get"); break;
265*36367Ssklower 		}
266*36367Ssklower 		printf(" %s to ", clnp_iso_addrp(isoa));
267*36367Ssklower 		for (i=0; i<6; i++)
268*36367Ssklower 			printf("%x%c", ar->arp_ha.sa_data[i], i < 5 ? ':' : '\n');
269*36367Ssklower 	ENDDEBUG
270*36367Ssklower 
271*36367Ssklower 	MAPTAB_LOOK(at, isoa);
272*36367Ssklower 	if (at == NULL) {	 /* not found */
273*36367Ssklower 		if (cmd != SIOCSISOMAP)
274*36367Ssklower 			return(ENXIO);
275*36367Ssklower 
276*36367Ssklower 		/* TODO: what if setting and net is not directly attached */
277*36367Ssklower 	}
278*36367Ssklower 
279*36367Ssklower 	switch(cmd) {
280*36367Ssklower 		case SIOCSISOMAP:	/* set entry */
281*36367Ssklower 			if (at == NULL) {
282*36367Ssklower 				at = isomap_new(isoa);
283*36367Ssklower 				if (at == NULL)
284*36367Ssklower 					return(ENOBUFS);
285*36367Ssklower 			}
286*36367Ssklower 			bcopy((caddr_t)isoa, (caddr_t)&at->map_isoa,
287*36367Ssklower 				sizeof (struct iso_addr));
288*36367Ssklower 			bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->map_enaddr,
289*36367Ssklower 				sizeof(at->map_enaddr));
290*36367Ssklower 			at->map_valid++;
291*36367Ssklower 			break;
292*36367Ssklower 
293*36367Ssklower 		case SIOCDISOMAP:	/* delete entry */
294*36367Ssklower 			isomap_free(at);
295*36367Ssklower 			break;
296*36367Ssklower 
297*36367Ssklower 		case SIOCGISOMAP:	/* get entry */
298*36367Ssklower 			bcopy((caddr_t)at->map_enaddr, (caddr_t)ar->arp_ha.sa_data,
299*36367Ssklower 				sizeof(at->map_enaddr));
300*36367Ssklower 	}
301*36367Ssklower 	return(0);
302*36367Ssklower }
303*36367Ssklower #endif	ISO
304