78eed0d727f11be850bd83a13181de3e7d34ad41
[dragonfly.git] / usr.sbin / IPXrouted / sap_input.c
1 /*
2  * Copyright (c) 1995 John Hay.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by John Hay.
15  * 4. Neither the name of the author nor the names of any co-contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD: src/usr.sbin/IPXrouted/sap_input.c,v 1.7 1999/08/28 01:15:04 peter Exp $
32  * $DragonFly: src/usr.sbin/IPXrouted/sap_input.c,v 1.2 2003/06/17 04:29:52 dillon Exp $
33  */
34
35 /*
36  * IPX Routing Table Management Daemon
37  */
38 #include "defs.h"
39
40 int dognreply = 1;
41
42 /*
43  * Process a newly received packet.
44  */
45 void
46 sap_input(from, size)
47         struct sockaddr *from;
48         int size;
49 {
50         int newsize;
51         int sapchanged = 0;
52         struct sap_entry *sap;
53         struct sap_info *n;
54         struct interface *ifp = 0;
55         struct afswitch *afp;
56         struct sockaddr_ipx *ipxp;
57
58         ifp = if_ifwithnet(from);
59         ipxp = (struct sockaddr_ipx *)from;
60         if (ifp == 0) {
61                 if(ftrace) {
62                         fprintf(ftrace, "Received bogus packet from %s\n",
63                                 ipxdp_ntoa(&ipxp->sipx_addr));
64                 }
65                 return;
66         }
67
68         if (ftrace) 
69                 dumpsappacket(ftrace, "received", from, (char *)sap_msg , size);
70
71         if (from->sa_family >= AF_MAX)
72                 return;
73         afp = &afswitch[from->sa_family];
74         
75         size -= sizeof (u_short)        /* command */;
76         n = sap_msg->sap;
77
78         switch (ntohs(sap_msg->sap_cmd)) {
79
80         case SAP_REQ_NEAR:
81                 if (ftrace)
82                         fprintf(ftrace, "Received a sap REQ_NEAR packet.\n");
83                 if (!dognreply)
84                         return;
85                 sap = sap_nearestserver(n->ServType, ifp);
86                 if (sap == NULL)
87                         return;
88                 sap_msg->sap_cmd = htons(SAP_RESP_NEAR);
89                 *n = sap->sap;
90                 n->hops = htons(ntohs(n->hops) + 1);
91                 if (ntohs(n->hops) >= HOPCNT_INFINITY)
92                         return;
93
94                 newsize = sizeof(struct sap_info) + sizeof(struct sap_packet);
95                 (*afp->af_output)(sapsock, 0, from, newsize);
96                 if (ftrace) {
97                         fprintf(ftrace, "sap_nearestserver %X %s returned:\n",
98                                 ntohs(n->ServType),
99                                 ifp->int_name);
100                         fprintf(ftrace, "  service %04X %-20.20s "
101                                         "addr %s.%04X metric %d\n",
102                                         ntohs(sap->sap.ServType),
103                                         sap->sap.ServName,
104                                         ipxdp_ntoa(&sap->sap.ipx),
105                                         ntohs(sap->sap.ipx.x_port),
106                                         ntohs(sap->sap.hops));
107                 }
108                 return;
109
110         case SAP_REQ:
111                 if (ftrace)
112                         fprintf(ftrace, "Received a sap REQ packet.\n");
113
114                 sap_supply(from, 0, ifp, n->ServType, 0);
115                 return;
116
117         case SAP_RESP_NEAR:
118                 /* XXX We do nothing here, for the moment.
119                  * Maybe we should check if the service is in our table?
120                  *
121                  */
122                 if (ftrace)
123                         fprintf(ftrace, "Received a sap RESP_NEAR packet.\n");
124
125                 return;
126
127         case SAP_RESP:
128                 if (ftrace)
129                         fprintf(ftrace, "Received a sap RESP packet.\n");
130
131                 (*afp->af_canon)(from);
132
133                 for (; size > 0; size -= sizeof (struct sap_info), n++) {
134                         if (size < sizeof (struct netinfo))
135                                 break;
136                         /*
137                          * The idea here is that if the hop count is more
138                          * than INFINITY it is bogus and should be discarded.
139                          * If it is equal to INFINITY it is a message to say
140                          * that a service went down. If we don't allready
141                          * have it in our tables discard it. Otherwise
142                          * update our table and set the timer to EXPIRE_TIME
143                          * so that it is removed next time we go through the
144                          * tables.
145                          */
146                         if (ntohs(n->hops) > HOPCNT_INFINITY)
147                                 continue;
148                         sap = sap_lookup(n->ServType, n->ServName);
149                         if (sap == 0) {
150                                 if (ntohs(n->hops) == HOPCNT_INFINITY)
151                                         continue;
152                                 sap_add(n, from);
153                                 sapchanged = 1;
154                                 continue;
155                         }
156
157                         /*
158                          * A clone is a different route to the same service
159                          * with exactly the same cost (metric).
160                          * They must all be recorded because those interfaces
161                          * must be handled in the same way as the first route
162                          * to that service. ie When using the split horizon
163                          * algorithm we must look at these interfaces also.
164                          *
165                          * Update if from gateway and different,
166                          * from anywhere and less hops or
167                          * getting stale and equivalent.
168                          */
169                         if (((ifp != sap->ifp) ||
170                              !equal(&sap->source, from)) &&
171                             (n->hops == sap->sap.hops) &&
172                             (ntohs(n->hops) != HOPCNT_INFINITY)) {
173                                 register struct sap_entry *tsap = sap->clone;
174
175                                 while (tsap) {
176                                         if ((ifp == tsap->ifp) &&
177                                             equal(&tsap->source, from)) {
178                                                 tsap->timer = 0;
179                                                 break;
180                                         }
181                                         tsap = tsap->clone;
182                                 }
183                                 if (tsap == NULL) {
184                                         sap_add_clone(sap, n, from);
185                                 }
186                                 continue;
187                         }
188                         if ((ifp == sap->ifp) &&
189                             equal(&sap->source, from) &&
190                             (ntohs(n->hops) == ntohs(sap->sap.hops)))
191                                 sap->timer = 0;
192                         else if (((ifp == sap->ifp) &&
193                                   equal(&sap->source, from) &&
194                                   (n->hops != sap->sap.hops)) ||
195                                  (ntohs(n->hops) < ntohs(sap->sap.hops)) ||
196                                  (sap->timer > (EXPIRE_TIME*2/3) &&
197                                   ntohs(sap->sap.hops) == ntohs(n->hops) &&
198                                   ntohs(n->hops) != HOPCNT_INFINITY)) {
199                                 sap_change(sap, n, from);
200                                 sapchanged = 1;
201                         }
202                 }
203                 if (sapchanged) {
204                         register struct sap_entry *sap;
205                         register struct sap_hash *sh;
206                         sap_supply_toall(1);
207
208                         for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++)
209                                 for (sap = sh->forw;
210                                     sap != (struct sap_entry *)sh;
211                                     sap = sap->forw)
212                                         sap->state &= ~RTS_CHANGED;
213                 }
214                 return;
215         }
216 }