]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/ddp_r_rtmp.c
2 * Copyright (c) 1994, 1996-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /*--------------------------------------------------------------------------
23 * Router RTMP protocol functions:
25 * This file contains Routing specifics to handle RTMP packets and
26 * the maintenance of the routing table through....
28 * The entry point for the rtmp input in ddp is valid only when we're
29 * running in router mode.
32 * 0.01 03/22/94 Laurent Dumont Creation
33 * Modified for MP, 1996 by Tuyen Nguyen
34 * Added AURP support, April 8, 1996 by Tuyen Nguyen
35 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
37 *-------------------------------------------------------------------------
40 #include <sys/errno.h>
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <machine/spl.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
47 #include <sys/filedesc.h>
48 #include <sys/fcntl.h>
50 #include <sys/ioctl.h>
51 #include <sys/malloc.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
57 #include <netat/sysglue.h>
58 #include <netat/appletalk.h>
59 #include <netat/at_var.h>
60 #include <netat/ddp.h>
61 #include <netat/rtmp.h>
62 #include <netat/at_pcb.h>
63 #include <netat/zip.h>
64 #include <netat/routing_tables.h>
65 #include <netat/aurp.h>
66 #include <netat/debug.h>
68 extern void (*ddp_AURPsendx
)();
69 extern at_ifaddr_t
*aurp_ifID
;
70 extern at_ifaddr_t
*ifID_table
[];
71 extern at_ifaddr_t
*ifID_home
;
74 static int dump_counter
=0;
77 static at_kern_err_t ke
;
78 /* Used to record error discovered in rtmp_update() */
79 gbuf_t
*rtmp_prep_new_packet();
82 void rtmp_send_port();
83 void rtmp_send_port_funnel();
86 static void rtmp_update();
87 static void rtmp_request();
88 extern int elap_online3();
90 extern pktsIn
, pktsOut
, pktsDropped
, pktsHome
;
91 extern short ErrorRTMPoverflow
, ErrorZIPoverflow
;
92 extern atlock_t ddpinp_lock
;
95 * rtmp_router_input: function called by DDP (in router mode) to handle
96 * all incoming RTMP packets. Listen to the RTMP socket
97 * for all the connected ports.
98 * Switch to the relevant rtmp functions.
101 void rtmp_router_input(mp
, ifID
)
103 register at_ifaddr_t
*ifID
;
105 register at_ddp_t
*ddp
= (at_ddp_t
*)gbuf_rptr(mp
);
106 /* NOTE: there is an assumption here that the
107 * DATA follows the header. */
109 register at_net_al OurNet
;
110 register at_node OurNode
;
111 register at_net_al DstNet
;
112 register at_node DstNode
;
116 if (!ifID
|| (ifID
->ifRoutingState
< PORT_ACTIVATING
)) {
122 OurNet
= ifID
->ifThisNode
.s_net
;
123 OurNode
= ifID
->ifThisNode
.s_node
;
126 if (gbuf_type(mp
) != MSG_DATA
) {
128 /* If this is a M_ERROR message, DDP is shutting down,
129 * nothing to do here...If it's something else, we don't
130 * understand what it is
132 dPrintf(D_M_RTMP
, D_L_WARNING
,
133 ("rtmp_router_input: Not an M_DATA type\n"));
138 DstNet
= NET_VALUE(ddp
->dst_net
);
139 DstNode
= ddp
->dst_node
;
141 /* check the kind of RTMP packet we received */
147 tuples
= gbuf_len(mp
) - DDP_X_HDR_SIZE
- RTMP_IDLENGTH
;
149 * we need to make sure that the size of 'tuples' is
150 * not less than or equal to 0 due to a bad packet
157 if (tuples
% 3) {/* not a valid RTMP data packet */
159 dPrintf(D_M_RTMP
, D_L_WARNING
,
160 ("rtmp_input: bad number of tuple in RTMP packet\n"));
166 rtmp_update(ifID
, (at_rtmp
*)ddp
->data
, tuples
);
173 /* we should treat requests a bit differently.
174 * - if the request if not for the port, route it and also respond
175 * for this port if not locally connected.
176 * - if the request for this port, then just respond to it.
183 if (DstNode
== 255) {
184 if (((DstNet
>= CableStart
) && (DstNet
<= CableStop
)) ||
186 rtmp_request(ifID
, ddp
);
191 /* check if directly connected port */
192 if ((Entry
= rt_blookup(DstNet
)) &&
193 (Entry
->NetDist
== 0)) {
194 dPrintf(D_M_RTMP
, D_L_WARNING
,
195 ("rtmp_router_input: request for %d.%d, port %d\n",
196 DstNet
, DstNode
, Entry
->NetPort
));
197 rtmp_request(ifID_table
[Entry
->NetPort
], ddp
);
202 dPrintf(D_M_RTMP
, D_L_WARNING
,
203 ("rtmp_router_input: RTMP packet received for %d.%d, also forward\n",
204 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
));
205 routing_needed(mp
, ifID
, TRUE
);
212 if ((DstNode
== OurNode
) && (DstNet
== OurNet
)) {
213 rtmp_request(ifID
, ddp
);
218 dPrintf(D_M_RTMP
, D_L_WARNING
,
219 ("rtmp_router_input: RTMP packet received for %d.%d, forward\n",
220 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
));
221 routing_needed(mp
, ifID
, TRUE
);
229 dPrintf(D_M_RTMP
, D_L_WARNING
,
230 ("rtmp_input: RTMP packet type=%d, route it\n", ddp
->type
));
231 routing_needed(mp
, ifID
, TRUE
);
235 } /* rtmp_router_input */
242 static void rtmp_update(ifID
, rtmp
, tuple_nb
)
243 register at_ifaddr_t
*ifID
;
244 register at_rtmp
*rtmp
;
245 register short tuple_nb
;
247 register int PortFlags
= ifID
->ifFlags
;
248 register at_rtmp_tuple
*FirstTuple
= (at_rtmp_tuple
*)&rtmp
->at_rtmp_id
[1];
249 register at_rtmp_tuple
*SecondTuple
= (at_rtmp_tuple
*)&rtmp
->at_rtmp_id
[4];
250 RT_entry NewRoute
, *CurrentRoute
;
252 register u_char SenderNodeID
= rtmp
->at_rtmp_id
[0];
257 /* Make sure this an AppleTalk node sending us the RTMP packet */
259 if (rtmp
->at_rtmp_id_length
!= 8) {
260 dPrintf(D_M_RTMP
, D_L_WARNING
,
261 ("rtmp_update : RTMP ID not as expected Net=%d L=x%x\n",
262 NET_VALUE(rtmp
->at_rtmp_this_net
), rtmp
->at_rtmp_id_length
));
267 * If the port is activating, only take the Network range from the
268 * the RTMP packet received.
269 * Check if there is a conflict with our seed infos.
272 if (ifID
->ifRoutingState
== PORT_ACTIVATING
) {
273 if (PortFlags
& RTR_XNET_PORT
) {
274 if ((PortFlags
& RTR_SEED_PORT
) &&
275 ((CableStart
!= TUPLENET(FirstTuple
)) ||
276 (CableStop
!= TUPLENET(SecondTuple
)))) {
277 ifID
->ifRoutingState
= PORT_ERR_SEED
;
278 ke
.error
= KE_CONF_SEED_RNG
;
279 ke
.port1
= ifID
->ifPort
;
280 strncpy(ke
.name1
, ifID
->ifName
, sizeof(ke
.name1
));
281 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
282 ke
.node
= SenderNodeID
;
283 ke
.netr1b
= TUPLENET(FirstTuple
);
284 ke
.netr1e
= TUPLENET(SecondTuple
);
285 ke
.netr2b
= CableStart
;
286 ke
.netr2e
= CableStop
;
287 RouterError(ifID
->ifPort
, ERTR_SEED_CONFLICT
);
290 CableStart
= TUPLENET(FirstTuple
);
291 CableStop
= TUPLENET(SecondTuple
);
293 dPrintf(D_M_RTMP, D_L_INFO,
294 ("rtmp_update: Port #%d activating, set Cable %d-%d\n",
295 ifID->ifPort, CableStart, CableStop));
298 else { /* non extended cable */
299 if ((PortFlags
& RTR_SEED_PORT
) &&
300 (ifID
->ifThisCableEnd
!= NET_VALUE(rtmp
->at_rtmp_this_net
))) {
301 ke
.error
= KE_CONF_SEED1
;
302 ke
.port1
= ifID
->ifPort
;
303 strncpy(ke
.name1
, ifID
->ifName
,sizeof(ke
.name1
));
304 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
305 ke
.node
= SenderNodeID
;
306 ke
.netr1e
= ifID
->ifThisCableEnd
;
307 ifID
->ifRoutingState
= PORT_ERR_SEED
;
308 RouterError(ifID
->ifPort
, ERTR_SEED_CONFLICT
);
311 CableStop
= NET_VALUE(rtmp
->at_rtmp_this_net
);
313 dPrintf(D_M_RTMP
, D_L_INFO
,
314 ("rtmp_update: Port #%d NONX activating, set Cable %d-%d\n",
315 ifID
->ifPort
, CableStart
, CableStop
));
320 * Perform a few sanity checks on the received RTMP data packet
323 if ((PortFlags
& RTR_XNET_PORT
) && (tuple_nb
>= 2)) {
325 /* The first tuple must be extended */
327 if (! TUPLERANGE(FirstTuple
)) {
328 dPrintf(D_M_RTMP
, D_L_WARNING
,
329 ("rtmp_update: bad range value in 1st tuple =%d\n",
330 TUPLERANGE(FirstTuple
)));
334 if (PortFlags
& RTR_SEED_PORT
)
335 if ((TUPLENET(FirstTuple
) != CableStart
) ||
336 (TUPLENET(SecondTuple
) != CableStop
)) {
337 dPrintf(D_M_RTMP
, D_L_WARNING
, ("rtmp_update: conflict on Seed Port\n"));
338 ifID
->ifRoutingState
= PORT_ERR_CABLER
;
339 ke
.error
= KE_CONF_SEED_NODE
;
340 ke
.port1
= ifID
->ifPort
;
341 strncpy(ke
.name1
, ifID
->ifName
,sizeof(ke
.name1
));
342 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
343 ke
.node
= SenderNodeID
;
344 ke
.netr1b
= TUPLENET(FirstTuple
);
345 ke
.netr1e
= TUPLENET(SecondTuple
);
346 ke
.netr2b
= CableStart
;
347 ke
.netr2e
= CableStop
;
348 RouterError(ifID
->ifPort
, ERTR_CABLE_CONFLICT
);
352 /* check that the tuple matches the range */
354 if ((TUPLENET(SecondTuple
) < TUPLENET(FirstTuple
)) ||
355 (TUPLENET(FirstTuple
) == 0) ||
356 (TUPLENET(FirstTuple
) >= DDP_STARTUP_LOW
) ||
357 (TUPLENET(SecondTuple
) == 0) ||
358 (TUPLENET(SecondTuple
) >= DDP_STARTUP_LOW
)) {
361 * IS THIS NON-FATAL?????
363 dPrintf(D_M_RTMP
, D_L_WARNING
,
364 ("rtmp_update: STARTUP RANGE!!! 1st %d-%d\n",
365 TUPLENET(FirstTuple
), TUPLENET(SecondTuple
)));
366 ifID
->ifRoutingState
= PORT_ERR_STARTUP
;
367 ke
.error
= KE_SEED_STARTUP
;
368 ke
.port1
= ifID
->ifPort
;
369 strncpy(ke
.name1
, ifID
->ifName
,sizeof(ke
.name1
));
370 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
371 ke
.node
= SenderNodeID
;
372 RouterError(ifID
->ifPort
, ERTR_CABLE_STARTUP
);
376 if (TUPLEDIST(FirstTuple
) != 0) {
377 dPrintf(D_M_RTMP
, D_L_WARNING
,
378 ("rtmp_update: Invalid distance in 1st tuple\n"));
382 if (rtmp
->at_rtmp_id
[6] != RTMP_VERSION_NUMBER
) {
383 dPrintf(D_M_RTMP
, D_L_WARNING
,
384 ("rtmp_update: Invalid RTMP version = x%x\n",
385 rtmp
->at_rtmp_id
[6]));
390 else { /* non extended interface or problem in tuple*/
392 if (PortFlags
& RTR_XNET_PORT
) {
393 dPrintf(D_M_RTMP
, D_L_WARNING
,
394 ("rtmp_update: invalid number of tuple for X-net\n"));
398 if (TUPLENET(FirstTuple
) == 0) { /* non extended RTMP data */
400 if (rtmp
->at_rtmp_id
[3] > RTMP_VERSION_NUMBER
) {
401 dPrintf(D_M_RTMP
, D_L_WARNING
,
402 ("rtmp_update: Invalid non extended RTMP version\n"));
408 dPrintf(D_M_RTMP
, D_L_WARNING
,
409 ("rtmp_update: version 1.0 non Xtended net not supported\n"));
410 ifID
->ifRoutingState
= PORT_ERR_BADRTMP
;
411 ke
.error
= KE_BAD_VER
;
412 ke
.rtmp_id
= rtmp
->at_rtmp_id
[6];
413 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
414 ke
.node
= SenderNodeID
;
415 RouterError(ifID
->ifPort
, ERTR_RTMP_BAD_VERSION
);
420 NewRoute
.NextIRNet
= NET_VALUE(rtmp
->at_rtmp_this_net
);
421 NewRoute
.NextIRNode
= SenderNodeID
;
422 NewRoute
.NetPort
= ifID
->ifPort
;
425 * Process the case where a non-seed port needs to acquire the right
429 if (!(PortFlags
& RTR_SEED_PORT
) && (ifID
->ifRoutingState
== PORT_ACTIVATING
)) {
430 dPrintf(D_M_RTMP_LOW
, D_L_INFO
,
431 ("rtmp_update: Port# %d, set non seed cable %d-%d\n",
432 ifID
->ifPort
, TUPLENET(FirstTuple
), TUPLENET(SecondTuple
)));
434 if (PortFlags
& RTR_XNET_PORT
) {
435 NewRoute
.NetStart
= TUPLENET(FirstTuple
);
436 NewRoute
.NetStop
= TUPLENET(SecondTuple
);
437 ifID
->ifThisCableStart
= TUPLENET(FirstTuple
);
438 ifID
->ifThisCableEnd
= TUPLENET(SecondTuple
);
443 NewRoute
.NetStart
= 0;
444 NewRoute
.NetStop
= NET_VALUE(rtmp
->at_rtmp_this_net
);
445 ifID
->ifThisCableStart
= NET_VALUE(rtmp
->at_rtmp_this_net
);
446 ifID
->ifThisCableEnd
= NET_VALUE(rtmp
->at_rtmp_this_net
);
449 * Now, check if we already know this route, or we need to add it
450 * (or modify it in the table accordingly)
453 if ((CurrentRoute
= rt_blookup(NewRoute
.NetStop
)) &&
454 (CurrentRoute
->NetStop
== NewRoute
.NetStop
) &&
455 (CurrentRoute
->NetStart
== NewRoute
.NetStart
)) {
456 /*LD 7/31/95 tempo########*/
457 if (NewRoute
.NetPort
!= CurrentRoute
->NetPort
) {
458 dPrintf(D_M_RTMP
, D_L_WARNING
,
459 ("rtmp_update: port# %d, not the port we waited for %d\n",
460 ifID
->ifPort
, CurrentRoute
->NetPort
));
461 /* propose to age the entry we know... */
463 state
= CurrentRoute
->EntryState
& 0x0F;
464 /* if entry has been updated recently, just clear the UPDATED
465 bit. if bit not set, then we can age the entry */
467 if (CurrentRoute
->EntryState
& RTE_STATE_UPDATED
) {
468 CurrentRoute
->EntryState
&= ~RTE_STATE_UPDATED
;
471 state
= state
>> 1 ; /* decrement state */
474 CurrentRoute
->EntryState
= (CurrentRoute
->EntryState
& 0xF0) | state
;
478 else { /* add the new route */
480 dPrintf(D_M_RTMP
, D_L_INFO
,
481 ("rtmp_update: P# %d, 1st tuple route not known, add %d-%d\n",
482 ifID
->ifPort
, NewRoute
.NetStart
, NewRoute
.NetStop
));
484 NewRoute
.EntryState
= RTE_STATE_GOOD
|RTE_STATE_UPDATED
;
485 NewRoute
.NetDist
= 0;
487 if (rt_insert(NewRoute
.NetStop
, NewRoute
.NetStart
, 0,
488 0, NewRoute
.NetDist
, NewRoute
.NetPort
,
489 NewRoute
.EntryState
) == (RT_entry
*)NULL
)
491 ErrorRTMPoverflow
= 1;
496 if (ifID
->ifRoutingState
== PORT_ACTIVATING
) {
497 dPrintf(D_M_RTMP
, D_L_INFO
,
498 ("rtmp_update: port activating, ignoring remaining tuples\n"));
503 * Process all the tuples against our routing table
506 TuplePtr
= (char *)FirstTuple
;
508 while (tuple_nb
-- > 0) {
510 if (TUPLEDIST(TuplePtr
) == NOTIFY_N_DIST
) {
511 dPrintf(D_M_RTMP
, D_L_INFO
,
512 ("rtmp_update: Port# %d, Tuple with Notify Neighbour\n",
514 NewRoute
.NetDist
= NOTIFY_N_DIST
;
515 NewRoute
.EntryState
= RTE_STATE_BAD
;
518 NewRoute
.NetDist
= TUPLEDIST(TuplePtr
) + 1;
519 NewRoute
.EntryState
= RTE_STATE_GOOD
;
520 NewRoute
.EntryState
= RTE_STATE_GOOD
|RTE_STATE_UPDATED
;
524 if (TUPLERANGE(TuplePtr
)) { /* Extended Tuple */
527 NewRoute
.NetStart
= TUPLENET(TuplePtr
);
529 NewRoute
.NetStop
= TUPLENET((TuplePtr
));
533 if ((NewRoute
.NetDist
== 0) ||
534 (NewRoute
.NetStart
== 0) ||
535 (NewRoute
.NetStop
== 0) ||
536 (NewRoute
.NetStop
< NewRoute
.NetStart
) ||
537 (NewRoute
.NetStart
>= DDP_STARTUP_LOW
) ||
538 (NewRoute
.NetStop
>= DDP_STARTUP_LOW
)) {
540 dPrintf(D_M_RTMP
, D_L_WARNING
,
541 ("rtmp_update: P# %d, non valid xtuple received [%d-%d]\n",
542 ifID
->ifPort
, NewRoute
.NetStart
, NewRoute
.NetStop
));
548 else { /* Non Extended Tuple */
550 NewRoute
.NetStart
= 0;
551 NewRoute
.NetStop
= TUPLENET(TuplePtr
);
555 if ((NewRoute
.NetDist
== 0) ||
556 (NewRoute
.NetStop
== 0) ||
557 (NewRoute
.NetStop
>= DDP_STARTUP_LOW
)) {
559 dPrintf(D_M_RTMP
, D_L_WARNING
,
560 ("rtmp_update: P# %d, non valid tuple received [%d]\n",
561 ifID
->ifPort
, NewRoute
.NetStop
));
567 if ((CurrentRoute
= rt_blookup(NewRoute
.NetStop
))) {
568 /* found something... */
570 if (NewRoute
.NetDist
< 16 ||
571 NewRoute
.NetDist
== NOTIFY_N_DIST
) {
574 * Check if the definition of the route changed
577 if (NewRoute
.NetStop
!= CurrentRoute
->NetStop
||
578 NewRoute
.NetStart
!= CurrentRoute
->NetStart
) {
580 if (NewRoute
.NetStop
== CurrentRoute
->NetStop
&&
581 NewRoute
.NetStop
== CurrentRoute
->NetStart
&&
582 NewRoute
.NetStart
== 0)
584 NewRoute
.NetStart
= NewRoute
.NetStop
;
586 else if (NewRoute
.NetStop
== CurrentRoute
->NetStop
&&
587 NewRoute
.NetStart
== NewRoute
.NetStop
&&
588 CurrentRoute
->NetStart
== 0) {
589 dPrintf(D_M_RTMP
, D_L_WARNING
,
590 ("rtmp_update: Range %d-%d has changed to %d-%d Dist=%d\n",
591 CurrentRoute
->NetStart
, CurrentRoute
->NetStop
,
592 NewRoute
.NetStart
, NewRoute
.NetStop
, NewRoute
.NetDist
));
593 NewRoute
.NetStart
= 0;
597 dPrintf(D_M_RTMP
, D_L_WARNING
,
598 ("rtmp_update: Net Conflict Cur=%d, New=%d\n",
599 CurrentRoute
->NetStop
, NewRoute
.NetStop
));
600 CurrentRoute
->EntryState
=
601 (CurrentRoute
->EntryState
& 0xF0) | RTE_STATE_BAD
;
608 * If we don't know the associated zones
611 if (!RT_ALL_ZONES_KNOWN(CurrentRoute
)) {
613 dPrintf(D_M_RTMP_LOW
, D_L_INFO
,
614 ("rtmp_update: Zone unknown for %d-%d state=0x%x\n",
615 CurrentRoute
->NetStart
, CurrentRoute
->NetStop
,
616 CurrentRoute
->EntryState
));
618 /* set the flag in the ifID structure telling
619 * that a scheduling of Zip Query is needed.
622 ifID
->ifZipNeedQueries
= 1;
626 if (((CurrentRoute
->EntryState
& 0x0F) <= RTE_STATE_SUSPECT
) &&
627 NewRoute
.NetDist
!= NOTIFY_N_DIST
) {
629 dPrintf(D_M_RTMP
, D_L_INFO
,
630 ("rtmp_update: update suspect entry %d-%d State=%d\n",
631 NewRoute
.NetStart
, NewRoute
.NetStop
,
632 (CurrentRoute
->EntryState
& 0x0F)));
634 if (NewRoute
.NetDist
<= CurrentRoute
->NetDist
) {
635 CurrentRoute
->NetDist
= NewRoute
.NetDist
;
636 CurrentRoute
->NetPort
= NewRoute
.NetPort
;
637 CurrentRoute
->NextIRNode
= NewRoute
.NextIRNode
;
638 CurrentRoute
->NextIRNet
= NewRoute
.NextIRNet
;
639 CurrentRoute
->EntryState
=
640 (CurrentRoute
->EntryState
& 0xF0) |
641 (RTE_STATE_GOOD
|RTE_STATE_UPDATED
);
647 if (NewRoute
.NetDist
== NOTIFY_N_DIST
) {
649 CurrentRoute
->EntryState
=
650 (CurrentRoute
->EntryState
& 0xF0) | RTE_STATE_SUSPECT
;
651 CurrentRoute
->NetDist
= NOTIFY_N_DIST
;
659 if ((NewRoute
.NetDist
<= CurrentRoute
->NetDist
) && (NewRoute
.NetDist
<16)) {
661 /* Found a shorter or more recent Route,
662 * Replace with the New entryi
665 CurrentRoute
->NetDist
= NewRoute
.NetDist
;
666 CurrentRoute
->NetPort
= NewRoute
.NetPort
;
667 CurrentRoute
->NextIRNode
= NewRoute
.NextIRNode
;
668 CurrentRoute
->NextIRNet
= NewRoute
.NextIRNet
;
669 CurrentRoute
->EntryState
|= RTE_STATE_UPDATED
;
671 /* Can we consider now that the entry is updated? */
672 dPrintf(D_M_RTMP_LOW
, D_L_INFO
,
673 ("rtmp_update: Shorter route found %d-%d, update\n",
674 NewRoute
.NetStart
, NewRoute
.NetStop
));
676 if (ddp_AURPsendx
&& (aurp_ifID
->ifFlags
& AT_IFF_AURP
))
677 ddp_AURPsendx(AURPCODE_RTUPDATE
,
678 (void *)&NewRoute
, AURPEV_NetDistChange
);
681 else { /* no entry found */
683 if (NewRoute
.NetDist
< 16 && NewRoute
.NetDist
!= NOTIFY_N_DIST
&&
684 NewRoute
.NextIRNet
>= ifID
->ifThisCableStart
&&
685 NewRoute
.NextIRNet
<= ifID
->ifThisCableEnd
) {
687 NewRoute
.EntryState
= (RTE_STATE_GOOD
|RTE_STATE_UPDATED
);
689 dPrintf(D_M_RTMP_LOW
, D_L_INFO
,
690 ("rtmp_update: NewRoute %d-%d Tuple #%d\n",
691 NewRoute
.NetStart
, NewRoute
.NetStop
, tuple_nb
));
693 ifID
->ifZipNeedQueries
= 1;
695 if (rt_insert(NewRoute
.NetStop
, NewRoute
.NetStart
, NewRoute
.NextIRNet
,
696 NewRoute
.NextIRNode
, NewRoute
.NetDist
, NewRoute
.NetPort
,
697 NewRoute
.EntryState
) == (RT_entry
*)NULL
)
698 ErrorRTMPoverflow
= 1;
700 else if (ddp_AURPsendx
&& (aurp_ifID
->ifFlags
& AT_IFF_AURP
))
701 ddp_AURPsendx(AURPCODE_RTUPDATE
,
702 (void *)&NewRoute
, AURPEV_NetAdded
);
706 } /* end of main while */
707 ifID
->ifRouterState
= ROUTER_UPDATED
;
708 if (ifID
->ifZipNeedQueries
)
709 zip_send_queries(ifID
, 0, 0xFF);
712 timeout(rtmp_timeout, (caddr_t) ifID, 20*SYS_HZ);
716 /* The RTMP validity timer expired, we need to update the
717 * state of each routing entry in the table
718 * because there is only one validity timer and it is always running,
719 * we can't just age all the entries automatically, as we might be
720 * aging entries that were just updated. So, when an entry is updated,
721 * the RTE_STATE_UPDATED bit is set and when the aging routine is called
722 * it just resets this bit if it is set, only if it is not set will the
723 * route actually be aged.
724 * Note there are 4 states for an entry, the state is decremented until
725 * it reaches the bad state. At this point, the entry is removed
727 * RTE_STATE_GOOD : The entry was valid (will be SUSPECT)
728 * RTE_STATE_SUSPECT: The entry was suspect (can still be used for routing)
729 * RTE_STATE_BAD : The entry was bad and is now deleted
730 * RTE_STATE_UNUSED : Unused or removed entry in the table
733 void rtmp_timeout(ifID
)
734 register at_ifaddr_t
*ifID
;
736 register u_char state
;
737 register unsigned int s
;
739 RT_entry
*en
= &RT_table
[0];
740 boolean_t funnel_state
;
742 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
744 if (ifID
->ifRoutingState
< PORT_ONLINE
) {
745 (void) thread_funnel_set(network_flock
, FALSE
);
749 /* for multihoming mode, we use ifRouterState to tell if there
750 is a router out there, so we know when to use cable multicast */
751 if (ifID
->ifRouterState
> NO_ROUTER
)
752 ifID
->ifRouterState
--;
754 ATDISABLE(s
, ddpinp_lock
);
755 for (i
= 0 ; i
< RT_maxentry
; i
++,en
++) {
757 /* we want to age "learned" nets, not directly connected ones */
758 state
= en
->EntryState
& 0x0F;
761 if (state
> RTE_STATE_UNUSED
&&
762 !(en
->EntryState
& RTE_STATE_PERMANENT
) && en
->NetStop
&&
763 en
->NetDist
&& en
->NetPort
== ifID
->ifPort
) {
765 /* if entry has been updated recently, just clear the UPDATED
766 bit. if bit not set, then we can age the entry */
767 if (en
->EntryState
& RTE_STATE_UPDATED
) {
768 en
->EntryState
&= ~RTE_STATE_UPDATED
;
772 state
= state
>> 1 ; /* decrement state */
774 if (state
== RTE_STATE_UNUSED
) {/* was BAD, needs to delete */
775 dPrintf(D_M_RTMP
, D_L_INFO
,
776 ("rtmp_timeout: Bad State for %d-%d (e#%d): remove\n",
777 en
->NetStart
, en
->NetStop
, i
));
779 if (ddp_AURPsendx
&& (aurp_ifID
->ifFlags
& AT_IFF_AURP
))
780 ddp_AURPsendx(AURPCODE_RTUPDATE
,
781 (void *)en
, AURPEV_NetDeleted
);
783 /* then clear the bit in the table concerning this entry.
784 If the zone Count reaches zero, remove the entry */
786 zt_remove_zones(en
->ZoneBitMap
);
788 RT_DELETE(en
->NetStop
, en
->NetStart
);
791 en
->EntryState
= (en
->EntryState
& 0xF0) | state
;
792 dPrintf(D_M_RTMP
, D_L_INFO
, ("Change State for %d-%d to %d (e#%d)\n",
793 en
->NetStart
, en
->NetStop
, state
, i
));
797 ATENABLE(s
, ddpinp_lock
);
798 timeout(rtmp_timeout
, (caddr_t
) ifID
, 20*SYS_HZ
);
800 (void) thread_funnel_set(network_flock
, FALSE
);
804 * rtmp_prep_new_packet: allocate a ddp packet for RTMP use (reply to a RTMP request or
805 * Route Data Request, or generation of RTMP data packets.
806 * The ddp header is filled with relevant information, as well as
807 * the beginning of the rtmp packet with the following info:
808 * Router's net number (2bytes)
809 * ID Length = 8 (1byte)
810 * Router's node ID (1byte)
811 * Extended Range Start (2bytes)
812 * Range + dist (0x80) (1byte)
813 * Extended Range End (2bytes)
814 * Rtmp version (0x82) (1byte)
818 gbuf_t
*rtmp_prep_new_packet (ifID
, DstNet
, DstNode
, socket
)
819 register at_ifaddr_t
*ifID
;
820 register at_net DstNet
;
821 register u_char DstNode
;
822 register char socket
;
826 register at_ddp_t
*ddp
;
827 register char * rtmp_data
;
829 if ((m
= gbuf_alloc(AT_WR_OFFSET
+1024, PRI_HI
)) == NULL
) {
830 dPrintf(D_M_RTMP
, D_L_WARNING
, ("rtmp_new_packet: Can't allocate mblock\n"));
831 return ((gbuf_t
*)NULL
);
834 gbuf_rinc(m
,AT_WR_OFFSET
);
835 gbuf_wset(m
,DDP_X_HDR_SIZE
+ 10);
836 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
839 * Prepare the DDP header of the new packet
843 ddp
->unused
= ddp
->hopcount
= 0;
845 UAS_ASSIGN(ddp
->checksum
, 0);
847 NET_NET(ddp
->dst_net
, DstNet
);
848 ddp
->dst_node
= DstNode
;
849 ddp
->dst_socket
= socket
;
851 NET_ASSIGN(ddp
->src_net
, ifID
->ifThisNode
.s_net
);
852 ddp
->src_node
= ifID
->ifThisNode
.s_node
;
853 ddp
->src_socket
= RTMP_SOCKET
;
854 ddp
->type
= DDP_RTMP
;
857 * Prepare the RTMP header (Router Net, ID, Node and Net Tuple
858 * (this works only if we are on an extended net)
861 rtmp_data
= ddp
->data
;
863 *rtmp_data
++ = (ifID
->ifThisNode
.s_net
& 0xff00) >> 8;
864 *rtmp_data
++ = ifID
->ifThisNode
.s_net
& 0x00ff ;
866 *rtmp_data
++ = (u_char
)ifID
->ifThisNode
.s_node
;
867 *rtmp_data
++ = (CableStart
& 0xff00) >> 8;
868 *rtmp_data
++ = CableStart
& 0x00ff ;
869 *rtmp_data
++ = 0x80; /* first tuple, so distance is always zero */
870 *rtmp_data
++ = (CableStop
& 0xff00) >> 8;
871 *rtmp_data
++ = CableStop
& 0x00ff ;
872 *rtmp_data
++ = RTMP_VERSION_NUMBER
;
878 int rtmp_r_find_bridge(ifID
, orig_ddp
)
879 register at_ifaddr_t
*ifID
;
880 register at_ddp_t
*orig_ddp
;
884 register int size
, status
;
885 register at_ddp_t
*ddp
;
886 register char * rtmp_data
;
890 /* find the bridge for the querried net */
892 Entry
= rt_blookup(NET_VALUE(orig_ddp
->dst_net
));
895 dPrintf(D_M_RTMP
, D_L_WARNING
, ("rtmp_r_find_bridge: no info for net %d\n",
896 NET_VALUE(orig_ddp
->dst_net
)));
901 size
= DDP_X_HDR_SIZE
+ 10 ;
902 if ((m
= gbuf_alloc(AT_WR_OFFSET
+size
, PRI_HI
)) == NULL
) {
903 dPrintf(D_M_RTMP
, D_L_WARNING
,
904 ("rtmp_r_find_bridge: Can't allocate mblock\n"));
908 gbuf_rinc(m
,AT_WR_OFFSET
);
910 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
913 * Prepare the DDP header of the new packet
916 ddp
->unused
= ddp
->hopcount
= 0;
918 DDPLEN_ASSIGN(ddp
, size
);
919 UAS_ASSIGN(ddp
->checksum
, 0);
921 NET_NET(ddp
->dst_net
, orig_ddp
->src_net
);
922 ddp
->dst_node
= orig_ddp
->src_node
;
923 ddp
->dst_socket
= orig_ddp
->src_socket
;
925 NET_ASSIGN(ddp
->src_net
, Entry
->NextIRNet
);
926 ddp
->src_node
= Entry
->NextIRNode
;
927 ddp
->src_socket
= RTMP_SOCKET
;
928 ddp
->type
= DDP_RTMP
;
931 * Prepare the RTMP header (Router Net, ID, Node and Net Tuple
932 * (this works only if we are on an extended net)
935 rtmp_data
= ddp
->data
;
937 *rtmp_data
++ = (Entry
->NextIRNet
& 0xff00) >> 8;
938 *rtmp_data
++ = Entry
->NextIRNet
& 0x00ff ;
940 *rtmp_data
++ = (u_char
)Entry
->NextIRNode
;
941 *rtmp_data
++ = (Entry
->NetStart
& 0xff00) >> 8;
942 *rtmp_data
++ = Entry
->NetStart
& 0x00ff ;
943 *rtmp_data
++ = 0x80; /* first tuple, so distance is always zero */
944 *rtmp_data
++ = (Entry
->NetStop
& 0xff00) >> 8;
945 *rtmp_data
++ = Entry
->NetStop
& 0x00ff ;
946 *rtmp_data
++ = RTMP_VERSION_NUMBER
;
949 dPrintf(D_M_RTMP
, D_L_INFO
, ("rtmp_r_find_bridge: for net %d send back router %d.%d\n",
950 NET_VALUE(orig_ddp
->dst_net
), Entry
->NextIRNet
, Entry
->NextIRNode
));
951 if (status
= ddp_router_output(m
, ifID
, AT_ADDR
, NET_VALUE(orig_ddp
->src_net
),
952 orig_ddp
->src_node
, 0)){
953 dPrintf(D_M_RTMP
, D_L_WARNING
,
954 ("rtmp_r_find_bridge: ddp_router_output failed status=%d\n", status
));
962 * Send the routing table entries in RTMP data packets.
963 * Use split horizon if specified. The Data packets are sent
964 * as full DDP packets, if the last packet is full an empty
965 * packet is sent to tell the recipients that this is the end of
969 static int rtmp_send_table(ifID
, DestNet
, DestNode
, split_hz
, socket
,
971 register at_ifaddr_t
*ifID
; /* interface/port params */
972 register at_net DestNet
; /* net where to send the table */
973 register u_char DestNode
; /* node where to send to table */
974 short split_hz
; /* use split horizon */
975 char socket
; /* the destination socket to send to */
976 short n_neighbors
; /* used to send packets telling we are going down */
984 register at_ddp_t
*ddp
;
985 register short EntNb
= 0, sent_tuple
= 0;
986 register unsigned int s
;
988 if (ifID
->ifRoutingState
< PORT_ONLINE
) {
989 dPrintf(D_M_RTMP
, D_L_INFO
,
990 ("rtmp_send_table: port %d activating, we don't send anything!\n",
995 /* prerare tuples and packets for DDP*/
996 /* if split horizon, do not send tuples we can reach on the port we
1000 Entry
= &RT_table
[0];
1002 if (!(m
= rtmp_prep_new_packet(ifID
, DestNet
, DestNode
, socket
))) {
1003 dPrintf(D_M_RTMP
, D_L_WARNING
,
1004 ("rtmp_send_table: rtmp_prep_new_packet failed\n"));
1008 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
1009 Buff_ptr
= (char *)((char *)ddp
+ DDP_X_HDR_SIZE
+ 10);
1011 ATDISABLE(s
, ddpinp_lock
);
1012 while (EntNb
< RT_maxentry
) {
1014 if (Entry
->NetStop
&& ((Entry
->EntryState
& 0x0F) >= RTE_STATE_SUSPECT
)) {
1015 if (!(split_hz
&& ifID
->ifPort
== Entry
->NetPort
)) {
1018 if (((Entry
->EntryState
& 0x0F) < RTE_STATE_SUSPECT
) || n_neighbors
)
1019 NewDist
= NOTIFY_N_DIST
;
1021 NewDist
= Entry
->NetDist
& 0x1F;
1023 if (Entry
->NetStart
) { /* Extended */
1024 *Buff_ptr
++ = (Entry
->NetStart
& 0xFF00) >> 8;
1025 *Buff_ptr
++ = (Entry
->NetStart
& 0x00FF);
1026 *Buff_ptr
++ = 0x80 | NewDist
;
1027 *Buff_ptr
++ = (Entry
->NetStop
& 0xFF00) >> 8;
1028 *Buff_ptr
++ = (Entry
->NetStop
& 0x00FF);
1029 *Buff_ptr
++ = RTMP_VERSION_NUMBER
;
1032 else { /* non extended tuple */
1033 *Buff_ptr
++ = (Entry
->NetStop
& 0xFF00) >> 8;
1034 *Buff_ptr
++ = (Entry
->NetStop
& 0x00FF);
1035 *Buff_ptr
++ = NewDist
;
1041 if (size
> (DDP_DATA_SIZE
-20)) {
1042 DDPLEN_ASSIGN(ddp
, size
+ DDP_X_HDR_SIZE
+ 10);
1044 ATENABLE(s
, ddpinp_lock
);
1045 if (status
= ddp_router_output(m
, ifID
, AT_ADDR
,
1046 NET_VALUE(DestNet
),DestNode
, 0)){
1047 dPrintf(D_M_RTMP
, D_L_WARNING
,
1048 ("rtmp_send_table: ddp_router_output failed status=%d\n",
1052 if ((m
= rtmp_prep_new_packet (ifID
, DestNet
, DestNode
, socket
)) == NULL
){
1053 dPrintf(D_M_RTMP
, D_L_WARNING
,
1054 ("rtmp_send_table: rtmp_prep_new_poacket failed status=%d\n",
1058 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
1059 Buff_ptr
= (char *)((char *)ddp
+ DDP_X_HDR_SIZE
+ 10);
1061 dPrintf(D_M_RTMP_LOW
, D_L_OUTPUT
,
1062 ("rtmp_s_tble: Send %d tuples on port %d\n",
1063 sent_tuple
, ifID
->ifPort
));
1066 ATDISABLE(s
, ddpinp_lock
);
1072 ATENABLE(s
, ddpinp_lock
);
1075 * If we have some remaining entries to send, send them now.
1076 * otherwise, the last packet we sent was full, we need to send an empty one
1079 DDPLEN_ASSIGN(ddp
, size
+ DDP_X_HDR_SIZE
+ 10);
1082 ddp_router_output(m
, ifID
, AT_ADDR
, NET_VALUE(DestNet
),DestNode
, 0))){
1083 dPrintf(D_M_RTMP
, D_L_WARNING
,
1084 ("rtmp_send_table: ddp_router_output failed status=%d\n", status
));
1087 dPrintf(D_M_RTMP_LOW
, D_L_OUTPUT
,
1088 ("rtmp_s_tble: LAST Packet split=%d with %d tuples sent on port %d\n",
1089 split_hz
, sent_tuple
, ifID
->ifPort
));
1095 * rtmp_request: respond to the 3 types of RTMP requests RTMP may receive
1096 * RTMP func =1 : respond with an RTMP Reponse Packet
1097 * RTMP func =2 : respond with the routing table RTMP packet with split horizon
1098 * RTMP func =3 : respond with the routing table RTMP packet no split horizon
1100 * see Inside AppleTalk around page 5-18 for "details"
1103 static void rtmp_request(ifID
, ddp
)
1104 register at_ifaddr_t
*ifID
;
1105 register at_ddp_t
*ddp
;
1108 short split_horizon
= FALSE
;
1112 /* We ignore the request if we're activating on that port */
1114 if (ifID
->ifRoutingState
< PORT_ONLINE
)
1117 /* check RTMP function code */
1119 code
= ddp
->data
[0];
1123 case RTMP_REQ_FUNC1
: /* RTMP Find Bridge */
1125 /* RTMP Request Packet: we send a response with the next IRrange */
1126 dPrintf(D_M_RTMP
, D_L_INPUT
,
1127 ( "rtmp_request: find bridge for net %d port %d node %d.%d\n",
1128 NET_VALUE(ddp
->dst_net
), ifID
->ifPort
,
1129 NET_VALUE(ddp
->src_net
), ddp
->src_node
));
1131 if ((error
= rtmp_r_find_bridge (ifID
, ddp
))) {
1132 dPrintf(D_M_RTMP
, D_L_WARNING
,
1133 ("rtmp_request: Code 1 ddp_r_output failed error=%d\n",
1140 case RTMP_REQ_FUNC2
:
1142 split_horizon
= TRUE
;
1144 case RTMP_REQ_FUNC3
:
1146 /* RTMP Route Request Packet */
1148 dPrintf(D_M_RTMP
, D_L_INPUT
,
1149 ("rtmp_request: received code=%d from %d.%d for %d.%d\n",
1150 code
, NET_VALUE(ddp
->src_net
), ddp
->src_node
,
1151 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
));
1153 rtmp_send_table(ifID
, ddp
->src_net
, ddp
->src_node
,
1154 split_horizon
, ddp
->src_socket
, 0);
1160 /* unknown type of request */
1161 dPrintf(D_M_RTMP
, D_L_WARNING
,
1162 ("rtmp_request : invalid type of request =%d\n",
1169 /* funnel version of rtmp_send_port */
1170 void rtmp_send_port_funnel(ifID
)
1171 register at_ifaddr_t
*ifID
;
1173 thread_funnel_set(network_flock
, TRUE
);
1174 rtmp_send_port(ifID
);
1175 thread_funnel_set(network_flock
, FALSE
);
1180 * rtmp_send_all_ports : send the routing table on all connected ports
1181 * check for the port status and if ok, send the
1182 * rtmp tuples to the broadcast address for the port
1183 * usually called on timeout every 10 seconds.
1186 void rtmp_send_port(ifID
)
1187 register at_ifaddr_t
*ifID
;
1191 NET_ASSIGN(DestNet
, 0);
1193 if (ifID
&& ifID
->ifRoutingState
== PORT_ONLINE
) {
1194 dPrintf(D_M_RTMP_LOW
, D_L_OUTPUT
,
1195 ("rtmp_send_port: do stuff for port=%d\n",
1197 if (ifID
->ifZipNeedQueries
)
1198 zip_send_queries(ifID
, 0, 0xFF);
1199 if (!ROUTING_MODE
) {
1202 rtmp_send_table(ifID
, DestNet
, 0xFF, 1, RTMP_SOCKET
, 0);
1205 if (ifID
== ifID_home
)
1206 dPrintf(D_M_RTMP_LOW
, D_L_VERBOSE
,
1207 ("I:%5d O:%5d H:%5d dropped:%d\n",
1208 pktsIn
, pktsOut
, pktsHome
, pktsDropped
));
1210 dPrintf(D_M_RTMP_LOW
, D_L_TRACE
,
1211 ("rtmp_send_port: func=0x%x, ifID=0x%x\n",
1212 (u_int
) rtmp_send_port
, (u_int
) ifID
));
1213 timeout (rtmp_send_port_funnel
, (caddr_t
)ifID
, 10 * SYS_HZ
);
1217 /* rtmp_dropper: check the number of packet received every x secondes.
1218 * the actual packet dropping is done in ddp_input
1223 boolean_t funnel_state
;
1225 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1227 pktsIn
= pktsOut
= pktsHome
= pktsDropped
= 0;
1228 timeout(rtmp_dropper
, NULL
, 2*SYS_HZ
);
1230 (void) thread_funnel_set(network_flock
, FALSE
);
1234 * rtmp_router_start: perform the sanity checks before declaring the router up
1235 * and running. This function looks for discrepency between the net infos
1236 * for the different ports and seed problems.
1237 * If everything is fine, the state of each port is brought to PORT_ONLINE.\
1238 * ### LD 01/09/95 Changed to correct Zone problem on non seed ports.
1241 int rtmp_router_start(keP
)
1242 at_kern_err_t
*keP
; /* used to report errors (if any) */
1245 register at_ifaddr_t
*ifID
, *ifID2
;
1246 register short Index
, router_starting_timer
= 0;
1247 register RT_entry
*Entry
;
1248 register at_net_al netStart
, netStop
;
1249 boolean_t funnel_state
;
1251 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1253 /* clear the static structure used to record routing errors */
1254 bzero(&ke
, sizeof(ke
));
1256 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1258 /* if non seed, need to acquire the right node address */
1260 if ((ifID
->ifFlags
& RTR_SEED_PORT
) == 0) {
1261 if ((ifID
->ifThisCableStart
== 0 && ifID
->ifThisCableEnd
== 0) ||
1262 (ifID
->ifThisCableStart
>= DDP_STARTUP_LOW
&&
1263 ifID
->ifThisCableEnd
<= DDP_STARTUP_HIGH
)) {
1265 if (ifID
->ifThisCableEnd
== 0) {
1266 keP
->error
= KE_NO_SEED
;
1267 keP
->port1
= ifID
->ifPort
;
1268 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1271 keP
->error
= KE_INVAL_RANGE
;
1272 keP
->port1
= ifID
->ifPort
;
1273 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1274 keP
->netr1b
= ifID
->ifThisCableStart
;
1275 keP
->netr1e
= ifID
->ifThisCableEnd
;
1277 ifID
->ifRoutingState
= PORT_ERR_STARTUP
;
1278 RouterError(ifID
->ifPort
, ERTR_CABLE_STARTUP
);
1283 /* we are non seed, so try to acquire the zones for that guy */
1284 ifID
->ifZipNeedQueries
= 1;
1286 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1287 ("rtmp_router_start: call elap_online for Non Seed port #%d cable =%d-%d\n",
1288 ifID
->ifPort
, CableStart
, CableStop
));
1289 if ((err
= elap_online3(ifID
)))
1294 /* Check if we have a problem with the routing table size */
1296 if (ErrorRTMPoverflow
) {
1297 keP
->error
= KE_RTMP_OVERFLOW
;
1302 /* Now, check that we don't have a conflict in between our interfaces */
1303 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1305 /* check if the RoutingState != PORT_ONERROR */
1306 if (ifID
->ifRoutingState
< PORT_ACTIVATING
) {
1310 if ((ifID
->ifThisCableStart
== 0 && ifID
->ifThisCableEnd
== 0) ||
1311 (ifID
->ifThisCableStart
>= DDP_STARTUP_LOW
&&
1312 ifID
->ifThisCableEnd
<= DDP_STARTUP_HIGH
)) {
1314 if (ifID
->ifThisCableEnd
== 0) {
1315 keP
->error
= KE_NO_SEED
;
1316 keP
->port1
= ifID
->ifPort
;
1317 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1320 keP
->error
= KE_INVAL_RANGE
;
1321 keP
->port1
= ifID
->ifPort
;
1322 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1323 keP
->netr1b
= ifID
->ifThisCableStart
;
1324 keP
->netr1e
= ifID
->ifThisCableEnd
;
1327 ifID
->ifRoutingState
= PORT_ERR_STARTUP
;
1328 RouterError(ifID
->ifPort
, ERTR_CABLE_STARTUP
);
1333 /* check the interface address against all other ifs */
1335 netStart
= ifID
->ifThisCableStart
;
1336 netStop
= ifID
->ifThisCableEnd
;
1338 for (ifID2
= TAILQ_NEXT(ifID
, aa_link
); ifID2
;
1339 ifID2
= TAILQ_NEXT(ifID2
, aa_link
)) {
1341 if (((netStart
>= ifID2
->ifThisCableStart
) &&
1342 (netStart
<= ifID2
->ifThisCableEnd
)) ||
1343 ((netStop
>= ifID2
->ifThisCableStart
) &&
1344 (netStop
<= ifID2
->ifThisCableEnd
)) ||
1345 ((ifID2
->ifThisCableStart
>= netStart
) &&
1346 (ifID2
->ifThisCableStart
<= netStop
)) ||
1347 ((ifID2
->ifThisCableEnd
>= netStart
) &&
1348 (ifID2
->ifThisCableEnd
<= netStop
)) ) {
1350 keP
->error
= KE_CONF_RANGE
;
1351 keP
->port1
= ifID
->ifPort
;
1352 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1353 keP
->port2
= ifID2
->ifPort
;
1354 strncpy(keP
->name2
, ifID2
->ifName
,sizeof(keP
->name2
));
1355 keP
->netr1b
= ifID
->ifThisCableStart
;
1356 keP
->netr1e
= ifID
->ifThisCableEnd
;
1357 ifID
->ifRoutingState
= PORT_ERR_CABLER
;
1358 RouterError(ifID
->ifPort
, ERTR_CABLE_CONFLICT
);
1364 /* ### LD 01/04/94: We need to fill in the next IR info in the routing table */
1365 Entry
= rt_blookup(ifID
->ifThisCableEnd
);
1367 if (Entry
== NULL
) {
1368 dPrintf(D_M_RTMP
, D_L_ERROR
,
1369 ("rtmp_router_start: we don't know our cable range port=%d\n",
1376 * Note: At this point, non seed ports may not be aware of their Default zone
1379 if (!(ifID
->ifFlags
& RTR_SEED_PORT
)) {
1380 ifID
->ifDefZone
= 0;
1381 Entry
->EntryState
|= (RTE_STATE_GOOD
|RTE_STATE_UPDATED
);
1384 ifID
->ifRoutingState
= PORT_ONLINE
;
1385 ifID
->ifState
= LAP_ONLINE
;
1387 /* set the right net and node for each port */
1388 Entry
->NextIRNet
= ifID
->ifThisNode
.s_net
;
1389 Entry
->NextIRNode
= ifID
->ifThisNode
.s_node
;
1391 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1392 ("rtmp_router_start: bring port=%d [%d.%d]... on line\n",
1393 ifID
->ifPort
, ifID
->ifThisNode
.s_net
,
1394 ifID
->ifThisNode
.s_node
));
1399 * Everything is fine, we can begin to babble on the net...
1402 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1403 if (ifID
->ifRoutingState
== PORT_ONLINE
) {
1404 rtmp_send_port(ifID
);
1405 timeout(rtmp_timeout
, (caddr_t
)ifID
, (50+ifID
->ifPort
) * SYS_HZ
);
1406 if (ifID
->ifRoutingState
< PORT_ACTIVATING
) {
1412 /* Check if we have a problem with the routing or zip table size */
1414 if (ErrorRTMPoverflow
) {
1415 keP
->error
= KE_RTMP_OVERFLOW
;
1418 if (ErrorZIPoverflow
) {
1419 keP
->error
= KE_ZIP_OVERFLOW
;
1423 /* sleep for 10 seconds */
1425 /* *** eventually this will be the ifID for the interface
1426 being brought up in router mode *** */
1427 /* *** router sends rtmp packets every 10 seconds *** */
1428 tsleep(&ifID_home
->startup_inprogress
,
1429 PSOCK
| PCATCH
, "router_start1", (10+1) * SYS_HZ
))
1436 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1438 if (ifID
->ifRoutingState
< PORT_ACTIVATING
) {
1442 if ((ifID
->ifZipNeedQueries
)
1443 && (ifID
->ifFlags
& RTR_SEED_PORT
) == 0) {
1444 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1445 ("rtmp_router_start: send Zip Queries for Port %d\n",
1447 zip_send_queries(ifID
, 0, 0xFF);
1449 if (router_starting_timer
>= 10) {
1450 dPrintf(D_M_RTMP
, D_L_WARNING
,
1451 ("rtmp_router_start: no received response to ZipNeedQueries\n"));
1452 keP
->error
= KE_NO_ZONES_FOUND
;
1453 keP
->port1
= ifID
->ifPort
;
1454 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1455 keP
->netr1b
= ifID
->ifThisCableStart
;
1456 keP
->netr1e
= ifID
->ifThisCableEnd
;
1457 ifID
->ifRoutingState
= PORT_ERR_CABLER
;
1458 RouterError(ifID
->ifPort
, ERTR_CABLE_CONFLICT
);
1462 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1463 ("rtmp_router_start: waiting for zone info to complete\n"));
1464 /* sleep for 10 seconds */
1466 /* *** eventually this will be the ifID for the
1467 interface being brought up in router mode *** */
1468 tsleep(&ifID_home
->startup_inprogress
,
1469 PSOCK
| PCATCH
, "router_start2", 10 * SYS_HZ
))
1475 router_starting_timer
++;
1481 /* At This Point, check if we know the default zones for non seed port */
1483 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1485 if (ifID
->ifRoutingState
< PORT_ACTIVATING
)
1488 if (!(ifID
->ifFlags
& RTR_SEED_PORT
)) {
1489 Entry
= rt_blookup(ifID
->ifThisCableEnd
);
1491 if (Entry
== NULL
) {
1492 dPrintf(D_M_RTMP
, D_L_ERROR
,
1493 ("rtmp_router_start: (2)we don't know our cable range port=%d\n",
1498 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1499 ("rtmp_router_start: if %s set to permanent\n",
1501 Entry
->NetDist
= 0; /* added 4-29-96 jjs, prevent direct
1502 nets from showing non-zero
1504 /* upgrade the non seed ports. */
1505 Entry
->EntryState
|= RTE_STATE_PERMANENT
;
1507 Index
= zt_ent_zindex(Entry
->ZoneBitMap
);
1509 dPrintf(D_M_RTMP
, D_L_ERROR
,
1510 ("rtmp_router_start: still don't know default zone for port %d\n",
1513 ifID
->ifDefZone
= Index
;
1514 if ((ifID
== ifID_home
) || MULTIHOME_MODE
) {
1515 ifID
->ifZoneName
= ZT_table
[Index
-1].Zone
;
1516 (void)regDefaultZone(ifID
);
1522 /* Check if we have a problem with the routing or zip table size */
1524 if (ErrorRTMPoverflow
) {
1525 keP
->error
= KE_RTMP_OVERFLOW
;
1528 if (ErrorZIPoverflow
) {
1529 keP
->error
= KE_ZIP_OVERFLOW
;
1534 * Handle the Home Port specifics
1537 /* set the router address as being us no matter what*/
1538 ifID_home
->ifARouter
= ifID_home
->ifThisNode
;
1539 ifID_home
->ifRouterState
= ROUTER_UPDATED
;
1541 /* prepare the packet dropper timer */
1542 timeout (rtmp_dropper
, NULL
, 1*SYS_HZ
);
1544 (void) thread_funnel_set(network_flock
, funnel_state
);
1548 dPrintf(D_M_RTMP
,D_L_ERROR
,
1549 ("rtmp_router_start: error type=%d occured on port %d\n",
1550 ifID
->ifRoutingState
, ifID
->ifPort
));
1552 /* if there's no keP->error, copy the local ke structure,
1553 since the error occured asyncronously */
1554 if ((!keP
->error
) && ke
.error
)
1555 bcopy(&ke
, keP
, sizeof(ke
));
1558 /* to return the error in keP, the ioctl has to return 0 */
1559 (void) thread_funnel_set(network_flock
, funnel_state
);
1561 return((keP
->error
)? 0: err
);
1562 } /* rtmp_router_start */
1565 void rtmp_shutdown()
1567 register at_ifaddr_t
*ifID
;
1571 NET_ASSIGN(DestNet
, 0);
1573 dPrintf(D_M_RTMP
, D_L_SHUTDN
,
1574 ("rtmp_shutdown:stop sending to all ports\n"));
1576 untimeout(rtmp_dropper
, (caddr_t
)0);
1577 untimeout(rtmp_router_start
, 1); /* added for 2225395 */
1578 untimeout(rtmp_router_start
, 3); /* added for 2225395 */
1580 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1581 if (ifID
->ifRoutingState
> PORT_OFFLINE
) {
1582 if (ifID
->ifRoutingState
== PORT_ONLINE
) {
1583 untimeout(rtmp_send_port_funnel
, (caddr_t
)ifID
);
1584 untimeout(rtmp_timeout
, (caddr_t
) ifID
);
1587 * it's better to notify the neighbour routers that we are going down
1590 rtmp_send_table(ifID
, DestNet
, 0xFF, TRUE
,
1593 ifID
->ifRoutingState
= PORT_OFFLINE
;
1595 dPrintf(D_M_RTMP
, D_L_SHUTDN
,
1596 ("rtmp_shutdown: routing on port=%d... off line\nStats:\n",
1598 dPrintf(D_M_RTMP
, D_L_SHUTDN
,
1599 ("fwdBytes : %ld\nfwdPackets : %ld\ndroppedBytes : %ld\ndroppedPkts : %ld\n",
1600 ifID
->ifStatistics
.fwdBytes
, ifID
->ifStatistics
.fwdPkts
,
1601 ifID
->ifStatistics
.droppedBytes
, ifID
->ifStatistics
.droppedPkts
));
1609 * Remove all entries associated with the specified port.
1611 void rtmp_purge(ifID
)
1616 RT_entry
*en
= &RT_table
[0];
1618 ATDISABLE(s
, ddpinp_lock
);
1619 for (i
=0; i
< RT_maxentry
; i
++) {
1620 state
= en
->EntryState
& 0x0F;
1621 if ((state
> RTE_STATE_UNUSED
) && (state
!= RTE_STATE_PERMANENT
)
1622 && en
->NetStop
&& en
->NetDist
&& (en
->NetPort
== ifID
->ifPort
)) {
1623 zt_remove_zones(en
->ZoneBitMap
);
1624 RT_DELETE(en
->NetStop
, en
->NetStart
);
1628 ATENABLE(s
, ddpinp_lock
);