2
* $Id: rtmp.c,v 1.12 2002/09/29 23:24:47 sibaz Exp $
4
* Copyright (c) 1990,1993 Regents of The University of Michigan.
5
* All Rights Reserved. See COPYRIGHT.
10
#endif /* HAVE_CONFIG_H */
15
#include <atalk/logger.h>
16
#include <sys/types.h>
17
#include <sys/param.h>
18
#include <sys/socket.h>
19
#include <sys/ioctl.h>
22
#include <net/route.h>
25
#include <net/route.h>
26
#include <netatalk/endian.h>
27
#include <netatalk/at.h>
30
#include <sys/sockio.h>
33
#include <atalk/ddp.h>
34
#include <atalk/atp.h>
35
#include <atalk/rtmp.h>
37
#include "interface.h"
46
void rtmp_delzonemap(rtmp)
49
struct list *lz, *flz, *lr, *flr;
53
while ( lz ) { /* for each zone */
54
zt = (struct ziptab *)lz->l_data;
56
while ( lr ) { /* for each route */
57
if ( (struct rtmptab *)lr->l_data == rtmp ) {
58
if ( lr->l_prev == NULL ) { /* head */
59
if ( lr->l_next == NULL ) { /* last route in zone */
60
if ( zt->zt_prev == NULL ) {
63
zt->zt_prev->zt_next = zt->zt_next;
65
if ( zt->zt_next == NULL ) {
66
ziplast = zt->zt_prev;
68
zt->zt_next->zt_prev = zt->zt_prev;
74
zt->zt_rt = lr->l_next;
77
lr->l_prev->l_next = lr->l_next;
79
if ( lr->l_next != NULL ) {
80
lr->l_next->l_prev = lr->l_prev;
98
* Complete configuration for phase 1 interface using RTMP information.
100
static int rtmp_config( rh, iface )
101
struct rtmp_head *rh;
102
struct interface *iface;
104
extern int stabletimer;
108
* If we're configuring a phase 2 interface, don't complete
109
* configuration with RTMP.
111
if ( iface->i_flags & IFACE_PHASE2 ) {
112
LOG(log_info, logtype_atalkd, "rtmp_config ignoring data" );
117
* Check our seed information, and reconfigure.
119
if ( rh->rh_net != iface->i_addr.sat_addr.s_net ) {
120
if (( iface->i_flags & IFACE_SEED ) &&
121
rh->rh_net != iface->i_caddr.sat_addr.s_net) {
122
LOG(log_error, logtype_atalkd, "rtmp_config net mismatch %u != %u",
124
ntohs( iface->i_addr.sat_addr.s_net ));
127
iface->i_addr.sat_addr.s_net = rh->rh_net;
130
* It is possible that we will corrupt our route database
131
* by just forcing this change. XXX
133
iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = rh->rh_net;
135
setaddr( iface, IFACE_PHASE1, iface->i_addr.sat_addr.s_net,
136
iface->i_addr.sat_addr.s_node, rh->rh_net, rh->rh_net );
137
stabletimer = UNSTABLE;
140
/* add addr to loopback route */
141
if ((cc = looproute( iface, RTMP_ADD )) < 0 )
145
LOG(log_error, logtype_atalkd, "rtmp_config: can't route %u.%u to loopback: %s",
146
ntohs( iface->i_addr.sat_addr.s_net ),
147
iface->i_addr.sat_addr.s_node,
151
LOG(log_info, logtype_atalkd, "rtmp_config configured %s", iface->i_name );
152
iface->i_flags |= IFACE_CONFIG;
153
if ( iface == ciface ) {
154
ciface = ciface->i_next;
162
* Delete rtmp from the per-interface in-use table, remove all
163
* zone references, and remove the route from the kernel.
165
static void rtmp_delinuse( rtmp )
166
struct rtmptab *rtmp;
170
irt = rtmp->rt_gate->g_iface->i_rt;
171
if ( irt->rt_inext == rtmp ) { /* first */
172
if ( rtmp->rt_iprev == rtmp ) { /* only */
173
irt->rt_inext = NULL;
175
irt->rt_inext = rtmp->rt_inext;
176
rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
179
if ( rtmp->rt_inext == NULL ) { /* last */
180
rtmp->rt_iprev->rt_inext = NULL;
181
irt->rt_inext->rt_iprev = rtmp->rt_iprev;
183
rtmp->rt_iprev->rt_inext = rtmp->rt_inext;
184
rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
187
rtmp->rt_iprev = NULL;
188
rtmp->rt_inext = NULL;
190
/* remove zone map */
191
rtmp_delzonemap(rtmp);
193
/* remove old route */
194
gateroute( RTMP_DEL, rtmp );
198
* Add rtmp to the per-interface in-use table. No verification is done...
200
static void rtmp_addinuse( rtmp )
201
struct rtmptab *rtmp;
205
gateroute( RTMP_ADD, rtmp );
207
irt = rtmp->rt_gate->g_iface->i_rt;
208
if ( irt->rt_inext == NULL ) { /* empty list */
209
rtmp->rt_inext = NULL;
210
rtmp->rt_iprev = rtmp;
211
irt->rt_inext = rtmp;
213
rtmp->rt_inext = irt->rt_inext;
214
rtmp->rt_iprev = irt->rt_inext->rt_iprev;
215
irt->rt_inext->rt_iprev = rtmp;
216
irt->rt_inext = rtmp;
222
* Change the zone mapping to replace "from" with "to". This code assumes
223
* the consistency of both the route -> zone map and the zone -> route map.
224
* This is probably a bad idea. How can we insure that the data is good
225
* at this point? What do we do if we get several copies of a route in
228
static int rtmp_copyzones( to, from )
229
struct rtmptab *to, *from;
231
struct list *lz, *lr;
233
to->rt_zt = from->rt_zt;
235
if ( from->rt_flags & RTMPTAB_HASZONES ) {
236
to->rt_flags |= RTMPTAB_HASZONES;
238
for ( lz = to->rt_zt; lz; lz = lz->l_next ) {
239
for ( lr = ((struct ziptab *)lz->l_data)->zt_rt; lr; lr = lr->l_next ) {
240
if ( (struct rtmptab *)lr->l_data == from ) {
241
lr->l_data = (void *)to; /* cast BS */
246
LOG(log_error, logtype_atalkd, "rtmp_copyzones z -> r without r -> z, abort" );
256
* Remove rtmp from the in-use table and the per-gate table.
257
* Free any associated space.
259
void rtmp_free( rtmp )
260
struct rtmptab *rtmp;
264
LOG(log_info, logtype_atalkd, "rtmp_free: %u-%u", ntohs(rtmp->rt_firstnet),
265
ntohs(rtmp->rt_lastnet));
266
if ( rtmp->rt_iprev ) {
267
rtmp_delinuse( rtmp );
270
/* remove from per-gate */
271
gate = rtmp->rt_gate;
272
if ( gate->g_rt == rtmp ) { /* first */
273
if ( rtmp->rt_prev == rtmp ) { /* only */
276
gate->g_rt = rtmp->rt_next;
277
rtmp->rt_next->rt_prev = rtmp->rt_prev;
280
if ( rtmp->rt_next == NULL ) { /* last */
281
rtmp->rt_prev->rt_next = NULL;
282
gate->g_rt->rt_prev = rtmp->rt_prev;
284
rtmp->rt_prev->rt_next = rtmp->rt_next;
285
rtmp->rt_next->rt_prev = rtmp->rt_prev;
294
* Find a replacement for "replace". If we can't find a replacement,
295
* return 1. If we do find a replacement, return 0. -1 on error.
297
int rtmp_replace( replace )
298
struct rtmptab *replace;
300
struct interface *iface;
302
struct rtmptab *rtmp, *found = NULL;
304
LOG(log_info, logtype_atalkd, "rtmp_replace %u-%u", ntohs(replace->rt_firstnet),
305
ntohs(replace->rt_lastnet));
306
for ( iface = interfaces; iface; iface = iface->i_next ) {
307
if ((replace->rt_iface != iface) &&
308
((iface->i_flags & IFACE_ISROUTER) == 0))
311
for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
312
for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
313
if ( rtmp->rt_firstnet == replace->rt_firstnet &&
314
rtmp->rt_lastnet == replace->rt_lastnet ) {
315
if ( found == NULL || rtmp->rt_hops < found->rt_hops ) {
324
if ( found != replace ) {
325
if (rtmp_copyzones( found, replace ) < 0)
327
rtmp_delinuse( replace );
328
rtmp_addinuse( found );
329
if ( replace->rt_state == RTMPTAB_BAD ) {
330
rtmp_free( replace );
334
if ( replace->rt_hops == RTMPHOPS_POISON ) {
335
gateroute( RTMP_DEL, replace );
342
static int rtmp_new( rtmp )
343
struct rtmptab *rtmp;
347
extern int newrtmpdata;
352
* Do we already have a gateway for this route?
354
for ( i = interfaces; i; i = i->i_next ) {
355
if ((rtmp->rt_iface != i) &&
356
((i->i_flags & IFACE_ISROUTER) == 0))
359
for ( r = i->i_rt; r; r = r->rt_inext ) {
360
/* Should check RTMPTAB_EXTENDED here. XXX */
361
if (( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_firstnet ) &&
362
ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_firstnet )) ||
363
( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_lastnet ) &&
364
ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_lastnet ))) {
374
* This part of this routine is almost never run.
376
if ( i ) { /* can we get here without r being set? */
377
if ( r->rt_firstnet != rtmp->rt_firstnet ||
378
r->rt_lastnet != rtmp->rt_lastnet ) {
379
LOG(log_info, logtype_atalkd, "rtmp_new netrange mismatch %u-%u != %u-%u",
380
ntohs( r->rt_firstnet ), ntohs( r->rt_lastnet ),
381
ntohs( rtmp->rt_firstnet ), ntohs( rtmp->rt_lastnet ));
386
* Note that our whole methodology is wrong, if we want to do
387
* route "load balancing." This entails changing our route
388
* each time we receive a tuple of equal value. In fact, we can't
389
* do this, using our method, since we only check against in-use
390
* routes when a tuple is new from a router.
392
if ( r->rt_hops < rtmp->rt_hops ) {
396
if (rtmp_copyzones( rtmp, r ) < 0)
401
rtmp_addinuse( rtmp );
406
int rtmp_packet( ap, from, data, len )
408
struct sockaddr_at *from;
413
struct rtmp_tuple rt, xrt;
415
struct interface *iface;
416
struct rtmptab *rtmp;
417
char *end, packet[ ATP_BUFSIZ ];
423
LOG(log_info, logtype_atalkd, "rtmp_packet no data" );
427
iface = ap->ap_iface;
429
/* ignore our own packets */
430
if ( from->sat_addr.s_net == iface->i_addr.sat_addr.s_net &&
431
from->sat_addr.s_node == iface->i_addr.sat_addr.s_node ) {
436
case DDPTYPE_RTMPRD :
440
if ( data + sizeof( struct rtmprdhdr ) > end ) {
441
LOG(log_info, logtype_atalkd, "rtmp_packet no data header" );
444
memcpy( &rh, data, sizeof( struct rtmprdhdr ));
445
data += sizeof( struct rtmprdhdr );
447
/* check rh address against from address */
448
if ( rh.rh_nodelen != 8 ) {
449
LOG(log_info, logtype_atalkd, "rtmp_packet bad node len (%d)", rh.rh_nodelen );
452
if (( from->sat_addr.s_net != 0 &&
453
from->sat_addr.s_net != rh.rh_net ) ||
454
from->sat_addr.s_node != rh.rh_node ) {
455
LOG(log_info, logtype_atalkd, "rtmp_packet address mismatch" );
459
if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG )) == IFACE_ADDR ) {
460
if ( iface->i_flags & IFACE_NOROUTER ) {
461
/* remove addr to loopback route */
462
if ((cc = looproute( iface, RTMP_DEL )) < 0) {
463
LOG(log_error, logtype_atalkd, "rtmp_packet: looproute");
468
LOG(log_error, logtype_atalkd, "rtmp_packet: can't remove loopback: %s",
471
iface->i_flags &= ~IFACE_NOROUTER;
473
LOG(log_info, logtype_atalkd, "rtmp_packet router has become available" );
475
if ( iface->i_flags & IFACE_PHASE1 ) {
476
if (rtmp_config( &rh, iface ) < 0) {
477
LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_config");
480
} else if (zip_getnetinfo( iface ) < 0) {
481
LOG(log_error, logtype_atalkd, "rtmp_packet: zip_getnetinfo");
487
if (( iface->i_flags & IFACE_CONFIG ) == 0 ) {
492
* Parse first tuple. For phase 2, verify that net is correct.
494
if ( data + SZ_RTMPTUPLE > end ) {
495
LOG(log_info, logtype_atalkd, "rtmp_packet missing first tuple" );
498
memcpy( &rt, data, SZ_RTMPTUPLE );
499
data += SZ_RTMPTUPLE;
501
if ( rt.rt_net == 0 ) {
502
if ( rt.rt_dist != 0x82 ) {
503
LOG(log_info, logtype_atalkd, "rtmp_packet bad phase 1 version" );
508
* Grab the next tuple, since we don't want to pass the version
509
* number to the parsing code. We're assuming that there are
510
* no extended tuples in this packet.
512
if ( data + SZ_RTMPTUPLE > end ) {
513
LOG(log_info, logtype_atalkd, "rtmp_packet missing second tuple" );
516
memcpy( &rt, data, SZ_RTMPTUPLE );
517
data += SZ_RTMPTUPLE;
518
} else if ( rt.rt_dist & 0x80 ) {
519
if ( data + SZ_RTMPTUPLE > end ) {
520
LOG(log_info, logtype_atalkd, "rtmp_packet missing first range-end" );
523
memcpy( &xrt, data, SZ_RTMPTUPLE );
524
data += SZ_RTMPTUPLE;
526
if ( xrt.rt_dist != 0x82 ) {
527
LOG(log_info, logtype_atalkd, "rtmp_packet bad phase 2 version" );
532
* Check for net range conflict.
534
if ( rt.rt_net != iface->i_rt->rt_firstnet ||
535
xrt.rt_net != iface->i_rt->rt_lastnet ) {
536
LOG(log_info, logtype_atalkd, "rtmp_packet interface mismatch" );
542
* Gatorboxes put a net number in the first tuple, even on
543
* phase 1 nets. This is wrong, but since we've got it, we
544
* might just as well check it.
545
if ( rt.rt_net != iface->i_rt->rt_firstnet ||
546
rt.rt_net != iface->i_rt->rt_lastnet ) {
547
LOG(log_info, logtype_atalkd, "rtmp_packet phase 1 interface mismatch" );
551
#else /* PHASE1NET */
552
LOG(log_info, logtype_atalkd, "rtmp_packet bad first tuple" );
554
#endif /* PHASE1NET */
560
for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
561
if ( gate->g_sat.sat_addr.s_net == from->sat_addr.s_net &&
562
gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
566
if ( !gate ) { /* new gateway */
567
if (( gate = (struct gate *)malloc( sizeof( struct gate ))) == 0 ) {
568
LOG(log_error, logtype_atalkd, "rtmp_packet: malloc: %s", strerror(errno) );
571
gate->g_next = iface->i_gate;
574
gate->g_iface = iface; /* need this? */
576
if ( iface->i_gate ) {
577
iface->i_gate->g_prev = gate;
579
iface->i_gate = gate;
580
LOG(log_info, logtype_atalkd, "rtmp_packet gateway %u.%u up",
581
ntohs( gate->g_sat.sat_addr.s_net ),
582
gate->g_sat.sat_addr.s_node );
586
* Reset the timeout on this gateway. We'll remove the gateway
587
* entry, if the timeout gets to RTMPTAB_BAD.
589
gate->g_state = RTMPTAB_GOOD;
592
* Parse remaining tuples.
596
* Is route on this gateway?
598
for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
599
if ( ntohs( rtmp->rt_firstnet ) <= ntohs( rt.rt_net ) &&
600
ntohs( rtmp->rt_lastnet ) >= ntohs( rt.rt_net )) {
603
if (( rt.rt_dist & 0x80 ) &&
604
ntohs( rtmp->rt_firstnet ) <= ntohs( xrt.rt_net ) &&
605
ntohs( rtmp->rt_lastnet ) >= ntohs( xrt.rt_net )) {
610
if ( rtmp ) { /* found it */
612
* Check for range conflicts. (This is getting a little
615
if ( rtmp->rt_firstnet != rt.rt_net ) {
616
LOG(log_info, logtype_atalkd, "rtmp_packet firstnet mismatch %u!=%u",
617
ntohs( rtmp->rt_firstnet ), ntohs( rt.rt_net ));
620
if ( rt.rt_dist & 0x80 ) {
621
if (( rtmp->rt_flags & RTMPTAB_EXTENDED ) == 0 ) {
622
LOG(log_info, logtype_atalkd, "rtmp_packet extended mismatch %u",
623
ntohs( rtmp->rt_firstnet ));
626
if ( rtmp->rt_lastnet != xrt.rt_net ) {
627
LOG(log_info, logtype_atalkd, "rtmp_packet lastnet mismatch %u!=%u",
628
ntohs( rtmp->rt_lastnet ), ntohs( xrt.rt_net ));
632
if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
633
LOG(log_info, logtype_atalkd, "rtmp_packet !extended mismatch %u",
634
ntohs( rtmp->rt_firstnet ));
637
if ( rtmp->rt_lastnet != rt.rt_net ) {
638
LOG(log_info, logtype_atalkd, "rtmp_packet lastnet mismatch %u!=%u",
639
ntohs( rtmp->rt_lastnet ), ntohs( rt.rt_net ));
644
rtmp->rt_state = RTMPTAB_GOOD;
647
* Check hop count. If the count has changed, update
648
* the routing database.
650
if (( rtmp->rt_hops != ( rt.rt_dist & 0x7f ) + 1 ) &&
651
( rtmp->rt_hops != RTMPHOPS_POISON ||
652
( rt.rt_dist & 0x7f ) + 1 <= RTMPHOPS_MAX )) {
653
if ( rtmp->rt_iprev ) { /* route is in use */
654
if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
656
* If this was POISON, we've deleted it from
657
* the kernel. Add it back in.
659
if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
660
gateroute( RTMP_ADD, rtmp );
662
rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
665
* Hop count has gone up for this route.
666
* Search for a new best route. If we can't
667
* find one, just keep this route. "poison"
668
* route are deleted in as_timer().
670
if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
671
rtmp->rt_hops = RTMPHOPS_POISON;
673
rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
675
if (rtmp_replace( rtmp ) < 0) {
676
LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_replace");
680
} else { /* route not in use */
681
rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
682
if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
683
if (rtmp_new( rtmp ) < 0) {
684
LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_new");
692
* Make the *next* node the head, since
693
* we're not likely to be asked for the same tuple twice
696
if ( rtmp->rt_next != 0 ) {
697
gate->g_rt->rt_prev->rt_next = gate->g_rt;
698
gate->g_rt = rtmp->rt_next;
701
} else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
702
LOG(log_info, logtype_atalkd, "rtmp_packet bad hop count from %u.%u for %u",
703
ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
705
} else { /* new for router */
706
if (( rtmp = newrt(iface)) == NULL ) {
707
LOG(log_error, logtype_atalkd, "rtmp_packet: newrt: %s", strerror(errno) );
710
rtmp->rt_firstnet = rt.rt_net;
711
if ( rt.rt_dist & 0x80 ) {
712
rtmp->rt_lastnet = xrt.rt_net;
713
rtmp->rt_flags = RTMPTAB_EXTENDED;
715
rtmp->rt_lastnet = rt.rt_net;
717
rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
718
rtmp->rt_state = RTMPTAB_GOOD;
719
rtmp->rt_gate = gate;
722
* Add rtmptab entry to end of list (leave head alone).
724
if ( gate->g_rt == 0 ) {
725
rtmp->rt_prev = rtmp;
728
rtmp->rt_prev = gate->g_rt->rt_prev;
729
gate->g_rt->rt_prev->rt_next = rtmp;
730
gate->g_rt->rt_prev = rtmp;
733
if (rtmp_new( rtmp ) < 0) {
734
LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_new");
739
if ( data + SZ_RTMPTUPLE > end ) {
742
memcpy( &rt, data, SZ_RTMPTUPLE );
743
data += SZ_RTMPTUPLE;
744
if ( rt.rt_dist & 0x80 ) {
745
if ( data + SZ_RTMPTUPLE > end ) {
746
LOG(log_info, logtype_atalkd, "rtmp_packet missing range-end" );
749
memcpy( &xrt, data, SZ_RTMPTUPLE );
750
data += SZ_RTMPTUPLE;
755
* Make sure we've processed the whole packet.
758
LOG(log_info, logtype_atalkd, "rtmp_packet length and count mismatch" );
766
if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
767
iface->i_rt->rt_zt == 0 ||
768
( iface->i_flags & IFACE_CONFIG ) == 0 ) {
773
*data++ = DDPTYPE_RTMPRD;
774
rh.rh_net = iface->i_addr.sat_addr.s_net;
776
rh.rh_node = iface->i_addr.sat_addr.s_node;
777
memcpy( data, &rh, sizeof( struct rtmp_head ));
778
data += sizeof( struct rtmp_head );
780
if ( iface->i_flags & IFACE_PHASE2 ) {
781
rt.rt_net = iface->i_rt->rt_firstnet;
783
memcpy( data, &rt, SZ_RTMPTUPLE );
784
data += SZ_RTMPTUPLE;
786
rt.rt_net = iface->i_rt->rt_lastnet;
788
memcpy( data, &rt, SZ_RTMPTUPLE );
789
data += SZ_RTMPTUPLE;
791
if ( sendto( ap->ap_fd, packet, data - packet, 0,
792
(struct sockaddr *)from,
793
sizeof( struct sockaddr_at )) < 0 ) {
794
LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
796
} else if ( *data == 2 || *data == 3 ) {
798
printf( "rtmp_packet rdr (%d) from %u.%u\n",
799
*data, ntohs( from->sat_addr.s_net ),
800
from->sat_addr.s_node );
803
LOG(log_info, logtype_atalkd, "rtmp_packet unknown request from %u.%u\n",
804
ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
809
LOG(log_info, logtype_atalkd, "rtmp_packet bad ddp type from %u.%u",
810
ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
817
int rtmp_request( iface )
818
struct interface *iface;
820
struct sockaddr_at sat;
822
char *data, packet[ 2 ];
824
LOG(log_info, logtype_atalkd, "rtmp_request for %s", iface->i_name );
826
for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
827
if ( ap->ap_packet == rtmp_packet ) {
832
LOG(log_error, logtype_atalkd, "rtmp_request can't find rtmp socket!" );
837
*data++ = DDPTYPE_RTMPR;
838
*data++ = RTMPROP_REQUEST;
841
* There is a problem with the net zero "hint" hack.
843
memset( &sat, 0, sizeof( struct sockaddr_at ));
845
sat.sat_len = sizeof( struct sockaddr_at );
847
sat.sat_family = AF_APPLETALK;
848
sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
849
sat.sat_addr.s_node = ATADDR_BCAST;
850
sat.sat_port = ap->ap_port;
851
if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
852
sizeof( struct sockaddr_at )) < 0 ) {
853
LOG(log_error, logtype_atalkd, "rtmp_request sendto: %s", strerror(errno) );
860
int looproute( iface, cmd )
861
struct interface *iface;
864
struct sockaddr_at dst, loop;
866
if ( cmd == RTMP_DEL && ( iface->i_flags & IFACE_LOOP ) == 0 ) {
867
LOG(log_error, logtype_atalkd, "looproute panic no route" );
871
if ( cmd == RTMP_ADD && ( iface->i_flags & IFACE_LOOP )) {
872
LOG(log_error, logtype_atalkd, "looproute panic two routes" );
876
memset( &dst, 0, sizeof( struct sockaddr_at ));
878
dst.sat_len = sizeof( struct sockaddr_at );
880
dst.sat_family = AF_APPLETALK;
881
dst.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
882
dst.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
883
memset( &loop, 0, sizeof( struct sockaddr_at ));
885
loop.sat_len = sizeof( struct sockaddr_at );
887
loop.sat_family = AF_APPLETALK;
888
loop.sat_addr.s_net = htons( ATADDR_ANYNET );
889
loop.sat_addr.s_node = ATADDR_ANYNODE;
893
(struct sockaddr *) &dst,
894
(struct sockaddr *) &loop,
895
RTF_UP | RTF_HOST ) ) {
900
(struct sockaddr_at *) &dst,
901
(struct sockaddr_at *) &loop,
902
RTF_UP | RTF_HOST ) ) {
906
if ( cmd == RTMP_ADD ) {
907
iface->i_flags |= IFACE_LOOP;
909
if ( cmd == RTMP_DEL ) {
910
iface->i_flags &= ~IFACE_LOOP;
915
int gateroute( command, rtmp )
916
unsigned int command;
917
struct rtmptab *rtmp;
919
struct sockaddr_at dst, gate;
922
if ( command == RTMP_DEL && ( rtmp->rt_flags & RTMPTAB_ROUTE ) == 0 ) {
925
if ( command == RTMP_ADD && ( rtmp->rt_flags & RTMPTAB_ROUTE )) {
929
net = ntohs( rtmp->rt_firstnet );
931
* Since we will accept routes from gateways who advertise their
932
* address as 0.YY, we must munge the gateway address we give to
933
* the kernel. Otherwise, we'll get a bunch of routes to the loop
934
* back interface, and who wants that?
936
memset( &gate, 0, sizeof( struct sockaddr_at ));
938
gate.sat_len = sizeof( struct sockaddr_at );
940
gate.sat_family = AF_APPLETALK;
941
gate.sat_addr.s_net = rtmp->rt_gate->g_sat.sat_addr.s_net;
942
gate.sat_addr.s_node = rtmp->rt_gate->g_sat.sat_addr.s_node;
943
if ( gate.sat_addr.s_net == 0 ) {
944
gate.sat_addr.s_net = net;
947
memset( &dst, 0, sizeof( struct sockaddr_at ));
949
dst.sat_len = sizeof( struct sockaddr_at );
951
dst.sat_family = AF_APPLETALK;
952
dst.sat_addr.s_node = ATADDR_ANYNODE;
955
dst.sat_addr.s_net = htons( net );
958
(struct sockaddr *) &dst,
959
(struct sockaddr *) &gate,
960
RTF_UP | RTF_GATEWAY )) {
961
LOG(log_error, logtype_atalkd, "route: %u -> %u.%u: %s", net,
962
ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node,
968
(struct sockaddr_at *) &dst,
969
(struct sockaddr_at *) &gate,
970
RTF_UP | RTF_GATEWAY )) {
971
LOG(log_error, logtype_atalkd, "route: %u -> %u.%u: %m", net,
972
ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
975
#endif /* ! BSD4_4 */
976
} while ( net++ < ntohs( rtmp->rt_lastnet ));
978
if ( command == RTMP_ADD ) {
979
rtmp->rt_flags |= RTMPTAB_ROUTE;
981
if ( command == RTMP_DEL ) {
982
rtmp->rt_flags &= ~RTMPTAB_ROUTE;
989
newrt(const struct interface *iface)
991
struct rtmptab *rtmp;
993
if (( rtmp = (struct rtmptab *)calloc(1, sizeof(struct rtmptab))) == 0 ) {
997
rtmp->rt_iface = iface;