lockd.c (173411) | lockd.c (177633) |
---|---|
1/* $NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $ */ | 1/* $NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $ */ |
2/* $FreeBSD: head/usr.sbin/rpc.lockd/lockd.c 173411 2007-11-07 10:21:36Z matteo $ */ | 2/* $FreeBSD: head/usr.sbin/rpc.lockd/lockd.c 177633 2008-03-26 15:23:12Z dfr $ */ |
3 4/* 5 * Copyright (c) 1995 6 * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: --- 32 unchanged lines hidden (view full) --- 43 * main() function for NFS lock daemon. Most of the code in this 44 * file was generated by running rpcgen /usr/include/rpcsvc/nlm_prot.x. 45 * 46 * The actual program logic is in the file lock_proc.c 47 */ 48 49#include <sys/types.h> 50#include <sys/socket.h> | 3 4/* 5 * Copyright (c) 1995 6 * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: --- 32 unchanged lines hidden (view full) --- 43 * main() function for NFS lock daemon. Most of the code in this 44 * file was generated by running rpcgen /usr/include/rpcsvc/nlm_prot.x. 45 * 46 * The actual program logic is in the file lock_proc.c 47 */ 48 49#include <sys/types.h> 50#include <sys/socket.h> |
51#include <sys/stat.h> |
|
51 52#include <netinet/in.h> 53#include <arpa/inet.h> 54 55#include <err.h> 56#include <stdio.h> 57#include <stdlib.h> 58#include <errno.h> --- 12 unchanged lines hidden (view full) --- 71#include "lockd.h" 72#include <rpcsvc/nlm_prot.h> 73 74int debug_level = 0; /* 0 = no debugging syslog() calls */ 75int _rpcsvcdirty = 0; 76 77int grace_expired; 78int nsm_state; | 52 53#include <netinet/in.h> 54#include <arpa/inet.h> 55 56#include <err.h> 57#include <stdio.h> 58#include <stdlib.h> 59#include <errno.h> --- 12 unchanged lines hidden (view full) --- 72#include "lockd.h" 73#include <rpcsvc/nlm_prot.h> 74 75int debug_level = 0; /* 0 = no debugging syslog() calls */ 76int _rpcsvcdirty = 0; 77 78int grace_expired; 79int nsm_state; |
80int kernel_lockd; |
|
79pid_t client_pid; 80struct mon mon_host; 81char **hosts, *svcport_str = NULL; 82int nhosts = 0; 83int xcreated = 0; | 81pid_t client_pid; 82struct mon mon_host; 83char **hosts, *svcport_str = NULL; 84int nhosts = 0; 85int xcreated = 0; |
86char **addrs; /* actually (netid, uaddr) pairs */ 87int naddrs; /* count of how many (netid, uaddr) pairs */ |
|
84 85void create_service(struct netconfig *nconf); | 88 89void create_service(struct netconfig *nconf); |
90void lookup_addresses(struct netconfig *nconf); |
|
86void init_nsm(void); 87void nlm_prog_0(struct svc_req *, SVCXPRT *); 88void nlm_prog_1(struct svc_req *, SVCXPRT *); 89void nlm_prog_3(struct svc_req *, SVCXPRT *); 90void nlm_prog_4(struct svc_req *, SVCXPRT *); 91void out_of_mem(void); 92void usage(void); 93 94void sigalarm_handler(void); 95 | 91void init_nsm(void); 92void nlm_prog_0(struct svc_req *, SVCXPRT *); 93void nlm_prog_1(struct svc_req *, SVCXPRT *); 94void nlm_prog_3(struct svc_req *, SVCXPRT *); 95void nlm_prog_4(struct svc_req *, SVCXPRT *); 96void out_of_mem(void); 97void usage(void); 98 99void sigalarm_handler(void); 100 |
101/* 102 * XXX move to some header file. 103 */ 104#define _PATH_RPCLOCKDSOCK "/var/run/rpclockd.sock" 105 |
|
96int 97main(int argc, char **argv) 98{ 99 int ch, i, s; 100 void *nc_handle; 101 char *endptr, **hosts_bak; 102 struct sigaction sigalarm; 103 int grace_period = 30; 104 struct netconfig *nconf; 105 int have_v6 = 1; 106 int maxrec = RPC_MAXDATASIZE; 107 in_port_t svcport = 0; 108 | 106int 107main(int argc, char **argv) 108{ 109 int ch, i, s; 110 void *nc_handle; 111 char *endptr, **hosts_bak; 112 struct sigaction sigalarm; 113 int grace_period = 30; 114 struct netconfig *nconf; 115 int have_v6 = 1; 116 int maxrec = RPC_MAXDATASIZE; 117 in_port_t svcport = 0; 118 |
109 while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) { | 119 while ((ch = getopt(argc, argv, "d:g:h:kp:")) != (-1)) { |
110 switch (ch) { 111 case 'd': 112 debug_level = atoi(optarg); 113 if (!debug_level) { 114 usage(); 115 /* NOTREACHED */ 116 } 117 break; --- 20 unchanged lines hidden (view full) --- 138 hosts[nhosts - 1] = strdup(optarg); 139 if (hosts[nhosts - 1] == NULL) { 140 for (i = 0; i < (nhosts - 1); i++) 141 free(hosts[i]); 142 free(hosts); 143 out_of_mem(); 144 } 145 break; | 120 switch (ch) { 121 case 'd': 122 debug_level = atoi(optarg); 123 if (!debug_level) { 124 usage(); 125 /* NOTREACHED */ 126 } 127 break; --- 20 unchanged lines hidden (view full) --- 148 hosts[nhosts - 1] = strdup(optarg); 149 if (hosts[nhosts - 1] == NULL) { 150 for (i = 0; i < (nhosts - 1); i++) 151 free(hosts[i]); 152 free(hosts); 153 out_of_mem(); 154 } 155 break; |
156 case 'k': 157 kernel_lockd = TRUE; 158 break; |
|
146 case 'p': 147 endptr = NULL; 148 svcport = (in_port_t)strtoul(optarg, &endptr, 10); 149 if (endptr == NULL || *endptr != '\0' || 150 svcport == 0 || svcport >= IPPORT_MAX) 151 usage(); 152 svcport_str = strdup(optarg); 153 break; --- 62 unchanged lines hidden (view full) --- 216 } else { 217 nhosts += 1; 218 hosts = hosts_bak; 219 } 220 } 221 hosts[nhosts - 1] = "127.0.0.1"; 222 } 223 | 159 case 'p': 160 endptr = NULL; 161 svcport = (in_port_t)strtoul(optarg, &endptr, 10); 162 if (endptr == NULL || *endptr != '\0' || 163 svcport == 0 || svcport >= IPPORT_MAX) 164 usage(); 165 svcport_str = strdup(optarg); 166 break; --- 62 unchanged lines hidden (view full) --- 229 } else { 230 nhosts += 1; 231 hosts = hosts_bak; 232 } 233 } 234 hosts[nhosts - 1] = "127.0.0.1"; 235 } 236 |
224 nc_handle = setnetconfig(); 225 while ((nconf = getnetconfig(nc_handle))) { 226 /* We want to listen only on udp6, tcp6, udp, tcp transports */ 227 if (nconf->nc_flag & NC_VISIBLE) { 228 /* Skip if there's no IPv6 support */ 229 if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { 230 /* DO NOTHING */ 231 } else { 232 create_service(nconf); | 237 if (kernel_lockd) { 238 /* 239 * For the kernel lockd case, we run a cut-down RPC 240 * service on a local-domain socket. The kernel's RPC 241 * server will pass what it can't handle (mainly 242 * client replies) down to us. This can go away 243 * entirely if/when we move the client side of NFS 244 * locking into the kernel. 245 */ 246 struct sockaddr_un sun; 247 int fd, oldmask; 248 SVCXPRT *xprt; 249 250 memset(&sun, 0, sizeof sun); 251 sun.sun_family = AF_LOCAL; 252 unlink(_PATH_RPCLOCKDSOCK); 253 strcpy(sun.sun_path, _PATH_RPCLOCKDSOCK); 254 sun.sun_len = SUN_LEN(&sun); 255 fd = socket(AF_LOCAL, SOCK_STREAM, 0); 256 if (!fd) { 257 err(1, "Can't create local lockd socket"); 258 } 259 oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO); 260 if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) { 261 err(1, "Can't bind local lockd socket"); 262 } 263 umask(oldmask); 264 if (listen(fd, SOMAXCONN) < 0) { 265 err(1, "Can't listen on local lockd socket"); 266 } 267 xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE); 268 if (!xprt) { 269 err(1, "Can't create transport for local lockd socket"); 270 } 271 if (!svc_reg(xprt, NLM_PROG, NLM_VERS4, nlm_prog_4, NULL)) { 272 err(1, "Can't register service for local lockd socket"); 273 } 274 275 /* 276 * We need to look up the addresses so that we can 277 * hand uaddrs (ascii encoded address+port strings) to 278 * the kernel. 279 */ 280 nc_handle = setnetconfig(); 281 while ((nconf = getnetconfig(nc_handle))) { 282 /* We want to listen only on udp6, tcp6, udp, tcp transports */ 283 if (nconf->nc_flag & NC_VISIBLE) { 284 /* Skip if there's no IPv6 support */ 285 if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { 286 /* DO NOTHING */ 287 } else { 288 lookup_addresses(nconf); 289 } |
233 } 234 } | 290 } 291 } |
292 endnetconfig(nc_handle); 293 } else { 294 nc_handle = setnetconfig(); 295 while ((nconf = getnetconfig(nc_handle))) { 296 /* We want to listen only on udp6, tcp6, udp, tcp transports */ 297 if (nconf->nc_flag & NC_VISIBLE) { 298 /* Skip if there's no IPv6 support */ 299 if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { 300 /* DO NOTHING */ 301 } else { 302 create_service(nconf); 303 } 304 } 305 } 306 endnetconfig(nc_handle); |
|
235 } | 307 } |
236 endnetconfig(nc_handle); | |
237 238 /* 239 * Note that it is NOT sensible to run this program from inetd - the 240 * protocol assumes that it will run immediately at boot time. 241 */ 242 if (daemon(0, debug_level > 0)) { 243 err(1, "cannot fork"); 244 /* NOTREACHED */ --- 9 unchanged lines hidden (view full) --- 254 sigemptyset(&sigalarm.sa_mask); 255 sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */ 256 sigalarm.sa_flags |= SA_RESTART; 257 if (sigaction(SIGALRM, &sigalarm, NULL) != 0) { 258 syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s", 259 strerror(errno)); 260 exit(1); 261 } | 308 309 /* 310 * Note that it is NOT sensible to run this program from inetd - the 311 * protocol assumes that it will run immediately at boot time. 312 */ 313 if (daemon(0, debug_level > 0)) { 314 err(1, "cannot fork"); 315 /* NOTREACHED */ --- 9 unchanged lines hidden (view full) --- 325 sigemptyset(&sigalarm.sa_mask); 326 sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */ 327 sigalarm.sa_flags |= SA_RESTART; 328 if (sigaction(SIGALRM, &sigalarm, NULL) != 0) { 329 syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s", 330 strerror(errno)); 331 exit(1); 332 } |
262 grace_expired = 0; 263 alarm(grace_period); | |
264 | 333 |
265 init_nsm(); | 334 if (kernel_lockd) { 335 client_pid = client_request(); |
266 | 336 |
267 client_pid = client_request(); | 337 /* 338 * Create a child process to enter the kernel and then 339 * wait for RPCs on our local domain socket. 340 */ 341 if (!fork()) 342 nlm_syscall(debug_level, grace_period, naddrs, addrs); 343 else 344 svc_run(); 345 } else { 346 grace_expired = 0; 347 alarm(grace_period); |
268 | 348 |
269 svc_run(); /* Should never return */ | 349 init_nsm(); 350 351 client_pid = client_request(); 352 353 svc_run(); /* Should never return */ 354 } |
270 exit(1); 271} 272 273/* 274 * This routine creates and binds sockets on the appropriate 275 * addresses. It gets called one time for each transport and 276 * registrates the service with rpcbind on that trasport. 277 */ --- 216 unchanged lines hidden (view full) --- 494 rpcb_set(NLM_PROG, NLM_VERS4, nconf, &servaddr); 495 496 xcreated++; 497 freeaddrinfo(res); 498 } 499 } /* end while */ 500} 501 | 355 exit(1); 356} 357 358/* 359 * This routine creates and binds sockets on the appropriate 360 * addresses. It gets called one time for each transport and 361 * registrates the service with rpcbind on that trasport. 362 */ --- 216 unchanged lines hidden (view full) --- 579 rpcb_set(NLM_PROG, NLM_VERS4, nconf, &servaddr); 580 581 xcreated++; 582 freeaddrinfo(res); 583 } 584 } /* end while */ 585} 586 |
587/* 588 * Look up addresses for the kernel to create transports for. 589 */ |
|
502void | 590void |
591lookup_addresses(struct netconfig *nconf) 592{ 593 struct addrinfo hints, *res = NULL; 594 struct sockaddr_in *sin; 595 struct sockaddr_in6 *sin6; 596 struct __rpc_sockinfo si; 597 struct netbuf servaddr; 598 SVCXPRT *transp = NULL; 599 int aicode; 600 int nhostsbak; 601 int r; 602 int registered = 0; 603 u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 604 char *uaddr; 605 606 if ((nconf->nc_semantics != NC_TPI_CLTS) && 607 (nconf->nc_semantics != NC_TPI_COTS) && 608 (nconf->nc_semantics != NC_TPI_COTS_ORD)) 609 return; /* not my type */ 610 611 /* 612 * XXX - using RPC library internal functions. 613 */ 614 if (!__rpc_nconf2sockinfo(nconf, &si)) { 615 syslog(LOG_ERR, "cannot get information for %s", 616 nconf->nc_netid); 617 return; 618 } 619 620 /* Get rpc.statd's address on this transport */ 621 memset(&hints, 0, sizeof hints); 622 hints.ai_flags = AI_PASSIVE; 623 hints.ai_family = si.si_af; 624 hints.ai_socktype = si.si_socktype; 625 hints.ai_protocol = si.si_proto; 626 627 /* 628 * Bind to specific IPs if asked to 629 */ 630 nhostsbak = nhosts; 631 while (nhostsbak > 0) { 632 --nhostsbak; 633 634 switch (hints.ai_family) { 635 case AF_INET: 636 if (inet_pton(AF_INET, hosts[nhostsbak], 637 host_addr) == 1) { 638 hints.ai_flags &= AI_NUMERICHOST; 639 } else { 640 /* 641 * Skip if we have an AF_INET6 address. 642 */ 643 if (inet_pton(AF_INET6, hosts[nhostsbak], 644 host_addr) == 1) { 645 continue; 646 } 647 } 648 break; 649 case AF_INET6: 650 if (inet_pton(AF_INET6, hosts[nhostsbak], 651 host_addr) == 1) { 652 hints.ai_flags &= AI_NUMERICHOST; 653 } else { 654 /* 655 * Skip if we have an AF_INET address. 656 */ 657 if (inet_pton(AF_INET, hosts[nhostsbak], 658 host_addr) == 1) { 659 continue; 660 } 661 } 662 break; 663 default: 664 break; 665 } 666 667 /* 668 * If no hosts were specified, just bind to INADDR_ANY 669 */ 670 if (strcmp("*", hosts[nhostsbak]) == 0) { 671 if (svcport_str == NULL) { 672 res = malloc(sizeof(struct addrinfo)); 673 if (res == NULL) 674 out_of_mem(); 675 res->ai_flags = hints.ai_flags; 676 res->ai_family = hints.ai_family; 677 res->ai_protocol = hints.ai_protocol; 678 switch (res->ai_family) { 679 case AF_INET: 680 sin = malloc(sizeof(struct sockaddr_in)); 681 if (sin == NULL) 682 out_of_mem(); 683 sin->sin_family = AF_INET; 684 sin->sin_port = htons(0); 685 sin->sin_addr.s_addr = htonl(INADDR_ANY); 686 res->ai_addr = (struct sockaddr*) sin; 687 res->ai_addrlen = (socklen_t) 688 sizeof(res->ai_addr); 689 break; 690 case AF_INET6: 691 sin6 = malloc(sizeof(struct sockaddr_in6)); 692 if (sin6 == NULL) 693 out_of_mem(); 694 sin6->sin6_family = AF_INET6; 695 sin6->sin6_port = htons(0); 696 sin6->sin6_addr = in6addr_any; 697 res->ai_addr = (struct sockaddr*) sin6; 698 res->ai_addrlen = (socklen_t) sizeof(res->ai_addr); 699 break; 700 default: 701 break; 702 } 703 } else { 704 if ((aicode = getaddrinfo(NULL, svcport_str, 705 &hints, &res)) != 0) { 706 syslog(LOG_ERR, 707 "cannot get local address for %s: %s", 708 nconf->nc_netid, 709 gai_strerror(aicode)); 710 continue; 711 } 712 } 713 } else { 714 if ((aicode = getaddrinfo(hosts[nhostsbak], svcport_str, 715 &hints, &res)) != 0) { 716 syslog(LOG_ERR, 717 "cannot get local address for %s: %s", 718 nconf->nc_netid, gai_strerror(aicode)); 719 continue; 720 } 721 } 722 723 servaddr.len = servaddr.maxlen = res->ai_addr->sa_len; 724 servaddr.buf = res->ai_addr; 725 uaddr = taddr2uaddr(nconf, &servaddr); 726 727 addrs = realloc(addrs, 2 * (naddrs + 1) * sizeof(char *)); 728 if (!addrs) 729 out_of_mem(); 730 addrs[2 * naddrs] = strdup(nconf->nc_netid); 731 addrs[2 * naddrs + 1] = uaddr; 732 naddrs++; 733 } /* end while */ 734} 735 736void |
|
503sigalarm_handler(void) 504{ 505 506 grace_expired = 1; 507} 508 509void 510usage() 511{ | 737sigalarm_handler(void) 738{ 739 740 grace_expired = 1; 741} 742 743void 744usage() 745{ |
512 errx(1, "usage: rpc.lockd [-d | 746 errx(1, "usage: rpc.lockd [-k] [-d <debuglevel>]" |
513 " [-g <grace period>] [-h <bindip>] [-p <port>]"); 514} 515 516/* 517 * init_nsm -- 518 * Reset the NSM state-of-the-world and acquire its state. 519 */ 520void --- 54 unchanged lines hidden --- | 747 " [-g <grace period>] [-h <bindip>] [-p <port>]"); 748} 749 750/* 751 * init_nsm -- 752 * Reset the NSM state-of-the-world and acquire its state. 753 */ 754void --- 54 unchanged lines hidden --- |