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