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