/* * Create an rpc client attached to the mount daemon. */ CLIENT * get_mount_client(char *unused_host, struct sockaddr_in *sin, struct timeval *tv, int *sock, u_long mnt_version) { CLIENT *client; /* * First try a TCP socket */ if ((*sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0) { /* * Bind to a privileged port */ if (bind_resv_port(*sock, (u_short *) NULL) < 0) plog(XLOG_ERROR, "can't bind privileged port (socket)"); /* * Find mountd port to connect to. * Connect to mountd. * Create a tcp client. */ if ((sin->sin_port = htons(pmap_getport(sin, MOUNTPROG, mnt_version, IPPROTO_TCP))) != 0) { if (connect(*sock, (struct sockaddr *) sin, sizeof(*sin)) >= 0 && ((client = clnttcp_create(sin, MOUNTPROG, mnt_version, sock, 0, 0)) != NULL)) return client; } /* * Failed so close socket */ (void) close(*sock); } /* tcp socket opened */ /* TCP failed so try UDP */ if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { plog(XLOG_ERROR, "Can't create socket to connect to mountd: %m"); *sock = RPC_ANYSOCK; return NULL; } /* * Bind to a privileged port */ if (bind_resv_port(*sock, (u_short *) NULL) < 0) plog(XLOG_ERROR, "can't bind privileged port"); /* * Zero out the port - make sure we recompute */ sin->sin_port = 0; /* * Make a UDP client */ if ((client = clntudp_create(sin, MOUNTPROG, mnt_version, *tv, sock)) == NULL) { (void) close(*sock); *sock = RPC_ANYSOCK; return NULL; } dlog("get_mount_client: Using udp, port %d", sin->sin_port); return client; }
/* * Register the autofs service for amd */ int register_autofs_service(char *autofs_conftype, void (*autofs_dispatch)(struct svc_req *rqstp, SVCXPRT *transp)) { int autofs_socket; SVCXPRT *autofs_xprt = NULL; autofs_socket = socket(AF_INET, SOCK_DGRAM, 0); if (autofs_socket < 0 || bind_resv_port(autofs_socket, NULL) < 0) { plog(XLOG_FATAL, "Can't create privileged autofs port (socket)"); return 1; } if ((autofs_xprt = svcudp_create(autofs_socket)) == NULL) { plog(XLOG_FATAL, "Can't create autofs rpc/udp service"); return 2; } if (autofs_xprt->xp_port >= IPPORT_RESERVED) { plog(XLOG_FATAL, "Can't create privileged autofs port"); return 1; } if (!svc_register(autofs_xprt, AUTOFS_PROG, AUTOFS_VERS, autofs_dispatch, 0)) { plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)", (u_long) AUTOFS_PROG, (u_long) AUTOFS_VERS); return 3; } return 0; /* all is well */ }
/* * Create the nfs service for amd */ int create_nfs_service(int *soNFSp, u_short *nfs_portp, SVCXPRT **nfs_xprtp, void (*dispatch_fxn)(struct svc_req *rqstp, SVCXPRT *transp)) { *soNFSp = socket(AF_INET, SOCK_DGRAM, 0); if (*soNFSp < 0 || bind_resv_port(*soNFSp, nfs_portp) < 0) { plog(XLOG_FATAL, "Can't create privileged nfs port (socket)"); if (*soNFSp >= 0) close(*soNFSp); return 1; } if ((*nfs_xprtp = svcudp_create(*soNFSp)) == NULL) { plog(XLOG_FATAL, "cannot create rpc/udp service"); close(*soNFSp); return 2; } if ((*nfs_portp = (*nfs_xprtp)->xp_port) >= IPPORT_RESERVED) { plog(XLOG_FATAL, "Can't create privileged nfs port"); svc_destroy(*nfs_xprtp); close(*soNFSp); return 1; } if (!svc_register(*nfs_xprtp, NFS_PROGRAM, NFS_VERSION, dispatch_fxn, 0)) { plog(XLOG_FATAL, "unable to register (%ld, %ld, 0)", (u_long) NFS_PROGRAM, (u_long) NFS_VERSION); svc_destroy(*nfs_xprtp); close(*soNFSp); return 3; } return 0; /* all is well */ }
/* * Create the amq service for amd (both TCP and UDP) */ int create_amq_service(int *udp_soAMQp, SVCXPRT **udp_amqpp, struct netconfig **dummy1, int *tcp_soAMQp, SVCXPRT **tcp_amqpp, struct netconfig **dummy2, u_short preferred_amq_port) { /* first create TCP service */ if (tcp_soAMQp) { *tcp_soAMQp = socket(AF_INET, SOCK_STREAM, 0); if (*tcp_soAMQp < 0) { plog(XLOG_FATAL, "cannot create tcp socket for amq service: %m"); return 1; } /* next, bind to a specific (TCP) port if asked for */ if (preferred_amq_port > 0) { /* * Note: if &preferred_amq_port is non-null and is greater than 0, * then the pointer will not be modified. We don't want it to be * modified because it was passed down to create_amq_service as a * non-pointer (a variable on the stack, not to be modified!) */ if (bind_resv_port(*tcp_soAMQp, &preferred_amq_port) < 0) { plog(XLOG_FATAL, "can't bind amq service to requested TCP port %d: %m)", preferred_amq_port); return 1; } } /* now create RPC service handle for amq */ if (tcp_amqpp && (*tcp_amqpp = svctcp_create(*tcp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) { plog(XLOG_FATAL, "cannot create tcp service for amq: soAMQp=%d", *tcp_soAMQp); return 1; } #ifdef SVCSET_CONNMAXREC /* * This is *BSD at its best. * They just had to do things differently than everyone else * so they fixed a library DoS issue by forcing client-side changes... */ # ifndef RPC_MAXDATASIZE # define RPC_MAXDATASIZE 9000 # endif /* not RPC_MAXDATASIZE */ if (tcp_amqpp) { int maxrec = RPC_MAXDATASIZE; SVC_CONTROL(*tcp_amqpp, SVCSET_CONNMAXREC, &maxrec); } #endif /* not SVCSET_CONNMAXREC */ } /* next create UDP service */ if (udp_soAMQp) { *udp_soAMQp = socket(AF_INET, SOCK_DGRAM, 0); if (*udp_soAMQp < 0) { plog(XLOG_FATAL, "cannot create udp socket for amq service: %m"); return 1; } /* next, bind to a specific (UDP) port if asked for */ if (preferred_amq_port > 0) { /* * Note: see comment about using &preferred_amq_port above in this * function. */ if (bind_resv_port(*udp_soAMQp, &preferred_amq_port) < 0) { plog(XLOG_FATAL, "can't bind amq service to requested UDP port %d: %m)", preferred_amq_port); return 1; } } /* now create RPC service handle for amq */ if (udp_amqpp && (*udp_amqpp = svcudp_bufcreate(*udp_soAMQp, AMQ_SIZE, AMQ_SIZE)) == NULL) { plog(XLOG_FATAL, "cannot create udp service for amq: soAMQp=%d", *udp_soAMQp); return 1; } } return 0; /* all is well */ }
/* * Create an rpc client attached to the mount daemon. */ CLIENT * get_mount_client(char *host, struct sockaddr_in *unused_sin, struct timeval *tv, int *sock, u_long mnt_version) { CLIENT *client; struct netbuf nb; struct netconfig *nc = NULL; struct sockaddr_in sin; nb.maxlen = sizeof(sin); nb.buf = (char *) &sin; /* * First try a TCP handler */ /* * Find mountd address on TCP */ if ((nc = getnetconfigent(NC_TCP)) == NULL) { plog(XLOG_ERROR, "getnetconfig for tcp failed: %s", nc_sperror()); goto tryudp; } if (!rpcb_getaddr(MOUNTPROG, mnt_version, nc, &nb, host)) { /* * don't print error messages here, since mountd might legitimately * serve udp only */ goto tryudp; } /* * Create privileged TCP socket */ *sock = t_open(nc->nc_device, O_RDWR, 0); if (*sock < 0) { plog(XLOG_ERROR, "t_open %s: %m", nc->nc_device); goto tryudp; } if (bind_resv_port(*sock, (u_short *) 0) < 0) plog(XLOG_ERROR, "couldn't bind mountd socket to privileged port"); if ((client = clnt_vc_create(*sock, &nb, MOUNTPROG, mnt_version, 0, 0)) == (CLIENT *) NULL) { plog(XLOG_ERROR, "clnt_vc_create failed"); t_close(*sock); goto tryudp; } /* tcp succeeded */ dlog("get_mount_client: using tcp, port %d", sin.sin_port); if (nc) freenetconfigent(nc); return client; tryudp: /* first free possibly previously allocated netconfig entry */ if (nc) freenetconfigent(nc); /* * TCP failed so try UDP */ /* * Find mountd address on UDP */ if ((nc = getnetconfigent(NC_UDP)) == NULL) { plog(XLOG_ERROR, "getnetconfig for udp failed: %s", nc_sperror()); goto badout; } if (!rpcb_getaddr(MOUNTPROG, mnt_version, nc, &nb, host)) { plog(XLOG_ERROR, "%s", clnt_spcreateerror("couldn't get mountd address on udp")); goto badout; } /* * Create privileged UDP socket */ *sock = t_open(nc->nc_device, O_RDWR, 0); if (*sock < 0) { plog(XLOG_ERROR, "t_open %s: %m", nc->nc_device); goto badout; /* neither tcp not udp succeeded */ } if (bind_resv_port(*sock, (u_short *) 0) < 0) plog(XLOG_ERROR, "couldn't bind mountd socket to privileged port"); if ((client = clnt_dg_create(*sock, &nb, MOUNTPROG, mnt_version, 0, 0)) == (CLIENT *) NULL) { plog(XLOG_ERROR, "clnt_dg_create failed"); t_close(*sock); goto badout; /* neither tcp not udp succeeded */ } if (clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) tv) == FALSE) { plog(XLOG_ERROR, "clnt_control CLSET_RETRY_TIMEOUT for udp failed"); clnt_destroy(client); goto badout; /* neither tcp not udp succeeded */ } /* udp succeeded */ dlog("get_mount_client: using udp, port %d", sin.sin_port); return client; badout: /* failed */ if (nc) freenetconfigent(nc); return NULL; }