Print this page
195 Need replacement for nfs/lockd+klm
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fs.d/nfs/statd/sm_proc.c
+++ new/usr/src/cmd/fs.d/nfs/statd/sm_proc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26 /*
27 27 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28 + * Copyright (c) 2012 by Delphix. All rights reserved.
28 29 */
29 30
30 31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
31 32 /* All Rights Reserved */
32 33
33 34 /*
34 35 * University Copyright- Copyright (c) 1982, 1986, 1988
35 36 * The Regents of the University of California
36 37 * All Rights Reserved
37 38 *
38 39 * University Acknowledgment- Portions of this document are derived from
39 40 * software developed by the University of California, Berkeley, and its
40 41 * contributors.
41 42 */
42 43
43 44 #include <stdio.h>
44 45 #include <sys/types.h>
45 46 #include <stdlib.h>
46 47 #include <unistd.h>
47 48 #include <string.h>
48 49 #include <syslog.h>
49 50 #include <rpc/rpc.h>
50 51 #include <rpcsvc/sm_inter.h>
51 52 #include <rpcsvc/nsm_addr.h>
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
52 53 #include <memory.h>
53 54 #include <net/if.h>
54 55 #include <sys/sockio.h>
55 56 #include <sys/socket.h>
56 57 #include <netinet/in.h>
57 58 #include <arpa/inet.h>
58 59 #include <netdb.h>
59 60 #include <netdir.h>
60 61 #include <synch.h>
61 62 #include <thread.h>
63 +#include <ifaddrs.h>
64 +#include <errno.h>
62 65 #include <assert.h>
63 66 #include "sm_statd.h"
64 67
65 68 static int local_state; /* fake local sm state */
66 69 /* client name-to-address translation table */
67 70 static name_addr_entry_t *name_addr = NULL;
68 71
69 72
70 73 #define LOGHOST "loghost"
71 74
72 75 static void delete_mon(char *mon_name, my_id *my_idp);
73 76 static void insert_mon(mon *monp);
74 77 static void pr_mon(char *);
75 78 static int statd_call_lockd(mon *monp, int state);
76 79 static int hostname_eq(char *host1, char *host2);
77 80 static char *get_system_id(char *hostname);
78 81 static void add_aliases(struct hostent *phost);
79 82 static void *thr_send_notice(void *);
80 83 static void delete_onemon(char *mon_name, my_id *my_idp,
81 84 mon_entry **monitor_q);
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
82 85 static void send_notice(char *mon_name, int state);
83 86 static void add_to_host_array(char *host);
84 87 static int in_host_array(char *host);
85 88 static void pr_name_addr(name_addr_entry_t *name_addr);
86 89
87 90 extern int self_check(char *hostname);
88 91 extern struct lifconf *getmyaddrs(void);
89 92
90 93 /* ARGSUSED */
91 94 void
92 -sm_status(namep, resp)
93 - sm_name *namep;
94 - sm_stat_res *resp;
95 +sm_stat_svc(sm_name *namep, sm_stat_res *resp)
95 96 {
96 97
97 98 if (debug)
98 99 (void) printf("proc sm_stat: mon_name = %s\n",
99 100 namep->mon_name);
100 101
101 102 resp->res_stat = stat_succ;
102 103 resp->state = LOCAL_STATE;
103 104 }
104 105
105 106 /* ARGSUSED */
106 107 void
107 -sm_mon(monp, resp)
108 - mon *monp;
109 - sm_stat_res *resp;
108 +sm_mon_svc(mon *monp, sm_stat_res *resp)
110 109 {
111 110 mon_id *monidp;
112 111 monidp = &monp->mon_id;
113 112
114 113 rw_rdlock(&thr_rwlock);
115 114 if (debug) {
116 115 (void) printf("proc sm_mon: mon_name = %s, id = %d\n",
117 116 monidp->mon_name, * ((int *)monp->priv));
118 117 pr_mon(monp->mon_id.mon_name);
119 118 }
120 119
121 120 /* only monitor other hosts */
122 121 if (self_check(monp->mon_id.mon_name) == 0) {
123 122 /* store monitor request into monitor_q */
124 123 insert_mon(monp);
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
125 124 }
126 125
127 126 pr_mon(monp->mon_id.mon_name);
128 127 resp->res_stat = stat_succ;
129 128 resp->state = local_state;
130 129 rw_unlock(&thr_rwlock);
131 130 }
132 131
133 132 /* ARGSUSED */
134 133 void
135 -sm_unmon(monidp, resp)
136 - mon_id *monidp;
137 - sm_stat *resp;
134 +sm_unmon_svc(mon_id *monidp, sm_stat *resp)
138 135 {
139 136 rw_rdlock(&thr_rwlock);
140 137 if (debug) {
141 138 (void) printf(
142 139 "proc sm_unmon: mon_name = %s, [%s, %d, %d, %d]\n",
143 140 monidp->mon_name, monidp->my_id.my_name,
144 141 monidp->my_id.my_prog, monidp->my_id.my_vers,
145 142 monidp->my_id.my_proc);
146 143 pr_mon(monidp->mon_name);
147 144 }
148 145
149 146 delete_mon(monidp->mon_name, &monidp->my_id);
150 147 pr_mon(monidp->mon_name);
151 148 resp->state = local_state;
152 149 rw_unlock(&thr_rwlock);
153 150 }
154 151
155 152 /* ARGSUSED */
156 153 void
157 -sm_unmon_all(myidp, resp)
158 - my_id *myidp;
159 - sm_stat *resp;
154 +sm_unmon_all_svc(my_id *myidp, sm_stat *resp)
160 155 {
161 156 rw_rdlock(&thr_rwlock);
162 157 if (debug)
163 158 (void) printf("proc sm_unmon_all: [%s, %d, %d, %d]\n",
164 159 myidp->my_name,
165 160 myidp->my_prog, myidp->my_vers,
166 161 myidp->my_proc);
167 162 delete_mon((char *)NULL, myidp);
168 163 pr_mon(NULL);
169 164 resp->state = local_state;
170 165 rw_unlock(&thr_rwlock);
171 166 }
172 167
173 168 /*
174 169 * Notifies lockd specified by name that state has changed for this server.
175 170 */
176 171 void
177 -sm_notify(ntfp)
178 - stat_chge *ntfp;
172 +sm_notify_svc(stat_chge *ntfp)
179 173 {
180 174 rw_rdlock(&thr_rwlock);
181 175 if (debug)
182 176 (void) printf("sm_notify: %s state =%d\n",
183 177 ntfp->mon_name, ntfp->state);
184 178 send_notice(ntfp->mon_name, ntfp->state);
185 179 rw_unlock(&thr_rwlock);
186 180 }
187 181
188 182 /* ARGSUSED */
189 183 void
190 -sm_simu_crash(myidp)
191 - void *myidp;
184 +sm_simu_crash_svc(void *myidp)
192 185 {
193 186 int i;
194 187 struct mon_entry *monitor_q;
195 188 int found = 0;
196 189
197 190 /* Only one crash should be running at a time. */
198 191 mutex_lock(&crash_lock);
199 192 if (debug)
200 193 (void) printf("proc sm_simu_crash\n");
201 194 if (in_crash) {
202 195 cond_wait(&crash_finish, &crash_lock);
203 196 mutex_unlock(&crash_lock);
204 197 return;
205 198 } else {
206 199 in_crash = 1;
207 200 }
208 201 mutex_unlock(&crash_lock);
209 202
210 203 for (i = 0; i < MAX_HASHSIZE; i++) {
211 204 mutex_lock(&mon_table[i].lock);
212 205 monitor_q = mon_table[i].sm_monhdp;
213 206 if (monitor_q != (struct mon_entry *)NULL) {
214 207 mutex_unlock(&mon_table[i].lock);
215 208 found = 1;
216 209 break;
217 210 }
218 211 mutex_unlock(&mon_table[i].lock);
219 212 }
220 213 /*
221 214 * If there are entries found in the monitor table,
222 215 * initiate a crash, else zero out the in_crash variable.
223 216 */
224 217 if (found) {
225 218 mutex_lock(&crash_lock);
226 219 die = 1;
227 220 /* Signal sm_retry() thread if sleeping. */
228 221 cond_signal(&retrywait);
229 222 mutex_unlock(&crash_lock);
230 223 rw_wrlock(&thr_rwlock);
231 224 sm_crash();
232 225 rw_unlock(&thr_rwlock);
233 226 } else {
234 227 mutex_lock(&crash_lock);
235 228 in_crash = 0;
236 229 mutex_unlock(&crash_lock);
237 230 }
238 231 }
239 232
240 233 /* ARGSUSED */
241 234 void
242 235 nsmaddrproc1_reg(regargs, regresp)
243 236 reg1args *regargs;
244 237 reg1res *regresp;
245 238 {
246 239 nsm_addr_res status;
247 240 name_addr_entry_t *entry;
248 241 char *tmp_n_bytes;
249 242 addr_entry_t *addr;
250 243
251 244 rw_rdlock(&thr_rwlock);
252 245 if (debug) {
253 246 int i;
254 247
255 248 (void) printf("nap1_reg: fam= %d, name= %s, len= %d\n",
256 249 regargs->family,
257 250 regargs->name,
258 251 regargs->address.n_len);
259 252 (void) printf("address is: ");
260 253 for (i = 0; i < regargs->address.n_len; i++) {
261 254 (void) printf("%d.",
262 255 (unsigned char)regargs->address.n_bytes[i]);
263 256 }
264 257 (void) printf("\n");
265 258 }
266 259
267 260 /*
268 261 * Locate the entry with the name in the NSM_ADDR_REG request if
269 262 * it exists. If it doesn't, create a new entry to hold this name.
270 263 * The first time through this code, name_addr starts out as NULL.
271 264 */
272 265 mutex_lock(&name_addrlock);
273 266 for (entry = name_addr; entry; entry = entry->next) {
274 267 if (strcmp(regargs->name, entry->name) == 0) {
275 268 if (debug) {
276 269 (void) printf("nap1_reg: matched name %s\n",
277 270 entry->name);
278 271 }
279 272 break;
280 273 }
281 274 }
282 275
283 276 if (entry == NULL) {
284 277 entry = (name_addr_entry_t *)malloc(sizeof (*entry));
285 278 if (entry == NULL) {
286 279 if (debug) {
287 280 (void) printf(
288 281 "nsmaddrproc1_reg: no memory for entry\n");
289 282 }
290 283 status = nsm_addr_fail;
291 284 goto done;
292 285 }
293 286
294 287 entry->name = strdup(regargs->name);
295 288 if (entry->name == NULL) {
296 289 if (debug) {
297 290 (void) printf(
298 291 "nsmaddrproc1_reg: no memory for name\n");
299 292 }
300 293 free(entry);
301 294 status = nsm_addr_fail;
302 295 goto done;
303 296 }
304 297 entry->addresses = NULL;
305 298
306 299 /*
307 300 * Link the new entry onto the *head* of the name_addr
308 301 * table.
309 302 *
310 303 * Note: there is code below in the address maintenance
311 304 * section that assumes this behavior.
312 305 */
313 306 entry->next = name_addr;
314 307 name_addr = entry;
315 308 }
316 309
317 310 /*
318 311 * Try to match the address in the request; if it doesn't match,
319 312 * add it to the entry's address list.
320 313 */
321 314 for (addr = entry->addresses; addr; addr = addr->next) {
322 315 if (addr->family == (sa_family_t)regargs->family &&
323 316 addr->ah.n_len == regargs->address.n_len &&
324 317 memcmp(addr->ah.n_bytes, regargs->address.n_bytes,
325 318 addr->ah.n_len) == 0) {
326 319 if (debug) {
327 320 int i;
328 321
329 322 (void) printf("nap1_reg: matched addr ");
330 323 for (i = 0; i < addr->ah.n_len; i++) {
331 324 (void) printf("%d.",
332 325 (unsigned char)addr->ah.n_bytes[i]);
333 326 }
334 327 (void) printf(" family %d for name %s\n",
335 328 addr->family,
336 329 entry->name);
337 330 }
338 331 break;
339 332 }
340 333 }
341 334
342 335 if (addr == NULL) {
343 336 addr = (addr_entry_t *)malloc(sizeof (*addr));
344 337 tmp_n_bytes = (char *)malloc(regargs->address.n_len);
345 338 if (addr == NULL || tmp_n_bytes == NULL) {
346 339 if (debug) {
347 340 (void) printf(
348 341 "nap1_reg: no memory for addr\n");
349 342 }
350 343
351 344 /*
352 345 * If this name entry was just newly made in the
353 346 * table, back it out now that we can't register
354 347 * an address with it anyway.
355 348 *
356 349 * Note: we are making an assumption about how
357 350 * names are added to (the head of) name_addr here.
358 351 */
359 352 if (entry == name_addr && entry->addresses == NULL) {
360 353 name_addr = name_addr->next;
361 354 free(entry->name);
362 355 free(entry);
363 356 if (tmp_n_bytes)
364 357 free(tmp_n_bytes);
365 358 if (addr)
366 359 free(addr);
367 360 status = nsm_addr_fail;
368 361 goto done;
369 362 }
370 363 }
371 364
372 365 /*
373 366 * Note: this check for address family assumes that we
374 367 * will get something different here someday for
375 368 * other supported address types, such as IPv6.
376 369 */
377 370 addr->ah.n_len = regargs->address.n_len;
378 371 addr->ah.n_bytes = tmp_n_bytes;
379 372 addr->family = regargs->family;
380 373 if (debug) {
381 374 if ((addr->family != AF_INET) && \
382 375 (addr->family != AF_INET6)) {
383 376 (void) printf(
384 377 "nap1_reg: unknown addr family %d\n",
385 378 addr->family);
386 379 }
387 380 }
388 381 (void) memcpy(addr->ah.n_bytes, regargs->address.n_bytes,
389 382 addr->ah.n_len);
390 383
391 384 addr->next = entry->addresses;
392 385 entry->addresses = addr;
393 386 }
394 387
395 388 status = nsm_addr_succ;
396 389
397 390 done:
398 391 regresp->status = status;
399 392 if (debug) {
400 393 pr_name_addr(name_addr);
401 394 }
402 395 mutex_unlock(&name_addrlock);
403 396 rw_unlock(&thr_rwlock);
404 397 }
405 398
406 399 /*
407 400 * Insert an entry into the monitor_q. Space for the entry is allocated
408 401 * here. It is then filled in from the information passed in.
409 402 */
410 403 static void
411 404 insert_mon(monp)
412 405 mon *monp;
413 406 {
414 407 mon_entry *new, *found;
415 408 my_id *my_idp, *nl_idp;
416 409 mon_entry *monitor_q;
417 410 unsigned int hash;
418 411 name_addr_entry_t *entry;
419 412 addr_entry_t *addr;
420 413
421 414 /* Allocate entry for new */
422 415 if ((new = (mon_entry *) malloc(sizeof (mon_entry))) == 0) {
423 416 syslog(LOG_ERR,
424 417 "statd: insert_mon: malloc error on mon %s (id=%d)\n",
425 418 monp->mon_id.mon_name, * ((int *)monp->priv));
426 419 return;
427 420 }
428 421
429 422 /* Initialize and copy contents of monp to new */
430 423 (void) memset(new, 0, sizeof (mon_entry));
431 424 (void) memcpy(&new->id, monp, sizeof (mon));
432 425
433 426 /* Allocate entry for new mon_name */
434 427 if ((new->id.mon_id.mon_name = strdup(monp->mon_id.mon_name)) == 0) {
435 428 syslog(LOG_ERR,
436 429 "statd: insert_mon: malloc error on mon %s (id=%d)\n",
437 430 monp->mon_id.mon_name, * ((int *)monp->priv));
438 431 free(new);
439 432 return;
440 433 }
441 434
442 435
443 436 /* Allocate entry for new my_name */
444 437 if ((new->id.mon_id.my_id.my_name =
445 438 strdup(monp->mon_id.my_id.my_name)) == 0) {
446 439 syslog(LOG_ERR,
447 440 "statd: insert_mon: malloc error on mon %s (id=%d)\n",
448 441 monp->mon_id.mon_name, * ((int *)monp->priv));
449 442 free(new->id.mon_id.mon_name);
450 443 free(new);
451 444 return;
452 445 }
453 446
454 447 if (debug)
455 448 (void) printf("add_mon(%x) %s (id=%d)\n",
456 449 (int)new, new->id.mon_id.mon_name, * ((int *)new->id.priv));
457 450
458 451 /*
459 452 * Record the name, and all addresses which have been registered
460 453 * for this name, in the filesystem name space.
461 454 */
462 455 record_name(new->id.mon_id.mon_name, 1);
463 456 if (regfiles_only == 0) {
464 457 mutex_lock(&name_addrlock);
465 458 for (entry = name_addr; entry; entry = entry->next) {
466 459 if (strcmp(new->id.mon_id.mon_name, entry->name) != 0) {
467 460 continue;
468 461 }
469 462
470 463 for (addr = entry->addresses; addr; addr = addr->next) {
471 464 record_addr(new->id.mon_id.mon_name,
472 465 addr->family, &addr->ah);
473 466 }
474 467 break;
475 468 }
476 469 mutex_unlock(&name_addrlock);
477 470 }
478 471
479 472 SMHASH(new->id.mon_id.mon_name, hash);
480 473 mutex_lock(&mon_table[hash].lock);
481 474 monitor_q = mon_table[hash].sm_monhdp;
482 475
483 476 /* If mon_table hash list is empty. */
484 477 if (monitor_q == (struct mon_entry *)NULL) {
485 478 if (debug)
486 479 (void) printf("\nAdding to monitor_q hash %d\n", hash);
487 480 new->nxt = new->prev = (mon_entry *)NULL;
488 481 mon_table[hash].sm_monhdp = new;
489 482 mutex_unlock(&mon_table[hash].lock);
490 483 return;
491 484 } else {
492 485 found = 0;
493 486 my_idp = &new->id.mon_id.my_id;
494 487 while (monitor_q != (mon_entry *)NULL) {
495 488 /*
496 489 * This list is searched sequentially for the
497 490 * tuple (hostname, prog, vers, proc). The tuples
498 491 * are inserted in the beginning of the monitor_q,
499 492 * if the hostname is not already present in the list.
500 493 * If the hostname is found in the list, the incoming
501 494 * tuple is inserted just after all the tuples with the
502 495 * same hostname. However, if the tuple matches exactly
503 496 * with an entry in the list, space allocated for the
504 497 * new entry is released and nothing is inserted in the
505 498 * list.
506 499 */
507 500
508 501 if (str_cmp_unqual_hostname(
509 502 monitor_q->id.mon_id.mon_name,
510 503 new->id.mon_id.mon_name) == 0) {
511 504 /* found */
512 505 nl_idp = &monitor_q->id.mon_id.my_id;
513 506 if ((str_cmp_unqual_hostname(my_idp->my_name,
514 507 nl_idp->my_name) == 0) &&
515 508 my_idp->my_prog == nl_idp->my_prog &&
516 509 my_idp->my_vers == nl_idp->my_vers &&
517 510 my_idp->my_proc == nl_idp->my_proc) {
518 511 /*
519 512 * already exists an identical one,
520 513 * release the space allocated for the
521 514 * mon_entry
522 515 */
523 516 free(new->id.mon_id.mon_name);
524 517 free(new->id.mon_id.my_id.my_name);
525 518 free(new);
526 519 mutex_unlock(&mon_table[hash].lock);
527 520 return;
528 521 } else {
529 522 /*
530 523 * mark the last callback that is
531 524 * not matching; new is inserted
532 525 * after this
533 526 */
534 527 found = monitor_q;
535 528 }
536 529 } else if (found)
537 530 break;
538 531 monitor_q = monitor_q->nxt;
539 532 }
540 533 if (found) {
541 534 /*
542 535 * insert just after the entry having matching tuple.
543 536 */
544 537 new->nxt = found->nxt;
545 538 new->prev = found;
546 539 if (found->nxt != (mon_entry *)NULL)
547 540 found->nxt->prev = new;
548 541 found->nxt = new;
549 542 } else {
550 543 /*
551 544 * not found, insert in front of list.
552 545 */
553 546 new->nxt = mon_table[hash].sm_monhdp;
554 547 new->prev = (mon_entry *) NULL;
555 548 if (new->nxt != (mon_entry *) NULL)
556 549 new->nxt->prev = new;
557 550 mon_table[hash].sm_monhdp = new;
558 551 }
559 552 mutex_unlock(&mon_table[hash].lock);
560 553 return;
561 554 }
562 555 }
563 556
564 557 /*
565 558 * Deletes a specific monitor name or deletes all monitors with same id
566 559 * in hash table.
567 560 */
568 561 static void
569 562 delete_mon(mon_name, my_idp)
570 563 char *mon_name;
571 564 my_id *my_idp;
572 565 {
573 566 unsigned int hash;
574 567
575 568 if (mon_name != (char *)NULL) {
576 569 record_name(mon_name, 0);
577 570 SMHASH(mon_name, hash);
578 571 mutex_lock(&mon_table[hash].lock);
579 572 delete_onemon(mon_name, my_idp, &mon_table[hash].sm_monhdp);
580 573 mutex_unlock(&mon_table[hash].lock);
581 574 } else {
582 575 for (hash = 0; hash < MAX_HASHSIZE; hash++) {
583 576 mutex_lock(&mon_table[hash].lock);
584 577 delete_onemon(mon_name, my_idp,
585 578 &mon_table[hash].sm_monhdp);
586 579 mutex_unlock(&mon_table[hash].lock);
587 580 }
588 581 }
589 582 }
590 583
591 584 /*
592 585 * Deletes a monitor in list.
593 586 * IF mon_name is NULL, delete all mon_names that have the same id,
594 587 * else delete specific monitor.
595 588 */
596 589 void
597 590 delete_onemon(mon_name, my_idp, monitor_q)
598 591 char *mon_name;
599 592 my_id *my_idp;
600 593 mon_entry **monitor_q;
601 594 {
602 595
603 596 mon_entry *next, *nl;
604 597 my_id *nl_idp;
605 598
606 599 next = *monitor_q;
607 600 while ((nl = next) != (struct mon_entry *)NULL) {
608 601 next = next->nxt;
609 602 if (mon_name == (char *)NULL || (mon_name != (char *)NULL &&
610 603 str_cmp_unqual_hostname(nl->id.mon_id.mon_name,
611 604 mon_name) == 0)) {
612 605 nl_idp = &nl->id.mon_id.my_id;
613 606 if ((str_cmp_unqual_hostname(my_idp->my_name,
614 607 nl_idp->my_name) == 0) &&
615 608 my_idp->my_prog == nl_idp->my_prog &&
616 609 my_idp->my_vers == nl_idp->my_vers &&
617 610 my_idp->my_proc == nl_idp->my_proc) {
618 611 /* found */
619 612 if (debug)
620 613 (void) printf("delete_mon(%x): %s\n",
621 614 (int)nl, mon_name ?
622 615 mon_name : "<NULL>");
623 616 /*
624 617 * Remove the monitor name from the
625 618 * record_q, if id matches.
626 619 */
627 620 record_name(nl->id.mon_id.mon_name, 0);
628 621 /* if nl is not the first entry on list */
629 622 if (nl->prev != (struct mon_entry *)NULL)
630 623 nl->prev->nxt = nl->nxt;
631 624 else {
632 625 *monitor_q = nl->nxt;
633 626 }
634 627 if (nl->nxt != (struct mon_entry *)NULL)
635 628 nl->nxt->prev = nl->prev;
636 629 free(nl->id.mon_id.mon_name);
637 630 free(nl_idp->my_name);
638 631 free(nl);
639 632 }
640 633 } /* end of if mon */
641 634 }
642 635
643 636 }
644 637 /*
645 638 * Notify lockd of host specified by mon_name that the specified state
646 639 * has changed.
647 640 */
648 641 static void
649 642 send_notice(mon_name, state)
650 643 char *mon_name;
651 644 int state;
652 645 {
653 646 struct mon_entry *next;
654 647 mon_entry *monitor_q;
655 648 unsigned int hash;
656 649 moninfo_t *minfop;
657 650 mon *monp;
658 651
659 652 SMHASH(mon_name, hash);
660 653 mutex_lock(&mon_table[hash].lock);
661 654 monitor_q = mon_table[hash].sm_monhdp;
662 655
663 656 next = monitor_q;
664 657 while (next != (struct mon_entry *)NULL) {
665 658 if (hostname_eq(next->id.mon_id.mon_name, mon_name)) {
666 659 monp = &next->id;
667 660 /*
668 661 * Prepare the minfop structure to pass to
669 662 * thr_create(). This structure is a copy of
670 663 * mon info and state.
671 664 */
672 665 if ((minfop =
673 666 (moninfo_t *)xmalloc(sizeof (moninfo_t))) !=
674 667 (moninfo_t *)NULL) {
675 668 (void) memcpy(&minfop->id, monp, sizeof (mon));
676 669 /* Allocate entry for mon_name */
677 670 if ((minfop->id.mon_id.mon_name =
678 671 strdup(monp->mon_id.mon_name)) == 0) {
679 672 syslog(LOG_ERR,
680 673 "statd: send_notice: malloc error on mon %s (id=%d)\n",
681 674 monp->mon_id.mon_name,
682 675 * ((int *)monp->priv));
683 676 free(minfop);
684 677 continue;
685 678 }
686 679 /* Allocate entry for my_name */
687 680 if ((minfop->id.mon_id.my_id.my_name =
688 681 strdup(monp->mon_id.my_id.my_name)) == 0) {
689 682 syslog(LOG_ERR,
690 683 "statd: send_notice: malloc error on mon %s (id=%d)\n",
691 684 monp->mon_id.mon_name,
692 685 * ((int *)monp->priv));
693 686 free(minfop->id.mon_id.mon_name);
694 687 free(minfop);
695 688 continue;
696 689 }
697 690 minfop->state = state;
698 691 /*
699 692 * Create detached threads to process each host
700 693 * to notify. If error, print out msg, free
701 694 * resources and continue.
702 695 */
703 696 if (thr_create(NULL, NULL, thr_send_notice,
704 697 (void *)minfop, THR_DETACHED,
705 698 NULL)) {
706 699 syslog(LOG_ERR,
707 700 "statd: unable to create thread to send_notice to %s.\n",
708 701 mon_name);
709 702 free(minfop->id.mon_id.mon_name);
710 703 free(minfop->id.mon_id.my_id.my_name);
711 704 free(minfop);
712 705 continue;
713 706 }
714 707 }
715 708 }
716 709 next = next->nxt;
717 710 }
718 711 mutex_unlock(&mon_table[hash].lock);
719 712 }
↓ open down ↓ |
518 lines elided |
↑ open up ↑ |
720 713
721 714 /*
722 715 * Work thread created to do the actual statd_call_lockd
723 716 */
724 717 static void *
725 718 thr_send_notice(void *arg)
726 719 {
727 720 moninfo_t *minfop;
728 721
729 722 minfop = (moninfo_t *)arg;
730 -
731 723 if (statd_call_lockd(&minfop->id, minfop->state) == -1) {
732 724 if (debug && minfop->id.mon_id.mon_name)
733 725 (void) printf("problem with notifying %s failure, "
734 726 "give up\n", minfop->id.mon_id.mon_name);
735 727 } else {
736 728 if (debug)
737 729 (void) printf("send_notice: %s, %d notified.\n",
738 730 minfop->id.mon_id.mon_name, minfop->state);
739 731 }
740 732
741 733 free(minfop->id.mon_id.mon_name);
742 734 free(minfop->id.mon_id.my_id.my_name);
743 735 free(minfop);
744 736
745 737 thr_exit((void *) 0);
746 738 #ifdef lint
747 739 /*NOTREACHED*/
748 740 return ((void *)0);
749 741 #endif
750 742 }
751 743
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
752 744 /*
753 745 * Contact lockd specified by monp.
754 746 */
755 747 static int
756 748 statd_call_lockd(monp, state)
757 749 mon *monp;
758 750 int state;
759 751 {
760 752 enum clnt_stat clnt_stat;
761 753 struct timeval tottimeout;
762 - struct status stat;
754 + struct sm_status stat;
763 755 my_id *my_idp;
764 756 char *mon_name;
765 757 int i;
766 758 int rc = 0;
767 759 CLIENT *clnt;
768 760
769 761 mon_name = monp->mon_id.mon_name;
770 762 my_idp = &monp->mon_id.my_id;
771 - (void) memset(&stat, 0, sizeof (struct status));
763 + (void) memset(&stat, 0, sizeof (stat));
772 764 stat.mon_name = mon_name;
773 765 stat.state = state;
774 766 for (i = 0; i < 16; i++) {
775 767 stat.priv[i] = monp->priv[i];
776 768 }
777 769 if (debug)
778 770 (void) printf("statd_call_lockd: %s state = %d\n",
779 771 stat.mon_name, stat.state);
780 772
781 773 tottimeout.tv_sec = SM_RPC_TIMEOUT;
782 774 tottimeout.tv_usec = 0;
783 775
784 - if ((clnt = create_client(my_idp->my_name, my_idp->my_prog,
785 - my_idp->my_vers, &tottimeout)) == (CLIENT *) NULL) {
786 - return (-1);
776 + clnt = create_client(my_idp->my_name, my_idp->my_prog, my_idp->my_vers,
777 + "ticotsord", &tottimeout);
778 + if (clnt == NULL) {
779 + return (-1);
787 780 }
788 781
789 - clnt_stat = clnt_call(clnt, my_idp->my_proc, xdr_status, (char *)&stat,
782 + clnt_stat = clnt_call(clnt, my_idp->my_proc,
783 + xdr_sm_status, (char *)&stat,
790 784 xdr_void, NULL, tottimeout);
791 785 if (debug) {
792 786 (void) printf("clnt_stat=%s(%d)\n",
793 787 clnt_sperrno(clnt_stat), clnt_stat);
794 788 }
795 789 if (clnt_stat != (int)RPC_SUCCESS) {
796 790 syslog(LOG_WARNING,
797 791 "statd: cannot talk to lockd at %s, %s(%d)\n",
798 792 my_idp->my_name, clnt_sperrno(clnt_stat), clnt_stat);
799 793 rc = -1;
800 794 }
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
801 795
802 796 clnt_destroy(clnt);
803 797 return (rc);
804 798
805 799 }
806 800
807 801 /*
808 802 * Client handle created.
809 803 */
810 804 CLIENT *
811 -create_client(host, prognum, versnum, utimeout)
812 - char *host;
813 - int prognum;
814 - int versnum;
815 - struct timeval *utimeout;
805 +create_client(char *host, int prognum, int versnum, char *netid,
806 + struct timeval *utimeout)
816 807 {
817 808 int fd;
818 809 struct timeval timeout;
819 810 CLIENT *client;
820 811 struct t_info tinfo;
821 812
822 - if ((client = clnt_create_timed(host, prognum, versnum,
823 - "netpath", utimeout)) == NULL) {
813 + if (netid == NULL) {
814 + client = clnt_create_timed(host, prognum, versnum,
815 + "netpath", utimeout);
816 + } else {
817 + struct netconfig *nconf;
818 +
819 + nconf = getnetconfigent(netid);
820 + if (nconf == NULL) {
821 + return (NULL);
822 + }
823 +
824 + client = clnt_tp_create_timed(host, prognum, versnum, nconf,
825 + utimeout);
826 +
827 + freenetconfigent(nconf);
828 + }
829 +
830 + if (client == NULL) {
824 831 return (NULL);
825 832 }
833 +
826 834 (void) CLNT_CONTROL(client, CLGET_FD, (caddr_t)&fd);
827 835 if (t_getinfo(fd, &tinfo) != -1) {
828 836 if (tinfo.servtype == T_CLTS) {
829 837 /*
830 838 * Set time outs for connectionless case
831 839 */
832 840 timeout.tv_usec = 0;
833 841 timeout.tv_sec = SM_CLTS_TIMEOUT;
834 842 (void) CLNT_CONTROL(client,
835 843 CLSET_RETRY_TIMEOUT, (caddr_t)&timeout);
836 844 }
837 845 } else
838 846 return (NULL);
839 847
840 848 return (client);
841 849 }
842 850
843 851 /*
844 852 * ONLY for debugging.
845 853 * Debug messages which prints out the monitor table information.
846 854 * If name is specified, just print out the hash list corresponding
847 855 * to name, otherwise print out the entire monitor table.
848 856 */
849 857 static void
850 858 pr_mon(name)
851 859 char *name;
852 860 {
853 861 mon_entry *nl;
854 862 int hash;
855 863
856 864 if (!debug)
857 865 return;
858 866
859 867 /* print all */
860 868 if (name == NULL) {
861 869 for (hash = 0; hash < MAX_HASHSIZE; hash++) {
862 870 mutex_lock(&mon_table[hash].lock);
863 871 nl = mon_table[hash].sm_monhdp;
864 872 if (nl == (struct mon_entry *)NULL) {
865 873 (void) printf(
866 874 "*****monitor_q = NULL hash %d\n",
867 875 hash);
868 876 mutex_unlock(&mon_table[hash].lock);
869 877 continue;
870 878 }
871 879 (void) printf("*****monitor_q:\n ");
872 880 while (nl != (mon_entry *)NULL) {
873 881 (void) printf("%s:(%x), ",
874 882 nl->id.mon_id.mon_name, (int)nl);
875 883 nl = nl->nxt;
876 884 }
877 885 mutex_unlock(&mon_table[hash].lock);
878 886 (void) printf("\n");
879 887 }
880 888 } else { /* print one hash list */
881 889 SMHASH(name, hash);
882 890 mutex_lock(&mon_table[hash].lock);
883 891 nl = mon_table[hash].sm_monhdp;
884 892 if (nl == (struct mon_entry *)NULL) {
885 893 (void) printf("*****monitor_q = NULL hash %d\n", hash);
886 894 } else {
887 895 (void) printf("*****monitor_q:\n ");
888 896 while (nl != (mon_entry *)NULL) {
889 897 (void) printf("%s:(%x), ",
890 898 nl->id.mon_id.mon_name, (int)nl);
891 899 nl = nl->nxt;
892 900 }
893 901 (void) printf("\n");
894 902 }
895 903 mutex_unlock(&mon_table[hash].lock);
896 904 }
897 905 }
898 906
899 907 /*
900 908 * Only for debugging.
901 909 * Dump the host name-to-address translation table passed in `name_addr'.
902 910 */
903 911 static void
904 912 pr_name_addr(name_addr_entry_t *name_addr)
905 913 {
906 914 name_addr_entry_t *entry;
907 915 addr_entry_t *addr;
908 916 struct in_addr ipv4_addr;
909 917 char *ipv6_addr;
910 918 char abuf[INET6_ADDRSTRLEN];
911 919
912 920 assert(MUTEX_HELD(&name_addrlock));
913 921 (void) printf("name-to-address translation table:\n");
914 922 for (entry = name_addr; entry != NULL; entry = entry->next) {
915 923 (void) printf("\t%s: ",
916 924 (entry->name ? entry->name : "(null)"));
917 925 for (addr = entry->addresses; addr; addr = addr->next) {
918 926 switch (addr->family) {
919 927 case AF_INET:
920 928 ipv4_addr = *(struct in_addr *)addr->ah.n_bytes;
921 929 (void) printf(" %s (fam %d)",
922 930 inet_ntoa(ipv4_addr), addr->family);
923 931 break;
924 932 case AF_INET6:
925 933 ipv6_addr = (char *)addr->ah.n_bytes;
926 934 (void) printf(" %s (fam %d)",
927 935 inet_ntop(addr->family, ipv6_addr, abuf,
928 936 sizeof (abuf)), addr->family);
929 937 break;
930 938 default:
931 939 return;
932 940 }
933 941 }
934 942 printf("\n");
935 943 }
936 944 }
937 945
938 946 /*
939 947 * First, try to compare the hostnames as strings. If the hostnames does not
940 948 * match we might deal with the hostname aliases. In this case two different
941 949 * aliases for the same machine don't match each other when using strcmp. To
942 950 * deal with this, the hostnames must be translated into some sort of universal
943 951 * identifier. These identifiers can be compared. Universal network addresses
944 952 * are currently used for this identifier because it is general and easy to do.
945 953 * Other schemes are possible and this routine could be converted if required.
946 954 *
947 955 * If it can't find an address for some reason, 0 is returned.
948 956 */
949 957 static int
950 958 hostname_eq(char *host1, char *host2)
951 959 {
952 960 char *sysid1;
953 961 char *sysid2;
954 962 int rv;
955 963
956 964 /* Compare hostnames as strings */
957 965 if (host1 != NULL && host2 != NULL && strcmp(host1, host2) == 0)
958 966 return (1);
959 967
960 968 /* Try harder if hostnames do not match */
961 969 sysid1 = get_system_id(host1);
962 970 sysid2 = get_system_id(host2);
963 971 if ((sysid1 == NULL) || (sysid2 == NULL))
964 972 rv = 0;
965 973 else
966 974 rv = (strcmp(sysid1, sysid2) == 0);
967 975 free(sysid1);
968 976 free(sysid2);
969 977 return (rv);
970 978 }
971 979
972 980 /*
973 981 * Convert a hostname character string into its network address.
974 982 * A network address is found by searching through all the entries
975 983 * in /etc/netconfig and doing a netdir_getbyname() for each inet
976 984 * entry found. The netbuf structure returned is converted into
977 985 * a universal address format.
978 986 *
979 987 * If a NULL hostname is given, then the name of the current host
980 988 * is used. If the hostname doesn't map to an address, a NULL
981 989 * pointer is returned.
982 990 *
983 991 * N.B. the character string returned is allocated in taddr2uaddr()
984 992 * and should be freed by the caller using free().
985 993 */
986 994 static char *
987 995 get_system_id(char *hostname)
988 996 {
989 997 void *hp;
990 998 struct netconfig *ncp;
991 999 struct nd_hostserv service;
992 1000 struct nd_addrlist *addrs;
993 1001 char *uaddr;
994 1002 int rv;
995 1003
996 1004 if (hostname == NULL)
997 1005 service.h_host = HOST_SELF;
998 1006 else
999 1007 service.h_host = hostname;
1000 1008 service.h_serv = NULL;
1001 1009 hp = setnetconfig();
1002 1010 if (hp == (void *) NULL) {
1003 1011 return (NULL);
1004 1012 }
1005 1013 while ((ncp = getnetconfig(hp)) != (struct netconfig *)NULL) {
1006 1014 if ((strcmp(ncp->nc_protofmly, NC_INET) == 0) ||
1007 1015 (strcmp(ncp->nc_protofmly, NC_INET6) == 0)) {
1008 1016 addrs = NULL;
1009 1017 rv = netdir_getbyname(ncp, &service, &addrs);
1010 1018 if (rv != 0) {
1011 1019 continue;
1012 1020 }
1013 1021 if (addrs) {
1014 1022 uaddr = taddr2uaddr(ncp, addrs->n_addrs);
1015 1023 netdir_free(addrs, ND_ADDRLIST);
1016 1024 endnetconfig(hp);
1017 1025 return (uaddr);
1018 1026 }
1019 1027 }
1020 1028 else
1021 1029 continue;
1022 1030 }
1023 1031 endnetconfig(hp);
1024 1032 return (NULL);
1025 1033 }
1026 1034
1027 1035 void
1028 1036 merge_hosts(void)
1029 1037 {
1030 1038 struct lifconf *lifc = NULL;
1031 1039 int sock = -1;
1032 1040 struct lifreq *lifrp;
1033 1041 struct lifreq lifr;
1034 1042 int n;
1035 1043 struct sockaddr_in *sin;
1036 1044 struct sockaddr_in6 *sin6;
1037 1045 struct sockaddr_storage *sa;
1038 1046 int af;
1039 1047 struct hostent *phost;
1040 1048 char *addr;
1041 1049 size_t alen;
1042 1050 int errnum;
1043 1051
1044 1052 /*
1045 1053 * This function will enumerate all the interfaces for
1046 1054 * this platform, then get the hostent for each i/f.
1047 1055 * With the hostent structure, we can get all of the
1048 1056 * aliases for the i/f. Then we'll merge all the aliases
1049 1057 * with the existing host_name[] list to come up with
1050 1058 * all of the known names for each interface. This solves
1051 1059 * the problem of a multi-homed host not knowing which
1052 1060 * name to publish when statd is started. All the aliases
1053 1061 * will be stored in the array, host_name.
1054 1062 *
1055 1063 * NOTE: Even though we will use all of the aliases we
1056 1064 * can get from the i/f hostent, the receiving statd
1057 1065 * will still need to handle aliases with hostname_eq.
1058 1066 * This is because the sender's aliases may not match
1059 1067 * those of the receiver.
1060 1068 */
1061 1069 lifc = getmyaddrs();
1062 1070 if (lifc == (struct lifconf *)NULL) {
1063 1071 goto finish;
1064 1072 }
1065 1073 lifrp = lifc->lifc_req;
1066 1074 for (n = lifc->lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) {
1067 1075
1068 1076 (void) strncpy(lifr.lifr_name, lifrp->lifr_name,
1069 1077 sizeof (lifr.lifr_name));
1070 1078
1071 1079 af = lifrp->lifr_addr.ss_family;
1072 1080 sock = socket(af, SOCK_DGRAM, 0);
1073 1081 if (sock == -1) {
1074 1082 syslog(LOG_ERR, "statd: socket failed\n");
1075 1083 goto finish;
1076 1084 }
1077 1085
1078 1086 /* If it's the loopback interface, ignore */
1079 1087 if (ioctl(sock, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
1080 1088 syslog(LOG_ERR,
1081 1089 "statd: SIOCGLIFFLAGS failed, error: %m\n");
1082 1090 goto finish;
1083 1091 }
1084 1092 if (lifr.lifr_flags & IFF_LOOPBACK)
1085 1093 continue;
1086 1094
1087 1095 if (ioctl(sock, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
1088 1096 syslog(LOG_ERR,
1089 1097 "statd: SIOCGLIFADDR failed, error: %m\n");
1090 1098 goto finish;
1091 1099 }
1092 1100 sa = (struct sockaddr_storage *)&(lifr.lifr_addr);
1093 1101
1094 1102 if (sa->ss_family == AF_INET) {
1095 1103 sin = (struct sockaddr_in *)&lifr.lifr_addr;
1096 1104 addr = (char *)(&sin->sin_addr);
1097 1105 alen = sizeof (struct in_addr);
1098 1106 } else if (sa->ss_family == AF_INET6) {
1099 1107 sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
1100 1108 addr = (char *)(&sin6->sin6_addr);
1101 1109 alen = sizeof (struct in6_addr);
1102 1110 } else {
1103 1111 syslog(LOG_WARNING,
1104 1112 "unexpected address family (%d)",
1105 1113 sa->ss_family);
1106 1114 continue;
1107 1115 }
1108 1116
1109 1117 phost = getipnodebyaddr(addr, alen, sa->ss_family, &errnum);
1110 1118
1111 1119 if (phost)
1112 1120 add_aliases(phost);
1113 1121 }
1114 1122 /*
1115 1123 * Now, just in case we didn't get them all byaddr,
1116 1124 * let's look by name.
1117 1125 */
1118 1126 phost = getipnodebyname(hostname, AF_INET6, AI_ALL, &errnum);
1119 1127
1120 1128 if (phost)
1121 1129 add_aliases(phost);
1122 1130
1123 1131 finish:
1124 1132 if (sock != -1)
1125 1133 (void) close(sock);
1126 1134 if (lifc) {
1127 1135 free(lifc->lifc_buf);
1128 1136 free(lifc);
1129 1137 }
1130 1138 }
1131 1139
1132 1140 /*
1133 1141 * add_aliases traverses a hostent alias list, compares
1134 1142 * the aliases to the contents of host_name, and if an
1135 1143 * alias is not already present, adds it to host_name[].
1136 1144 */
1137 1145
1138 1146 static void
1139 1147 add_aliases(struct hostent *phost)
1140 1148 {
1141 1149 char **aliases;
1142 1150
1143 1151 if (!in_host_array(phost->h_name)) {
1144 1152 add_to_host_array(phost->h_name);
1145 1153 }
1146 1154
1147 1155 if (phost->h_aliases == NULL)
1148 1156 return; /* no aliases to register */
1149 1157
1150 1158 for (aliases = phost->h_aliases; *aliases != NULL; aliases++) {
1151 1159 if (!in_host_array(*aliases)) {
1152 1160 add_to_host_array(*aliases);
1153 1161 }
1154 1162 }
1155 1163 }
1156 1164
1157 1165 /*
1158 1166 * in_host_array checks if the given hostname exists in the host_name
1159 1167 * array. Returns 0 if the host doesn't exist, and 1 if it does exist
1160 1168 */
1161 1169 static int
1162 1170 in_host_array(char *host)
1163 1171 {
1164 1172 int i;
1165 1173
1166 1174 if (debug)
1167 1175 (void) printf("%s ", host);
1168 1176
1169 1177 if ((strcmp(hostname, host) == 0) || (strcmp(LOGHOST, host) == 0))
1170 1178 return (1);
1171 1179
1172 1180 for (i = 0; i < addrix; i++) {
1173 1181 if (strcmp(host_name[i], host) == 0)
1174 1182 return (1);
1175 1183 }
1176 1184
1177 1185 return (0);
1178 1186 }
1179 1187
1180 1188 /*
1181 1189 * add_to_host_array adds a hostname to the host_name array. But if
1182 1190 * the array is already full, then it first reallocates the array with
1183 1191 * HOST_NAME_INCR extra elements. If the realloc fails, then it does
1184 1192 * nothing and leaves host_name the way it was previous to the call.
1185 1193 */
1186 1194 static void
1187 1195 add_to_host_array(char *host) {
1188 1196
1189 1197 void *new_block = NULL;
1190 1198
1191 1199 /* Make sure we don't overrun host_name. */
1192 1200 if (addrix >= host_name_count) {
1193 1201 host_name_count += HOST_NAME_INCR;
1194 1202 new_block = realloc((void *)host_name,
1195 1203 host_name_count*sizeof (char *));
1196 1204 if (new_block != NULL)
1197 1205 host_name = new_block;
1198 1206 else {
1199 1207 host_name_count -= HOST_NAME_INCR;
1200 1208 return;
1201 1209 }
1202 1210 }
1203 1211
1204 1212 if ((host_name[addrix] = strdup(host)) != NULL)
1205 1213 addrix++;
1206 1214 }
1207 1215
1208 1216 /*
1209 1217 * Compares the unqualified hostnames for hosts. Returns 0 if the
1210 1218 * names match, and 1 if the names fail to match.
1211 1219 */
1212 1220 int
1213 1221 str_cmp_unqual_hostname(char *rawname1, char *rawname2)
1214 1222 {
1215 1223 size_t unq_len1, unq_len2;
1216 1224 char *domain;
1217 1225
1218 1226 if (debug) {
1219 1227 (void) printf("str_cmp_unqual: rawname1= %s, rawname2= %s\n",
1220 1228 rawname1, rawname2);
1221 1229 }
1222 1230
1223 1231 unq_len1 = strcspn(rawname1, ".");
1224 1232 unq_len2 = strcspn(rawname2, ".");
1225 1233 domain = strchr(rawname1, '.');
1226 1234 if (domain != NULL) {
1227 1235 if ((strncmp(rawname1, SM_ADDR_IPV4, unq_len1) == 0) ||
1228 1236 (strncmp(rawname1, SM_ADDR_IPV6, unq_len1) == 0))
1229 1237 return (1);
1230 1238 }
1231 1239
1232 1240 if ((unq_len1 == unq_len2) &&
1233 1241 (strncmp(rawname1, rawname2, unq_len1) == 0)) {
1234 1242 return (0);
1235 1243 }
1236 1244
1237 1245 return (1);
1238 1246 }
1239 1247
1240 1248 /*
1241 1249 * Compares <family>.<address-specifier> ASCII names for hosts. Returns
1242 1250 * 0 if the addresses match, and 1 if the addresses fail to match.
1243 1251 * If the args are indeed specifiers, they should look like this:
1244 1252 *
1245 1253 * ipv4.192.9.200.1 or ipv6.::C009:C801
1246 1254 */
1247 1255 int
1248 1256 str_cmp_address_specifier(char *specifier1, char *specifier2)
1249 1257 {
1250 1258 size_t unq_len1, unq_len2;
1251 1259 char *rawaddr1, *rawaddr2;
1252 1260 int af1, af2, len;
1253 1261
1254 1262 if (debug) {
1255 1263 (void) printf("str_cmp_addr: specifier1= %s, specifier2= %s\n",
1256 1264 specifier1, specifier2);
1257 1265 }
1258 1266
1259 1267 /*
1260 1268 * Verify that:
1261 1269 * 1. The family tokens match;
1262 1270 * 2. The IP addresses following the `.' are legal; and
1263 1271 * 3. These addresses match.
1264 1272 */
1265 1273 unq_len1 = strcspn(specifier1, ".");
1266 1274 unq_len2 = strcspn(specifier2, ".");
1267 1275 rawaddr1 = strchr(specifier1, '.');
1268 1276 rawaddr2 = strchr(specifier2, '.');
1269 1277
1270 1278 if (strncmp(specifier1, SM_ADDR_IPV4, unq_len1) == 0) {
1271 1279 af1 = AF_INET;
1272 1280 len = 4;
1273 1281 } else if (strncmp(specifier1, SM_ADDR_IPV6, unq_len1) == 0) {
1274 1282 af1 = AF_INET6;
1275 1283 len = 16;
1276 1284 }
1277 1285 else
1278 1286 return (1);
1279 1287
1280 1288 if (strncmp(specifier2, SM_ADDR_IPV4, unq_len2) == 0)
1281 1289 af2 = AF_INET;
1282 1290 else if (strncmp(specifier2, SM_ADDR_IPV6, unq_len2) == 0)
1283 1291 af2 = AF_INET6;
1284 1292 else
1285 1293 return (1);
1286 1294
1287 1295 if (af1 != af2)
1288 1296 return (1);
1289 1297
1290 1298 if (rawaddr1 != NULL && rawaddr2 != NULL) {
1291 1299 char dst1[16];
1292 1300 char dst2[16];
↓ open down ↓ |
457 lines elided |
↑ open up ↑ |
1293 1301 ++rawaddr1;
1294 1302 ++rawaddr2;
1295 1303
1296 1304 if (inet_pton(af1, rawaddr1, dst1) == 1 &&
1297 1305 inet_pton(af2, rawaddr1, dst2) == 1 &&
1298 1306 memcmp(dst1, dst2, len) == 0) {
1299 1307 return (0);
1300 1308 }
1301 1309 }
1302 1310 return (1);
1311 +}
1312 +
1313 +/*
1314 + * Add IP address strings to the host_name list.
1315 + */
1316 +void
1317 +merge_ips(void)
1318 +{
1319 + struct ifaddrs *ifap, *cifap;
1320 + int error;
1321 +
1322 + error = getifaddrs(&ifap);
1323 + if (error) {
1324 + syslog(LOG_WARNING, "getifaddrs error: '%s'",
1325 + strerror(errno));
1326 + return;
1327 + }
1328 +
1329 + for (cifap = ifap; cifap != NULL; cifap = cifap->ifa_next) {
1330 + struct sockaddr *sa = cifap->ifa_addr;
1331 + char addr_str[INET6_ADDRSTRLEN];
1332 + void *addr = NULL;
1333 +
1334 + switch (sa->sa_family) {
1335 + case AF_INET: {
1336 + struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1337 +
1338 + /* Skip loopback addresses. */
1339 + if (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
1340 + continue;
1341 + }
1342 +
1343 + addr = &sin->sin_addr;
1344 + break;
1345 + }
1346 +
1347 + case AF_INET6: {
1348 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
1349 +
1350 + /* Skip loopback addresses. */
1351 + if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) {
1352 + continue;
1353 + }
1354 +
1355 + addr = &sin6->sin6_addr;
1356 + break;
1357 + }
1358 +
1359 + default:
1360 + syslog(LOG_WARNING, "Unknown address family %d for "
1361 + "interface %s", sa->sa_family, cifap->ifa_name);
1362 + continue;
1363 + }
1364 +
1365 + if (inet_ntop(sa->sa_family, addr, addr_str, sizeof (addr_str))
1366 + == NULL) {
1367 + syslog(LOG_WARNING, "Failed to convert address into "
1368 + "string representation for interface '%s' "
1369 + "address family %d", cifap->ifa_name,
1370 + sa->sa_family);
1371 + continue;
1372 + }
1373 +
1374 + if (!in_host_array(addr_str)) {
1375 + add_to_host_array(addr_str);
1376 + }
1377 + }
1378 +
1379 + freeifaddrs(ifap);
1303 1380 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX