121996Sdist /* 234566Skarels * Copyright (c) 1983, 1988 Regents of the University of California. 333489Sbostic * All rights reserved. 433489Sbostic * 533489Sbostic * Redistribution and use in source and binary forms are permitted 634771Sbostic * provided that the above copyright notice and this paragraph are 734771Sbostic * duplicated in all such forms and that any documentation, 834771Sbostic * advertising materials, and other materials related to such 934771Sbostic * distribution and use acknowledge that the software was developed 1034771Sbostic * by the University of California, Berkeley. The name of the 1134771Sbostic * University may not be used to endorse or promote products derived 1234771Sbostic * from this software without specific prior written permission. 1334771Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434771Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534771Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621996Sdist */ 1721996Sdist 189017Ssam #ifndef lint 1921996Sdist char copyright[] = 2034566Skarels "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ 2121996Sdist All rights reserved.\n"; 2233489Sbostic #endif /* not lint */ 239017Ssam 2421996Sdist #ifndef lint 25*34845Skarels static char sccsid[] = "@(#)main.c 5.15 (Berkeley) 06/27/88"; 2633489Sbostic #endif /* not lint */ 2721996Sdist 289017Ssam /* 299017Ssam * Routing Table Management Daemon 309017Ssam */ 3110245Ssam #include "defs.h" 329017Ssam #include <sys/ioctl.h> 3313602Ssam #include <sys/time.h> 3413602Ssam 359017Ssam #include <net/if.h> 3613602Ssam 3734566Skarels #include <sys/errno.h> 3834566Skarels #include <sys/signal.h> 3934566Skarels #include <sys/syslog.h> 409017Ssam 419017Ssam int supplier = -1; /* process should supply updates */ 4221847Skarels int gateway = 0; /* 1 if we are a gateway to parts beyond */ 4331220Skarels int debug = 0; 449017Ssam 459017Ssam struct rip *msg = (struct rip *)packet; 4634566Skarels int hup(), rtdeleteall(), sigtrace(); 479017Ssam 489017Ssam main(argc, argv) 499017Ssam int argc; 509017Ssam char *argv[]; 519017Ssam { 529017Ssam int cc; 539017Ssam struct sockaddr from; 5410245Ssam u_char retry; 559017Ssam 569017Ssam argv0 = argv; 57*34845Skarels #if BSD >= 43 5824848Seric openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); 5930930Skarels setlogmask(LOG_UPTO(LOG_WARNING)); 60*34845Skarels #else 61*34845Skarels openlog("routed", LOG_PID); 62*34845Skarels #define LOG_UPTO(x) (x) 63*34845Skarels #define setlogmask(x) (x) 64*34845Skarels #endif 659017Ssam sp = getservbyname("router", "udp"); 6610245Ssam if (sp == NULL) { 6710245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 689017Ssam exit(1); 699017Ssam } 7010245Ssam addr.sin_family = AF_INET; 7110245Ssam addr.sin_port = sp->s_port; 7210245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 7310245Ssam if (s < 0) 7410245Ssam exit(1); 759017Ssam argv++, argc--; 769017Ssam while (argc > 0 && **argv == '-') { 7710636Ssam if (strcmp(*argv, "-s") == 0) { 789017Ssam supplier = 1; 799017Ssam argv++, argc--; 809017Ssam continue; 819017Ssam } 8210636Ssam if (strcmp(*argv, "-q") == 0) { 839017Ssam supplier = 0; 849017Ssam argv++, argc--; 859017Ssam continue; 869017Ssam } 8710636Ssam if (strcmp(*argv, "-t") == 0) { 8834566Skarels if (tracehistory == 0) 8934566Skarels tracehistory++; 9034566Skarels else { 9134566Skarels tracehistory = 0; 9234566Skarels tracepackets++; 9334566Skarels } 9430930Skarels setlogmask(LOG_UPTO(LOG_DEBUG)); 9510636Ssam argv++, argc--; 9610636Ssam continue; 9710636Ssam } 9826341Skarels if (strcmp(*argv, "-d") == 0) { 9931220Skarels debug++; 10030930Skarels setlogmask(LOG_UPTO(LOG_DEBUG)); 10126341Skarels argv++, argc--; 10226341Skarels continue; 10326341Skarels } 10416326Skarels if (strcmp(*argv, "-g") == 0) { 10516326Skarels gateway = 1; 10616326Skarels argv++, argc--; 10716326Skarels continue; 10816326Skarels } 10916326Skarels fprintf(stderr, 11021847Skarels "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); 1119017Ssam exit(1); 1129017Ssam } 11331220Skarels if (tracepackets == 0 && debug == 0) { 11410636Ssam int t; 11510636Ssam 11610636Ssam if (fork()) 11710636Ssam exit(0); 11810637Ssam for (t = 0; t < 20; t++) 11910637Ssam if (t != s) 12024761Ssklower (void) close(t); 12110636Ssam (void) open("/", 0); 12210636Ssam (void) dup2(0, 1); 12310636Ssam (void) dup2(0, 2); 12410636Ssam t = open("/dev/tty", 2); 12510636Ssam if (t >= 0) { 12610636Ssam ioctl(t, TIOCNOTTY, (char *)0); 12710636Ssam (void) close(t); 12810636Ssam } 12910636Ssam } 1309017Ssam /* 13110245Ssam * Any extra argument is considered 13210245Ssam * a tracing log file. 13310245Ssam */ 13410245Ssam if (argc > 0) 13510245Ssam traceon(*argv); 13610245Ssam /* 1379017Ssam * Collect an initial view of the world by 13821847Skarels * checking the interface configuration and the gateway kludge 1399017Ssam * file. Then, send a request packet on all 1409017Ssam * directly connected networks to find out what 1419017Ssam * everyone else thinks. 1429017Ssam */ 1439017Ssam rtinit(); 14430927Skarels ifinit(); 1459017Ssam gwkludge(); 14621847Skarels if (gateway > 0) 14721847Skarels rtdefault(); 1489017Ssam if (supplier < 0) 1499017Ssam supplier = 0; 1509017Ssam msg->rip_cmd = RIPCMD_REQUEST; 15112726Ssam msg->rip_vers = RIPVERSION; 1529017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1539017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 15412726Ssam msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 15512726Ssam msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 1569017Ssam toall(sendmsg); 15713036Ssam signal(SIGALRM, timer); 15816314Skarels signal(SIGHUP, hup); 15917570Skarels signal(SIGTERM, hup); 16031220Skarels signal(SIGINT, rtdeleteall); 16134566Skarels signal(SIGUSR1, sigtrace); 16234566Skarels signal(SIGUSR2, sigtrace); 1639017Ssam timer(); 1649017Ssam 1659017Ssam for (;;) { 1669017Ssam int ibits; 1679017Ssam register int n; 1689017Ssam 16910245Ssam ibits = 1 << s; 17010245Ssam n = select(20, &ibits, 0, 0, 0); 1719017Ssam if (n < 0) 1729017Ssam continue; 1739017Ssam if (ibits & (1 << s)) 1749017Ssam process(s); 17510245Ssam /* handle ICMP redirects */ 1769017Ssam } 1779017Ssam } 1789017Ssam 1799017Ssam process(fd) 1809017Ssam int fd; 1819017Ssam { 1829017Ssam struct sockaddr from; 18313036Ssam int fromlen = sizeof (from), cc, omask; 18434566Skarels time_t now; 1859017Ssam 18610245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1879017Ssam if (cc <= 0) { 1889017Ssam if (cc < 0 && errno != EINTR) 18910245Ssam perror("recvfrom"); 1909017Ssam return; 1919017Ssam } 19210245Ssam if (fromlen != sizeof (struct sockaddr_in)) 19310245Ssam return; 19434566Skarels if (traceactions && !tracepackets) { 19534566Skarels (void) time(&now); 19634566Skarels curtime = ctime(&now); 19734566Skarels } 19824761Ssklower omask = sigblock(sigmask(SIGALRM)); 1999017Ssam rip_input(&from, cc); 20013036Ssam sigsetmask(omask); 2019017Ssam } 20210245Ssam 20310245Ssam getsocket(domain, type, sin) 20410245Ssam int domain, type; 20510245Ssam struct sockaddr_in *sin; 20610245Ssam { 20725516Skarels int s, on = 1; 20810245Ssam 20925702Smckusick if ((s = socket(domain, type, 0)) < 0) { 21010245Ssam perror("socket"); 21117570Skarels syslog(LOG_ERR, "socket: %m"); 21210245Ssam return (-1); 21317570Skarels } 214*34845Skarels #ifdef SO_BROADCAST 21517570Skarels if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 21617570Skarels syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 21725516Skarels close(s); 21825516Skarels return (-1); 21917570Skarels } 220*34845Skarels #endif 221*34845Skarels #ifdef SO_RCVBUF 22230927Skarels on = 48*1024; 22330927Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) < 0) 22430927Skarels syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m"); 225*34845Skarels #endif 22625516Skarels if (bind(s, sin, sizeof (*sin), 0) < 0) { 22710245Ssam perror("bind"); 22817570Skarels syslog(LOG_ERR, "bind: %m"); 22925516Skarels close(s); 23010245Ssam return (-1); 23117570Skarels } 23210245Ssam return (s); 23310245Ssam } 234