1/*
2 * Copyright (c) 1985, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Copyright (c) 1995 John Hay.  All rights reserved.
6 *
7 * This file includes significant work done at Cornell University by
8 * Bill Nesheim.  That work included by permission.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD$
35 */
36
37#ifndef lint
38static const char sccsid[] = "@(#)af.c	8.1 (Berkeley) 6/5/93";
39#endif /* not lint */
40
41#include "defs.h"
42
43/*
44 * Address family support routines
45 */
46af_hash_t	null_hash;
47af_netmatch_t	null_netmatch;
48af_output_t	null_output;
49af_portmatch_t	null_portmatch;
50af_portcheck_t	null_portcheck;
51af_checkhost_t	null_checkhost;
52af_ishost_t	null_ishost;
53af_canon_t	null_canon;
54
55void	ipxnet_hash(struct sockaddr_ipx *, struct afhash *);
56int	ipxnet_netmatch(struct sockaddr_ipx *, struct sockaddr_ipx *);
57void	ipxnet_output(int, int, struct sockaddr_ipx *, int);
58int	ipxnet_portmatch(struct sockaddr_ipx *);
59int	ipxnet_checkhost(struct sockaddr_ipx *);
60int	ipxnet_ishost(struct sockaddr_ipx *);
61void	ipxnet_canon(struct sockaddr_ipx *);
62
63#define NIL \
64	{ null_hash,		null_netmatch,		null_output, \
65	  null_portmatch,	null_portcheck,		null_checkhost, \
66	  null_ishost,		null_canon }
67#define	IPXNET \
68	{ (af_hash_t *)ipxnet_hash, \
69	  (af_netmatch_t *)ipxnet_netmatch, \
70	  (af_output_t *)ipxnet_output, \
71	  (af_portmatch_t *)ipxnet_portmatch, \
72	  (af_portcheck_t *)ipxnet_portmatch, \
73	  (af_checkhost_t *)ipxnet_checkhost, \
74	  (af_ishost_t *)ipxnet_ishost, \
75	  (af_canon_t *)ipxnet_canon }
76
77struct afswitch afswitch[AF_MAX] =
78	{ NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL,
79	  NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL,
80	  NIL, NIL, NIL, IPXNET, NIL, NIL };
81
82struct sockaddr_ipx ipxnet_default = { sizeof(struct sockaddr_ipx), AF_IPX };
83
84union ipx_net ipx_anynet;
85union ipx_net ipx_zeronet;
86
87void
88ipxnet_hash(sipx, hp)
89	register struct sockaddr_ipx *sipx;
90	struct afhash *hp;
91{
92	long hash;
93#if 0
94	u_short *s = sipx->sipx_addr.x_host.s_host;
95#endif
96	u_char *c;
97
98	c = sipx->sipx_addr.x_net.c_net;
99
100#define IMVAL	33
101	hash = 0;
102	hash = hash * IMVAL + *c++;
103	hash = hash * IMVAL + *c++;
104	hash = hash * IMVAL + *c++;
105	hash = hash * IMVAL + *c++;
106#undef IMVAL
107
108	hp->afh_nethash = hash;
109	hp->afh_nethash ^= (hash >> 8);
110	hp->afh_nethash ^= (hash >> 16);
111	hp->afh_nethash ^= (hash >> 24);
112
113#if 0
114	hash = 0;
115	hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
116	hp->afh_hosthash = hash;
117#endif
118}
119
120int
121ipxnet_netmatch(sxn1, sxn2)
122	struct sockaddr_ipx *sxn1, *sxn2;
123{
124	return (ipx_neteq(sxn1->sipx_addr, sxn2->sipx_addr));
125}
126
127/*
128 * Verify the message is from the right port.
129 */
130int
131ipxnet_portmatch(sipx)
132	register struct sockaddr_ipx *sipx;
133{
134
135	return (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP );
136}
137
138
139/*
140 * ipx output routine.
141 */
142#ifdef DEBUG
143int do_output = 0;
144#endif
145void
146ipxnet_output(s, flags, sipx, size)
147	int s;
148	int flags;
149	struct sockaddr_ipx *sipx;
150	int size;
151{
152	struct sockaddr_ipx dst;
153
154	dst = *sipx;
155	sipx = &dst;
156	if (sipx->sipx_addr.x_port == 0)
157		sipx->sipx_addr.x_port = htons(IPXPORT_RIP);
158#ifdef DEBUG
159	if(do_output || ntohs(msg->rip_cmd) == RIPCMD_REQUEST)
160#endif
161	/*
162	 * Kludge to allow us to get routes out to machines that
163	 * don't know their addresses yet; send to that address on
164	 * ALL connected nets
165	 */
166	 if (ipx_neteqnn(sipx->sipx_addr.x_net, ipx_zeronet)) {
167	 	extern  struct interface *ifnet;
168	 	register struct interface *ifp;
169
170		for (ifp = ifnet; ifp; ifp = ifp->int_next) {
171			sipx->sipx_addr.x_net =
172				satoipx_addr(ifp->int_addr).x_net;
173			(void) sendto(s, msg, size, flags,
174			    (struct sockaddr *)sipx, sizeof (*sipx));
175		}
176		return;
177	}
178
179	(void) sendto(s, msg, size, flags,
180	    (struct sockaddr *)sipx, sizeof (*sipx));
181}
182
183/*
184 * Return 1 if we want this route.
185 * We use this to disallow route net G entries for one for multiple
186 * point to point links.
187 */
188int
189ipxnet_checkhost(sipx)
190	struct sockaddr_ipx *sipx;
191{
192	register struct interface *ifp = if_ifwithnet((struct sockaddr *)sipx);
193	/*
194	 * We want this route if there is no more than one
195	 * point to point interface with this network.
196	 */
197	if (ifp == 0 || (ifp->int_flags & IFF_POINTOPOINT)==0) return (1);
198	return (ifp->int_sq.n == ifp->int_sq.p);
199}
200
201/*
202 * Return 1 if the address is
203 * for a host, 0 for a network.
204 */
205int
206ipxnet_ishost(sipx)
207struct sockaddr_ipx *sipx;
208{
209	register u_short *s = sipx->sipx_addr.x_host.s_host;
210
211	if ((s[0]==0x0000) && (s[1]==0x0000) && (s[2]==0x0000))
212		return (0);
213	if ((s[0]==0xffff) && (s[1]==0xffff) && (s[2]==0xffff))
214		return (0);
215
216	return (1);
217}
218
219void
220ipxnet_canon(sipx)
221	struct sockaddr_ipx *sipx;
222{
223
224	sipx->sipx_addr.x_port = 0;
225}
226
227void
228null_hash(addr, hp)
229	struct sockaddr *addr;
230	struct afhash *hp;
231{
232
233	hp->afh_nethash = hp->afh_hosthash = 0;
234}
235
236int
237null_netmatch(a1, a2)
238	struct sockaddr *a1, *a2;
239{
240
241	return (0);
242}
243
244void
245null_output(s, f, a1, n)
246	int s;
247	int f;
248	struct sockaddr *a1;
249	int n;
250{
251
252	;
253}
254
255int
256null_portmatch(a1)
257	struct sockaddr *a1;
258{
259
260	return (0);
261}
262
263int
264null_portcheck(a1)
265	struct sockaddr *a1;
266{
267
268	return (0);
269}
270
271int
272null_ishost(a1)
273	struct sockaddr *a1;
274{
275
276	return (0);
277}
278
279int
280null_checkhost(a1)
281	struct sockaddr *a1;
282{
283
284	return (0);
285}
286
287void
288null_canon(a1)
289	struct sockaddr *a1;
290{
291
292	;
293}
294
295