]>
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 #include <sys/kern_event.h>
70 extern void (*ddp_AURPsendx
)();
71 extern at_ifaddr_t
*aurp_ifID
;
72 extern at_ifaddr_t
*ifID_table
[];
73 extern at_ifaddr_t
*ifID_home
;
76 static int dump_counter
=0;
79 static at_kern_err_t ke
;
80 /* Used to record error discovered in rtmp_update() */
81 gbuf_t
*rtmp_prep_new_packet();
84 void rtmp_send_port();
85 void rtmp_send_port_funnel();
88 static void rtmp_update();
89 static void rtmp_request();
90 extern int elap_online3();
92 extern pktsIn
, pktsOut
, pktsDropped
, pktsHome
;
93 extern short ErrorRTMPoverflow
, ErrorZIPoverflow
;
94 extern atlock_t ddpinp_lock
;
97 * rtmp_router_input: function called by DDP (in router mode) to handle
98 * all incoming RTMP packets. Listen to the RTMP socket
99 * for all the connected ports.
100 * Switch to the relevant rtmp functions.
103 void rtmp_router_input(mp
, ifID
)
105 register at_ifaddr_t
*ifID
;
107 register at_ddp_t
*ddp
= (at_ddp_t
*)gbuf_rptr(mp
);
108 /* NOTE: there is an assumption here that the
109 * DATA follows the header. */
111 register at_net_al OurNet
;
112 register at_node OurNode
;
113 register at_net_al DstNet
;
114 register at_node DstNode
;
118 if (!ifID
|| (ifID
->ifRoutingState
< PORT_ACTIVATING
)) {
124 OurNet
= ifID
->ifThisNode
.s_net
;
125 OurNode
= ifID
->ifThisNode
.s_node
;
128 if (gbuf_type(mp
) != MSG_DATA
) {
130 /* If this is a M_ERROR message, DDP is shutting down,
131 * nothing to do here...If it's something else, we don't
132 * understand what it is
134 dPrintf(D_M_RTMP
, D_L_WARNING
,
135 ("rtmp_router_input: Not an M_DATA type\n"));
140 DstNet
= NET_VALUE(ddp
->dst_net
);
141 DstNode
= ddp
->dst_node
;
143 /* check the kind of RTMP packet we received */
149 tuples
= gbuf_len(mp
) - DDP_X_HDR_SIZE
- RTMP_IDLENGTH
;
151 * we need to make sure that the size of 'tuples' is
152 * not less than or equal to 0 due to a bad packet
159 if (tuples
% 3) {/* not a valid RTMP data packet */
161 dPrintf(D_M_RTMP
, D_L_WARNING
,
162 ("rtmp_input: bad number of tuple in RTMP packet\n"));
168 rtmp_update(ifID
, (at_rtmp
*)ddp
->data
, tuples
);
175 /* we should treat requests a bit differently.
176 * - if the request if not for the port, route it and also respond
177 * for this port if not locally connected.
178 * - if the request for this port, then just respond to it.
185 if (DstNode
== 255) {
186 if (((DstNet
>= CableStart
) && (DstNet
<= CableStop
)) ||
188 rtmp_request(ifID
, ddp
);
193 /* check if directly connected port */
194 if ((Entry
= rt_blookup(DstNet
)) &&
195 (Entry
->NetDist
== 0)) {
196 dPrintf(D_M_RTMP
, D_L_WARNING
,
197 ("rtmp_router_input: request for %d.%d, port %d\n",
198 DstNet
, DstNode
, Entry
->NetPort
));
199 rtmp_request(ifID_table
[Entry
->NetPort
], ddp
);
204 dPrintf(D_M_RTMP
, D_L_WARNING
,
205 ("rtmp_router_input: RTMP packet received for %d.%d, also forward\n",
206 NET_VALUE(ddp
->dst_net
),ddp
->dst_node
));
207 routing_needed(mp
, ifID
, TRUE
);
214 if ((DstNode
== OurNode
) && (DstNet
== OurNet
)) {
215 rtmp_request(ifID
, ddp
);
220 dPrintf(D_M_RTMP
, D_L_WARNING
,
221 ("rtmp_router_input: RTMP packet received for %d.%d, forward\n",
222 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
));
223 routing_needed(mp
, ifID
, TRUE
);
231 dPrintf(D_M_RTMP
, D_L_WARNING
,
232 ("rtmp_input: RTMP packet type=%d, route it\n", ddp
->type
));
233 routing_needed(mp
, ifID
, TRUE
);
237 } /* rtmp_router_input */
244 static void rtmp_update(ifID
, rtmp
, tuple_nb
)
245 register at_ifaddr_t
*ifID
;
246 register at_rtmp
*rtmp
;
247 register short tuple_nb
;
249 register int PortFlags
= ifID
->ifFlags
;
250 register at_rtmp_tuple
*FirstTuple
= (at_rtmp_tuple
*)&rtmp
->at_rtmp_id
[1];
251 register at_rtmp_tuple
*SecondTuple
= (at_rtmp_tuple
*)&rtmp
->at_rtmp_id
[4];
252 RT_entry NewRoute
, *CurrentRoute
;
254 register u_char SenderNodeID
= rtmp
->at_rtmp_id
[0];
259 /* Make sure this an AppleTalk node sending us the RTMP packet */
261 if (rtmp
->at_rtmp_id_length
!= 8) {
262 dPrintf(D_M_RTMP
, D_L_WARNING
,
263 ("rtmp_update : RTMP ID not as expected Net=%d L=x%x\n",
264 NET_VALUE(rtmp
->at_rtmp_this_net
), rtmp
->at_rtmp_id_length
));
269 * If the port is activating, only take the Network range from the
270 * the RTMP packet received.
271 * Check if there is a conflict with our seed infos.
274 if (ifID
->ifRoutingState
== PORT_ACTIVATING
) {
275 if (PortFlags
& RTR_XNET_PORT
) {
276 if ((PortFlags
& RTR_SEED_PORT
) &&
277 ((CableStart
!= TUPLENET(FirstTuple
)) ||
278 (CableStop
!= TUPLENET(SecondTuple
)))) {
279 ifID
->ifRoutingState
= PORT_ERR_SEED
;
280 ke
.error
= KE_CONF_SEED_RNG
;
281 ke
.port1
= ifID
->ifPort
;
282 strncpy(ke
.name1
, ifID
->ifName
, sizeof(ke
.name1
));
283 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
284 ke
.node
= SenderNodeID
;
285 ke
.netr1b
= TUPLENET(FirstTuple
);
286 ke
.netr1e
= TUPLENET(SecondTuple
);
287 ke
.netr2b
= CableStart
;
288 ke
.netr2e
= CableStop
;
289 RouterError(ifID
->ifPort
, ERTR_SEED_CONFLICT
);
292 CableStart
= TUPLENET(FirstTuple
);
293 CableStop
= TUPLENET(SecondTuple
);
295 dPrintf(D_M_RTMP, D_L_INFO,
296 ("rtmp_update: Port #%d activating, set Cable %d-%d\n",
297 ifID->ifPort, CableStart, CableStop));
300 else { /* non extended cable */
301 if ((PortFlags
& RTR_SEED_PORT
) &&
302 (ifID
->ifThisCableEnd
!= NET_VALUE(rtmp
->at_rtmp_this_net
))) {
303 ke
.error
= KE_CONF_SEED1
;
304 ke
.port1
= ifID
->ifPort
;
305 strncpy(ke
.name1
, ifID
->ifName
,sizeof(ke
.name1
));
306 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
307 ke
.node
= SenderNodeID
;
308 ke
.netr1e
= ifID
->ifThisCableEnd
;
309 ifID
->ifRoutingState
= PORT_ERR_SEED
;
310 RouterError(ifID
->ifPort
, ERTR_SEED_CONFLICT
);
313 CableStop
= NET_VALUE(rtmp
->at_rtmp_this_net
);
315 dPrintf(D_M_RTMP
, D_L_INFO
,
316 ("rtmp_update: Port #%d NONX activating, set Cable %d-%d\n",
317 ifID
->ifPort
, CableStart
, CableStop
));
322 * Perform a few sanity checks on the received RTMP data packet
325 if ((PortFlags
& RTR_XNET_PORT
) && (tuple_nb
>= 2)) {
327 /* The first tuple must be extended */
329 if (! TUPLERANGE(FirstTuple
)) {
330 dPrintf(D_M_RTMP
, D_L_WARNING
,
331 ("rtmp_update: bad range value in 1st tuple =%d\n",
332 TUPLERANGE(FirstTuple
)));
336 if (PortFlags
& RTR_SEED_PORT
)
337 if ((TUPLENET(FirstTuple
) != CableStart
) ||
338 (TUPLENET(SecondTuple
) != CableStop
)) {
339 dPrintf(D_M_RTMP
, D_L_WARNING
, ("rtmp_update: conflict on Seed Port\n"));
340 ifID
->ifRoutingState
= PORT_ERR_CABLER
;
341 ke
.error
= KE_CONF_SEED_NODE
;
342 ke
.port1
= ifID
->ifPort
;
343 strncpy(ke
.name1
, ifID
->ifName
,sizeof(ke
.name1
));
344 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
345 ke
.node
= SenderNodeID
;
346 ke
.netr1b
= TUPLENET(FirstTuple
);
347 ke
.netr1e
= TUPLENET(SecondTuple
);
348 ke
.netr2b
= CableStart
;
349 ke
.netr2e
= CableStop
;
350 RouterError(ifID
->ifPort
, ERTR_CABLE_CONFLICT
);
354 /* check that the tuple matches the range */
356 if ((TUPLENET(SecondTuple
) < TUPLENET(FirstTuple
)) ||
357 (TUPLENET(FirstTuple
) == 0) ||
358 (TUPLENET(FirstTuple
) >= DDP_STARTUP_LOW
) ||
359 (TUPLENET(SecondTuple
) == 0) ||
360 (TUPLENET(SecondTuple
) >= DDP_STARTUP_LOW
)) {
363 * IS THIS NON-FATAL?????
365 dPrintf(D_M_RTMP
, D_L_WARNING
,
366 ("rtmp_update: STARTUP RANGE!!! 1st %d-%d\n",
367 TUPLENET(FirstTuple
), TUPLENET(SecondTuple
)));
368 ifID
->ifRoutingState
= PORT_ERR_STARTUP
;
369 ke
.error
= KE_SEED_STARTUP
;
370 ke
.port1
= ifID
->ifPort
;
371 strncpy(ke
.name1
, ifID
->ifName
,sizeof(ke
.name1
));
372 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
373 ke
.node
= SenderNodeID
;
374 RouterError(ifID
->ifPort
, ERTR_CABLE_STARTUP
);
378 if (TUPLEDIST(FirstTuple
) != 0) {
379 dPrintf(D_M_RTMP
, D_L_WARNING
,
380 ("rtmp_update: Invalid distance in 1st tuple\n"));
384 if (rtmp
->at_rtmp_id
[6] != RTMP_VERSION_NUMBER
) {
385 dPrintf(D_M_RTMP
, D_L_WARNING
,
386 ("rtmp_update: Invalid RTMP version = x%x\n",
387 rtmp
->at_rtmp_id
[6]));
392 else { /* non extended interface or problem in tuple*/
394 if (PortFlags
& RTR_XNET_PORT
) {
395 dPrintf(D_M_RTMP
, D_L_WARNING
,
396 ("rtmp_update: invalid number of tuple for X-net\n"));
400 if (TUPLENET(FirstTuple
) == 0) { /* non extended RTMP data */
402 if (rtmp
->at_rtmp_id
[3] > RTMP_VERSION_NUMBER
) {
403 dPrintf(D_M_RTMP
, D_L_WARNING
,
404 ("rtmp_update: Invalid non extended RTMP version\n"));
410 dPrintf(D_M_RTMP
, D_L_WARNING
,
411 ("rtmp_update: version 1.0 non Xtended net not supported\n"));
412 ifID
->ifRoutingState
= PORT_ERR_BADRTMP
;
413 ke
.error
= KE_BAD_VER
;
414 ke
.rtmp_id
= rtmp
->at_rtmp_id
[6];
415 ke
.net
= NET_VALUE(rtmp
->at_rtmp_this_net
);
416 ke
.node
= SenderNodeID
;
417 RouterError(ifID
->ifPort
, ERTR_RTMP_BAD_VERSION
);
422 NewRoute
.NextIRNet
= NET_VALUE(rtmp
->at_rtmp_this_net
);
423 NewRoute
.NextIRNode
= SenderNodeID
;
424 NewRoute
.NetPort
= ifID
->ifPort
;
427 * Process the case where a non-seed port needs to acquire the right
431 if (!(PortFlags
& RTR_SEED_PORT
) && (ifID
->ifRoutingState
== PORT_ACTIVATING
)) {
432 dPrintf(D_M_RTMP_LOW
, D_L_INFO
,
433 ("rtmp_update: Port# %d, set non seed cable %d-%d\n",
434 ifID
->ifPort
, TUPLENET(FirstTuple
), TUPLENET(SecondTuple
)));
436 if (PortFlags
& RTR_XNET_PORT
) {
437 NewRoute
.NetStart
= TUPLENET(FirstTuple
);
438 NewRoute
.NetStop
= TUPLENET(SecondTuple
);
439 ifID
->ifThisCableStart
= TUPLENET(FirstTuple
);
440 ifID
->ifThisCableEnd
= TUPLENET(SecondTuple
);
445 NewRoute
.NetStart
= 0;
446 NewRoute
.NetStop
= NET_VALUE(rtmp
->at_rtmp_this_net
);
447 ifID
->ifThisCableStart
= NET_VALUE(rtmp
->at_rtmp_this_net
);
448 ifID
->ifThisCableEnd
= NET_VALUE(rtmp
->at_rtmp_this_net
);
451 * Now, check if we already know this route, or we need to add it
452 * (or modify it in the table accordingly)
455 if ((CurrentRoute
= rt_blookup(NewRoute
.NetStop
)) &&
456 (CurrentRoute
->NetStop
== NewRoute
.NetStop
) &&
457 (CurrentRoute
->NetStart
== NewRoute
.NetStart
)) {
458 /*LD 7/31/95 tempo########*/
459 if (NewRoute
.NetPort
!= CurrentRoute
->NetPort
) {
460 dPrintf(D_M_RTMP
, D_L_WARNING
,
461 ("rtmp_update: port# %d, not the port we waited for %d\n",
462 ifID
->ifPort
, CurrentRoute
->NetPort
));
463 /* propose to age the entry we know... */
465 state
= CurrentRoute
->EntryState
& 0x0F;
466 /* if entry has been updated recently, just clear the UPDATED
467 bit. if bit not set, then we can age the entry */
469 if (CurrentRoute
->EntryState
& RTE_STATE_UPDATED
) {
470 CurrentRoute
->EntryState
&= ~RTE_STATE_UPDATED
;
473 state
= state
>> 1 ; /* decrement state */
476 CurrentRoute
->EntryState
= (CurrentRoute
->EntryState
& 0xF0) | state
;
480 else { /* add the new route */
482 dPrintf(D_M_RTMP
, D_L_INFO
,
483 ("rtmp_update: P# %d, 1st tuple route not known, add %d-%d\n",
484 ifID
->ifPort
, NewRoute
.NetStart
, NewRoute
.NetStop
));
486 NewRoute
.EntryState
= RTE_STATE_GOOD
|RTE_STATE_UPDATED
;
487 NewRoute
.NetDist
= 0;
489 if (rt_insert(NewRoute
.NetStop
, NewRoute
.NetStart
, 0,
490 0, NewRoute
.NetDist
, NewRoute
.NetPort
,
491 NewRoute
.EntryState
) == (RT_entry
*)NULL
)
493 ErrorRTMPoverflow
= 1;
498 if (ifID
->ifRoutingState
== PORT_ACTIVATING
) {
499 dPrintf(D_M_RTMP
, D_L_INFO
,
500 ("rtmp_update: port activating, ignoring remaining tuples\n"));
505 * Process all the tuples against our routing table
508 TuplePtr
= (char *)FirstTuple
;
510 while (tuple_nb
-- > 0) {
512 if (TUPLEDIST(TuplePtr
) == NOTIFY_N_DIST
) {
513 dPrintf(D_M_RTMP
, D_L_INFO
,
514 ("rtmp_update: Port# %d, Tuple with Notify Neighbour\n",
516 NewRoute
.NetDist
= NOTIFY_N_DIST
;
517 NewRoute
.EntryState
= RTE_STATE_BAD
;
520 NewRoute
.NetDist
= TUPLEDIST(TuplePtr
) + 1;
521 NewRoute
.EntryState
= RTE_STATE_GOOD
;
522 NewRoute
.EntryState
= RTE_STATE_GOOD
|RTE_STATE_UPDATED
;
526 if (TUPLERANGE(TuplePtr
)) { /* Extended Tuple */
529 NewRoute
.NetStart
= TUPLENET(TuplePtr
);
531 NewRoute
.NetStop
= TUPLENET((TuplePtr
));
535 if ((NewRoute
.NetDist
== 0) ||
536 (NewRoute
.NetStart
== 0) ||
537 (NewRoute
.NetStop
== 0) ||
538 (NewRoute
.NetStop
< NewRoute
.NetStart
) ||
539 (NewRoute
.NetStart
>= DDP_STARTUP_LOW
) ||
540 (NewRoute
.NetStop
>= DDP_STARTUP_LOW
)) {
542 dPrintf(D_M_RTMP
, D_L_WARNING
,
543 ("rtmp_update: P# %d, non valid xtuple received [%d-%d]\n",
544 ifID
->ifPort
, NewRoute
.NetStart
, NewRoute
.NetStop
));
550 else { /* Non Extended Tuple */
552 NewRoute
.NetStart
= 0;
553 NewRoute
.NetStop
= TUPLENET(TuplePtr
);
557 if ((NewRoute
.NetDist
== 0) ||
558 (NewRoute
.NetStop
== 0) ||
559 (NewRoute
.NetStop
>= DDP_STARTUP_LOW
)) {
561 dPrintf(D_M_RTMP
, D_L_WARNING
,
562 ("rtmp_update: P# %d, non valid tuple received [%d]\n",
563 ifID
->ifPort
, NewRoute
.NetStop
));
569 if ((CurrentRoute
= rt_blookup(NewRoute
.NetStop
))) {
570 /* found something... */
572 if (NewRoute
.NetDist
< 16 ||
573 NewRoute
.NetDist
== NOTIFY_N_DIST
) {
576 * Check if the definition of the route changed
579 if (NewRoute
.NetStop
!= CurrentRoute
->NetStop
||
580 NewRoute
.NetStart
!= CurrentRoute
->NetStart
) {
582 if (NewRoute
.NetStop
== CurrentRoute
->NetStop
&&
583 NewRoute
.NetStop
== CurrentRoute
->NetStart
&&
584 NewRoute
.NetStart
== 0)
586 NewRoute
.NetStart
= NewRoute
.NetStop
;
588 else if (NewRoute
.NetStop
== CurrentRoute
->NetStop
&&
589 NewRoute
.NetStart
== NewRoute
.NetStop
&&
590 CurrentRoute
->NetStart
== 0) {
591 dPrintf(D_M_RTMP
, D_L_WARNING
,
592 ("rtmp_update: Range %d-%d has changed to %d-%d Dist=%d\n",
593 CurrentRoute
->NetStart
, CurrentRoute
->NetStop
,
594 NewRoute
.NetStart
, NewRoute
.NetStop
, NewRoute
.NetDist
));
595 NewRoute
.NetStart
= 0;
599 dPrintf(D_M_RTMP
, D_L_WARNING
,
600 ("rtmp_update: Net Conflict Cur=%d, New=%d\n",
601 CurrentRoute
->NetStop
, NewRoute
.NetStop
));
602 CurrentRoute
->EntryState
=
603 (CurrentRoute
->EntryState
& 0xF0) | RTE_STATE_BAD
;
610 * If we don't know the associated zones
613 if (!RT_ALL_ZONES_KNOWN(CurrentRoute
)) {
615 dPrintf(D_M_RTMP_LOW
, D_L_INFO
,
616 ("rtmp_update: Zone unknown for %d-%d state=0x%x\n",
617 CurrentRoute
->NetStart
, CurrentRoute
->NetStop
,
618 CurrentRoute
->EntryState
));
620 /* set the flag in the ifID structure telling
621 * that a scheduling of Zip Query is needed.
624 ifID
->ifZipNeedQueries
= 1;
628 if (((CurrentRoute
->EntryState
& 0x0F) <= RTE_STATE_SUSPECT
) &&
629 NewRoute
.NetDist
!= NOTIFY_N_DIST
) {
631 dPrintf(D_M_RTMP
, D_L_INFO
,
632 ("rtmp_update: update suspect entry %d-%d State=%d\n",
633 NewRoute
.NetStart
, NewRoute
.NetStop
,
634 (CurrentRoute
->EntryState
& 0x0F)));
636 if (NewRoute
.NetDist
<= CurrentRoute
->NetDist
) {
637 CurrentRoute
->NetDist
= NewRoute
.NetDist
;
638 CurrentRoute
->NetPort
= NewRoute
.NetPort
;
639 CurrentRoute
->NextIRNode
= NewRoute
.NextIRNode
;
640 CurrentRoute
->NextIRNet
= NewRoute
.NextIRNet
;
641 CurrentRoute
->EntryState
=
642 (CurrentRoute
->EntryState
& 0xF0) |
643 (RTE_STATE_GOOD
|RTE_STATE_UPDATED
);
649 if (NewRoute
.NetDist
== NOTIFY_N_DIST
) {
651 CurrentRoute
->EntryState
=
652 (CurrentRoute
->EntryState
& 0xF0) | RTE_STATE_SUSPECT
;
653 CurrentRoute
->NetDist
= NOTIFY_N_DIST
;
661 if ((NewRoute
.NetDist
<= CurrentRoute
->NetDist
) && (NewRoute
.NetDist
<16)) {
663 /* Found a shorter or more recent Route,
664 * Replace with the New entryi
667 CurrentRoute
->NetDist
= NewRoute
.NetDist
;
668 CurrentRoute
->NetPort
= NewRoute
.NetPort
;
669 CurrentRoute
->NextIRNode
= NewRoute
.NextIRNode
;
670 CurrentRoute
->NextIRNet
= NewRoute
.NextIRNet
;
671 CurrentRoute
->EntryState
|= RTE_STATE_UPDATED
;
673 /* Can we consider now that the entry is updated? */
674 dPrintf(D_M_RTMP_LOW
, D_L_INFO
,
675 ("rtmp_update: Shorter route found %d-%d, update\n",
676 NewRoute
.NetStart
, NewRoute
.NetStop
));
678 if (ddp_AURPsendx
&& (aurp_ifID
->ifFlags
& AT_IFF_AURP
))
679 ddp_AURPsendx(AURPCODE_RTUPDATE
,
680 (void *)&NewRoute
, AURPEV_NetDistChange
);
683 else { /* no entry found */
685 if (NewRoute
.NetDist
< 16 && NewRoute
.NetDist
!= NOTIFY_N_DIST
&&
686 NewRoute
.NextIRNet
>= ifID
->ifThisCableStart
&&
687 NewRoute
.NextIRNet
<= ifID
->ifThisCableEnd
) {
689 NewRoute
.EntryState
= (RTE_STATE_GOOD
|RTE_STATE_UPDATED
);
691 dPrintf(D_M_RTMP_LOW
, D_L_INFO
,
692 ("rtmp_update: NewRoute %d-%d Tuple #%d\n",
693 NewRoute
.NetStart
, NewRoute
.NetStop
, tuple_nb
));
695 ifID
->ifZipNeedQueries
= 1;
697 if (rt_insert(NewRoute
.NetStop
, NewRoute
.NetStart
, NewRoute
.NextIRNet
,
698 NewRoute
.NextIRNode
, NewRoute
.NetDist
, NewRoute
.NetPort
,
699 NewRoute
.EntryState
) == (RT_entry
*)NULL
)
700 ErrorRTMPoverflow
= 1;
702 else if (ddp_AURPsendx
&& (aurp_ifID
->ifFlags
& AT_IFF_AURP
))
703 ddp_AURPsendx(AURPCODE_RTUPDATE
,
704 (void *)&NewRoute
, AURPEV_NetAdded
);
708 } /* end of main while */
709 ifID
->ifRouterState
= ROUTER_UPDATED
;
710 if (ifID
->ifZipNeedQueries
)
711 zip_send_queries(ifID
, 0, 0xFF);
714 timeout(rtmp_timeout, (caddr_t) ifID, 20*SYS_HZ);
718 /* The RTMP validity timer expired, we need to update the
719 * state of each routing entry in the table
720 * because there is only one validity timer and it is always running,
721 * we can't just age all the entries automatically, as we might be
722 * aging entries that were just updated. So, when an entry is updated,
723 * the RTE_STATE_UPDATED bit is set and when the aging routine is called
724 * it just resets this bit if it is set, only if it is not set will the
725 * route actually be aged.
726 * Note there are 4 states for an entry, the state is decremented until
727 * it reaches the bad state. At this point, the entry is removed
729 * RTE_STATE_GOOD : The entry was valid (will be SUSPECT)
730 * RTE_STATE_SUSPECT: The entry was suspect (can still be used for routing)
731 * RTE_STATE_BAD : The entry was bad and is now deleted
732 * RTE_STATE_UNUSED : Unused or removed entry in the table
735 void rtmp_timeout(ifID
)
736 register at_ifaddr_t
*ifID
;
738 register u_char state
;
739 register unsigned int s
;
741 RT_entry
*en
= &RT_table
[0];
742 boolean_t funnel_state
;
744 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
746 if (ifID
->ifRoutingState
< PORT_ONLINE
) {
747 (void) thread_funnel_set(network_flock
, FALSE
);
751 /* for multihoming mode, we use ifRouterState to tell if there
752 is a router out there, so we know when to use cable multicast */
753 if (ifID
->ifRouterState
> NO_ROUTER
)
754 ifID
->ifRouterState
--;
756 ATDISABLE(s
, ddpinp_lock
);
757 for (i
= 0 ; i
< RT_maxentry
; i
++,en
++) {
759 /* we want to age "learned" nets, not directly connected ones */
760 state
= en
->EntryState
& 0x0F;
763 if (state
> RTE_STATE_UNUSED
&&
764 !(en
->EntryState
& RTE_STATE_PERMANENT
) && en
->NetStop
&&
765 en
->NetDist
&& en
->NetPort
== ifID
->ifPort
) {
767 /* if entry has been updated recently, just clear the UPDATED
768 bit. if bit not set, then we can age the entry */
769 if (en
->EntryState
& RTE_STATE_UPDATED
) {
770 en
->EntryState
&= ~RTE_STATE_UPDATED
;
774 state
= state
>> 1 ; /* decrement state */
776 if (state
== RTE_STATE_UNUSED
) {/* was BAD, needs to delete */
777 dPrintf(D_M_RTMP
, D_L_INFO
,
778 ("rtmp_timeout: Bad State for %d-%d (e#%d): remove\n",
779 en
->NetStart
, en
->NetStop
, i
));
781 if (ddp_AURPsendx
&& (aurp_ifID
->ifFlags
& AT_IFF_AURP
))
782 ddp_AURPsendx(AURPCODE_RTUPDATE
,
783 (void *)en
, AURPEV_NetDeleted
);
785 /* then clear the bit in the table concerning this entry.
786 If the zone Count reaches zero, remove the entry */
788 zt_remove_zones(en
->ZoneBitMap
);
790 RT_DELETE(en
->NetStop
, en
->NetStart
);
793 en
->EntryState
= (en
->EntryState
& 0xF0) | state
;
794 dPrintf(D_M_RTMP
, D_L_INFO
, ("Change State for %d-%d to %d (e#%d)\n",
795 en
->NetStart
, en
->NetStop
, state
, i
));
799 ATENABLE(s
, ddpinp_lock
);
800 timeout(rtmp_timeout
, (caddr_t
) ifID
, 20*SYS_HZ
);
802 (void) thread_funnel_set(network_flock
, FALSE
);
806 * rtmp_prep_new_packet: allocate a ddp packet for RTMP use (reply to a RTMP request or
807 * Route Data Request, or generation of RTMP data packets.
808 * The ddp header is filled with relevant information, as well as
809 * the beginning of the rtmp packet with the following info:
810 * Router's net number (2bytes)
811 * ID Length = 8 (1byte)
812 * Router's node ID (1byte)
813 * Extended Range Start (2bytes)
814 * Range + dist (0x80) (1byte)
815 * Extended Range End (2bytes)
816 * Rtmp version (0x82) (1byte)
820 gbuf_t
*rtmp_prep_new_packet (ifID
, DstNet
, DstNode
, socket
)
821 register at_ifaddr_t
*ifID
;
822 register at_net DstNet
;
823 register u_char DstNode
;
824 register char socket
;
828 register at_ddp_t
*ddp
;
829 register char * rtmp_data
;
831 if ((m
= gbuf_alloc(AT_WR_OFFSET
+1024, PRI_HI
)) == NULL
) {
832 dPrintf(D_M_RTMP
, D_L_WARNING
, ("rtmp_new_packet: Can't allocate mblock\n"));
833 return ((gbuf_t
*)NULL
);
836 gbuf_rinc(m
,AT_WR_OFFSET
);
837 gbuf_wset(m
,DDP_X_HDR_SIZE
+ 10);
838 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
841 * Prepare the DDP header of the new packet
845 ddp
->unused
= ddp
->hopcount
= 0;
847 UAS_ASSIGN(ddp
->checksum
, 0);
849 NET_NET(ddp
->dst_net
, DstNet
);
850 ddp
->dst_node
= DstNode
;
851 ddp
->dst_socket
= socket
;
853 NET_ASSIGN(ddp
->src_net
, ifID
->ifThisNode
.s_net
);
854 ddp
->src_node
= ifID
->ifThisNode
.s_node
;
855 ddp
->src_socket
= RTMP_SOCKET
;
856 ddp
->type
= DDP_RTMP
;
859 * Prepare the RTMP header (Router Net, ID, Node and Net Tuple
860 * (this works only if we are on an extended net)
863 rtmp_data
= ddp
->data
;
865 *rtmp_data
++ = (ifID
->ifThisNode
.s_net
& 0xff00) >> 8;
866 *rtmp_data
++ = ifID
->ifThisNode
.s_net
& 0x00ff ;
868 *rtmp_data
++ = (u_char
)ifID
->ifThisNode
.s_node
;
869 *rtmp_data
++ = (CableStart
& 0xff00) >> 8;
870 *rtmp_data
++ = CableStart
& 0x00ff ;
871 *rtmp_data
++ = 0x80; /* first tuple, so distance is always zero */
872 *rtmp_data
++ = (CableStop
& 0xff00) >> 8;
873 *rtmp_data
++ = CableStop
& 0x00ff ;
874 *rtmp_data
++ = RTMP_VERSION_NUMBER
;
880 int rtmp_r_find_bridge(ifID
, orig_ddp
)
881 register at_ifaddr_t
*ifID
;
882 register at_ddp_t
*orig_ddp
;
886 register int size
, status
;
887 register at_ddp_t
*ddp
;
888 register char * rtmp_data
;
892 /* find the bridge for the querried net */
894 Entry
= rt_blookup(NET_VALUE(orig_ddp
->dst_net
));
897 dPrintf(D_M_RTMP
, D_L_WARNING
, ("rtmp_r_find_bridge: no info for net %d\n",
898 NET_VALUE(orig_ddp
->dst_net
)));
903 size
= DDP_X_HDR_SIZE
+ 10 ;
904 if ((m
= gbuf_alloc(AT_WR_OFFSET
+size
, PRI_HI
)) == NULL
) {
905 dPrintf(D_M_RTMP
, D_L_WARNING
,
906 ("rtmp_r_find_bridge: Can't allocate mblock\n"));
910 gbuf_rinc(m
,AT_WR_OFFSET
);
912 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
915 * Prepare the DDP header of the new packet
918 ddp
->unused
= ddp
->hopcount
= 0;
920 DDPLEN_ASSIGN(ddp
, size
);
921 UAS_ASSIGN(ddp
->checksum
, 0);
923 NET_NET(ddp
->dst_net
, orig_ddp
->src_net
);
924 ddp
->dst_node
= orig_ddp
->src_node
;
925 ddp
->dst_socket
= orig_ddp
->src_socket
;
927 NET_ASSIGN(ddp
->src_net
, Entry
->NextIRNet
);
928 ddp
->src_node
= Entry
->NextIRNode
;
929 ddp
->src_socket
= RTMP_SOCKET
;
930 ddp
->type
= DDP_RTMP
;
933 * Prepare the RTMP header (Router Net, ID, Node and Net Tuple
934 * (this works only if we are on an extended net)
937 rtmp_data
= ddp
->data
;
939 *rtmp_data
++ = (Entry
->NextIRNet
& 0xff00) >> 8;
940 *rtmp_data
++ = Entry
->NextIRNet
& 0x00ff ;
942 *rtmp_data
++ = (u_char
)Entry
->NextIRNode
;
943 *rtmp_data
++ = (Entry
->NetStart
& 0xff00) >> 8;
944 *rtmp_data
++ = Entry
->NetStart
& 0x00ff ;
945 *rtmp_data
++ = 0x80; /* first tuple, so distance is always zero */
946 *rtmp_data
++ = (Entry
->NetStop
& 0xff00) >> 8;
947 *rtmp_data
++ = Entry
->NetStop
& 0x00ff ;
948 *rtmp_data
++ = RTMP_VERSION_NUMBER
;
951 dPrintf(D_M_RTMP
, D_L_INFO
, ("rtmp_r_find_bridge: for net %d send back router %d.%d\n",
952 NET_VALUE(orig_ddp
->dst_net
), Entry
->NextIRNet
, Entry
->NextIRNode
));
953 if (status
= ddp_router_output(m
, ifID
, AT_ADDR
, NET_VALUE(orig_ddp
->src_net
),
954 orig_ddp
->src_node
, 0)){
955 dPrintf(D_M_RTMP
, D_L_WARNING
,
956 ("rtmp_r_find_bridge: ddp_router_output failed status=%d\n", status
));
964 * Send the routing table entries in RTMP data packets.
965 * Use split horizon if specified. The Data packets are sent
966 * as full DDP packets, if the last packet is full an empty
967 * packet is sent to tell the recipients that this is the end of
971 static int rtmp_send_table(ifID
, DestNet
, DestNode
, split_hz
, socket
,
973 register at_ifaddr_t
*ifID
; /* interface/port params */
974 register at_net DestNet
; /* net where to send the table */
975 register u_char DestNode
; /* node where to send to table */
976 short split_hz
; /* use split horizon */
977 char socket
; /* the destination socket to send to */
978 short n_neighbors
; /* used to send packets telling we are going down */
986 register at_ddp_t
*ddp
;
987 register short EntNb
= 0, sent_tuple
= 0;
988 register unsigned int s
;
990 if (ifID
->ifRoutingState
< PORT_ONLINE
) {
991 dPrintf(D_M_RTMP
, D_L_INFO
,
992 ("rtmp_send_table: port %d activating, we don't send anything!\n",
997 /* prerare tuples and packets for DDP*/
998 /* if split horizon, do not send tuples we can reach on the port we
1002 Entry
= &RT_table
[0];
1004 if (!(m
= rtmp_prep_new_packet(ifID
, DestNet
, DestNode
, socket
))) {
1005 dPrintf(D_M_RTMP
, D_L_WARNING
,
1006 ("rtmp_send_table: rtmp_prep_new_packet failed\n"));
1010 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
1011 Buff_ptr
= (char *)((char *)ddp
+ DDP_X_HDR_SIZE
+ 10);
1013 ATDISABLE(s
, ddpinp_lock
);
1014 while (EntNb
< RT_maxentry
) {
1016 if (Entry
->NetStop
&& ((Entry
->EntryState
& 0x0F) >= RTE_STATE_SUSPECT
)) {
1017 if (!(split_hz
&& ifID
->ifPort
== Entry
->NetPort
)) {
1020 if (((Entry
->EntryState
& 0x0F) < RTE_STATE_SUSPECT
) || n_neighbors
)
1021 NewDist
= NOTIFY_N_DIST
;
1023 NewDist
= Entry
->NetDist
& 0x1F;
1025 if (Entry
->NetStart
) { /* Extended */
1026 *Buff_ptr
++ = (Entry
->NetStart
& 0xFF00) >> 8;
1027 *Buff_ptr
++ = (Entry
->NetStart
& 0x00FF);
1028 *Buff_ptr
++ = 0x80 | NewDist
;
1029 *Buff_ptr
++ = (Entry
->NetStop
& 0xFF00) >> 8;
1030 *Buff_ptr
++ = (Entry
->NetStop
& 0x00FF);
1031 *Buff_ptr
++ = RTMP_VERSION_NUMBER
;
1034 else { /* non extended tuple */
1035 *Buff_ptr
++ = (Entry
->NetStop
& 0xFF00) >> 8;
1036 *Buff_ptr
++ = (Entry
->NetStop
& 0x00FF);
1037 *Buff_ptr
++ = NewDist
;
1043 if (size
> (DDP_DATA_SIZE
-20)) {
1044 DDPLEN_ASSIGN(ddp
, size
+ DDP_X_HDR_SIZE
+ 10);
1046 ATENABLE(s
, ddpinp_lock
);
1047 if (status
= ddp_router_output(m
, ifID
, AT_ADDR
,
1048 NET_VALUE(DestNet
),DestNode
, 0)){
1049 dPrintf(D_M_RTMP
, D_L_WARNING
,
1050 ("rtmp_send_table: ddp_router_output failed status=%d\n",
1054 if ((m
= rtmp_prep_new_packet (ifID
, DestNet
, DestNode
, socket
)) == NULL
){
1055 dPrintf(D_M_RTMP
, D_L_WARNING
,
1056 ("rtmp_send_table: rtmp_prep_new_poacket failed status=%d\n",
1060 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
1061 Buff_ptr
= (char *)((char *)ddp
+ DDP_X_HDR_SIZE
+ 10);
1063 dPrintf(D_M_RTMP_LOW
, D_L_OUTPUT
,
1064 ("rtmp_s_tble: Send %d tuples on port %d\n",
1065 sent_tuple
, ifID
->ifPort
));
1068 ATDISABLE(s
, ddpinp_lock
);
1074 ATENABLE(s
, ddpinp_lock
);
1077 * If we have some remaining entries to send, send them now.
1078 * otherwise, the last packet we sent was full, we need to send an empty one
1081 DDPLEN_ASSIGN(ddp
, size
+ DDP_X_HDR_SIZE
+ 10);
1084 ddp_router_output(m
, ifID
, AT_ADDR
, NET_VALUE(DestNet
),DestNode
, 0))){
1085 dPrintf(D_M_RTMP
, D_L_WARNING
,
1086 ("rtmp_send_table: ddp_router_output failed status=%d\n", status
));
1089 dPrintf(D_M_RTMP_LOW
, D_L_OUTPUT
,
1090 ("rtmp_s_tble: LAST Packet split=%d with %d tuples sent on port %d\n",
1091 split_hz
, sent_tuple
, ifID
->ifPort
));
1097 * rtmp_request: respond to the 3 types of RTMP requests RTMP may receive
1098 * RTMP func =1 : respond with an RTMP Reponse Packet
1099 * RTMP func =2 : respond with the routing table RTMP packet with split horizon
1100 * RTMP func =3 : respond with the routing table RTMP packet no split horizon
1102 * see Inside AppleTalk around page 5-18 for "details"
1105 static void rtmp_request(ifID
, ddp
)
1106 register at_ifaddr_t
*ifID
;
1107 register at_ddp_t
*ddp
;
1110 short split_horizon
= FALSE
;
1114 /* We ignore the request if we're activating on that port */
1116 if (ifID
->ifRoutingState
< PORT_ONLINE
)
1119 /* check RTMP function code */
1121 code
= ddp
->data
[0];
1125 case RTMP_REQ_FUNC1
: /* RTMP Find Bridge */
1127 /* RTMP Request Packet: we send a response with the next IRrange */
1128 dPrintf(D_M_RTMP
, D_L_INPUT
,
1129 ( "rtmp_request: find bridge for net %d port %d node %d.%d\n",
1130 NET_VALUE(ddp
->dst_net
), ifID
->ifPort
,
1131 NET_VALUE(ddp
->src_net
), ddp
->src_node
));
1133 if ((error
= rtmp_r_find_bridge (ifID
, ddp
))) {
1134 dPrintf(D_M_RTMP
, D_L_WARNING
,
1135 ("rtmp_request: Code 1 ddp_r_output failed error=%d\n",
1142 case RTMP_REQ_FUNC2
:
1144 split_horizon
= TRUE
;
1146 case RTMP_REQ_FUNC3
:
1148 /* RTMP Route Request Packet */
1150 dPrintf(D_M_RTMP
, D_L_INPUT
,
1151 ("rtmp_request: received code=%d from %d.%d for %d.%d\n",
1152 code
, NET_VALUE(ddp
->src_net
), ddp
->src_node
,
1153 NET_VALUE(ddp
->dst_net
), ddp
->dst_node
));
1155 rtmp_send_table(ifID
, ddp
->src_net
, ddp
->src_node
,
1156 split_horizon
, ddp
->src_socket
, 0);
1162 /* unknown type of request */
1163 dPrintf(D_M_RTMP
, D_L_WARNING
,
1164 ("rtmp_request : invalid type of request =%d\n",
1171 /* funnel version of rtmp_send_port */
1172 void rtmp_send_port_funnel(ifID
)
1173 register at_ifaddr_t
*ifID
;
1175 thread_funnel_set(network_flock
, TRUE
);
1176 rtmp_send_port(ifID
);
1177 thread_funnel_set(network_flock
, FALSE
);
1182 * rtmp_send_all_ports : send the routing table on all connected ports
1183 * check for the port status and if ok, send the
1184 * rtmp tuples to the broadcast address for the port
1185 * usually called on timeout every 10 seconds.
1188 void rtmp_send_port(ifID
)
1189 register at_ifaddr_t
*ifID
;
1193 NET_ASSIGN(DestNet
, 0);
1195 if (ifID
&& ifID
->ifRoutingState
== PORT_ONLINE
) {
1196 dPrintf(D_M_RTMP_LOW
, D_L_OUTPUT
,
1197 ("rtmp_send_port: do stuff for port=%d\n",
1199 if (ifID
->ifZipNeedQueries
)
1200 zip_send_queries(ifID
, 0, 0xFF);
1201 if (!ROUTING_MODE
) {
1204 rtmp_send_table(ifID
, DestNet
, 0xFF, 1, RTMP_SOCKET
, 0);
1207 if (ifID
== ifID_home
)
1208 dPrintf(D_M_RTMP_LOW
, D_L_VERBOSE
,
1209 ("I:%5d O:%5d H:%5d dropped:%d\n",
1210 pktsIn
, pktsOut
, pktsHome
, pktsDropped
));
1212 dPrintf(D_M_RTMP_LOW
, D_L_TRACE
,
1213 ("rtmp_send_port: func=0x%x, ifID=0x%x\n",
1214 (u_int
) rtmp_send_port
, (u_int
) ifID
));
1215 timeout (rtmp_send_port_funnel
, (caddr_t
)ifID
, 10 * SYS_HZ
);
1219 /* rtmp_dropper: check the number of packet received every x secondes.
1220 * the actual packet dropping is done in ddp_input
1225 boolean_t funnel_state
;
1227 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1229 pktsIn
= pktsOut
= pktsHome
= pktsDropped
= 0;
1230 timeout(rtmp_dropper
, NULL
, 2*SYS_HZ
);
1232 (void) thread_funnel_set(network_flock
, FALSE
);
1236 * rtmp_router_start: perform the sanity checks before declaring the router up
1237 * and running. This function looks for discrepency between the net infos
1238 * for the different ports and seed problems.
1239 * If everything is fine, the state of each port is brought to PORT_ONLINE.\
1240 * ### LD 01/09/95 Changed to correct Zone problem on non seed ports.
1243 int rtmp_router_start(keP
)
1244 at_kern_err_t
*keP
; /* used to report errors (if any) */
1247 register at_ifaddr_t
*ifID
, *ifID2
;
1248 register short Index
, router_starting_timer
= 0;
1249 register RT_entry
*Entry
;
1250 register at_net_al netStart
, netStop
;
1251 boolean_t funnel_state
;
1253 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1255 /* clear the static structure used to record routing errors */
1256 bzero(&ke
, sizeof(ke
));
1258 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1260 /* if non seed, need to acquire the right node address */
1262 if ((ifID
->ifFlags
& RTR_SEED_PORT
) == 0) {
1263 if ((ifID
->ifThisCableStart
== 0 && ifID
->ifThisCableEnd
== 0) ||
1264 (ifID
->ifThisCableStart
>= DDP_STARTUP_LOW
&&
1265 ifID
->ifThisCableEnd
<= DDP_STARTUP_HIGH
)) {
1267 if (ifID
->ifThisCableEnd
== 0) {
1268 keP
->error
= KE_NO_SEED
;
1269 keP
->port1
= ifID
->ifPort
;
1270 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1273 keP
->error
= KE_INVAL_RANGE
;
1274 keP
->port1
= ifID
->ifPort
;
1275 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1276 keP
->netr1b
= ifID
->ifThisCableStart
;
1277 keP
->netr1e
= ifID
->ifThisCableEnd
;
1279 ifID
->ifRoutingState
= PORT_ERR_STARTUP
;
1280 RouterError(ifID
->ifPort
, ERTR_CABLE_STARTUP
);
1285 /* we are non seed, so try to acquire the zones for that guy */
1286 ifID
->ifZipNeedQueries
= 1;
1288 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1289 ("rtmp_router_start: call elap_online for Non Seed port #%d cable =%d-%d\n",
1290 ifID
->ifPort
, CableStart
, CableStop
));
1291 if ((err
= elap_online3(ifID
)))
1296 /* Check if we have a problem with the routing table size */
1298 if (ErrorRTMPoverflow
) {
1299 keP
->error
= KE_RTMP_OVERFLOW
;
1304 /* Now, check that we don't have a conflict in between our interfaces */
1305 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1307 /* check if the RoutingState != PORT_ONERROR */
1308 if (ifID
->ifRoutingState
< PORT_ACTIVATING
) {
1312 if ((ifID
->ifThisCableStart
== 0 && ifID
->ifThisCableEnd
== 0) ||
1313 (ifID
->ifThisCableStart
>= DDP_STARTUP_LOW
&&
1314 ifID
->ifThisCableEnd
<= DDP_STARTUP_HIGH
)) {
1316 if (ifID
->ifThisCableEnd
== 0) {
1317 keP
->error
= KE_NO_SEED
;
1318 keP
->port1
= ifID
->ifPort
;
1319 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1322 keP
->error
= KE_INVAL_RANGE
;
1323 keP
->port1
= ifID
->ifPort
;
1324 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1325 keP
->netr1b
= ifID
->ifThisCableStart
;
1326 keP
->netr1e
= ifID
->ifThisCableEnd
;
1329 ifID
->ifRoutingState
= PORT_ERR_STARTUP
;
1330 RouterError(ifID
->ifPort
, ERTR_CABLE_STARTUP
);
1335 /* check the interface address against all other ifs */
1337 netStart
= ifID
->ifThisCableStart
;
1338 netStop
= ifID
->ifThisCableEnd
;
1340 for (ifID2
= TAILQ_NEXT(ifID
, aa_link
); ifID2
;
1341 ifID2
= TAILQ_NEXT(ifID2
, aa_link
)) {
1343 if (((netStart
>= ifID2
->ifThisCableStart
) &&
1344 (netStart
<= ifID2
->ifThisCableEnd
)) ||
1345 ((netStop
>= ifID2
->ifThisCableStart
) &&
1346 (netStop
<= ifID2
->ifThisCableEnd
)) ||
1347 ((ifID2
->ifThisCableStart
>= netStart
) &&
1348 (ifID2
->ifThisCableStart
<= netStop
)) ||
1349 ((ifID2
->ifThisCableEnd
>= netStart
) &&
1350 (ifID2
->ifThisCableEnd
<= netStop
)) ) {
1352 keP
->error
= KE_CONF_RANGE
;
1353 keP
->port1
= ifID
->ifPort
;
1354 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1355 keP
->port2
= ifID2
->ifPort
;
1356 strncpy(keP
->name2
, ifID2
->ifName
,sizeof(keP
->name2
));
1357 keP
->netr1b
= ifID
->ifThisCableStart
;
1358 keP
->netr1e
= ifID
->ifThisCableEnd
;
1359 ifID
->ifRoutingState
= PORT_ERR_CABLER
;
1360 RouterError(ifID
->ifPort
, ERTR_CABLE_CONFLICT
);
1366 /* ### LD 01/04/94: We need to fill in the next IR info in the routing table */
1367 Entry
= rt_blookup(ifID
->ifThisCableEnd
);
1369 if (Entry
== NULL
) {
1370 dPrintf(D_M_RTMP
, D_L_ERROR
,
1371 ("rtmp_router_start: we don't know our cable range port=%d\n",
1378 * Note: At this point, non seed ports may not be aware of their Default zone
1381 if (!(ifID
->ifFlags
& RTR_SEED_PORT
)) {
1382 ifID
->ifDefZone
= 0;
1383 Entry
->EntryState
|= (RTE_STATE_GOOD
|RTE_STATE_UPDATED
);
1386 ifID
->ifRoutingState
= PORT_ONLINE
;
1387 ifID
->ifState
= LAP_ONLINE
;
1389 /* set the right net and node for each port */
1390 Entry
->NextIRNet
= ifID
->ifThisNode
.s_net
;
1391 Entry
->NextIRNode
= ifID
->ifThisNode
.s_node
;
1393 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1394 ("rtmp_router_start: bring port=%d [%d.%d]... on line\n",
1395 ifID
->ifPort
, ifID
->ifThisNode
.s_net
,
1396 ifID
->ifThisNode
.s_node
));
1401 * Everything is fine, we can begin to babble on the net...
1404 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1405 if (ifID
->ifRoutingState
== PORT_ONLINE
) {
1406 rtmp_send_port(ifID
);
1407 timeout(rtmp_timeout
, (caddr_t
)ifID
, (50+ifID
->ifPort
) * SYS_HZ
);
1408 if (ifID
->ifRoutingState
< PORT_ACTIVATING
) {
1414 /* Check if we have a problem with the routing or zip table size */
1416 if (ErrorRTMPoverflow
) {
1417 keP
->error
= KE_RTMP_OVERFLOW
;
1420 if (ErrorZIPoverflow
) {
1421 keP
->error
= KE_ZIP_OVERFLOW
;
1425 /* sleep for 10 seconds */
1427 /* *** eventually this will be the ifID for the interface
1428 being brought up in router mode *** */
1429 /* *** router sends rtmp packets every 10 seconds *** */
1430 tsleep(&ifID_home
->startup_inprogress
,
1431 PSOCK
| PCATCH
, "router_start1", (10+1) * SYS_HZ
))
1436 /* Is the stack still up ? */
1437 if (!(at_state
.flags
& AT_ST_STARTED
) || !ifID_home
) {
1444 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1446 if (ifID
->ifRoutingState
< PORT_ACTIVATING
) {
1450 if ((ifID
->ifZipNeedQueries
)
1451 && (ifID
->ifFlags
& RTR_SEED_PORT
) == 0) {
1452 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1453 ("rtmp_router_start: send Zip Queries for Port %d\n",
1455 zip_send_queries(ifID
, 0, 0xFF);
1457 if (router_starting_timer
>= 10) {
1458 dPrintf(D_M_RTMP
, D_L_WARNING
,
1459 ("rtmp_router_start: no received response to ZipNeedQueries\n"));
1460 keP
->error
= KE_NO_ZONES_FOUND
;
1461 keP
->port1
= ifID
->ifPort
;
1462 strncpy(keP
->name1
, ifID
->ifName
,sizeof(keP
->name1
));
1463 keP
->netr1b
= ifID
->ifThisCableStart
;
1464 keP
->netr1e
= ifID
->ifThisCableEnd
;
1465 ifID
->ifRoutingState
= PORT_ERR_CABLER
;
1466 RouterError(ifID
->ifPort
, ERTR_CABLE_CONFLICT
);
1470 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1471 ("rtmp_router_start: waiting for zone info to complete\n"));
1472 /* sleep for 10 seconds */
1474 /* *** eventually this will be the ifID for the
1475 interface being brought up in router mode *** */
1476 tsleep(&ifID_home
->startup_inprogress
,
1477 PSOCK
| PCATCH
, "router_start2", 10 * SYS_HZ
))
1482 /* Is the stack still up ? */
1483 if (!(at_state
.flags
& AT_ST_STARTED
) || !ifID_home
) {
1489 router_starting_timer
++;
1495 /* At This Point, check if we know the default zones for non seed port */
1497 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1499 if (ifID
->ifRoutingState
< PORT_ACTIVATING
)
1502 if (!(ifID
->ifFlags
& RTR_SEED_PORT
)) {
1503 Entry
= rt_blookup(ifID
->ifThisCableEnd
);
1505 if (Entry
== NULL
) {
1506 dPrintf(D_M_RTMP
, D_L_ERROR
,
1507 ("rtmp_router_start: (2)we don't know our cable range port=%d\n",
1512 dPrintf(D_M_RTMP
, D_L_STARTUP
,
1513 ("rtmp_router_start: if %s set to permanent\n",
1515 Entry
->NetDist
= 0; /* added 4-29-96 jjs, prevent direct
1516 nets from showing non-zero
1518 /* upgrade the non seed ports. */
1519 Entry
->EntryState
|= RTE_STATE_PERMANENT
;
1521 Index
= zt_ent_zindex(Entry
->ZoneBitMap
);
1523 dPrintf(D_M_RTMP
, D_L_ERROR
,
1524 ("rtmp_router_start: still don't know default zone for port %d\n",
1527 ifID
->ifDefZone
= Index
;
1528 if ((ifID
== ifID_home
) || MULTIHOME_MODE
) {
1529 ifID
->ifZoneName
= ZT_table
[Index
-1].Zone
;
1530 (void)regDefaultZone(ifID
);
1532 /* Send zone change event */
1533 atalk_post_msg(ifID
->aa_ifp
, KEV_ATALK_ZONEUPDATED
, 0, &(ifID
->ifZoneName
));
1539 /* Check if we have a problem with the routing or zip table size */
1541 if (ErrorRTMPoverflow
) {
1542 keP
->error
= KE_RTMP_OVERFLOW
;
1545 if (ErrorZIPoverflow
) {
1546 keP
->error
= KE_ZIP_OVERFLOW
;
1551 * Handle the Home Port specifics
1554 /* set the router address as being us no matter what*/
1555 ifID_home
->ifARouter
= ifID_home
->ifThisNode
;
1556 ifID_home
->ifRouterState
= ROUTER_UPDATED
;
1558 /* prepare the packet dropper timer */
1559 timeout (rtmp_dropper
, NULL
, 1*SYS_HZ
);
1561 (void) thread_funnel_set(network_flock
, funnel_state
);
1565 dPrintf(D_M_RTMP
,D_L_ERROR
,
1566 ("rtmp_router_start: error type=%d occured on port %d\n",
1567 ifID
->ifRoutingState
, ifID
->ifPort
));
1569 /* if there's no keP->error, copy the local ke structure,
1570 since the error occured asyncronously */
1571 if ((!keP
->error
) && ke
.error
)
1572 bcopy(&ke
, keP
, sizeof(ke
));
1575 /* to return the error in keP, the ioctl has to return 0 */
1576 (void) thread_funnel_set(network_flock
, funnel_state
);
1578 return((keP
->error
)? 0: err
);
1579 } /* rtmp_router_start */
1582 void rtmp_shutdown()
1584 register at_ifaddr_t
*ifID
;
1588 NET_ASSIGN(DestNet
, 0);
1590 dPrintf(D_M_RTMP
, D_L_SHUTDN
,
1591 ("rtmp_shutdown:stop sending to all ports\n"));
1593 untimeout(rtmp_dropper
, (caddr_t
)0);
1594 untimeout(rtmp_router_start
, 1); /* added for 2225395 */
1595 untimeout(rtmp_router_start
, 3); /* added for 2225395 */
1597 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1598 if (ifID
->ifRoutingState
> PORT_OFFLINE
) {
1599 if (ifID
->ifRoutingState
== PORT_ONLINE
) {
1600 untimeout(rtmp_send_port_funnel
, (caddr_t
)ifID
);
1601 untimeout(rtmp_timeout
, (caddr_t
) ifID
);
1604 * it's better to notify the neighbour routers that we are going down
1607 rtmp_send_table(ifID
, DestNet
, 0xFF, TRUE
,
1610 ifID
->ifRoutingState
= PORT_OFFLINE
;
1612 dPrintf(D_M_RTMP
, D_L_SHUTDN
,
1613 ("rtmp_shutdown: routing on port=%d... off line\nStats:\n",
1615 dPrintf(D_M_RTMP
, D_L_SHUTDN
,
1616 ("fwdBytes : %ld\nfwdPackets : %ld\ndroppedBytes : %ld\ndroppedPkts : %ld\n",
1617 ifID
->ifStatistics
.fwdBytes
, ifID
->ifStatistics
.fwdPkts
,
1618 ifID
->ifStatistics
.droppedBytes
, ifID
->ifStatistics
.droppedPkts
));
1626 * Remove all entries associated with the specified port.
1628 void rtmp_purge(ifID
)
1633 RT_entry
*en
= &RT_table
[0];
1635 ATDISABLE(s
, ddpinp_lock
);
1636 for (i
=0; i
< RT_maxentry
; i
++) {
1637 state
= en
->EntryState
& 0x0F;
1638 if ((state
> RTE_STATE_UNUSED
) && (state
!= RTE_STATE_PERMANENT
)
1639 && en
->NetStop
&& en
->NetDist
&& (en
->NetPort
== ifID
->ifPort
)) {
1640 zt_remove_zones(en
->ZoneBitMap
);
1641 RT_DELETE(en
->NetStop
, en
->NetStart
);
1645 ATENABLE(s
, ddpinp_lock
);