Lines 29-34
Link Here
|
29 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
30 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
31 |
* SUCH DAMAGE. |
31 |
* SUCH DAMAGE. |
|
|
32 |
|
33 |
* Modified by Philippe Troin <phil@fifi.org> (added options & implemented |
34 |
* them. |
35 |
|
32 |
*/ |
36 |
*/ |
33 |
|
37 |
|
34 |
char copyright[] = |
38 |
char copyright[] = |
Lines 47-52
Link Here
|
47 |
#include <signal.h> |
51 |
#include <signal.h> |
48 |
#include <sys/ioctl.h> |
52 |
#include <sys/ioctl.h> |
49 |
#include <sys/file.h> |
53 |
#include <sys/file.h> |
|
|
54 |
#include <sys/types.h> |
50 |
|
55 |
|
51 |
#include <net/if.h> |
56 |
#include <net/if.h> |
52 |
#include <netinet/in.h> |
57 |
#include <netinet/in.h> |
Lines 71-80
Link Here
|
71 |
#include <grp.h> |
76 |
#include <grp.h> |
72 |
#include <time.h> |
77 |
#include <time.h> |
73 |
|
78 |
|
74 |
#include "daemon.h" |
|
|
75 |
|
76 |
#include "../version.h" |
79 |
#include "../version.h" |
77 |
|
80 |
|
|
|
81 |
typedef struct sockaddr_in SA; |
82 |
|
78 |
#define ENDIAN LITTLE_ENDIAN |
83 |
#define ENDIAN LITTLE_ENDIAN |
79 |
|
84 |
|
80 |
/* |
85 |
/* |
Lines 98-124
Link Here
|
98 |
static int verify(const char *name); |
103 |
static int verify(const char *name); |
99 |
int getloadavg(double ptr[3], int n); |
104 |
int getloadavg(double ptr[3], int n); |
100 |
|
105 |
|
|
|
106 |
|
107 |
/* This is the list of interface we want to listen on */ |
108 |
struct wanted_neigh { |
109 |
struct wanted_neigh *w_next; |
110 |
char *w_ifname; |
111 |
enum { W_USED_NOT, W_USED_ONCE, W_USED_MULTI } w_used; |
112 |
}; |
113 |
|
101 |
/* |
114 |
/* |
102 |
* We communicate with each neighbor in |
115 |
* We communicate with each neighbor in |
103 |
* a list constructed at the time we're |
116 |
* a list constructed at the time we're |
104 |
* started up. Neighbors are currently |
117 |
* started up. Neighbors are currently |
105 |
* directly connected via a hardware interface. |
118 |
* directly connected via a hardware interface. |
106 |
*/ |
119 |
*/ |
107 |
struct neighbor { |
120 |
struct neighbor { |
108 |
struct neighbor *n_next; |
121 |
struct neighbor *n_next; |
109 |
char *n_name; /* interface name */ |
122 |
char *n_name; /* interface name */ |
110 |
char *n_addr; /* who to send to */ |
123 |
SA *n_myaddr; /* My address on this i/f */ |
|
|
124 |
SA *n_mask; /* Netmask on this i/f */ |
125 |
SA *n_dstaddr; /* who to send to */ |
111 |
int n_addrlen; /* size of address */ |
126 |
int n_addrlen; /* size of address */ |
112 |
int n_flags; /* should forward?, interface flags */ |
127 |
int n_flags; /* should forward?, interface flags */ |
113 |
}; |
128 |
}; |
114 |
|
129 |
|
|
|
130 |
static struct wanted_neigh *wanted_neigh; |
115 |
static struct neighbor *neighbors; |
131 |
static struct neighbor *neighbors; |
116 |
static struct servent *sp; |
132 |
static struct servent *sp; |
117 |
static int sk; |
133 |
static int sk; |
118 |
static int use_pointopoint = 0; |
134 |
static int use_pointopoint; |
119 |
static int use_broadcast = 0; |
135 |
static int use_broadcast; |
120 |
static int need_init = 1; |
136 |
static int need_init = 1; |
121 |
static int child_pid = 0; |
137 |
static int child_pid; |
|
|
138 |
static int use_forwarding; |
139 |
static int forwarded_packets; |
140 |
|
141 |
/* Max number of packets to forward between each alarm() tick. |
142 |
If this number is exceeded, then the forwarding is switched off. */ |
143 |
#define MAX_FWD_PACKETS (AL_INTERVAL) |
122 |
|
144 |
|
123 |
#define WHDRSIZE (((caddr_t) &((struct whod *) 0)->wd_we) \ |
145 |
#define WHDRSIZE (((caddr_t) &((struct whod *) 0)->wd_we) \ |
124 |
- ((caddr_t) 0)) |
146 |
- ((caddr_t) 0)) |
Lines 127-150
Link Here
|
127 |
static void termhandler(int); |
149 |
static void termhandler(int); |
128 |
static void sendpacket(struct whod *); |
150 |
static void sendpacket(struct whod *); |
129 |
static void getboottime(struct whod *); |
151 |
static void getboottime(struct whod *); |
|
|
152 |
static void forward(const SA *, const struct whod *, int cc); |
153 |
static void usage(void); |
130 |
|
154 |
|
131 |
int |
155 |
int |
132 |
main(int argc, char *argv[]) |
156 |
main(int argc, char *argv[]) |
133 |
{ |
157 |
{ |
|
|
158 |
struct wanted_neigh *wn; |
159 |
int wn_dup; |
134 |
struct sockaddr_in from; |
160 |
struct sockaddr_in from; |
135 |
struct passwd *pw = 0; |
161 |
struct passwd *pw; |
136 |
struct stat st; |
162 |
struct stat st; |
137 |
char path[64]; |
163 |
char path[64]; |
138 |
char *user = NULL; |
164 |
char *user = NULL; |
139 |
int on = 1; |
165 |
int on = 1; |
140 |
int opt; |
166 |
int opt; |
|
|
167 |
time_t before; |
141 |
|
168 |
|
142 |
if (getuid()) { |
169 |
if (getuid()) { |
143 |
fprintf(stderr, "rwhod: not super user\n"); |
170 |
fprintf(stderr, "rwhod: not super user\n"); |
|
|
171 |
} |
172 |
openlog("rwhod", LOG_PID, LOG_DAEMON); |
173 |
sp = getservbyname("who", "udp"); |
174 |
if (sp == 0) { |
175 |
fprintf(stderr, "rwhod: udp/who: unknown service\n"); |
176 |
exit(1); |
177 |
} |
178 |
if ((sk = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
179 |
syslog(LOG_ERR, "socket: %m"); |
180 |
exit(1); |
181 |
} |
182 |
if (setsockopt(sk, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { |
183 |
syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); |
184 |
exit(1); |
185 |
} |
186 |
sine.sin_family = AF_INET; |
187 |
sine.sin_port = sp->s_port; |
188 |
if (bind(sk, (struct sockaddr *)&sine, sizeof(sine)) < 0) { |
189 |
syslog(LOG_ERR, "bind: %m"); |
144 |
exit(1); |
190 |
exit(1); |
145 |
} |
191 |
} |
146 |
|
192 |
|
147 |
while ((opt = getopt(argc, argv, "bpau:")) != EOF) { |
193 |
while ((opt = getopt(argc, argv, "bpai:fu:")) != EOF) { |
148 |
switch (opt) { |
194 |
switch (opt) { |
149 |
case 'b': |
195 |
case 'b': |
150 |
use_broadcast = 1; |
196 |
use_broadcast = 1; |
Lines 156-184
Link Here
|
156 |
use_broadcast = 1; |
202 |
use_broadcast = 1; |
157 |
use_pointopoint = 1; |
203 |
use_pointopoint = 1; |
158 |
break; |
204 |
break; |
|
|
205 |
case 'f': |
206 |
use_forwarding = 1; |
207 |
break; |
208 |
case 'i': |
209 |
wn_dup = 0; |
210 |
for (wn = wanted_neigh; wn; wn = wn->w_next) { |
211 |
if (strcmp(wn->w_ifname, optarg)== 0) { |
212 |
wn_dup = 1; |
213 |
break; |
214 |
} |
215 |
} |
216 |
if (wn_dup) { |
217 |
fprintf(stderr, "rwhod: warning: " |
218 |
"duplicate interface %s in arguments\n", |
219 |
optarg); |
220 |
} else { |
221 |
wn = malloc(sizeof(struct wanted_neigh)); |
222 |
if (wn == NULL) { |
223 |
fprintf(stderr, "rwhod: out of memory\n"); |
224 |
exit(2); |
225 |
} |
226 |
wn->w_next = wanted_neigh; |
227 |
wn->w_ifname = malloc(strlen(optarg)+1); |
228 |
wn->w_used = W_USED_NOT; |
229 |
if (wn->w_ifname == NULL) { |
230 |
fprintf(stderr, "rwhod: out of memory\n"); |
231 |
exit(2); |
232 |
} |
233 |
strcpy(wn->w_ifname, optarg); |
234 |
wanted_neigh = wn; |
235 |
} |
236 |
break; |
159 |
case 'u': |
237 |
case 'u': |
160 |
user = optarg; |
238 |
user = optarg; |
161 |
break; |
239 |
break; |
162 |
case '?': |
240 |
case '?': |
163 |
default: |
241 |
default: |
164 |
fprintf(stderr, "usage: rwhod [-bpa] [-u user]\n"); |
242 |
usage(); |
165 |
exit(1); |
|
|
166 |
break; |
167 |
} |
243 |
} |
168 |
} |
244 |
} |
169 |
if (optind<argc) { |
245 |
if (optind<argc) { |
170 |
fprintf(stderr, "usage: rwhod [-bpa] [-u user]\n"); |
246 |
usage(); |
171 |
exit(1); |
|
|
172 |
} |
247 |
} |
173 |
if (!use_pointopoint && !use_broadcast) { |
248 |
if (!use_pointopoint && !use_broadcast && !wanted_neigh) { |
174 |
/* use none is nonsensical; default to all */ |
249 |
/* use none is nonsensical; default to all */ |
175 |
use_pointopoint = 1; |
250 |
use_pointopoint = 1; |
176 |
use_broadcast = 1; |
251 |
use_broadcast = 1; |
177 |
} |
252 |
} |
178 |
|
253 |
if ((use_pointopoint || use_broadcast) && wanted_neigh) { |
179 |
sp = getservbyname("who", "udp"); |
254 |
fprintf(stderr, "rwhod: cannot specify both -i and one of -b " |
180 |
if (sp == 0) { |
255 |
"-p -a\n"); |
181 |
fprintf(stderr, "rwhod: udp/who: unknown service\n"); |
|
|
182 |
exit(1); |
256 |
exit(1); |
183 |
} |
257 |
} |
184 |
#ifndef DEBUG |
258 |
#ifndef DEBUG |
Lines 190-215
Link Here
|
190 |
exit(1); |
264 |
exit(1); |
191 |
} |
265 |
} |
192 |
(void) signal(SIGHUP, huphandler); |
266 |
(void) signal(SIGHUP, huphandler); |
193 |
openlog("rwhod", LOG_PID, LOG_DAEMON); |
|
|
194 |
|
195 |
if ((sk = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { |
196 |
syslog(LOG_ERR, "socket: %m"); |
197 |
exit(1); |
198 |
} |
199 |
if (setsockopt(sk, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { |
200 |
syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); |
201 |
exit(1); |
202 |
} |
203 |
sine.sin_family = AF_INET; |
204 |
sine.sin_port = sp->s_port; |
205 |
if (bind(sk, (struct sockaddr *)&sine, sizeof(sine)) < 0) { |
206 |
syslog(LOG_ERR, "bind: %m"); |
207 |
exit(1); |
208 |
} |
209 |
|
267 |
|
210 |
(void) umask(022); |
268 |
(void) umask(022); |
211 |
|
269 |
|
212 |
signal(SIGTERM, termhandler); |
270 |
signal(SIGTERM, termhandler); |
|
|
271 |
|
272 |
if (user) { |
273 |
/* We have to drop privs in two steps--first get the |
274 |
* account info, then drop privs after chroot */ |
275 |
if ((pw = getpwnam(user)) == NULL) { |
276 |
syslog(LOG_ERR, "unknown user: %s", user); |
277 |
exit(1); |
278 |
} |
279 |
|
280 |
/* Now drop privs */ |
281 |
if (pw->pw_uid) { |
282 |
if (setgroups(1, &pw->pw_gid) < 0 |
283 |
|| setgid(pw->pw_gid) < 0 |
284 |
|| setuid(pw->pw_uid) < 0) { |
285 |
syslog(LOG_ERR,"failed to drop privilege: %m"); |
286 |
exit(1); |
287 |
} |
288 |
} |
289 |
} |
290 |
|
291 |
if (!configure(sk)) |
292 |
exit(1); |
293 |
|
213 |
child_pid = fork(); |
294 |
child_pid = fork(); |
214 |
if (child_pid < 0) { |
295 |
if (child_pid < 0) { |
215 |
syslog(LOG_ERR, "fork: %m"); |
296 |
syslog(LOG_ERR, "fork: %m"); |
Lines 220-254
Link Here
|
220 |
exit(0); |
301 |
exit(0); |
221 |
} |
302 |
} |
222 |
|
303 |
|
223 |
/* We have to drop privs in two steps--first get the |
304 |
before = 0; |
224 |
* account info, then drop privs after chroot */ |
|
|
225 |
if (user && (pw = getpwnam(user)) == NULL) { |
226 |
syslog(LOG_ERR, "unknown user: %s", user); |
227 |
exit(1); |
228 |
} |
229 |
|
230 |
/* Chroot to the spool directory |
231 |
* (note this is already our $cwd) */ |
232 |
if (chroot(_PATH_RWHODIR) < 0) { |
233 |
syslog(LOG_ERR, "chroot(%s): %m", _PATH_RWHODIR); |
234 |
kill(child_pid, SIGTERM); |
235 |
exit(1); |
236 |
} |
237 |
|
238 |
/* Now drop privs */ |
239 |
if (pw) { |
240 |
if (setgroups(1, &pw->pw_gid) < 0 |
241 |
|| setgid(pw->pw_gid) < 0 |
242 |
|| setuid(pw->pw_uid) < 0) { |
243 |
syslog(LOG_ERR, "failed to drop privilege: %m"); |
244 |
exit(1); |
245 |
} |
246 |
} |
247 |
|
248 |
for (;;) { |
305 |
for (;;) { |
249 |
struct whod wd; |
306 |
struct whod wd; |
250 |
int cc, whod; |
307 |
int cc, whod; |
|
|
308 |
#ifdef __GLIBC__ |
309 |
socklen_t len = sizeof(from); |
310 |
#else |
251 |
size_t len = sizeof(from); |
311 |
size_t len = sizeof(from); |
|
|
312 |
#endif |
252 |
|
313 |
|
253 |
memset(&wd, 0, sizeof(wd)); |
314 |
memset(&wd, 0, sizeof(wd)); |
254 |
cc = recvfrom(sk, (char *)&wd, sizeof(struct whod), 0, |
315 |
cc = recvfrom(sk, (char *)&wd, sizeof(struct whod), 0, |
Lines 262-267
Link Here
|
262 |
syslog(LOG_WARNING, "packet too small"); |
323 |
syslog(LOG_WARNING, "packet too small"); |
263 |
continue; |
324 |
continue; |
264 |
} |
325 |
} |
|
|
326 |
if (cc < WHDRSIZE) { |
327 |
syslog(LOG_WARNING, "packet too small"); |
328 |
continue; |
329 |
} |
330 |
if (cc < WHDRSIZE) |
331 |
continue; |
265 |
if (from.sin_port != sp->s_port) { |
332 |
if (from.sin_port != sp->s_port) { |
266 |
syslog(LOG_WARNING, "%d: bad from port", |
333 |
syslog(LOG_WARNING, "%d: bad from port", |
267 |
ntohs(from.sin_port)); |
334 |
ntohs(from.sin_port)); |
Lines 271-284
Link Here
|
271 |
continue; |
338 |
continue; |
272 |
if (wd.wd_type != WHODTYPE_STATUS) |
339 |
if (wd.wd_type != WHODTYPE_STATUS) |
273 |
continue; |
340 |
continue; |
|
|
341 |
|
342 |
if (use_forwarding) { |
343 |
time_t now = time(NULL); |
344 |
if ((uintmax_t) (now - before) >= AL_INTERVAL) { |
345 |
before = now; |
346 |
forwarded_packets = 0; |
347 |
} |
348 |
forward(&from, &wd, cc); |
349 |
} |
350 |
|
274 |
/* |
351 |
/* |
275 |
* Ensure null termination of the name within the packet. |
352 |
* Ensure null termination of the name within the packet. |
276 |
* Otherwise we might overflow or read past the end. |
353 |
* Otherwise we might overflow or read past the end. |
277 |
*/ |
354 |
*/ |
278 |
wd.wd_hostname[sizeof(wd.wd_hostname)-1] = 0; |
355 |
wd.wd_hostname[sizeof(wd.wd_hostname)-1] = 0; |
279 |
if (!verify(wd.wd_hostname)) { |
356 |
if (!verify(wd.wd_hostname)) { |
280 |
syslog(LOG_WARNING, "malformed host name from %x", |
357 |
syslog(LOG_WARNING, "malformed host name from %s", |
281 |
from.sin_addr.s_addr); |
358 |
inet_ntoa(from.sin_addr)); |
282 |
continue; |
359 |
continue; |
283 |
} |
360 |
} |
284 |
snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname); |
361 |
snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname); |
Lines 350-358
Link Here
|
350 |
size_t mynamelen; |
427 |
size_t mynamelen; |
351 |
struct whod mywd; |
428 |
struct whod mywd; |
352 |
|
429 |
|
353 |
if (!configure(sk)) |
|
|
354 |
exit(1); |
355 |
|
356 |
/* |
430 |
/* |
357 |
* Establish host name as returned by system. |
431 |
* Establish host name as returned by system. |
358 |
*/ |
432 |
*/ |
Lines 362-368
Link Here
|
362 |
} |
436 |
} |
363 |
if ((cp = index(myname, '.')) != NULL) |
437 |
if ((cp = index(myname, '.')) != NULL) |
364 |
*cp = '\0'; |
438 |
*cp = '\0'; |
365 |
mynamelen = strlen(myname); |
439 |
mynamelen = strlen(myname) + 1; |
366 |
if (mynamelen > sizeof(mywd.wd_hostname)) |
440 |
if (mynamelen > sizeof(mywd.wd_hostname)) |
367 |
mynamelen = sizeof(mywd.wd_hostname) - 1; |
441 |
mynamelen = sizeof(mywd.wd_hostname) - 1; |
368 |
strncpy(mywd.wd_hostname, myname, mynamelen); |
442 |
strncpy(mywd.wd_hostname, myname, mynamelen); |
Lines 453-459
Link Here
|
453 |
} |
527 |
} |
454 |
we = wd->wd_we; |
528 |
we = wd->wd_we; |
455 |
for (i = 0; i < nutmps; i++) { |
529 |
for (i = 0; i < nutmps; i++) { |
456 |
if (stat(we->we_utmp.out_line, &stb) >= 0) |
530 |
const char *p = we->we_utmp.out_line; |
|
|
531 |
|
532 |
if (!strchr(p, ':') && stat(p, &stb) >= 0) |
457 |
we->we_idle = htonl(now - stb.st_atime); |
533 |
we->we_idle = htonl(now - stb.st_atime); |
458 |
we++; |
534 |
we++; |
459 |
} |
535 |
} |
Lines 465-474
Link Here
|
465 |
wd->wd_vers = WHODVERSION; |
541 |
wd->wd_vers = WHODVERSION; |
466 |
wd->wd_type = WHODTYPE_STATUS; |
542 |
wd->wd_type = WHODTYPE_STATUS; |
467 |
for (np = neighbors; np != NULL; np = np->n_next) { |
543 |
for (np = neighbors; np != NULL; np = np->n_next) { |
468 |
if (sendto(sk, (char *)wd, cc, 0, |
544 |
if (sendto(sk, wd, cc, 0, |
469 |
(struct sockaddr *) np->n_addr, np->n_addrlen) < 0) |
545 |
(struct sockaddr *) np->n_dstaddr, np->n_addrlen) < 0) |
470 |
syslog(LOG_ERR, "sendto(%s): %m", |
546 |
syslog(LOG_ERR, "sendto(%s): %m", |
471 |
inet_ntoa(((struct sockaddr_in *)np->n_addr)->sin_addr)); |
547 |
inet_ntoa(np->n_dstaddr->sin_addr)); |
472 |
} |
548 |
} |
473 |
|
549 |
|
474 |
if (nutmps && chdir(_PATH_RWHODIR)) { |
550 |
if (nutmps && chdir(_PATH_RWHODIR)) { |
Lines 477-482
Link Here
|
477 |
} |
553 |
} |
478 |
} |
554 |
} |
479 |
|
555 |
|
|
|
556 |
#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) |
480 |
/* |
557 |
/* |
481 |
* Taken from: |
558 |
* Taken from: |
482 |
* |
559 |
* |
Lines 523-528
Link Here
|
523 |
fclose(fp); |
600 |
fclose(fp); |
524 |
return 0; |
601 |
return 0; |
525 |
} |
602 |
} |
|
|
603 |
#endif /* __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) */ |
526 |
|
604 |
|
527 |
|
605 |
|
528 |
void |
606 |
void |
Lines 571-577
Link Here
|
571 |
exit(1); |
649 |
exit(1); |
572 |
} |
650 |
} |
573 |
(void) lseek(kmemf, (long)nl[NL_BOOTTIME].n_value, L_SET); |
651 |
(void) lseek(kmemf, (long)nl[NL_BOOTTIME].n_value, L_SET); |
574 |
(void) read(kmemf, (char *)&wd->wd_boottime, |
652 |
(void) read(kmemf, &wd->wd_boottime, |
575 |
sizeof (wd->wd_boottime)); |
653 |
sizeof (wd->wd_boottime)); |
576 |
wd->wd_boottime = htonl(wd->wd_boottime); |
654 |
wd->wd_boottime = htonl(wd->wd_boottime); |
577 |
#endif |
655 |
#endif |
Lines 589-598
Link Here
|
589 |
struct ifreq ifreq, *ifr; |
667 |
struct ifreq ifreq, *ifr; |
590 |
struct sockaddr_in *sn; |
668 |
struct sockaddr_in *sn; |
591 |
register struct neighbor *np; |
669 |
register struct neighbor *np; |
|
|
670 |
struct wanted_neigh *wn; |
592 |
|
671 |
|
593 |
ifc.ifc_len = sizeof (buf); |
672 |
ifc.ifc_len = sizeof (buf); |
594 |
ifc.ifc_buf = buf; |
673 |
ifc.ifc_buf = buf; |
595 |
if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { |
674 |
if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { |
596 |
syslog(LOG_ERR, "ioctl (get interface configuration)"); |
675 |
syslog(LOG_ERR, "ioctl (get interface configuration)"); |
597 |
return (0); |
676 |
return (0); |
598 |
} |
677 |
} |
Lines 605-611
Link Here
|
605 |
#endif |
684 |
#endif |
606 |
cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ |
685 |
cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ |
607 |
for (cp = buf; cp < cplim; |
686 |
for (cp = buf; cp < cplim; |
|
|
687 |
#ifdef linux |
688 |
cp += sizeof(struct ifreq)) { |
689 |
#else |
608 |
cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { |
690 |
cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { |
|
|
691 |
#endif |
609 |
ifr = (struct ifreq *)cp; |
692 |
ifr = (struct ifreq *)cp; |
610 |
for (np = neighbors; np != NULL; np = np->n_next) |
693 |
for (np = neighbors; np != NULL; np = np->n_next) |
611 |
if (np->n_name && |
694 |
if (np->n_name && |
Lines 619-681
Link Here
|
619 |
continue; |
702 |
continue; |
620 |
np->n_name = malloc(strlen(ifr->ifr_name) + 1); |
703 |
np->n_name = malloc(strlen(ifr->ifr_name) + 1); |
621 |
if (np->n_name == NULL) { |
704 |
if (np->n_name == NULL) { |
622 |
free((char *)np); |
705 |
free(np); |
623 |
continue; |
706 |
continue; |
624 |
} |
707 |
} |
625 |
strcpy(np->n_name, ifr->ifr_name); |
708 |
strcpy(np->n_name, ifr->ifr_name); |
626 |
np->n_addrlen = sizeof (ifr->ifr_addr); |
709 |
np->n_addrlen = sizeof (ifr->ifr_addr); |
627 |
np->n_addr = malloc(np->n_addrlen); |
710 |
|
628 |
if (np->n_addr == NULL) { |
711 |
np->n_dstaddr = malloc(np->n_addrlen); |
|
|
712 |
if (np->n_dstaddr == NULL) { |
713 |
free(np->n_name); |
714 |
free(np); |
715 |
continue; |
716 |
} |
717 |
bzero(np->n_dstaddr, np->n_addrlen); |
718 |
|
719 |
np->n_myaddr = malloc(np->n_addrlen); |
720 |
if (np->n_myaddr == NULL) { |
721 |
free(np->n_dstaddr); |
629 |
free(np->n_name); |
722 |
free(np->n_name); |
630 |
free((char *)np); |
723 |
free(np); |
631 |
continue; |
724 |
continue; |
632 |
} |
725 |
} |
633 |
bcopy((char *)&ifr->ifr_addr, np->n_addr, np->n_addrlen); |
726 |
bzero(np->n_myaddr, np->n_addrlen); |
634 |
if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { |
727 |
|
|
|
728 |
np->n_mask = malloc(np->n_addrlen); |
729 |
if (np->n_mask == NULL) { |
730 |
free(np->n_myaddr); |
731 |
free(np->n_dstaddr); |
732 |
free(np->n_name); |
733 |
free(np); |
734 |
continue; |
735 |
} |
736 |
bzero(np->n_mask, np->n_addrlen); |
737 |
|
738 |
/* Initialize both my address and destination address by |
739 |
the interface address. The destination address will be |
740 |
overwritten when the interface has IFF_BROADCAST or |
741 |
IFF_POINTOPOINT. */ |
742 |
bcopy(&ifr->ifr_addr, np->n_dstaddr, np->n_addrlen); |
743 |
bcopy(&ifr->ifr_addr, np->n_myaddr, np->n_addrlen); |
744 |
|
745 |
if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) { |
635 |
syslog(LOG_ERR, "ioctl (get interface flags)"); |
746 |
syslog(LOG_ERR, "ioctl (get interface flags)"); |
636 |
free((char *)np); |
747 |
free(np->n_myaddr); |
|
|
748 |
free(np->n_dstaddr); |
749 |
free(np->n_name); |
750 |
free(np); |
637 |
continue; |
751 |
continue; |
638 |
} |
752 |
} |
639 |
if ((ifreq.ifr_flags & IFF_UP) == 0 || |
753 |
if ((ifreq.ifr_flags & IFF_UP) == 0 || |
640 |
(ifreq.ifr_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0) { |
754 |
(ifreq.ifr_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0 || |
641 |
free((char *)np); |
755 |
(ifreq.ifr_flags & IFF_LOOPBACK) != 0) { |
|
|
756 |
free(np->n_myaddr); |
757 |
free(np->n_dstaddr); |
758 |
free(np->n_name); |
759 |
free(np); |
642 |
continue; |
760 |
continue; |
643 |
} |
761 |
} |
|
|
762 |
if (wanted_neigh) { |
763 |
int found = 0; |
764 |
for (wn = wanted_neigh; wn; wn = wn->w_next) |
765 |
if (strcmp(wn->w_ifname, ifreq.ifr_name)==0) { |
766 |
found = 1; |
767 |
break; |
768 |
} |
769 |
if (!found) { |
770 |
free(np->n_mask); |
771 |
free(np->n_myaddr); |
772 |
free(np->n_dstaddr); |
773 |
free(np->n_name); |
774 |
free(np); |
775 |
continue; |
776 |
} |
777 |
switch (wn->w_used) { |
778 |
case W_USED_NOT: |
779 |
wn->w_used = W_USED_ONCE; |
780 |
break; |
781 |
case W_USED_ONCE: |
782 |
syslog(LOG_ERR, |
783 |
"specified interface %s more than once", |
784 |
wn->w_ifname); |
785 |
wn->w_used = W_USED_MULTI; |
786 |
break; |
787 |
case W_USED_MULTI: |
788 |
/* oh well... don't tell again... */ |
789 |
break; |
790 |
default: |
791 |
syslog(LOG_CRIT, "w_used=%d on %s", |
792 |
wn->w_used, wn->w_ifname); |
793 |
abort(); |
794 |
} |
795 |
} |
644 |
np->n_flags = ifreq.ifr_flags; |
796 |
np->n_flags = ifreq.ifr_flags; |
645 |
if (np->n_flags & IFF_POINTOPOINT) { |
797 |
if (np->n_flags & IFF_POINTOPOINT) { |
646 |
if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { |
798 |
if (ioctl(s, SIOCGIFDSTADDR, &ifreq) < 0) { |
647 |
syslog(LOG_ERR, "ioctl (get dstaddr)"); |
799 |
syslog(LOG_ERR, "ioctl (get dstaddr)"); |
|
|
800 |
free(np->n_mask); |
801 |
free(np->n_myaddr); |
802 |
free(np->n_dstaddr); |
803 |
free(np->n_name); |
648 |
free(np); |
804 |
free(np); |
649 |
continue; |
805 |
continue; |
650 |
} |
806 |
} |
651 |
if (!use_pointopoint) { |
807 |
if (!wanted_neigh && !use_pointopoint) { |
|
|
808 |
free(np->n_mask); |
809 |
free(np->n_myaddr); |
810 |
free(np->n_dstaddr); |
811 |
free(np->n_name); |
652 |
free(np); |
812 |
free(np); |
653 |
continue; |
813 |
continue; |
654 |
} |
814 |
} |
655 |
/* we assume addresses are all the same size */ |
815 |
/* we assume addresses are all the same size */ |
656 |
bcopy((char *)&ifreq.ifr_dstaddr, |
816 |
bcopy(&ifreq.ifr_dstaddr, np->n_dstaddr, np->n_addrlen); |
657 |
np->n_addr, np->n_addrlen); |
|
|
658 |
} |
817 |
} |
659 |
if (np->n_flags & IFF_BROADCAST) { |
818 |
if (np->n_flags & IFF_BROADCAST) { |
660 |
if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { |
819 |
if (ioctl(s, SIOCGIFBRDADDR, &ifreq) < 0) { |
661 |
syslog(LOG_ERR, "ioctl (get broadaddr)"); |
820 |
syslog(LOG_ERR, "ioctl (get broadaddr)"); |
|
|
821 |
free(np->n_mask); |
822 |
free(np->n_myaddr); |
823 |
free(np->n_dstaddr); |
824 |
free(np->n_name); |
662 |
free(np); |
825 |
free(np); |
663 |
continue; |
826 |
continue; |
664 |
} |
827 |
} |
665 |
if (!use_broadcast) { |
828 |
if (!wanted_neigh && !use_broadcast) { |
|
|
829 |
free(np->n_mask); |
830 |
free(np->n_myaddr); |
831 |
free(np->n_dstaddr); |
832 |
free(np->n_name); |
666 |
free(np); |
833 |
free(np); |
667 |
continue; |
834 |
continue; |
668 |
} |
835 |
} |
669 |
/* we assume addresses are all the same size */ |
836 |
/* we assume addresses are all the same size */ |
670 |
bcopy((char *)&ifreq.ifr_broadaddr, |
837 |
bcopy(&ifreq.ifr_broadaddr, np->n_dstaddr, np->n_addrlen); |
671 |
np->n_addr, np->n_addrlen); |
838 |
|
|
|
839 |
/* Get netmask */ |
840 |
if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0) { |
841 |
syslog(LOG_ERR, "ioctl (get netmask)"); |
842 |
free(np->n_mask); |
843 |
free(np->n_myaddr); |
844 |
free(np->n_dstaddr); |
845 |
free(np->n_name); |
846 |
free(np); |
847 |
continue; |
848 |
} |
849 |
bcopy((char*)&ifreq.ifr_netmask, |
850 |
np->n_mask, np->n_addrlen); |
672 |
} |
851 |
} |
673 |
/* gag, wish we could get rid of Internet dependencies */ |
852 |
/* gag, wish we could get rid of Internet dependencies */ |
674 |
sn = (struct sockaddr_in *)np->n_addr; |
853 |
sn = (SA *)np->n_dstaddr; |
675 |
sn->sin_port = sp->s_port; |
854 |
sn->sin_port = sp->s_port; |
676 |
np->n_next = neighbors; |
855 |
np->n_next = neighbors; |
677 |
neighbors = np; |
856 |
neighbors = np; |
678 |
} |
857 |
} |
|
|
858 |
|
859 |
/* Check for unfound i/f */ |
860 |
for (wn = wanted_neigh; wn; wn = wn->w_next) |
861 |
if (wn->w_used == W_USED_NOT) |
862 |
syslog(LOG_WARNING, "didn't find interface %s", |
863 |
wn->w_ifname); |
864 |
|
865 |
/* Dump out used i/f */ |
866 |
for (np = neighbors; np; np = np->n_next) |
867 |
syslog(LOG_INFO, "sending on interface %s", np->n_name); |
868 |
|
679 |
return (1); |
869 |
return (1); |
680 |
} |
870 |
} |
681 |
|
871 |
|
Lines 697-703
Link Here
|
697 |
{ |
887 |
{ |
698 |
register struct whod *w = (struct whod *)buf; |
888 |
register struct whod *w = (struct whod *)buf; |
699 |
register struct whoent *we; |
889 |
register struct whoent *we; |
700 |
struct sockaddr_in *sn = (struct sockaddr_in *)to; |
890 |
struct sockaddr_in *sn = (SA *)to; |
701 |
char *interval(); |
891 |
char *interval(); |
702 |
|
892 |
|
703 |
printf("sendto %x.%d\n", ntohl(sn->sin_addr.s_addr), ntohs(sn->sin_port)); |
893 |
printf("sendto %x.%d\n", ntohl(sn->sin_addr.s_addr), ntohs(sn->sin_port)); |
Lines 751-753
Link Here
|
751 |
return (resbuf); |
941 |
return (resbuf); |
752 |
} |
942 |
} |
753 |
#endif |
943 |
#endif |
|
|
944 |
|
945 |
/* Eventually forward the packet */ |
946 |
static void |
947 |
forward(const SA *from, const struct whod *wd, int cc) |
948 |
{ |
949 |
struct neighbor *np; |
950 |
int looped_back = 0; |
951 |
|
952 |
/* Scan to see if the packet was sent by us */ |
953 |
for (np = neighbors; np != NULL; np = np->n_next) |
954 |
if (from->sin_addr.s_addr == |
955 |
np->n_myaddr->sin_addr.s_addr) { |
956 |
looped_back = 1; |
957 |
break; |
958 |
} |
959 |
|
960 |
if (!looped_back) { |
961 |
sigset_t saved_set; |
962 |
sigset_t mask_set; |
963 |
|
964 |
sigemptyset(&mask_set); |
965 |
sigaddset(&mask_set, SIGALRM); |
966 |
sigprocmask(SIG_BLOCK, &mask_set, &saved_set); |
967 |
|
968 |
if (++forwarded_packets > MAX_FWD_PACKETS) { |
969 |
syslog(LOG_ERR, "too many forward requests, " |
970 |
"disabling forwarding"); |
971 |
use_forwarding = 0; |
972 |
} |
973 |
|
974 |
sigprocmask(SIG_SETMASK, &saved_set, NULL); |
975 |
|
976 |
/* Re-broadcast packet on all interfaces... */ |
977 |
for (np = neighbors; np != NULL; np = np->n_next) { |
978 |
/* .. but do not rebroadcast on the incoming interface */ |
979 |
if (((np->n_flags & IFF_BROADCAST) && |
980 |
(from->sin_addr.s_addr & |
981 |
np->n_mask->sin_addr.s_addr) != |
982 |
(np->n_myaddr->sin_addr.s_addr & |
983 |
np->n_mask->sin_addr.s_addr)) || |
984 |
((np->n_flags & IFF_POINTOPOINT) && |
985 |
(from->sin_addr.s_addr) != |
986 |
np->n_dstaddr->sin_addr.s_addr)) { |
987 |
if (sendto(sk, wd, cc, 0, |
988 |
(struct sockaddr *)np->n_dstaddr, |
989 |
np->n_addrlen) < 0) |
990 |
syslog(LOG_ERR, |
991 |
"forwarding sendto(%s): %m", |
992 |
inet_ntoa(np->n_dstaddr->sin_addr)); |
993 |
} |
994 |
} |
995 |
} |
996 |
} |
997 |
|
998 |
static void |
999 |
usage() |
1000 |
{ |
1001 |
fprintf(stderr, "usage: rwhod [-bpaf] [-i <ifname>] [-u user]...\n"); |
1002 |
exit(1); |
1003 |
} |