1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Rdisc (this program) was developed by Sun Microsystems, Inc. and is 3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * provided for unrestricted use provided that this legend is included on 4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * all tape media and as a part of the software program in whole or part. 5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Users may copy or modify Rdisc without charge, and they may freely 6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * distribute it. 7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * RDISC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Rdisc is provided with no support and without any obligation on the 13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * part of Sun Microsystems, Inc. to assist in its use, correction, 14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * modification or enhancement. 15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 16313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY RDISC 18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OR ANY PART THEREOF. 19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * In no event will Sun Microsystems, Inc. be liable for any lost revenue 21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * or profits or other special, indirect and consequential damages, even if 22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Sun has been advised of the possibility of such damages. 23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Sun Microsystems, Inc. 25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 2550 Garcia Avenue 26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Mountain View, California 94043 27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <stdio.h> 29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <errno.h> 30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <signal.h> 31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <unistd.h> 32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <stdlib.h> 33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/types.h> 34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/time.h> 35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Do not use "improved" glibc version! */ 36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/limits.h> 37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/param.h> 39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/socket.h> 40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/file.h> 41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <malloc.h> 42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/ioctl.h> 44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/if.h> 45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <linux/route.h> 46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netinet/in.h> 48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netinet/ip.h> 49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netinet/ip_icmp.h> 50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * The next include contains all defs and structures for multicast 53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * that are not in SunOS 4.1.x. On a SunOS 4.1.x system none of this code 54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * is ever used because it does not support multicast 55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Fraser Gardiner - Sun Microsystems Australia 56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <netdb.h> 59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <arpa/inet.h> 60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <string.h> 62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <syslog.h> 63313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "SNAPSHOT.h" 65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct interface 67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct in_addr address; /* Used to identify the interface */ 69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct in_addr localaddr; /* Actual address if the interface */ 70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int preference; 71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int flags; 72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct in_addr bcastaddr; 73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct in_addr remoteaddr; 74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct in_addr netmask; 75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int ifindex; 76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char name[IFNAMSIZ]; 77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * TBD 81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Use 255.255.255.255 for broadcasts - not the interface broadcast 82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * address. 83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define ALLIGN(ptr) (ptr) 86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int join(int sock, struct sockaddr_in *sin); 88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void solicitor(struct sockaddr_in *); 89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void advertise(struct sockaddr_in *, int lft); 91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic char *pr_name(struct in_addr addr); 93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void pr_pack(char *buf, int cc, struct sockaddr_in *from); 94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void age_table(int time); 95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void record_router(struct in_addr router, int preference, int ttl); 96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void add_route(struct in_addr addr); 97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void del_route(struct in_addr addr); 98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void rtioctl(struct in_addr addr, int op); 99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int support_multicast(void); 100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sendbcast(int s, char *packet, int packetlen); 101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sendmcast(int s, char *packet, int packetlen, struct sockaddr_in *); 102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sendbcastif(int s, char *packet, int packetlen, struct interface *ifp); 103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int sendmcastif(int s, char *packet, int packetlen, struct sockaddr_in *sin, struct interface *ifp); 104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int is_directly_connected(struct in_addr in); 105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void initlog(void); 106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void discard_table(void); 107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void init(void); 108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define ICMP_ROUTER_ADVERTISEMENT 9 110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define ICMP_ROUTER_SOLICITATION 10 111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define ALL_HOSTS_ADDRESS "224.0.0.1" 113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define ALL_ROUTERS_ADDRESS "224.0.0.2" 114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MAXIFS 32 116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if !defined(__GLIBC__) || __GLIBC__ < 2 118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* For router advertisement */ 119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct icmp_ra 120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_char icmp_type; /* type of message, see below */ 122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_char icmp_code; /* type sub code */ 123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_short icmp_cksum; /* ones complement cksum of struct */ 124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_char icmp_num_addrs; 125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_char icmp_wpa; /* Words per address */ 126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti short icmp_lifetime; 127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct icmp_ra_addr 130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti __u32 ira_addr; 132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti __u32 ira_preference; 133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define icmp_ra icmp 136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Router constants */ 139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MAX_INITIAL_ADVERT_INTERVAL 16 140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MAX_INITIAL_ADVERTISEMENTS 3 141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MAX_RESPONSE_DELAY 2 /* Not used */ 142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Host constants */ 144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MAX_SOLICITATIONS 3 145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define SOLICITATION_INTERVAL 3 146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MAX_SOLICITATION_DELAY 1 /* Not used */ 147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define INELIGIBLE_PREF 0x80000000 /* Maximum negative */ 149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MAX_ADV_INT 600 151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Statics */ 153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int num_interfaces; 154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct interface *interfaces; 156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int interfaces_size; /* Number of elements in interfaces */ 157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define MAXPACKET 4096 /* max packet size */ 160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* fraser */ 162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint debugfile; 163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitticonst char usage[] = 165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti"Usage: rdisc [-b] [-d] [-s] [-v] [-f] [-a] [-V] [send_address] [receive_address]\n" 166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti" rdisc -r [-b] [-d] [-s] [-v] [-f] [-a] [-V] [-p <preference>] [-T <secs>]\n" 168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti" [send_address] [receive_address]\n" 169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti; 171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint s; /* Socket file descriptor */ 174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct sockaddr_in whereto;/* Address to send to */ 175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Common variables */ 177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint verbose = 0; 178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint debug = 0; 179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint trace = 0; 180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint solicit = 0; 181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint ntransmitted = 0; 182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint nreceived = 0; 183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint forever = 0; /* Never give up on host. If 0 defer fork until 184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * first response. 185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Router variables */ 189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint responder; 190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint max_adv_int = MAX_ADV_INT; 191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint min_adv_int; 192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint lifetime; 193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint initial_advert_interval = MAX_INITIAL_ADVERT_INTERVAL; 194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint initial_advertisements = MAX_INITIAL_ADVERTISEMENTS; 195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint preference = 0; /* Setable with -p option */ 196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Host variables */ 199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint max_solicitations = MAX_SOLICITATIONS; 200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiunsigned int solicitation_interval = SOLICITATION_INTERVAL; 201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint best_preference = 1; /* Set to record only the router(s) with the 202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti best preference in the kernel. Not set 203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti puts all routes in the kernel. */ 204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void graceful_finish(void); 207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void finish(void); 208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void timer(void); 209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void initifs(void); 210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic u_short in_cksum(u_short *addr, int len); 211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int logging = 0; 213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define logerr(fmt...) ({ if (logging) syslog(LOG_ERR, fmt); \ 215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else fprintf(stderr, fmt); }) 216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define logtrace(fmt...) ({ if (logging) syslog(LOG_INFO, fmt); \ 217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else fprintf(stderr, fmt); }) 218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define logdebug(fmt...) ({ if (logging) syslog(LOG_DEBUG, fmt); \ 219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else fprintf(stderr, fmt); }) 220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void logperror(char *str); 221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic __inline__ int isbroadcast(struct sockaddr_in *sin) 223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (sin->sin_addr.s_addr == INADDR_BROADCAST); 225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic __inline__ int ismulticast(struct sockaddr_in *sin) 228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return IN_CLASSD(ntohl(sin->sin_addr.s_addr)); 230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic void prusage(void) 233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti fputs(usage, stderr); 235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(1); 236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid do_fork(void) 239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int t; 241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pid_t pid; 242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti long open_max; 243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (trace) 245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((open_max = sysconf(_SC_OPEN_MAX)) == -1) { 247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (errno == 0) { 248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) fprintf(stderr, "OPEN_MAX is not supported\n"); 249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else { 251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) fprintf(stderr, "sysconf() error\n"); 252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(1); 254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((pid=fork()) != 0) 258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(0); 259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (t = 0; t < open_max; t++) 261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (t != s) 262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti close(t); 263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setsid(); 265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti initlog(); 266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid signal_setup(int signo, void (*handler)(void)) 269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sigaction sa; 271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&sa, 0, sizeof(sa)); 273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sa.sa_handler = (void (*)(int))handler; 275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef SA_INTERRUPT 276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sa.sa_flags = SA_INTERRUPT; 277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigaction(signo, &sa, NULL); 279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * M A I N 283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *sendaddress, *recvaddress; 285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint main(int argc, char **argv) 287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_in from; 289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char **av = argv; 290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_in *to = &whereto; 291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_in joinaddr; 292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigset_t sset, sset_empty; 293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int val; 295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti min_adv_int =( max_adv_int * 3 / 4); 297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti lifetime = (3*max_adv_int); 298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti argc--, av++; 301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (argc > 0 && *av[0] == '-') { 302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (*++av[0]) { 303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti switch (*av[0]) { 304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'd': 305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti debug = 1; 306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 't': 308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti trace = 1; 309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'v': 311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti verbose++; 312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 's': 314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti solicit = 1; 315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'r': 318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti responder = 1; 319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'a': 322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti best_preference = 0; 323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'b': 325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti best_preference = 1; 326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'f': 328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti forever = 1; 329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'V': 331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti printf("rdisc utility, iputils-%s\n", SNAPSHOT); 332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(0); 333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'T': 335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti argc--, av++; 336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (argc != 0) { 337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti val = strtol(av[0], (char **)NULL, 0); 338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (val < 4 || val > 1800) { 339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) fprintf(stderr, 340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Bad Max Advertizement Interval\n"); 341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(1); 342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti max_adv_int = val; 344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti min_adv_int =( max_adv_int * 3 / 4); 345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti lifetime = (3*max_adv_int); 346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti prusage(); 348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* NOTREACHED*/ 349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto next; 351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case 'p': 352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti argc--, av++; 353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (argc != 0) { 354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti val = strtol(av[0], (char **)NULL, 0); 355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti preference = val; 356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti prusage(); 358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* NOTREACHED*/ 359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti goto next; 361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti default: 363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti prusage(); 364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* NOTREACHED*/ 365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittinext: 369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti argc--, av++; 371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if( argc < 1) { 373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (support_multicast()) { 374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sendaddress = ALL_ROUTERS_ADDRESS; 375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (responder) 377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sendaddress = ALL_HOSTS_ADDRESS; 378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else 380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sendaddress = "255.255.255.255"; 381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sendaddress = av[0]; 383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti argc--; 384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (argc < 1) { 387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (support_multicast()) { 388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti recvaddress = ALL_HOSTS_ADDRESS; 389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (responder) 391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti recvaddress = ALL_ROUTERS_ADDRESS; 392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else 394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti recvaddress = "255.255.255.255"; 395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti recvaddress = av[0]; 397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti argc--; 398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (argc != 0) { 400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) fprintf(stderr, "Extra parameters\n"); 401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti prusage(); 402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* NOTREACHED */ 403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (solicit && responder) { 407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti prusage(); 408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* NOTREACHED */ 409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(solicit && !forever)) { 413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti do_fork(); 414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Added the next line to stop forking a second time 416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Fraser Gardiner - Sun Microsystems Australia 417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti forever = 1; 419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset( (char *)&whereto, 0, sizeof(struct sockaddr_in) ); 422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti to->sin_family = AF_INET; 423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti to->sin_addr.s_addr = inet_addr(sendaddress); 424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset( (char *)&joinaddr, 0, sizeof(struct sockaddr_in) ); 426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti joinaddr.sin_family = AF_INET; 427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti joinaddr.sin_addr.s_addr = inet_addr(recvaddress); 428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (responder) 431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti srandom((int)gethostid()); 432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { 435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("socket"); 436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(5); 437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setlinebuf( stdout ); 440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti signal_setup(SIGINT, finish ); 442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti signal_setup(SIGTERM, graceful_finish ); 443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti signal_setup(SIGHUP, initifs ); 444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti signal_setup(SIGALRM, timer ); 445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigemptyset(&sset); 447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigemptyset(&sset_empty); 448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigaddset(&sset, SIGALRM); 449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigaddset(&sset, SIGHUP); 450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigaddset(&sset, SIGTERM); 451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigaddset(&sset, SIGINT); 452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti init(); 454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (join(s, &joinaddr) < 0) { 455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("Failed joining addresses\n"); 456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit (2); 457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti timer(); /* start things going */ 460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (;;) { 462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_char packet[MAXPACKET]; 463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int len = sizeof (packet); 464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti socklen_t fromlen = sizeof (from); 465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int cc; 466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc=recvfrom(s, (char *)packet, len, 0, 468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (struct sockaddr *)&from, &fromlen); 469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc<0) { 470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (errno == EINTR) 471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("recvfrom"); 473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigprocmask(SIG_SETMASK, &sset, NULL); 477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_pack( (char *)packet, cc, &from ); 478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sigprocmask(SIG_SETMASK, &sset_empty, NULL); 479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /*NOTREACHED*/ 481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define TIMER_INTERVAL 3 484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#define GETIFCONF_TIMER 30 485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int left_until_advertise; 487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Called every TIMER_INTERVAL */ 489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid timer() 490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static int time; 492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static int left_until_getifconf; 493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static int left_until_solicit; 494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti time += TIMER_INTERVAL; 497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti left_until_getifconf -= TIMER_INTERVAL; 499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti left_until_advertise -= TIMER_INTERVAL; 500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti left_until_solicit -= TIMER_INTERVAL; 501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (left_until_getifconf < 0) { 503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti initifs(); 504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti left_until_getifconf = GETIFCONF_TIMER; 505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (responder && left_until_advertise <= 0) { 508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntransmitted++; 509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti advertise(&whereto, lifetime); 510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ntransmitted < initial_advertisements) 511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti left_until_advertise = initial_advert_interval; 512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti left_until_advertise = min_adv_int + 514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ((max_adv_int - min_adv_int) * 515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (random() % 1000)/1000); 516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else 517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (solicit && left_until_solicit <= 0) { 519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntransmitted++; 520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti solicitor(&whereto); 521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ntransmitted < max_solicitations) 522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti left_until_solicit = solicitation_interval; 523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else { 524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti solicit = 0; 525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!forever && nreceived == 0) 526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(5); 527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti age_table(TIMER_INTERVAL); 530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti alarm(TIMER_INTERVAL); 531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * S O L I C I T O R 535313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 536313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Compose and transmit an ICMP ROUTER SOLICITATION REQUEST packet. 537313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * The IP packet will be added on by the kernel. 538313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 539313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 540313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittisolicitor(struct sockaddr_in *sin) 541313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 542313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static u_char outpack[MAXPACKET]; 543313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct icmphdr *icp = (struct icmphdr *) ALLIGN(outpack); 544313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int packetlen, i; 545313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 546313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) { 547313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("Sending solicitation to %s\n", 548313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(sin->sin_addr)); 549313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 550313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icp->type = ICMP_ROUTER_SOLICITATION; 551313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icp->code = 0; 552313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icp->checksum = 0; 553313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icp->un.gateway = 0; /* Reserved */ 554313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti packetlen = 8; 555313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 556313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Compute ICMP checksum here */ 557313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icp->checksum = in_cksum( (u_short *)icp, packetlen ); 558313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 559313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (isbroadcast(sin)) 560313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti i = sendbcast(s, (char *)outpack, packetlen); 561313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else if (ismulticast(sin)) 562313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti i = sendmcast(s, (char *)outpack, packetlen, sin); 563313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 564313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti i = sendto( s, (char *)outpack, packetlen, 0, 565313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (struct sockaddr *)sin, sizeof(struct sockaddr)); 566313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 567313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if( i < 0 || i != packetlen ) { 568313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if( i<0 ) { 569313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("solicitor:sendto"); 570313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 571313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("wrote %s %d chars, ret=%d\n", 572313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sendaddress, packetlen, i ); 573313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 574313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 575313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 576313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 577313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 578313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * A V E R T I S E 579313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 580313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Compose and transmit an ICMP ROUTER ADVERTISEMENT packet. 581313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * The IP packet will be added on by the kernel. 582313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 583313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 584313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiadvertise(struct sockaddr_in *sin, int lft) 585313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 586313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static u_char outpack[MAXPACKET]; 587313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct icmp_ra *rap = (struct icmp_ra *) ALLIGN(outpack); 588313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct icmp_ra_addr *ap; 589313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int packetlen, i, cc; 590313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 591313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) { 592313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("Sending advertisement to %s\n", 593313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(sin->sin_addr)); 594313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 595313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 596313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < num_interfaces; i++) { 597313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_type = ICMP_ROUTER_ADVERTISEMENT; 598313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_code = 0; 599313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_cksum = 0; 600313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_num_addrs = 0; 601313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_wpa = 2; 602313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_lifetime = htons(lft); 603313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti packetlen = 8; 604313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 605313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* 606313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * TODO handle multiple logical interfaces per 607313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * physical interface. (increment with rap->icmp_wpa * 4 for 608313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * each address.) 609313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 610313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ap = (struct icmp_ra_addr *)ALLIGN(outpack + ICMP_MINLEN); 611313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ap->ira_addr = interfaces[i].localaddr.s_addr; 612313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ap->ira_preference = htonl(interfaces[i].preference); 613313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti packetlen += rap->icmp_wpa * 4; 614313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_num_addrs++; 615313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 616313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Compute ICMP checksum here */ 617313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_cksum = in_cksum( (u_short *)rap, packetlen ); 618313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 619313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (isbroadcast(sin)) 620313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = sendbcastif(s, (char *)outpack, packetlen, 621313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti &interfaces[i]); 622313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else if (ismulticast(sin)) 623313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = sendmcastif( s, (char *)outpack, packetlen, sin, 624313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti &interfaces[i]); 625313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else { 626313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct interface *ifp = &interfaces[i]; 627313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* 628313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Verify that the interface matches the destination 629313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * address. 630313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 631313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((sin->sin_addr.s_addr & ifp->netmask.s_addr) == 632313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (ifp->address.s_addr & ifp->netmask.s_addr)) { 633313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (debug) { 634313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("Unicast to %s ", 635313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(sin->sin_addr)); 636313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("on interface %s, %s\n", 637313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifp->name, 638313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(ifp->address)); 639313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 640313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = sendto( s, (char *)outpack, packetlen, 0, 641313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (struct sockaddr *)sin, 642313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sizeof(struct sockaddr)); 643313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else 644313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = packetlen; 645313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 646313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if( cc < 0 || cc != packetlen ) { 647313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc < 0) { 648313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("sendto"); 649313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 650313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("wrote %s %d chars, ret=%d\n", 651313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sendaddress, packetlen, cc ); 652313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 653313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 654313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 655313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 656313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 657313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 658313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 659313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * P R _ T Y P E 660313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 661313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Convert an ICMP "type" field to a printable string. 662313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 663313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar * 664313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittipr_type(int t) 665313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 666313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static char *ttab[] = { 667313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Echo Reply", 668313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "ICMP 1", 669313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "ICMP 2", 670313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Dest Unreachable", 671313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Source Quench", 672313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Redirect", 673313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "ICMP 6", 674313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "ICMP 7", 675313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Echo", 676313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Router Advertise", 677313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Router Solicitation", 678313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Time Exceeded", 679313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Parameter Problem", 680313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Timestamp", 681313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Timestamp Reply", 682313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Info Request", 683313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Info Reply", 684313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Netmask Request", 685313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti "Netmask Reply" 686313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti }; 687313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 688313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ( t < 0 || t > 16 ) 689313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return("OUT-OF-RANGE"); 690313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 691313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return(ttab[t]); 692313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 693313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 694313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 695313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * P R _ N A M E 696313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 697313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Return a string name for the given IP address. 698313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 699313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar *pr_name(struct in_addr addr) 700313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 701313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct hostent *phe; 702313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti static char buf[80]; 703313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 704313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti phe = gethostbyaddr((char *)&addr.s_addr, 4, AF_INET); 705313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (phe == NULL) 706313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return( inet_ntoa(addr)); 707313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti snprintf(buf, sizeof(buf), "%s (%s)", phe->h_name, inet_ntoa(addr)); 708313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return(buf); 709313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 710313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 711313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 712313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * P R _ P A C K 713313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 714313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Print out the packet, if it came from us. This logic is necessary 715313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * because ALL readers of the ICMP socket get a copy of ALL ICMP packets 716313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * which arrive ('tis only fair). This permits multiple copies of this 717313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * program to be run without having intermingled output (or statistics!). 718313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 719313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 720313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittipr_pack(char *buf, int cc, struct sockaddr_in *from) 721313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 722313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct iphdr *ip; 723313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct icmphdr *icp; 724313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 725313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int hlen; 726313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 727313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ip = (struct iphdr *) ALLIGN(buf); 728313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti hlen = ip->ihl << 2; 729313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc < hlen + 8) { 730313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 731313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("packet too short (%d bytes) from %s\n", cc, 732313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr)); 733313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 734313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 735313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc -= hlen; 736313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icp = (struct icmphdr *)ALLIGN(buf + hlen); 737313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 738313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti switch (icp->type) { 739313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case ICMP_ROUTER_ADVERTISEMENT: 740313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti { 741313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct icmp_ra *rap = (struct icmp_ra *)ALLIGN(icp); 742313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct icmp_ra_addr *ap; 743313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 744313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 745313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (responder) 746313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 747313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 748313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 749313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* TBD verify that the link is multicast or broadcast */ 750313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* XXX Find out the link it came in over? */ 751313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (in_cksum((u_short *)ALLIGN(buf+hlen), cc)) { 752313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 753313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: Bad checksum\n", 754313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)rap->icmp_type), 755313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr)); 756313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 757313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 758313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rap->icmp_code != 0) { 759313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 760313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: Code = %d\n", 761313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)rap->icmp_type), 762313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr), 763313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_code); 764313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 765313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 766313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rap->icmp_num_addrs < 1) { 767313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 768313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: No addresses\n", 769313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)rap->icmp_type), 770313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr)); 771313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 772313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 773313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (rap->icmp_wpa < 2) { 774313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 775313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: Words/addr = %d\n", 776313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)rap->icmp_type), 777313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr), 778313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rap->icmp_wpa); 779313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 780313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 781313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((unsigned)cc < 782313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 8 + rap->icmp_num_addrs * rap->icmp_wpa * 4) { 783313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 784313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: Too short %d, %d\n", 785313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)rap->icmp_type), 786313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr), 787313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc, 788313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 8 + rap->icmp_num_addrs * rap->icmp_wpa * 4); 789313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 790313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 791313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 792313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 793313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s, lifetime %d\n", 794313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)rap->icmp_type), 795313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr), 796313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntohs(rap->icmp_lifetime)); 797313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 798313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Check that at least one router address is a neighboor 799313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * on the arriving link. 800313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 801313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; (unsigned)i < rap->icmp_num_addrs; i++) { 802313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct in_addr ina; 803313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ap = (struct icmp_ra_addr *) 804313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ALLIGN(buf + hlen + 8 + 805313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti i * rap->icmp_wpa * 4); 806313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ina.s_addr = ap->ira_addr; 807313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 808313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("\taddress %s, preference 0x%x\n", 809313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(ina), 810313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (unsigned int)ntohl(ap->ira_preference)); 811313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (is_directly_connected(ina)) 812313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti record_router(ina, 813313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntohl(ap->ira_preference), 814313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntohs(rap->icmp_lifetime)); 815313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 816313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nreceived++; 817313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!forever) { 818313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti do_fork(); 819313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti forever = 1; 820313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 821313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * The next line was added so that the alarm is set for the new procces 822313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Fraser Gardiner Sun Microsystems Australia 823313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 824313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) alarm(TIMER_INTERVAL); 825313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 826313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 827313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 828313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 829313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 830313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti case ICMP_ROUTER_SOLICITATION: 831313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti { 832313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_in sin; 833313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 834313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!responder) 835313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 836313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 837313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* TBD verify that the link is multicast or broadcast */ 838313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* XXX Find out the link it came in over? */ 839313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 840313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (in_cksum((u_short *)ALLIGN(buf+hlen), cc)) { 841313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 842313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: Bad checksum\n", 843313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)icp->type), 844313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr)); 845313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 846313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 847313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (icp->code != 0) { 848313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 849313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: Code = %d\n", 850313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)icp->type), 851313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr), 852313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti icp->code); 853313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 854313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 855313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 856313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc < ICMP_MINLEN) { 857313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 858313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: Too short %d, %d\n", 859313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)icp->type), 860313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr), 861313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc, 862313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ICMP_MINLEN); 863313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 864313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 865313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 866313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 867313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s\n", 868313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)icp->type), 869313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr)); 870313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 871313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Check that ip_src is either a neighboor 872313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * on the arriving link or 0. 873313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 874313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin.sin_family = AF_INET; 875313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ip->saddr == 0) { 876313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* If it was sent to the broadcast address we respond 877313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * to the broadcast address. 878313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 879313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (IN_CLASSD(ntohl(ip->daddr))) 880313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin.sin_addr.s_addr = htonl(0xe0000001); 881313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 882313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin.sin_addr.s_addr = INADDR_BROADCAST; 883313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Restart the timer when we broadcast */ 884313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti left_until_advertise = min_adv_int + 885313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ((max_adv_int - min_adv_int) 886313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * (random() % 1000)/1000); 887313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 888313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin.sin_addr.s_addr = ip->saddr; 889313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!is_directly_connected(sin.sin_addr)) { 890313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (verbose) 891313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("ICMP %s from %s: source not directly connected\n", 892313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_type((int)icp->type), 893313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(from->sin_addr)); 894313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 895313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 896313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 897313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nreceived++; 898313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntransmitted++; 899313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti advertise(&sin, lifetime); 900313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 901313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 902313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 903313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 904313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 905313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 906313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 907313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 908313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * I N _ C K S U M 909313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 910313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Checksum routine for Internet Protocol family headers (C Version) 911313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 912313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 913313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if BYTE_ORDER == LITTLE_ENDIAN 914313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define ODDBYTE(v) (v) 915313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#elif BYTE_ORDER == BIG_ENDIAN 916313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define ODDBYTE(v) ((u_short)(v) << 8) 917313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 918313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define ODDBYTE(v) htons((u_short)(v) << 8) 919313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 920313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 921313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiu_short in_cksum(u_short *addr, int len) 922313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 923313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti register int nleft = len; 924313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti register u_short *w = addr; 925313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti register u_short answer; 926313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti register int sum = 0; 927313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 928313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* 929313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Our algorithm is simple, using a 32 bit accumulator (sum), 930313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * we add sequential 16 bit words to it, and at the end, fold 931313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * back all the carry bits from the top 16 bits into the lower 932313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 16 bits. 933313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 934313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while( nleft > 1 ) { 935313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sum += *w++; 936313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti nleft -= 2; 937313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 938313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 939313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* mop up an odd byte, if necessary */ 940313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if( nleft == 1 ) 941313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sum += ODDBYTE(*(u_char *)w); /* le16toh() may be unavailable on old systems */ 942313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 943313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* 944313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * add back carry outs from top 16 bits to low 16 bits 945313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 946313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 947313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sum += (sum >> 16); /* add carry */ 948313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti answer = ~sum; /* truncate to 16 bits */ 949313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (answer); 950313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 951313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 952313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 953313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * F I N I S H 954313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 955313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Print out statistics, and give up. 956313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Heavily buffered STDIO is used here, so that all the statistics 957313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * will be written with 1 sys-write call. This is nice when more 958313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * than one copy of the program is running on a terminal; it prevents 959313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * the statistics output from becomming intermingled. 960313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 961313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 962313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittifinish() 963313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 964313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 965313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (responder) { 966313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Send out a packet with a preference so that all 967313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * hosts will know that we are dead. 968313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 969313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Wrong comment, wrong code. 970313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ttl must be set to 0 instead. --ANK 971313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 972313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("terminated\n"); 973313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ntransmitted++; 974313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti advertise(&whereto, 0); 975313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 976313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 977313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("\n----%s rdisc Statistics----\n", sendaddress ); 978313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("%d packets transmitted, ", ntransmitted ); 979313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("%d packets received, ", nreceived ); 980313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logtrace("\n"); 981313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) fflush(stdout); 982313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(0); 983313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 984313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 985313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 986313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittigraceful_finish() 987313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 988313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti discard_table(); 989313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti finish(); 990313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti exit(0); 991313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 992313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 993313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 994313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* From libc/rpc/pmap_rmt.c */ 995313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 996313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint 997313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittisendbcast(int s, char *packet, int packetlen) 998313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 999313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i, cc; 1000313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1001313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < num_interfaces; i++) { 1002313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((interfaces[i].flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0) 1003313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1004313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = sendbcastif(s, packet, packetlen, &interfaces[i]); 1005313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc!= packetlen) { 1006313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (cc); 1007313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1008313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1009313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (packetlen); 1010313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1011313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1012313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint 1013313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittisendbcastif(int s, char *packet, int packetlen, struct interface *ifp) 1014313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1015313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int on; 1016313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int cc; 1017313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_in baddr; 1018313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1019313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti baddr.sin_family = AF_INET; 1020313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti baddr.sin_addr = ifp->bcastaddr; 1021313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (debug) 1022313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("Broadcast to %s\n", 1023313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(baddr.sin_addr)); 1024313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti on = 1; 1025313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on)); 1026313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = sendto(s, packet, packetlen, 0, 1027313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (struct sockaddr *)&baddr, sizeof (struct sockaddr)); 1028313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc!= packetlen) { 1029313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("sendbcast: sendto"); 1030313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("Cannot send broadcast packet to %s\n", 1031313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(baddr.sin_addr)); 1032313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1033313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti on = 0; 1034313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on)); 1035313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (cc); 1036313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1037313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1038313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint 1039313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittisendmcast(int s, char *packet, int packetlen, struct sockaddr_in *sin) 1040313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1041313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i, cc; 1042313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1043313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < num_interfaces; i++) { 1044313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((interfaces[i].flags & (IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST)) == 0) 1045313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1046313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = sendmcastif(s, packet, packetlen, sin, &interfaces[i]); 1047313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc!= packetlen) { 1048313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (cc); 1049313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1050313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1051313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (packetlen); 1052313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1053313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1054313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint 1055313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittisendmcastif(int s, char *packet, int packetlen, struct sockaddr_in *sin, 1056313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct interface *ifp) 1057313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1058313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int cc; 1059313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ip_mreqn mreq; 1060313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1061313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(&mreq, 0, sizeof(mreq)); 1062313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti mreq.imr_ifindex = ifp->ifindex; 1063313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti mreq.imr_address = ifp->localaddr; 1064313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (debug) 1065313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("Multicast to interface %s, %s\n", 1066313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifp->name, 1067313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(mreq.imr_address)); 1068313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, 1069313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (char *)&mreq, 1070313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sizeof(mreq)) < 0) { 1071313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("setsockopt (IP_MULTICAST_IF)"); 1072313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("Cannot send multicast packet over interface %s, %s\n", 1073313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifp->name, 1074313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(mreq.imr_address)); 1075313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (-1); 1076313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1077313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti cc = sendto(s, packet, packetlen, 0, 1078313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (struct sockaddr *)sin, sizeof (struct sockaddr)); 1079313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (cc!= packetlen) { 1080313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("sendmcast: sendto"); 1081313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("Cannot send multicast packet over interface %s, %s\n", 1082313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifp->name, pr_name(mreq.imr_address)); 1083313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1084313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (cc); 1085313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1086313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1087313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 1088313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiinit() 1089313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1090313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti initifs(); 1091313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef RDISC_SERVER 1092313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti { 1093313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 1094313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < interfaces_size; i++) 1095313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].preference = preference; 1096313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1097313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 1098313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1099313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 1101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiinitifs() 1102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int sock; 1104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ifconf ifc; 1105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ifreq ifreq, *ifr; 1106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_in *sin; 1107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int n, i; 1108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti char *buf; 1109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int numifs; 1110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti unsigned bufsize; 1111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sock = socket(AF_INET, SOCK_DGRAM, 0); 1113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sock < 0) { 1114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("initifs: socket"); 1115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 1116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef SIOCGIFNUM 1118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) { 1119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti numifs = MAXIFS; 1120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else 1122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti numifs = MAXIFS; 1123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 1124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti bufsize = numifs * sizeof(struct ifreq); 1125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti buf = (char *)malloc(bufsize); 1126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (buf == NULL) { 1127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("out of memory\n"); 1128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) close(sock); 1129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 1130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (interfaces != NULL) 1132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) free(interfaces); 1133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces = (struct interface *)ALLIGN(malloc(numifs * 1134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sizeof(struct interface))); 1135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (interfaces == NULL) { 1136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("out of memory\n"); 1137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) close(sock); 1138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) free(buf); 1139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 1140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces_size = numifs; 1142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifc.ifc_len = bufsize; 1144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifc.ifc_buf = buf; 1145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { 1146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("initifs: ioctl (get interface configuration)"); 1147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) close(sock); 1148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) free(buf); 1149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 1150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifr = ifc.ifc_req; 1152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) { 1153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ifreq = *ifr; 1154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (strlen(ifreq.ifr_name) >= IFNAMSIZ) 1155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) { 1157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("initifs: ioctl (get interface flags)"); 1158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifr->ifr_addr.sa_family != AF_INET) 1161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((ifreq.ifr_flags & IFF_UP) == 0) 1163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifreq.ifr_flags & IFF_LOOPBACK) 1165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((ifreq.ifr_flags & (IFF_MULTICAST|IFF_BROADCAST|IFF_POINTOPOINT)) == 0) 1167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti strncpy(interfaces[i].name, ifr->ifr_name, IFNAMSIZ-1); 1169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin = (struct sockaddr_in *)ALLIGN(&ifr->ifr_addr); 1171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].localaddr = sin->sin_addr; 1172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].flags = ifreq.ifr_flags; 1173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].netmask.s_addr = (__u32)0xffffffff; 1174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(sock, SIOCGIFINDEX, (char *)&ifreq) < 0) { 1175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("initifs: ioctl (get ifindex)"); 1176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].ifindex = ifreq.ifr_ifindex; 1179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifreq.ifr_flags & IFF_POINTOPOINT) { 1180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(sock, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { 1181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("initifs: ioctl (get destination addr)"); 1182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin = (struct sockaddr_in *)ALLIGN(&ifreq.ifr_addr); 1185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* A pt-pt link is identified by the remote address */ 1186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].address = sin->sin_addr; 1187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].remoteaddr = sin->sin_addr; 1188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Simulate broadcast for pt-pt */ 1189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].bcastaddr = sin->sin_addr; 1190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].flags |= IFF_BROADCAST; 1191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 1192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Non pt-pt links are identified by the local address */ 1193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].address = interfaces[i].localaddr; 1194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].remoteaddr = interfaces[i].address; 1195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) { 1196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("initifs: ioctl (get netmask)"); 1197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin = (struct sockaddr_in *)ALLIGN(&ifreq.ifr_addr); 1200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].netmask = sin->sin_addr; 1201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ifreq.ifr_flags & IFF_BROADCAST) { 1202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { 1203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("initifs: ioctl (get broadcast address)"); 1204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin = (struct sockaddr_in *)ALLIGN(&ifreq.ifr_addr); 1207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].bcastaddr = sin->sin_addr; 1208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef notdef 1211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (debug) 1212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("Found interface %s, flags 0x%x\n", 1213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(interfaces[i].localaddr), 1214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti interfaces[i].flags); 1215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 1216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti i++; 1217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti num_interfaces = i; 1219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef notdef 1220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (debug) 1221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("Found %d interfaces\n", num_interfaces); 1222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif 1223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) close(sock); 1224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) free(buf); 1225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint 1228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittijoin(int sock, struct sockaddr_in *sin) 1229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i, j; 1231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct ip_mreqn mreq; 1232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int joined[num_interfaces]; 1233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset(joined, 0, sizeof(joined)); 1235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (isbroadcast(sin)) 1237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (0); 1238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti mreq.imr_multiaddr = sin->sin_addr; 1240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < num_interfaces; i++) { 1241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (j = 0; j < i; j++) { 1242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (joined[j] == interfaces[i].ifindex) 1243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti break; 1244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (j != i) 1246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti continue; 1247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti mreq.imr_ifindex = interfaces[i].ifindex; 1249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti mreq.imr_address.s_addr = 0; 1250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, 1252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (char *)&mreq, sizeof(mreq)) < 0) { 1253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("setsockopt (IP_ADD_MEMBERSHIP)"); 1254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (-1); 1255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti joined[i] = interfaces[i].ifindex; 1258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (0); 1260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint support_multicast() 1263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int sock; 1265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti u_char ttl = 1; 1266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 1268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sock < 0) { 1269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("support_multicast: socket"); 1270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (0); 1271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, 1274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (char *)&ttl, sizeof(ttl)) < 0) { 1275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) close(sock); 1276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (0); 1277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) close(sock); 1279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (1); 1280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint 1283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiis_directly_connected(struct in_addr in) 1284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int i; 1286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti for (i = 0; i < num_interfaces; i++) { 1288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Check that the subnetwork numbers match */ 1289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if ((in.s_addr & interfaces[i].netmask.s_addr ) == 1291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (interfaces[i].remoteaddr.s_addr & interfaces[i].netmask.s_addr)) 1292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (1); 1293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (0); 1295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 1298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * TABLES 1299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 1300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct table { 1301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct in_addr router; 1302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int preference; 1303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int remaining_time; 1304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int in_kernel; 1305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct table *next; 1306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}; 1307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct table *table; 1309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistruct table * 1311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittifind_router(struct in_addr addr) 1312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct table *tp; 1314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = table; 1316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (tp) { 1317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->router.s_addr == addr.s_addr) 1318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (tp); 1319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = tp->next; 1320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (NULL); 1322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint max_preference(void) 1325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct table *tp; 1327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int max = (int)INELIGIBLE_PREF; 1328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = table; 1330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (tp) { 1331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->preference > max) 1332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti max = tp->preference; 1333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = tp->next; 1334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return (max); 1336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Note: this might leave the kernel with no default route for a short time. */ 1340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 1341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiage_table(int time) 1342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct table **tpp, *tp; 1344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int recalculate_max = 0; 1345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int max = max_preference(); 1346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tpp = &table; 1348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (*tpp != NULL) { 1349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = *tpp; 1350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->remaining_time -= time; 1351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->remaining_time <= 0) { 1352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *tpp = tp->next; 1353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->in_kernel) 1354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti del_route(tp->router); 1355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (best_preference && 1356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->preference == max) 1357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti recalculate_max++; 1358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free((char *)tp); 1359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 1360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tpp = &tp->next; 1361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (recalculate_max) { 1364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int max = max_preference(); 1365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (max != INELIGIBLE_PREF) { 1367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = table; 1368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (tp) { 1369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->preference == max && !tp->in_kernel) { 1370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti add_route(tp->router); 1371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->in_kernel++; 1372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = tp->next; 1374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid discard_table(void) 1380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct table **tpp, *tp; 1382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tpp = &table; 1384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (*tpp != NULL) { 1385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = *tpp; 1386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *tpp = tp->next; 1387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->in_kernel) 1388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti del_route(tp->router); 1389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti free((char *)tp); 1390313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1391313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1392313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1393313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1394313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 1395313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittirecord_router(struct in_addr router, int preference, int ttl) 1396313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1397313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct table *tp; 1398313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int old_max = max_preference(); 1399313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int changed_up = 0; /* max preference could have increased */ 1400313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int changed_down = 0; /* max preference could have decreased */ 1401313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1402313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ttl < 4) 1403313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti preference = INELIGIBLE_PREF; 1404313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1405313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (debug) 1406313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("Recording %s, ttl %d, preference 0x%x\n", 1407313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti pr_name(router), 1408313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti ttl, 1409313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti preference); 1410313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = find_router(router); 1411313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp) { 1412313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->preference > preference && 1413313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->preference == old_max) 1414313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti changed_down++; 1415313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else if (preference > tp->preference) 1416313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti changed_up++; 1417313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->preference = preference; 1418313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->remaining_time = ttl; 1419313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } else { 1420313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (preference > old_max) 1421313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti changed_up++; 1422313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = (struct table *)ALLIGN(malloc(sizeof(struct table))); 1423313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp == NULL) { 1424313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logerr("Out of memory\n"); 1425313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 1426313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1427313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->router = router; 1428313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->preference = preference; 1429313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->remaining_time = ttl; 1430313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->in_kernel = 0; 1431313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->next = table; 1432313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti table = tp; 1433313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1434313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!tp->in_kernel && 1435313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (!best_preference || tp->preference == max_preference()) && 1436313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->preference != INELIGIBLE_PREF) { 1437313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti add_route(tp->router); 1438313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->in_kernel++; 1439313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1440313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->preference == INELIGIBLE_PREF && tp->in_kernel) { 1441313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti del_route(tp->router); 1442313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->in_kernel = 0; 1443313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1444313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (best_preference && changed_down) { 1445313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Check if we should add routes */ 1446313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int new_max = max_preference(); 1447313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (new_max != INELIGIBLE_PREF) { 1448313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = table; 1449313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (tp) { 1450313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->preference == new_max && 1451313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti !tp->in_kernel) { 1452313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti add_route(tp->router); 1453313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->in_kernel++; 1454313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1455313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = tp->next; 1456313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1457313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1458313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1459313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (best_preference && (changed_up || changed_down)) { 1460313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti /* Check if we should remove routes already in the kernel */ 1461313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int new_max = max_preference(); 1462313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = table; 1463313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti while (tp) { 1464313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (tp->preference < new_max && tp->in_kernel) { 1465313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti del_route(tp->router); 1466313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp->in_kernel = 0; 1467313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1468313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti tp = tp->next; 1469313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1470313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1471313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1472313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1473313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 1474313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiadd_route(struct in_addr addr) 1475313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1476313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (debug) 1477313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("Add default route to %s\n", pr_name(addr)); 1478313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rtioctl(addr, SIOCADDRT); 1479313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1480313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1481313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 1482313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittidel_route(struct in_addr addr) 1483313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1484313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (debug) 1485313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logdebug("Delete default route to %s\n", pr_name(addr)); 1486313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rtioctl(addr, SIOCDELRT); 1487313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1488313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1489313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 1490313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittirtioctl(struct in_addr addr, int op) 1491313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1492313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti int sock; 1493313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct rtentry rt; 1494313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti struct sockaddr_in *sin; 1495313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1496313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti memset((char *)&rt, 0, sizeof(struct rtentry)); 1497313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rt.rt_dst.sa_family = AF_INET; 1498313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rt.rt_gateway.sa_family = AF_INET; 1499313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rt.rt_genmask.sa_family = AF_INET; 1500313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin = (struct sockaddr_in *)ALLIGN(&rt.rt_gateway); 1501313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sin->sin_addr = addr; 1502313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti rt.rt_flags = RTF_UP | RTF_GATEWAY; 1503313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1504313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 1505313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (sock < 0) { 1506313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("rtioctl: socket"); 1507313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti return; 1508313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1509313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (ioctl(sock, op, (char *)&rt) < 0) { 1510313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (!(op == SIOCADDRT && errno == EEXIST)) 1511313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logperror("ioctl (add/delete route)"); 1512313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti } 1513313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) close(sock); 1514313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1515313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1516313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* 1517313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * LOGGER 1518313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */ 1519313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1520313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid initlog(void) 1521313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1522313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti logging++; 1523313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti openlog("in.rdiscd", LOG_PID | LOG_CONS, LOG_DAEMON); 1524313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1525313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1526313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti 1527313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid 1528313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittilogperror(char *str) 1529313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{ 1530313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti if (logging) 1531313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti syslog(LOG_ERR, "%s: %m", str); 1532313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti else 1533313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti (void) fprintf(stderr, "%s: %s\n", str, strerror(errno)); 1534313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti} 1535