1/* 2 * $Id: main.c,v 1.25 2009-12-13 02:21:47 didg Exp $ 3 * 4 * Copyright (c) 1990,1993 Regents of The University of Michigan. 5 * All Rights Reserved. See COPYRIGHT. 6 */ 7 8#ifdef HAVE_CONFIG_H 9#include "config.h" 10#endif /* HAVE_CONFIG_H */ 11 12#include <sys/param.h> 13#include <sys/socket.h> 14#include <sys/file.h> 15#include <sys/time.h> 16#include <sys/resource.h> 17#include <sys/ioctl.h> 18 19/* POSIX.1 check */ 20#include <sys/types.h> 21#ifdef HAVE_SYS_WAIT_H 22#include <sys/wait.h> 23#endif /* HAVE_SYS_WAIT_H */ 24#ifndef WEXITSTATUS 25#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 26#endif /* ! WEXITSTATUS */ 27#ifndef WIFEXITED 28#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 29#endif /* ! WIFEXITED */ 30#ifndef WIFSTOPPED 31#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) 32#endif 33 34#include <errno.h> 35#ifdef TRU64 36#include <sys/mbuf.h> 37#include <net/route.h> 38#endif /* TRU64 */ 39#include <net/if.h> 40#include <net/route.h> 41 42#include <netinet/in.h> 43 44#include <signal.h> 45#include <atalk/logger.h> 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <netdb.h> 50#include <fcntl.h> 51#include <unistd.h> 52 53#include <netatalk/endian.h> 54#include <netatalk/at.h> 55#include <atalk/compat.h> 56#include <atalk/zip.h> 57#include <atalk/rtmp.h> 58#include <atalk/nbp.h> 59#include <atalk/ddp.h> 60#include <atalk/atp.h> 61#include <atalk/paths.h> 62#include <atalk/util.h> 63 64#ifdef __svr4__ 65#include <sys/sockio.h> 66#include <termios.h> 67#endif /* __svr4__ */ 68 69#include "interface.h" 70#include "gate.h" 71#include "list.h" 72#include "rtmp.h" 73#include "zip.h" 74#include "nbp.h" 75#include "atserv.h" 76#include "main.h" 77 78/* Forward Declarations */ 79int ifconfig(const char *iname, unsigned long cmd, struct sockaddr_at *sa); 80 81/* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */ 82#ifndef SOCKLEN_T 83#define SOCKLEN_T unsigned int 84#endif /* SOCKLEN_T */ 85 86#ifndef WEXITSTATUS 87#define WEXITSTATUS(x) ((x).w_retcode) 88#endif /* WEXITSTATUS */ 89 90/* linux has a special ioctl for appletalk device destruction. as of 91 * 2.1.57, SIOCDIFADDR works w/ linux. okay, we need to deal with the 92 * fact that SIOCDIFADDR may be defined on linux despite the fact that 93 * it doesn't work. */ 94#if !defined(SIOCDIFADDR) && defined(SIOCATALKDIFADDR) 95#define SIOCDIFADDR SIOCATALKDIFADDR 96#endif 97 98#define elements(a) (sizeof(a)/sizeof((a)[0])) 99 100#define PKTSZ 1024 101 102extern int aep_packet(struct atport *ap, struct sockaddr_at *from, char *data, int len); 103 104int rtfd; 105int transition = 0; 106int stabletimer, newrtmpdata = 0; 107 108static struct atserv atserv[] = { 109 { "rtmp", 1, rtmp_packet }, /* 0 */ 110 { "nbp", 2, nbp_packet }, /* 1 */ 111 { "echo", 4, aep_packet }, /* 2 */ 112 { "zip", 6, zip_packet }, /* 3 */ 113}; 114static int atservNATSERV = elements( atserv ); 115 116struct interface *interfaces = NULL, *ciface = NULL; 117 118static int debug = 0, quiet = 0, chatty = 0; 119static char *configfile = NULL; 120static int ziptimeout = 0; 121static int stable = 0, noparent = 0; 122static int ninterfaces; 123static int defphase = IFACE_PHASE2; 124static int nfds = 0; 125static fd_set fds; 126static char Packet[ PKTSZ ]; 127static char *version = VERSION; 128static char *pidfile = _PATH_ATALKDLOCK; 129 130 131/* from config.c */ 132 133int readconf( char * ); 134int getifconf( void ); 135int writeconf( char * ); 136 137/* this is the messiest of the bunch as atalkd can exit pretty much 138 * everywhere. we delete interfaces here instead of in as_down. */ 139static void atalkd_exit(const int i) 140{ 141#ifdef SIOCDIFADDR 142 struct interface *iface; 143 144 for (iface = interfaces; iface; iface = iface->i_next) { 145 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr)) { 146#ifdef SIOCATALKDIFADDR 147#if (SIOCDIFADDR != SIOCATALKDIFADDR) 148 if (!ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr)) 149 continue; 150#endif /* SIOCDIFADDR != SIOCATALKDIFADDR */ 151#endif /* SIOCATALKIFADDR */ 152 LOG(log_error, logtype_atalkd, "difaddr(%u.%u): %s", 153 ntohs(iface->i_addr.sat_addr.s_net), 154 iface->i_addr.sat_addr.s_node, strerror(errno)); 155 } 156#ifdef linux 157 if (!(iface->i_flags & IFACE_WASALLMULTI) && (iface->i_flags & IFACE_ALLMULTI)) 158 ifsetallmulti(iface->i_name, 0); 159#endif /* linux */ 160 } 161#endif /* SOPCDOFADDR */ 162 163 server_unlock(pidfile); 164 exit(i); 165} 166 167/* XXX need better error handling for gone interfaces, delete routes and so on 168 * moreover there's no way to put an interface back short of restarting atalkd 169 * thus after the first time, silently fail 170*/ 171static ssize_t sendto_iface(struct interface *iface, int sockfd, const void *buf, size_t len, 172 const struct sockaddr_at *dest_addr) 173{ 174 ssize_t ret = sendto( sockfd, buf, len, 0, (struct sockaddr *)dest_addr, sizeof( struct sockaddr_at )); 175 176 if (ret < 0 ) { 177 if (!(iface->i_flags & IFACE_ERROR)) { 178 LOG(log_error, logtype_atalkd, "as_timer sendto %u.%u (%u): %s", 179 ntohs( dest_addr->sat_addr.s_net ), 180 dest_addr->sat_addr.s_node, 181 ntohs( iface->i_rt->rt_firstnet ), 182 strerror(errno) ); 183 } 184 iface->i_flags |= IFACE_ERROR; 185 } 186 else { 187 iface->i_flags &= ~IFACE_ERROR; 188 } 189 return ret; 190} 191 192static void as_timer(int sig _U_) 193{ 194 struct sockaddr_at sat; 195 struct ziphdr zh; 196 struct rtmp_head rh; 197 struct rtmp_tuple rt; 198 struct atport *ap, *zap, *rap; 199 struct interface *iface, *iface2; 200 struct gate *gate, *fgate = NULL; 201 struct rtmptab *rtmp, *frtmp; 202 struct ziptab *zt; 203 char *data, *end, packet[ ATP_BUFSIZ ]; 204 int sentzipq = 0; 205 int n, cc; 206 207 ap=zap=rap=NULL; 208 209 memset(&sat, 0, sizeof( struct sockaddr_at )); 210 211 for ( iface = interfaces; iface; iface = iface->i_next ) { 212 if ( iface->i_flags & IFACE_LOOPBACK ) { 213 continue; 214 } 215 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) { 216 if ( ap->ap_packet == zip_packet ) { 217 zap = ap; 218 } 219 if ( ap->ap_packet == rtmp_packet ) { 220 rap = ap; 221 } 222 } 223 224 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG|IFACE_NOROUTER )) == IFACE_ADDR ) { 225 if ( iface->i_time < 3 ) { 226 if ( iface->i_flags & IFACE_PHASE1 ) { 227 if (rtmp_request( iface ) < 0) { 228 LOG(log_error, logtype_atalkd, "rtmp_request: %s", strerror(errno)); 229 atalkd_exit(1); 230 } 231 newrtmpdata = 1; 232 } else { 233 if (zip_getnetinfo( iface ) < 0) { 234 LOG(log_error, logtype_atalkd, "zip_getnetinfo: %s", strerror(errno)); 235 atalkd_exit(1); 236 } 237 sentzipq = 1; 238 } 239 iface->i_time++; 240 } else { 241 iface->i_flags |= IFACE_NOROUTER; 242 if ((iface->i_flags & IFACE_ISROUTER)) { 243 if (( iface->i_flags & IFACE_SEED ) == 0 ) { 244 /* 245 * No seed info, and we've got multiple interfaces. 246 * Wait forever. 247 */ 248 LOG(log_info, logtype_atalkd, "as_timer multiple interfaces, no seed" ); 249 LOG(log_info, logtype_atalkd, "as_timer can't configure %s", iface->i_name ); 250 LOG(log_info, logtype_atalkd, "as_timer waiting for router" ); 251 iface->i_time = 0; 252 continue; 253 } else { 254 /* 255 * Complete configuration for iface, and boot next 256 * interface. 257 */ 258 iface->i_flags |= IFACE_CONFIG; 259 for ( zt = iface->i_czt; zt; zt = zt->zt_next ) { 260 if (addzone( iface->i_rt, zt->zt_len, zt->zt_name) < 0) { 261 LOG(log_error, logtype_atalkd, "addzone: %s", strerror(errno)); 262 atalkd_exit(1); 263 } 264 } 265 if ( iface->i_rt->rt_zt ) { 266 iface->i_rt->rt_flags &= ~RTMPTAB_ZIPQUERY; 267 iface->i_rt->rt_flags |= RTMPTAB_HASZONES; 268 } 269 if ( iface->i_flags & IFACE_PHASE1 ) { 270 LOG(log_info, logtype_atalkd, "as_timer configured %s phase 1 from seed", iface->i_name ); 271 setaddr( iface, IFACE_PHASE1, 272 iface->i_caddr.sat_addr.s_net, 273 iface->i_addr.sat_addr.s_node, 274 iface->i_caddr.sat_addr.s_net, 275 iface->i_caddr.sat_addr.s_net ); 276 } else { 277 LOG(log_info, logtype_atalkd, "as_timer configured %s phase 2 from seed", iface->i_name ); 278 } 279 280 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */ 281 LOG(log_error, logtype_atalkd, "as_timer: can't route %u.%u to loop: %s", 282 ntohs( iface->i_addr.sat_addr.s_net ), 283 iface->i_addr.sat_addr.s_node, strerror(errno) ); 284 atalkd_exit( 1 ); 285 } 286 if ( iface == ciface ) { 287 ciface = ciface->i_next; 288 bootaddr( ciface ); 289 } 290 } 291 } else { 292 /* 293 * Configure for no router operation. Wait for a route 294 * to become available in rtmp_packet(). 295 */ 296 LOG(log_info, logtype_atalkd, "config for no router" ); 297 298 if ( iface->i_flags & IFACE_PHASE2 ) { 299 iface->i_rt->rt_firstnet = 0; 300 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET ); 301 setaddr( iface, IFACE_PHASE2, iface->i_addr.sat_addr.s_net, iface->i_addr.sat_addr.s_node, 302 0, htons( STARTUP_LASTNET )); 303 } 304 if ( looproute( iface, RTMP_ADD ) ) { /* -1 or 1 */ 305 LOG(log_error, logtype_atalkd, "as_timer: can't route %u.%u to loopback: %s", 306 ntohs( iface->i_addr.sat_addr.s_net ), iface->i_addr.sat_addr.s_node, 307 strerror(errno) ); 308 atalkd_exit( 1 ); 309 } 310 311 if ( iface == ciface ) { 312 ciface = ciface->i_next; 313 bootaddr( ciface ); 314 } 315 } 316 } 317 } 318 319 for ( gate = iface->i_gate; gate; gate = gate->g_next ) { 320 if ( fgate ) { 321 free( (caddr_t)fgate ); 322 fgate = NULL; 323 } 324 325 n = 0; 326 data = packet + 1 + sizeof( struct ziphdr ); 327 end = packet + sizeof( packet ); 328 329 sat = gate->g_sat; 330 sat.sat_port = zap->ap_port; 331 332 /* 333 * Perform timeouts on routers. If we've only got one 334 * interface, we'll use these timeouts to decide that 335 * our zone has gone away. 336 */ 337 if ( ++gate->g_state >= RTMPTAB_BAD ) { 338 LOG(log_info, logtype_atalkd, "as_timer gateway %u.%u down", ntohs( gate->g_sat.sat_addr.s_net ), 339 gate->g_sat.sat_addr.s_node ); 340 rtmp = gate->g_rt; 341 while ( rtmp ) { 342 frtmp = rtmp->rt_next; 343 if ( rtmp->rt_hops == RTMPHOPS_POISON || rtmp->rt_iprev == NULL ) { 344 rtmp_free( rtmp ); 345 } else { 346 rtmp->rt_hops = RTMPHOPS_POISON; 347 if ((cc = rtmp_replace( rtmp )) < 0) { 348 LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno)); 349 atalkd_exit(1); 350 } 351 if (cc) { 352 gate->g_state = rtmp->rt_state = RTMPTAB_GOOD; 353 } 354 } 355 rtmp = frtmp; 356 } 357 if ( gate->g_rt == NULL ) { 358 if ( gate->g_prev == NULL ) { 359 gate->g_iface->i_gate = gate->g_next; 360 } else { 361 gate->g_prev->g_next = gate->g_next; 362 } 363 if ( gate->g_next != NULL ) { 364 gate->g_next->g_prev = gate->g_prev; 365 } 366 fgate = gate; /* can't free here, just mark it */ 367 } 368 /* 369 * If this is the last router on the only interface, 370 * reconfigure our netrange. By marking the interface 371 * as having no router, we will notice when a router 372 * comes back up. 373 * 374 * XXX: actually, we always reconfigure an interface 375 * if we're not a seed router. 376 */ 377 378 if ( gate->g_iface->i_gate == NULL && ((iface->i_flags & IFACE_SEED) == 0)) { 379 gate->g_iface->i_flags |= IFACE_NOROUTER; 380 gate->g_iface->i_flags &= ~IFACE_CONFIG; 381 382 /* get rid of any zones associated with this iface */ 383 if (gate->g_iface->i_rt->rt_zt) { 384 rtmp_delzonemap(gate->g_iface->i_rt); 385 gate->g_iface->i_rt->rt_flags &= ~RTMPTAB_HASZONES; 386 } 387 388 LOG(log_info, logtype_atalkd, "as_timer last gateway down" ); 389 390 /* Set netrange to 0-fffe. */ 391 if ( gate->g_iface->i_flags & IFACE_PHASE2 ) { 392 gate->g_iface->i_rt->rt_firstnet = 0; 393 gate->g_iface->i_rt->rt_lastnet = 394 htons( STARTUP_LASTNET ); 395 setaddr( iface, IFACE_PHASE2, 396 iface->i_addr.sat_addr.s_net, 397 iface->i_addr.sat_addr.s_node, 398 0, htons( STARTUP_LASTNET )); 399 } 400 } 401 continue; 402 } 403 404 /* 405 * If we don't have a zone for our interface yet, ask for 406 * it from any router (all routers) on the interface. 407 */ 408 if (( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) == 0 ) { 409 iface->i_rt->rt_flags |= RTMPTAB_ZIPQUERY; 410 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short )); 411 data += sizeof( u_short ); 412 n++; 413 } 414 415 rtmp = gate->g_rt; 416 while ( rtmp ) { 417 /* 418 * Delete old routing tuples. 419 */ 420 if ( rtmp->rt_state != RTMPTAB_PERM ) { 421 rtmp->rt_state++; 422 } 423 424 /* 425 * We've not been updated for this route in a while. If 426 * it's not in use, go ahead and remove it. If it is in 427 * use, mark the route as down (POISON), and look for a 428 * better route. If one is found, delete this route and use 429 * the new one. If it's not found, mark the route as GOOD 430 * (so we'll propogate our poison) and delete it the next 431 * time it becomes BAD. 432 */ 433 if ( rtmp->rt_state >= RTMPTAB_BAD ) { 434 frtmp = rtmp->rt_next; 435 if ( rtmp->rt_iprev == NULL ) { /* not in use */ 436 rtmp_free( rtmp ); 437 } else { /* in use */ 438 if ( rtmp->rt_hops == RTMPHOPS_POISON ) { 439 rtmp_free( rtmp ); 440 } else { 441 rtmp->rt_hops = RTMPHOPS_POISON; 442 if ((cc = rtmp_replace( rtmp )) < 0) { 443 LOG(log_error, logtype_atalkd, "rtmp_replace: %s", strerror(errno)); 444 atalkd_exit(1); 445 } 446 if (cc) 447 rtmp->rt_state = RTMPTAB_GOOD; 448 } 449 } 450 rtmp = frtmp; 451 continue; 452 } 453 454 /* 455 * Do ZIP lookups. 456 */ 457 if ( rtmp->rt_iprev && ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) { 458 if ( data + sizeof( u_short ) > end || n == 255 ) { 459 /* send what we've got */ 460 zh.zh_op = ZIPOP_QUERY; 461 zh.zh_count = n; 462 cc = data - packet; 463 data = packet; 464 *data++ = DDPTYPE_ZIP; 465 memcpy( data, &zh, sizeof( struct ziphdr )); 466 467 sendto_iface(iface, zap->ap_fd, packet, cc, &sat); 468 sentzipq = 1; 469 470 n = 0; 471 data = packet + 1 + sizeof( struct ziphdr ); 472 end = packet + sizeof( packet ); 473 } 474 475 /* 476 * rt_nzq is number of ZIP Queries we've issued for a 477 * given netrange. If we've got ziptimeout on, we 478 * will only ask 3 times for any given netrange. 479 * Interestingly enough, since rt_nzq is a u_char, 480 * it will overflow after a while. This means we will 481 * periodically ask for nets that we've decided not to 482 * ask about, and warn that we can't get it's zone. 483 */ 484 if ( rtmp->rt_nzq++ == 3 ) { 485 LOG(log_info, logtype_atalkd, "as_timer can't get zone for %u", ntohs( rtmp->rt_firstnet )); 486 } 487 if ( rtmp->rt_nzq > 3 ) { 488 if ( ziptimeout ) { 489 rtmp = rtmp->rt_next; 490 continue; 491 } 492 } else { 493 sentzipq = 1; 494 } 495 rtmp->rt_flags |= RTMPTAB_ZIPQUERY; 496 memcpy( data, &rtmp->rt_firstnet, sizeof( u_short )); 497 data += sizeof( u_short ); 498 n++; 499 } 500 rtmp = rtmp->rt_next; 501 } 502 503 /* send what we've got */ 504 if ( n > 0 ) { 505 zh.zh_op = ZIPOP_QUERY; 506 zh.zh_count = n; 507 cc = data - packet; 508 data = packet; 509 *data++ = DDPTYPE_ZIP; 510 memcpy( data, &zh, sizeof( struct ziphdr )); 511 512 sendto_iface( iface, zap->ap_fd, packet, cc, &sat); 513 } 514 } 515 if ( fgate ) { 516 free( (caddr_t)fgate ); 517 fgate = NULL; 518 } 519 520 /* 521 * Send RTMP broadcasts if we have multiple interfaces or our 522 * interface is configured as a router. 523 */ 524 if ((iface->i_flags & IFACE_ISROUTER)) { 525#ifdef BSD4_4 526 sat.sat_len = sizeof( struct sockaddr_at ); 527#endif /* BSD4_4 */ 528 sat.sat_family = AF_APPLETALK; 529 sat.sat_addr.s_net = ATADDR_ANYNET; 530 sat.sat_addr.s_node = ATADDR_BCAST; 531 sat.sat_port = rap->ap_port; 532 533 data = packet; 534 end = data + sizeof( packet ); 535 *data++ = DDPTYPE_RTMPRD; 536 rh.rh_net = iface->i_addr.sat_addr.s_net; 537 rh.rh_nodelen = 8; 538 rh.rh_node = iface->i_addr.sat_addr.s_node; 539 memcpy( data, &rh, sizeof( struct rtmp_head )); 540 data += sizeof( struct rtmp_head ); 541 n = 0; 542 543 544 if ( iface->i_flags & IFACE_PHASE1 ) { 545 rt.rt_net = 0; 546 rt.rt_dist = 0x82; 547 memcpy( data, &rt, SZ_RTMPTUPLE ); 548 data += SZ_RTMPTUPLE; 549 } else { 550 rt.rt_net = iface->i_rt->rt_firstnet; 551 rt.rt_dist = 0x80; 552 memcpy( data, &rt, SZ_RTMPTUPLE ); 553 data += SZ_RTMPTUPLE; 554 555 rt.rt_net = iface->i_rt->rt_lastnet; 556 rt.rt_dist = 0x82; 557 memcpy( data, &rt, SZ_RTMPTUPLE ); 558 data += SZ_RTMPTUPLE; 559 } 560 561 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) { 562 563 /* XXX: there used to be a bit checking against iface == 564 iface2. also, we don't want to send an rtmp broadcast 565 to an interface that doesn't want it. */ 566 if ((( iface2->i_flags & IFACE_CONFIG ) == 0) || 567 ((iface2->i_flags & IFACE_ISROUTER) == 0)) { 568 continue; 569 } 570 /* 571 * Fill in tuples. Always send the same thing, regardless 572 * of the phase of the destination. Routers who don't 573 * understand extended rtmp packets will toss extended 574 * tuples because their distance will have the high bit set. 575 */ 576 for ( rtmp = iface2->i_rt; rtmp; rtmp = rtmp->rt_inext ) { 577 /* don't broadcast routes we have no zone for */ 578 if ( rtmp->rt_zt == NULL || 579 ( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) || 580 ( rtmp->rt_flags & RTMPTAB_HASZONES ) == 0 ) { 581 continue; 582 } 583 584 /* split horizon */ 585 if (rtmp->rt_iface == iface) { 586 continue; 587 } 588 589 if ((( rtmp->rt_flags & RTMPTAB_EXTENDED ) && 590 data + 2 * SZ_RTMPTUPLE > end ) || 591 data + SZ_RTMPTUPLE > end ) { 592 593 sendto_iface(iface,rap->ap_fd, packet, data - packet, &sat); 594 595 if ( iface->i_flags & IFACE_PHASE2 ) { 596 data = packet + 1 + sizeof( struct rtmp_head ) + 2 * SZ_RTMPTUPLE; 597 } else { 598 data = packet + 1 + sizeof( struct rtmp_head ) + SZ_RTMPTUPLE; 599 } 600 n = 0; 601 } 602 603 rt.rt_net = rtmp->rt_firstnet; 604 rt.rt_dist = rtmp->rt_hops; 605 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) { 606 rt.rt_dist |= 0x80; 607 } 608 memcpy( data, &rt, SZ_RTMPTUPLE ); 609 data += SZ_RTMPTUPLE; 610 611 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) { 612 rt.rt_net = rtmp->rt_lastnet; 613 rt.rt_dist = 0x82; 614 memcpy( data, &rt, SZ_RTMPTUPLE ); 615 data += SZ_RTMPTUPLE; 616 } 617 n++; 618 } 619 } 620 621 /* send rest */ 622 if ( n ) { 623 sendto_iface(iface, rap->ap_fd, packet, data - packet, &sat); 624 } 625 } 626 } 627 628 /* 629 * Check if we're stable. Each time we configure an interface, we 630 * sent stabletimer to UNSTABLE. If stabletimer ever gets to 631 * STABLEANYWAY, we give up and decide to "be" stable anyway. 632 * Normally, we wait for stabletimer get <= STABLE with no new rtmp 633 * data and all zip data complete. 634 */ 635 if ( !stable ) { 636 if ( stabletimer <= STABLE && !newrtmpdata && !sentzipq ) { 637 /* write out config file */ 638 stable = 1; 639 writeconf( configfile ); 640 } else { 641 if ( stabletimer-- <= STABLEANYWAY ) { 642 stable = 1; 643 } 644 } 645 newrtmpdata = 0; 646 647 if ( stable && !noparent ) { 648 noparent = 1; 649 LOG(log_info, logtype_atalkd, "ready %d/%d/%d", stabletimer, newrtmpdata, 650 sentzipq ); 651 if ( !debug ) { 652 /* 653 * Seems like we could get here more than once... 654 */ 655 if ( kill( getpid(), SIGSTOP ) < 0 ) { 656 LOG(log_error, logtype_atalkd, "as_timer: kill-self failed!" ); 657 atalkd_exit( 1 ); 658 } 659 } 660 } 661 } 662 663#ifdef DEBUG 664 consistency(); 665#endif /* DEBUG */ 666} 667 668#ifdef DEBUG 669/* 670* Consistency check... 671*/ 672consistency() 673{ 674 struct rtmptab *rtmp; 675 struct list *lr, *lz; 676 struct ziptab *zt; 677 678 for ( zt = ziptab; zt; zt = zt->zt_next ) { 679 for ( lr = zt->zt_rt; lr; lr = lr->l_next ) { 680 rtmp = (struct rtmptab *)lr->l_data; 681 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) { 682 LOG(log_error, logtype_atalkd, "%.*s has %u-%u (unused)", 683 zt->zt_len, zt->zt_name, ntohs( rtmp->rt_firstnet ), 684 ntohs( rtmp->rt_lastnet )); 685 atalkd_exit(1); 686 } 687 for ( lz = rtmp->rt_zt; lz; lz = lz->l_next ) { 688 if ( zt == (struct ziptab *)lz->l_data ) { 689 break; 690 } 691 } 692 if ( lz == 0 ) { 693 LOG(log_error, logtype_atalkd, "no map from %u-%u to %.*s", 694 ntohs( rtmp->rt_firstnet ), 695 ntohs( rtmp->rt_lastnet ), 696 zt->zt_len, zt->zt_name ); 697 atalkd_exit(1); 698 } 699 } 700 } 701} 702#endif /* DEBUG */ 703 704static void 705as_debug(int sig _U_) 706{ 707 struct interface *iface; 708 struct list *l; 709 struct ziptab *zt; 710 struct gate *gate; 711 struct rtmptab *rt; 712 FILE *rtmpdebug; 713 714 if (( rtmpdebug = fopen( _PATH_ATALKDEBUG, "w" )) == NULL ) { 715 LOG(log_error, logtype_atalkd, "rtmp: %s", strerror(errno) ); 716 } 717 718 for ( iface = interfaces; iface; iface = iface->i_next ) { 719 fprintf( rtmpdebug, "interface %s %u.%u ", iface->i_name, 720 ntohs( iface->i_addr.sat_addr.s_net ), 721 iface->i_addr.sat_addr.s_node ); 722 if ( iface->i_flags & IFACE_PHASE1 ) { 723 putc( '1', rtmpdebug ); 724 } 725 if ( iface->i_flags & IFACE_PHASE2 ) { 726 putc( '2', rtmpdebug ); 727 } 728 if ( iface->i_flags & IFACE_RSEED ) { 729 putc( 'R', rtmpdebug ); 730 } 731 if ( iface->i_flags & IFACE_SEED ) { 732 putc( 'S', rtmpdebug ); 733 } 734 if ( iface->i_flags & IFACE_DONTROUTE ) { 735 putc( 'D', rtmpdebug ); 736 } 737 if ( iface->i_flags & IFACE_ADDR ) { 738 putc( 'A', rtmpdebug ); 739 } 740 if ( iface->i_flags & IFACE_CONFIG ) { 741 putc( 'C', rtmpdebug ); 742 } 743 if ( iface->i_flags & IFACE_NOROUTER ) { 744 putc( 'N', rtmpdebug ); 745 } 746 if ( iface->i_flags & IFACE_LOOP ) { 747 putc( 'L', rtmpdebug ); 748 } 749 putc( '\n', rtmpdebug ); 750 751 if ( iface->i_rt ) { 752 fprintf( rtmpdebug, "\t%u-%u ", 753 ntohs( iface->i_rt->rt_firstnet ), 754 ntohs( iface->i_rt->rt_lastnet )); 755 if ( iface->i_rt->rt_flags & RTMPTAB_ZIPQUERY ) { 756 putc( 'q', rtmpdebug ); 757 } 758 if ( iface->i_rt->rt_flags & RTMPTAB_HASZONES ) { 759 putc( 'z', rtmpdebug ); 760 } 761 if ( iface->i_rt->rt_flags & RTMPTAB_EXTENDED ) { 762 putc( 'x', rtmpdebug ); 763 } 764 putc( 'i', rtmpdebug ); 765 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) { 766 zt = (struct ziptab *)l->l_data; 767 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name ); 768 } 769 fprintf( rtmpdebug, "\n" ); 770 } 771 772 for ( gate = iface->i_gate; gate; gate = gate->g_next ) { 773 fprintf( rtmpdebug, "gate %u.%u %X\n", 774 ntohs( gate->g_sat.sat_addr.s_net ), 775 gate->g_sat.sat_addr.s_node, gate->g_state ); 776 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) { 777 fprintf( rtmpdebug, "\t%u-%u ", ntohs( rt->rt_firstnet ), 778 ntohs( rt->rt_lastnet )); 779 if ( rt->rt_flags & RTMPTAB_ZIPQUERY ) { 780 putc( 'q', rtmpdebug ); 781 } 782 if ( rt->rt_flags & RTMPTAB_HASZONES ) { 783 putc( 'z', rtmpdebug ); 784 } 785 if ( rt->rt_flags & RTMPTAB_EXTENDED ) { 786 putc( 'x', rtmpdebug ); 787 } 788 if ( rt->rt_iprev ) { 789 putc( 'i', rtmpdebug ); 790 } 791 for ( l = rt->rt_zt; l; l = l->l_next ) { 792 zt = (struct ziptab *)l->l_data; 793 fprintf( rtmpdebug, " '%.*s'", zt->zt_len, zt->zt_name ); 794 } 795 fprintf( rtmpdebug, "\n" ); 796 } 797 } 798 } 799 800 fclose( rtmpdebug ); 801} 802 803/* 804 * Called when SIGTERM is recieved. Remove all routes and then exit. 805 */ 806static void 807as_down(int sig _U_) 808{ 809 struct interface *iface; 810 struct gate *gate; 811 struct rtmptab *rt; 812 813 for ( iface = interfaces; iface; iface = iface->i_next ) { 814 for ( gate = iface->i_gate; gate; gate = gate->g_next ) { 815 for ( rt = gate->g_rt; rt; rt = rt->rt_next ) { 816 if ( rt->rt_iprev ) { 817 if ( gateroute( RTMP_DEL, rt ) < 0 ) { 818 LOG(log_error, logtype_atalkd, "as_down remove %u-%u failed: %s", 819 ntohs( rt->rt_firstnet ), 820 ntohs( rt->rt_lastnet ), 821 strerror(errno) ); 822 } 823 } 824 } 825 } 826 if ( iface->i_flags & IFACE_LOOP ) { 827 if (looproute( iface, RTMP_DEL )) { 828 LOG(log_error, logtype_atalkd, "as_down remove %s %u.%u failed: %s", 829 iface->i_name, ntohs( iface->i_addr.sat_addr.s_net ), 830 iface->i_addr.sat_addr.s_node, 831 strerror(errno) ); 832 } 833 } 834 } 835 836 LOG(log_info, logtype_atalkd, "done" ); 837 atalkd_exit( 0 ); 838} 839 840int main( int ac, char **av) 841{ 842 extern char *optarg; 843 extern int optind; 844 845 struct sockaddr_at sat; 846 struct sigaction sv; 847 struct itimerval it; 848 sigset_t signal_set, old_set; 849 850 struct interface *iface; 851 int status; 852 struct atport *ap; 853 fd_set readfds; 854 int i, c; 855 SOCKLEN_T fromlen; 856 char *prog; 857 858 while (( c = getopt( ac, av, "12qsdtf:P:v" )) != EOF ) { 859 switch ( c ) { 860 case '1' : 861 defphase = IFACE_PHASE1; 862 break; 863 864 case '2' : 865 defphase = IFACE_PHASE2; 866 break; 867 868 case 'd' : 869 debug++; 870 break; 871 872 case 'f' : 873 configfile = optarg; 874 break; 875 876 case 'q' : /* don't seed */ 877 quiet++; 878 break; 879 880 case 's' : /* seed */ 881 chatty++; 882 break; 883 884 case 't' : /* transition */ 885 transition++; 886 break; 887 888 case 'P' : /* pid file */ 889 pidfile = optarg; 890 break; 891 892 case 'v' : /* version */ 893 printf( "atalkd (version %s)\n", version ); 894 exit ( 1 ); 895 break; 896 897 default : 898 fprintf( stderr, "Unknown option -- '%c'\n", c ); 899 exit( 1 ); 900 } 901 } 902 if ( optind != ac ) { 903 fprintf( stderr, "Too many arguments.\n" ); 904 exit( 1 ); 905 } 906 907 if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) { 908 prog = av[ 0 ]; 909 } else { 910 prog++; 911 } 912 913 /* 914 * Configure loop back address first, so appearances of "lo0" in 915 * the config file fail. Also insures that lo0 gets configured, 916 * even if there's some hangup during configuration of some 917 * other interface. 918 */ 919 if (( interfaces = newiface( LOOPIFACE )) == NULL ) { 920 perror( "newiface" ); 921 exit( 1 ); 922 } 923 interfaces->i_flags |= IFACE_PHASE2 | IFACE_LOOPBACK; 924 925 /* 926 * Check our initial configuration before we fork. This way we can 927 * complain about syntax errors on stdout. 928 * 929 * Basically, if we're going to read our config file, we should read 930 * it and initialize our data structures. If we're not going to read 931 * our config file, use GIFCONF to initialize our data structures. 932 */ 933 if ( readconf( configfile ) < 0 && getifconf() < 0 ) { 934 fprintf( stderr, "%s: can't get interfaces, exiting.\n", prog ); 935 exit( 1 ); 936 } 937 938 /* we need to count up our interfaces so that we can simplify things 939 * later. we also need to figure out if we have more than one interface 940 * that is routing. */ 941 for (i = 0, ninterfaces = 0, iface = interfaces; iface; 942 iface=iface->i_next) { 943 if (iface->i_flags & IFACE_DONTROUTE) 944 i++; 945 ninterfaces++; 946 } 947 i = ninterfaces - i; /* number of routable interfaces */ 948 949 /* 950 * At this point, we have (at least partially) initialized data 951 * structures. Fill in what we can and verify that nothing is obviously 952 * broken. 953 */ 954 for (iface = interfaces; iface; iface = iface->i_next) { 955 /* Apply the default phase */ 956 if (( iface->i_flags & IFACE_PHASE1 ) == 0 && 957 ( iface->i_flags & IFACE_PHASE2 ) == 0 ) { 958 iface->i_flags |= defphase; 959 } 960 961 /* set up router flag information. if we have multiple interfaces 962 * and DONTROUTE isn't set, set up ROUTER. i is the number of 963 * interfaces that don't have the DONTROUTE flag set. */ 964 if ((i > IFBASE) && ((iface->i_flags & IFACE_DONTROUTE) == 0)) { 965 iface->i_flags |= IFACE_ISROUTER; 966 } 967 968 /* Set default addresses */ 969 if ( iface->i_rt == NULL ) { 970 if (( iface->i_rt = newrt(iface)) == NULL ) { 971 perror( "newrt" ); 972 exit( 1 ); 973 } 974 975 if ( iface->i_flags & IFACE_PHASE1 ) { 976 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = 977 iface->i_caddr.sat_addr.s_net; 978 } else { 979 if ( iface->i_caddr.sat_addr.s_net != ATADDR_ANYNET || 980 ( iface->i_flags & IFACE_LOOPBACK )) { 981 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = 982 iface->i_caddr.sat_addr.s_net; 983 } else { 984 iface->i_rt->rt_firstnet = htons( STARTUP_FIRSTNET ); 985 iface->i_rt->rt_lastnet = htons( STARTUP_LASTNET ); 986 } 987 } 988 } 989 990 if (( iface->i_flags & IFACE_PHASE1 ) == 0 ) { 991 iface->i_rt->rt_flags |= RTMPTAB_EXTENDED; 992 } 993 994 if ( iface->i_caddr.sat_addr.s_net == ATADDR_ANYNET ) { 995 iface->i_caddr.sat_addr.s_net = iface->i_rt->rt_firstnet; 996 } 997 998 if ( debug ) { 999 dumpconfig( iface ); /* probably needs args */ 1000 } 1001 } 1002 1003 /* 1004 * A little consistency check... 1005 */ 1006 if ( ninterfaces < IFBASE ) { 1007 fprintf( stderr, "%s: zero interfaces, exiting.\n", prog ); 1008 exit( 1 ); 1009 } 1010 1011 /* 1012 * Set process name for logging 1013 */ 1014 1015 set_processname("atalkd"); 1016 1017 /* do this here so that we can use ifconfig */ 1018#ifdef __svr4__ 1019 if ( plumb() < 0 ) { 1020 fprintf(stderr, "can't establish STREAMS plumbing, exiting.\n" ); 1021 atalkd_exit( 1 ); 1022 } 1023#endif /* __svr4__ */ 1024 1025 /* delete pre-existing interface addresses. */ 1026#ifdef SIOCDIFADDR 1027 for (iface = interfaces; iface; iface = iface->i_next) { 1028 if (ifconfig(iface->i_name, SIOCDIFADDR, &iface->i_addr)) { 1029#ifdef SIOCATALKDIFADDR 1030#if (SIOCDIFADDR != SIOCATALKDIFADDR) 1031 ifconfig(iface->i_name, SIOCATALKDIFADDR, &iface->i_addr); 1032#endif /* SIOCDIFADDR != SIOCATALKDIFADDR */ 1033#endif /* SIOCATALKDIFADDR */ 1034 } 1035 } 1036#endif /* SIOCDIFADDR */ 1037 1038 /* 1039 * Disassociate. The child will send itself a signal when it is 1040 * stable. This indicates that other processes may begin using 1041 * AppleTalk. 1042 */ 1043 switch (i = server_lock("atalkd", pidfile, debug)) { 1044 case -1: 1045 exit(1); 1046 case 0: /* child */ 1047 break; 1048 default: /* parent */ 1049 /* 1050 * Wait for the child to send itself a SIGSTOP, after which 1051 * we send it a SIGCONT and exit ourself. 1052 */ 1053 if ( wait3( &status, WUNTRACED, (struct rusage *)0 ) != i) { 1054 perror( "wait3" ); /* Child died? */ 1055 atalkd_exit( 1 ); 1056 } 1057 if ( !WIFSTOPPED( status )) { 1058 fprintf( stderr, "AppleTalk not up! Check your syslog for the reason." ); 1059 if ( WIFEXITED( status )) { 1060 fprintf( stderr, " Child exited with %d.\n", 1061 WEXITSTATUS( status )); 1062 } else { 1063 fprintf( stderr, " Child died.\n" ); 1064 } 1065 atalkd_exit( 1 ); 1066 } 1067 if ( kill(i, SIGCONT ) < 0 ) { 1068 perror( "kill" ); 1069 atalkd_exit( 1 ); 1070 } 1071 exit( 0 ); 1072 } 1073 1074#ifdef ultrix 1075 openlog( prog, LOG_PID ); 1076#else /* ultrix */ 1077 set_processname(prog); 1078 syslog_setup(log_debug, logtype_default, logoption_pid, logfacility_daemon ); 1079#endif /* ultrix */ 1080 1081 LOG(log_info, logtype_atalkd, "restart (%s)", version ); 1082 1083 /* 1084 * Socket for use in routing ioctl()s. Can't add routes to our 1085 * interfaces until we have our routing socket. 1086 */ 1087#ifdef BSD4_4 1088 if (( rtfd = socket( PF_ROUTE, SOCK_RAW, AF_APPLETALK )) < 0 ) { 1089 LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) ); 1090 atalkd_exit( 1 ); 1091 } 1092 if ( shutdown( rtfd, 0 ) < 0 ) { 1093 LOG(log_error, logtype_atalkd, "route shutdown: %s", strerror(errno) ); 1094 atalkd_exit( 1 ); 1095 } 1096#else /* BSD4_4 */ 1097 if (( rtfd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) { 1098 LOG(log_error, logtype_atalkd, "route socket: %s", strerror(errno) ); 1099 atalkd_exit( 1 ); 1100 } 1101#endif /* BSD4_4 */ 1102 1103 ciface = interfaces; 1104 bootaddr( ciface ); 1105 1106 memset(&sv, 0, sizeof(sv)); 1107 sv.sa_handler = as_down; 1108 sigemptyset( &sv.sa_mask ); 1109 sigaddset( &sv.sa_mask, SIGUSR1 ); 1110 sigaddset( &sv.sa_mask, SIGALRM ); 1111 sigaddset( &sv.sa_mask, SIGTERM ); 1112 sv.sa_flags = SA_RESTART; 1113 if ( sigaction( SIGTERM, &sv, NULL) < 0 ) { 1114 LOG(log_error, logtype_atalkd, "sigterm: %s", strerror(errno) ); 1115 atalkd_exit( 1 ); 1116 } 1117 1118 sv.sa_handler = as_debug; 1119 sigemptyset( &sv.sa_mask ); 1120 sigaddset( &sv.sa_mask, SIGUSR1 ); 1121 sigaddset( &sv.sa_mask, SIGALRM ); 1122 sigaddset( &sv.sa_mask, SIGTERM ); 1123 sv.sa_flags = SA_RESTART; 1124 if ( sigaction( SIGUSR1, &sv, NULL) < 0 ) { 1125 LOG(log_error, logtype_atalkd, "sigusr1: %s", strerror(errno) ); 1126 atalkd_exit( 1 ); 1127 } 1128 1129 sv.sa_handler = as_timer; 1130 sigemptyset( &sv.sa_mask ); 1131 sigaddset( &sv.sa_mask, SIGUSR1 ); 1132 sigaddset( &sv.sa_mask, SIGALRM ); 1133 sigaddset( &sv.sa_mask, SIGTERM ); 1134 sv.sa_flags = SA_RESTART; 1135 if ( sigaction( SIGALRM, &sv, NULL) < 0 ) { 1136 LOG(log_error, logtype_atalkd, "sigalrm: %s", strerror(errno) ); 1137 atalkd_exit( 1 ); 1138 } 1139 1140 it.it_interval.tv_sec = 10L; 1141 it.it_interval.tv_usec = 0L; 1142 it.it_value.tv_sec = 10L; 1143 it.it_value.tv_usec = 0L; 1144 if ( setitimer( ITIMER_REAL, &it, NULL) < 0 ) { 1145 LOG(log_error, logtype_atalkd, "setitimer: %s", strerror(errno) ); 1146 atalkd_exit( 1 ); 1147 } 1148 1149 sigemptyset( &signal_set ); 1150 sigaddset(&signal_set, SIGALRM); 1151#if 0 1152 /* don't block SIGTERM */ 1153 sigaddset(&signal_set, SIGTERM); 1154#endif 1155 sigaddset(&signal_set, SIGUSR1); 1156 1157 for (;;) { 1158 readfds = fds; 1159 if ( select( nfds, &readfds, NULL, NULL, NULL) < 0 ) { 1160 if ( errno == EINTR ) { 1161 errno = 0; 1162 continue; 1163 } else { 1164 LOG(log_error, logtype_atalkd, "select: %s", strerror(errno) ); 1165 atalkd_exit( 1 ); 1166 } 1167 } 1168 1169 for ( iface = interfaces; iface; iface = iface->i_next ) { 1170 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) { 1171 if ( FD_ISSET( ap->ap_fd, &readfds )) { 1172 if ( ap->ap_packet ) { 1173 fromlen = sizeof( struct sockaddr_at ); 1174 if (( c = recvfrom( ap->ap_fd, Packet, sizeof( Packet ), 1175 0, (struct sockaddr *)&sat, &fromlen )) < 0 ) { 1176 LOG(log_error, logtype_atalkd, "recvfrom: %s", strerror(errno) ); 1177 continue; 1178 } 1179#ifdef DEBUG1 1180 if ( debug ) { 1181 printf( "packet from %u.%u on %s (%x) %d (%d)\n", 1182 ntohs( sat.sat_addr.s_net ), 1183 sat.sat_addr.s_node, iface->i_name, 1184 iface->i_flags, ap->ap_port, ap->ap_fd ); 1185 bprint( Packet, c ); 1186 } 1187#endif 1188 if (sigprocmask(SIG_BLOCK, &signal_set, &old_set) < 0) { 1189 LOG(log_error, logtype_atalkd, "sigprocmask: %s", strerror(errno) ); 1190 atalkd_exit( 1 ); 1191 } 1192 1193 if (( *ap->ap_packet )( ap, &sat, Packet, c ) < 0) { 1194 LOG(log_error, logtype_atalkd, "ap->ap_packet: %s", strerror(errno)); 1195 atalkd_exit(1); 1196 } 1197 1198#ifdef DEBUG 1199 consistency(); 1200#endif 1201 if (sigprocmask(SIG_SETMASK, &old_set, NULL) < 0) { 1202 LOG(log_error, logtype_atalkd, "sigprocmask old set: %s", strerror(errno) ); 1203 atalkd_exit( 1 ); 1204 } 1205 1206 } 1207 } 1208 } 1209 } 1210 } 1211} 1212 1213/* 1214 * This code is called (from main(), as_timer(), zip_packet(), 1215 * and rtmp_packet()) to set the initial "bootstrapping" address 1216 * on an interface. 1217 */ 1218void bootaddr(struct interface *iface) 1219{ 1220 if ( iface == NULL ) { 1221 return; 1222 } 1223 1224 /* consistency */ 1225 if ( iface->i_flags & IFACE_ADDR ) { 1226 LOG(log_error, logtype_atalkd, "bootaddr OOPS!" ); 1227 atalkd_exit(1); 1228 } 1229 1230 if ( iface->i_flags & IFACE_PHASE1 ) { 1231 setaddr( iface, IFACE_PHASE1, 0, 1232 iface->i_caddr.sat_addr.s_node, 0, 0 ); 1233 1234 if ( iface->i_flags & IFACE_LOOPBACK ) { 1235 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR; 1236 if ( ciface == iface ) { 1237 ciface = ciface->i_next; 1238 bootaddr( ciface ); 1239 } 1240 1241 } else if (rtmp_request( iface ) < 0) { 1242 LOG(log_error, logtype_atalkd, "bootaddr (rtmp_request): %s", strerror(errno)); 1243 atalkd_exit(1); 1244 } 1245 1246 } else { 1247 setaddr( iface, IFACE_PHASE2, iface->i_caddr.sat_addr.s_net, 1248 iface->i_caddr.sat_addr.s_node, 1249 iface->i_rt->rt_firstnet, iface->i_rt->rt_lastnet ); 1250 1251 if ( iface->i_flags & IFACE_LOOPBACK ) { 1252 iface->i_flags |= IFACE_CONFIG | IFACE_ADDR; 1253 if ( ciface == iface ) { 1254 ciface = ciface->i_next; 1255 bootaddr( ciface ); 1256 } 1257 1258 } else if (zip_getnetinfo( iface ) < 0) { 1259 LOG(log_error, logtype_atalkd, "bootaddr (zip_getnetinfo): %s", strerror(errno)); 1260 atalkd_exit(1); 1261 } 1262 } 1263 ++iface->i_time; 1264 iface->i_flags |= IFACE_ADDR; 1265 stabletimer = UNSTABLE; 1266} 1267 1268 1269/* 1270 * Change setaddr() 1271 * to manage the i_ports field and the fds for select(). 1272 */ 1273void setaddr(struct interface *iface, 1274 u_int8_t phase, u_int16_t net, u_int8_t node, 1275 u_int16_t first, u_int16_t last) 1276{ 1277 int i; 1278 struct atserv *as; 1279 struct atport *ap; 1280 struct servent *se; 1281 struct sockaddr_at sat; 1282 struct netrange nr; 1283 1284 if ( iface->i_ports == NULL ) { /* allocate port structures */ 1285 for ( i = 0, as = atserv; i < atservNATSERV; i++, as++ ) { 1286 if (( se = getservbyname( as->as_name, "ddp" )) == NULL ) { 1287 LOG(log_info, logtype_atalkd, "%s: service unknown", as->as_name ); 1288 } else { 1289 as->as_port = ntohs( se->s_port ); 1290 } 1291 if (( ap = (struct atport *)malloc( sizeof( struct atport ))) == 1292 NULL ) { 1293 LOG(log_error, logtype_atalkd, "malloc: %s", strerror(errno) ); 1294 atalkd_exit( 1 ); 1295 } 1296 ap->ap_fd = 0; 1297 ap->ap_next = iface->i_ports; 1298 ap->ap_iface = iface; 1299 ap->ap_port = as->as_port; 1300 ap->ap_packet = as->as_packet; 1301 1302 iface->i_ports = ap; 1303 } 1304 } else { /* close ports */ 1305 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) { 1306 (void)close( ap->ap_fd ); 1307 } 1308 } 1309 1310#ifdef BSD4_4 1311 iface->i_addr.sat_len = sizeof( struct sockaddr_at ); 1312#endif /* BSD4_4 */ 1313 iface->i_addr.sat_family = AF_APPLETALK; 1314 iface->i_addr.sat_addr.s_net = net; 1315 iface->i_addr.sat_addr.s_node = node; 1316 1317 nr.nr_phase = phase; 1318 nr.nr_firstnet = first; 1319 nr.nr_lastnet = last; 1320 memcpy( iface->i_addr.sat_zero, &nr, sizeof( struct netrange )); 1321 1322 if ( ifconfig( iface->i_name, SIOCSIFADDR, &iface->i_addr )) { 1323 LOG(log_error, logtype_atalkd, "setifaddr: %s (%u-%u): %s. try specifying a \ 1324smaller net range.", iface->i_name, ntohs(first), ntohs(last), strerror(errno)); 1325 atalkd_exit( 1 ); 1326 } 1327 if ( ifconfig( iface->i_name, SIOCGIFADDR, &iface->i_addr )) { 1328 LOG(log_error, logtype_atalkd, "getifaddr: %s: %s", iface->i_name, strerror(errno) ); 1329 atalkd_exit( 1 ); 1330 } 1331 1332 /* open ports */ 1333 i = 1; /* enable broadcasts */ 1334#if 0 1335 /* useless message, no? */ 1336 LOG(log_info, logtype_atalkd, "setsockopt incompatible w/ Solaris STREAMS module."); 1337#endif /* __svr4__ */ 1338 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) { 1339 if (( ap->ap_fd = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) { 1340 LOG(log_error, logtype_atalkd, "socket: %s", strerror(errno) ); 1341 atalkd_exit( 1 ); 1342 } 1343#ifndef __svr4__ 1344 setsockopt(ap->ap_fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i)); 1345#endif /* ! __svr4 */ 1346 1347 memset( &sat, 0, sizeof( struct sockaddr_at )); 1348#ifdef BSD4_4 1349 sat.sat_len = sizeof( struct sockaddr_at ); 1350#endif /* BSD4_4 */ 1351 sat.sat_family = AF_APPLETALK; 1352 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net; 1353 sat.sat_addr.s_node = iface->i_addr.sat_addr.s_node; 1354 sat.sat_port = ap->ap_port; 1355 1356 if ( bind( ap->ap_fd, (struct sockaddr *)&sat, 1357 sizeof( struct sockaddr_at )) < 0 ) { 1358 LOG(log_error, logtype_atalkd, "bind %u.%u:%u: %s", 1359 ntohs( sat.sat_addr.s_net ), 1360 sat.sat_addr.s_node, sat.sat_port, strerror(errno) ); 1361#ifdef SIOCDIFADDR 1362 /* remove all interfaces if we have a problem with bind */ 1363 for (iface = interfaces; iface; iface = iface->i_next) { 1364 if (ifconfig( iface->i_name, SIOCDIFADDR, &iface->i_addr )) { 1365#ifdef SIOCATALKDIFADDR 1366#if (SIOCDIFADDR != SIOCATALKDIFADDR) 1367 ifconfig( iface->i_name, SIOCATALKDIFADDR, &iface->i_addr ); 1368#endif /* SIOCDIFADDR != SIOCATALKDIFADDR */ 1369#endif /* SIOCATALKDIFADDR */ 1370 } 1371 } 1372#endif /* SIOCDIFADDR */ 1373 atalkd_exit( 1 ); 1374 } 1375 } 1376 1377 /* recalculate nfds and fds */ 1378 FD_ZERO( &fds ); 1379 for ( nfds = 0, iface = interfaces; iface; iface = iface->i_next ) { 1380 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) { 1381 FD_SET( ap->ap_fd, &fds ); 1382 if ( ap->ap_fd > nfds ) { 1383 nfds = ap->ap_fd; 1384 } 1385 } 1386 } 1387 nfds++; 1388} 1389 1390int ifsetallmulti (const char *iname, int set) 1391{ 1392 int sock; 1393 struct ifreq ifr; 1394 1395 memset(&ifr, 0, sizeof(ifr)); 1396 1397 if (( sock = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) { 1398 return( -1 ); 1399 } 1400 1401 /* get interface config */ 1402 strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name)); 1403 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { 1404 close(sock); 1405 return (-1); 1406 } 1407 1408 /* should we set or unset IFF_ALLMULTI */ 1409 if (set) 1410 ifr.ifr_flags |= IFF_ALLMULTI; 1411 else 1412 ifr.ifr_flags &= ~IFF_ALLMULTI; 1413 1414 /* set interface config */ 1415 strlcpy(ifr.ifr_name, iname, sizeof(ifr.ifr_name)); 1416 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { 1417 close(sock); 1418 return -1; 1419 } 1420 1421 close(sock); 1422 return (0); 1423} 1424 1425int ifconfig( const char *iname, unsigned long cmd, struct sockaddr_at *sa) 1426{ 1427 struct ifreq ifr; 1428 int s; 1429 1430 memset(&ifr, 0, sizeof(ifr)); 1431 strcpy( ifr.ifr_name, iname ); 1432 ifr.ifr_addr = *(struct sockaddr *)sa; 1433 1434 if (( s = socket( AF_APPLETALK, SOCK_DGRAM, 0 )) < 0 ) { 1435 return( 1 ); 1436 } 1437 if ( ioctl( s, cmd, &ifr ) < 0 ) { 1438 close(s); 1439 return( 1 ); 1440 } 1441 close( s ); 1442 if ( cmd == SIOCGIFADDR ) { 1443 *(struct sockaddr *)sa = ifr.ifr_addr; 1444 } 1445 return( 0 ); 1446} 1447 1448void dumpconfig( struct interface *iface) 1449{ 1450 struct list *l; 1451 1452 printf( "%s", iface->i_name ); 1453 if ( iface->i_flags & IFACE_RSEED ) { 1454 printf( " -router" ); 1455 } else if ( iface->i_flags & IFACE_SEED ) { 1456 printf( " -seed" ); 1457 } 1458 1459 if ( iface->i_flags & IFACE_DONTROUTE) 1460 printf( " -dontroute"); 1461 1462 printf( " -phase" ); 1463 if ( iface->i_flags & IFACE_PHASE1 ) { 1464 printf( " 1" ); 1465 } else { 1466 printf( " 2" ); 1467 } 1468 printf( " -net %d", ntohs( iface->i_rt->rt_firstnet )); 1469 if ( iface->i_rt->rt_lastnet != iface->i_rt->rt_firstnet ) { 1470 printf( "-%d", ntohs( iface->i_rt->rt_lastnet )); 1471 } 1472 printf( " -addr %u.%u", ntohs( iface->i_addr.sat_addr.s_net ), 1473 iface->i_addr.sat_addr.s_node ); 1474 printf( " -caddr %u.%u", ntohs( iface->i_caddr.sat_addr.s_net ), 1475 iface->i_caddr.sat_addr.s_node ); 1476 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) { 1477 printf( " -zone %.*s", ((struct ziptab *)l->l_data)->zt_len, 1478 ((struct ziptab *)l->l_data)->zt_name ); 1479 } 1480 printf( "\n" ); 1481} 1482 1483#ifdef DEBUG 1484void dumproutes(void) 1485{ 1486 struct interface *iface; 1487 struct rtmptab *rtmp; 1488 struct list *l; 1489 struct ziptab *zt; 1490 1491 for ( iface = interfaces; iface; iface = iface->i_next ) { 1492 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) { 1493 if ( rtmp->rt_gate == 0 ) { 1494 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) { 1495 printf( "%u-%u", ntohs( rtmp->rt_firstnet ), 1496 ntohs( rtmp->rt_lastnet )); 1497 } else { 1498 printf( "%u", ntohs( rtmp->rt_firstnet )); 1499 } 1500 } else { 1501 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) { 1502 printf( "%u.%u for %u-%u", 1503 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ), 1504 rtmp->rt_gate->g_sat.sat_addr.s_node, 1505 ntohs( rtmp->rt_firstnet ), 1506 ntohs( rtmp->rt_lastnet )); 1507 } else { 1508 printf( "%u.%u for %u", 1509 ntohs( rtmp->rt_gate->g_sat.sat_addr.s_net ), 1510 rtmp->rt_gate->g_sat.sat_addr.s_node, 1511 ntohs( rtmp->rt_firstnet )); 1512 } 1513 } 1514 1515 if ( rtmp->rt_iprev == 0 && rtmp != iface->i_rt ) { 1516 printf( " *" ); 1517 } 1518 1519 for ( l = rtmp->rt_zt; l; l = l->l_next ) { 1520 zt = (struct ziptab *)l->l_data; 1521 printf( " %.*s", zt->zt_len, zt->zt_name ); 1522 } 1523 1524 printf( "\n" ); 1525 } 1526 } 1527 1528 printf( "\n" ); 1529 fflush( stdout ); 1530} 1531 1532void dumpzones(void) 1533{ 1534 struct interface *iface; 1535 struct rtmptab *rtmp; 1536 struct list *l; 1537 struct ziptab *zt; 1538 1539 for ( zt = ziptab; zt; zt = zt->zt_next ) { 1540 printf( "%.*s", zt->zt_len, zt->zt_name ); 1541 for ( l = zt->zt_rt; l; l = l->l_next ) { 1542 rtmp = (struct rtmptab *)l->l_data; 1543 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) { 1544 printf( " %u-%u", ntohs( rtmp->rt_firstnet ), 1545 ntohs( rtmp->rt_lastnet )); 1546 } else { 1547 printf( " %u", ntohs( rtmp->rt_firstnet )); 1548 } 1549 if ( rtmp->rt_iprev == 0 && rtmp->rt_gate != 0 ) { 1550 printf( "*" ); 1551 } 1552 } 1553 printf( "\n" ); 1554 } 1555 1556 printf( "\n" ); 1557 fflush( stdout ); 1558} 1559#endif /* DEBUG */ 1560