Exemple #1
0
void
net_add_close_func(int sd, void (*func)(int))
{
	int	conn_idx = connection_find_actual_index(sd);

	if (conn_idx == -1)
		return;

	if (svr_conn[conn_idx].cn_active == Idle)
		return;

	svr_conn[conn_idx].cn_oncl =  func;
}
Exemple #2
0
/**
 * @brief
 * 		Function that causes a rerun request to return with a timeout message.
 *
 * @param[in,out]	pwt	-	work task which contains the job structure which holds the rerun request
 */
static void
timeout_rerun_request(struct work_task *pwt)
{
	job     *pjob = (job *)pwt->wt_parm1;
	int      conn_idx = -1;

	if ((pjob == NULL) || (pjob->ji_rerun_preq == NULL)) {
		return;	/* nothing to timeout */
	}
	if (pjob->ji_rerun_preq->rq_conn != PBS_LOCAL_CONNECTION) {
		conn_idx = connection_find_actual_index(pjob->ji_rerun_preq->rq_conn);
	}
	reply_text(pjob->ji_rerun_preq, PBSE_INTERNAL,
		"Response timed out. Job rerun request still in progress for");

	/* clear no-timeout flag on connection */
	if (conn_idx != -1)
		svr_conn[conn_idx].cn_authen &= ~PBS_NET_CONN_NOTIMEOUT;

	pjob->ji_rerun_preq = NULL;

}
Exemple #3
0
static void
post_hold(struct work_task *pwt)
{
	int			code;
	job			*pjob;
	struct batch_request	*preq;
	int			conn_idx;

	if (pwt->wt_aux2 != 1)
		svr_disconnect(pwt->wt_event);	/* close connection to MOM */
	preq = pwt->wt_parm1;
	code = preq->rq_reply.brp_code;
	preq->rq_conn = preq->rq_orgconn;	/* restore client socket */

	if (pwt->wt_aux2 != 1) { /* not rpp */
		conn_idx = connection_find_actual_index(preq->rq_conn);

		if (conn_idx == -1) {
			req_reject(PBSE_SYSTEM, 0, preq);
			return;
		}

		svr_conn[conn_idx].cn_authen &= ~PBS_NET_CONN_NOTIMEOUT;
	}

	pjob = find_job(preq->rq_ind.rq_hold.rq_orig.rq_objname);
	if (pjob  == (job *)0) {
		log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_DEBUG,
			preq->rq_ind.rq_hold.rq_orig.rq_objname,
			msg_postmomnojob);
		req_reject(PBSE_UNKJOBID, 0, preq);
		return;
	}
	if (code != 0) {
		if (code != PBSE_CKPBSY)
			pjob->ji_qs.ji_substate = JOB_SUBSTATE_RUNNING;	/* reset it */
		if (code != PBSE_NOSUP) {
			/* a "real" error - log message with return error code */
			(void)sprintf(log_buffer, msg_mombadhold, code);
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_DEBUG,
				pjob->ji_qs.ji_jobid, log_buffer);
			/* send message back to server for display to user */
			reply_text(preq, code, log_buffer);
			return;
		}
	} else if (code == 0) {

		/* record that MOM has a checkpoint file */

		if (preq->rq_reply.brp_auxcode)	/* chkpt can be moved */
			pjob->ji_qs.ji_svrflags =
				(pjob->ji_qs.ji_svrflags & ~JOB_SVFLG_CHKPT) |
			JOB_SVFLG_HASRUN | JOB_SVFLG_ChkptMig;

		pjob->ji_modified = 1;	  /* indicate attributes changed     */
		(void)job_save(pjob, SAVEJOB_QUICK);

		/* note in accounting file */

		account_record(PBS_ACCT_CHKPNT, pjob, (char *)0);
	}
	reply_ack(preq);
}
Exemple #4
0
void
dispatch_request(int sfds, struct batch_request *request)
{

	int	conn_idx = -1;
	int rpp = request->isrpp;

	if (!rpp) {
		if (sfds != PBS_LOCAL_CONNECTION) {
			conn_idx = connection_find_actual_index(sfds);
			if (conn_idx == -1) {
				log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST,
				LOG_ERR,
							"dispatch_request", "did not find socket in connection table");
				req_reject(PBSE_SYSTEM, 0, request);
				close_client(sfds);
				return;
			}
		}
	}

	switch (request->rq_type) {

		case PBS_BATCH_QueueJob:
			if (rpp) {
				request->rpp_ack = 0;
				rpp_add_close_func(sfds, close_quejob);
			} else
				net_add_close_func(sfds, close_quejob);
			req_quejob(request);
			break;

		case PBS_BATCH_JobCred:
#ifndef  PBS_MOM

			/* Reject if a user client (qsub -Wpwd) and not a */
			/* server (qmove) enqueued a job with JobCredential */
			if ( !request->rq_fromsvr && \
			     (server.sv_attr[SRV_ATR_ssignon_enable].at_flags \
                                                         & ATR_VFLAG_SET) &&  \
                             (server.sv_attr[SRV_ATR_ssignon_enable].at_val.at_long == 1) ) {
				req_reject(PBSE_SSIGNON_SET_REJECT, 0, request);
				close_client(sfds);
				break;
			}
#endif
			if (rpp)
				request->rpp_ack = 0;
			req_jobcredential(request);
			break;

		case PBS_BATCH_UserCred:
#ifdef PBS_MOM
#ifdef	WIN32
			req_reject(PBSE_NOSUP, 0, request);
#else
			req_reject(PBSE_UNKREQ, 0, request);
#endif
			close_client(sfds);
#else
			req_usercredential(request);
#endif
			break;

		case PBS_BATCH_UserMigrate:
#ifdef	PBS_MOM
#ifdef	WIN32
			req_reject(PBSE_NOSUP, 0, request);
#else
			req_reject(PBSE_UNKREQ, 0, request);
#endif	/* WIN32 */
			close_client(sfds);
#else
			req_user_migrate(request);
#endif	/* PBS_MOM */
			break;

		case PBS_BATCH_GSS_Context:
			req_gsscontext(request);
			break;

		case PBS_BATCH_jobscript:
			if (rpp)
				request->rpp_ack = 0;
			req_jobscript(request);
			break;

			/*
			 * The PBS_BATCH_Rdytocommit message is deprecated.
			 * The server does not do anything with it anymore, but
			 * simply acks the request (in case some client makes this call)
			 */
		case PBS_BATCH_RdytoCommit:
			if (request->isrpp)
				request->rpp_ack = 0;
			reply_ack(request);
			break;

		case PBS_BATCH_Commit:
			if (rpp)
				request->rpp_ack = 0;
			req_commit(request);
			if (rpp)
				rpp_add_close_func(sfds, (void (*)(int))0);
			else
				net_add_close_func(sfds, (void (*)(int))0);
			break;

		case PBS_BATCH_DeleteJob:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO,
				request->rq_ind.rq_delete.rq_objname,
				"delete job request received");
			req_deletejob(request);
			break;

#ifndef PBS_MOM
		case PBS_BATCH_SubmitResv:
			req_resvSub(request);
			break;

		case PBS_BATCH_DeleteResv:
			req_deleteReservation(request);
			break;
#endif

		case PBS_BATCH_HoldJob:
			if (sfds != PBS_LOCAL_CONNECTION && !rpp)
				svr_conn[conn_idx].cn_authen |= PBS_NET_CONN_NOTIMEOUT;
			req_holdjob(request);
			break;
#ifndef PBS_MOM
		case PBS_BATCH_LocateJob:
			req_locatejob(request);
			break;

		case PBS_BATCH_Manager:
			req_manager(request);
			break;
#endif
		case PBS_BATCH_MessJob:
			req_messagejob(request);
			break;

		case PBS_BATCH_PySpawn:
			if (sfds != PBS_LOCAL_CONNECTION && !rpp)
				svr_conn[conn_idx].cn_authen |= PBS_NET_CONN_NOTIMEOUT;
			req_py_spawn(request);
			break;

		case PBS_BATCH_ModifyJob:
			req_modifyjob(request);
			break;

		case PBS_BATCH_Rerun:
			req_rerunjob(request);
			break;
#ifndef PBS_MOM
		case PBS_BATCH_MoveJob:
			req_movejob(request);
			break;

		case PBS_BATCH_OrderJob:
			req_orderjob(request);
			break;

		case PBS_BATCH_Rescq:
			req_reject(PBSE_NOSUP, 0, request);
			break;

		case PBS_BATCH_ReserveResc:
			req_reject(PBSE_NOSUP, 0, request);
			break;

		case PBS_BATCH_ReleaseResc:
			req_reject(PBSE_NOSUP, 0, request);
			break;

		case PBS_BATCH_ReleaseJob:
			if (sfds != PBS_LOCAL_CONNECTION && !rpp)
				svr_conn[conn_idx].cn_authen |= PBS_NET_CONN_NOTIMEOUT;
			req_releasejob(request);
			break;

		case PBS_BATCH_RunJob:
		case PBS_BATCH_AsyrunJob:
			req_runjob(request);
			break;

		case PBS_BATCH_DefSchReply:
			req_defschedreply(request);
			break;

		case PBS_BATCH_ConfirmResv:
			req_confirmresv(request);
			break;

		case PBS_BATCH_SelectJobs:
		case PBS_BATCH_SelStat:
			req_selectjobs(request);
			break;

#endif /* !PBS_MOM */

		case PBS_BATCH_Shutdown:
			req_shutdown(request);
			break;

		case PBS_BATCH_SignalJob:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO,
				request->rq_ind.rq_signal.rq_jid,
				"signal job request received");
			req_signaljob(request);
			break;

		case PBS_BATCH_MvJobFile:
			req_mvjobfile(request);
			break;

#ifndef PBS_MOM		/* Server Only Functions */

		case PBS_BATCH_StatusJob:
			if (set_to_non_blocking(sfds, conn_idx) == -1) {
				req_reject(PBSE_SYSTEM, 0, request);
				close_client(sfds);
				return;
			}
			req_stat_job(request);
			clear_non_blocking(sfds, conn_idx);
			break;

		case PBS_BATCH_StatusQue:
			if (set_to_non_blocking(sfds, conn_idx) == -1) {
				req_reject(PBSE_SYSTEM, 0, request);
				close_client(sfds);
				return;
			}
			req_stat_que(request);
			clear_non_blocking(sfds, conn_idx);
			break;

		case PBS_BATCH_StatusNode:
			if (set_to_non_blocking(sfds, conn_idx) == -1) {
				req_reject(PBSE_SYSTEM, 0, request);
				close_client(sfds);
				return;
			}
			req_stat_node(request);
			clear_non_blocking(sfds, conn_idx);
			break;

		case PBS_BATCH_StatusResv:
			if (set_to_non_blocking(sfds, conn_idx) == -1) {
				req_reject(PBSE_SYSTEM, 0, request);
				close_client(sfds);
				return;
			}
			req_stat_resv(request);
			clear_non_blocking(sfds, conn_idx);
			break;

		case PBS_BATCH_StatusSvr:
			req_stat_svr(request);
			break;

		case PBS_BATCH_StatusSched:
			req_stat_sched(request);
			break;

		case PBS_BATCH_StatusHook:

			if (!is_local_root(request->rq_user,
				request->rq_host)) {
				sprintf(log_buffer, "%s@%s is unauthorized to "
					"access hooks data from server %s",
					request->rq_user, request->rq_host, server_host);
				reply_text(request, PBSE_HOOKERROR, log_buffer);
				log_event(PBSEVENT_ADMIN, PBS_EVENTCLASS_HOOK,
					LOG_INFO, "", log_buffer);
				/* don't call close_client() to allow other */
				/* non-hook related requests to continue */
				break;
			}

			if (set_to_non_blocking(sfds, conn_idx) == -1) {
				req_reject(PBSE_SYSTEM, 0, request);
				close_client(sfds);
				return;
			}
			req_stat_hook(request);
			clear_non_blocking(sfds, conn_idx);
			break;

		case PBS_BATCH_TrackJob:
			req_track(request);
			break;

		case PBS_BATCH_RegistDep:
			req_register(request);
			break;

		case PBS_BATCH_AuthenResvPort:
			if (pbs_conf.auth_method == AUTH_MUNGE) {
                                req_reject(PBSE_BADCRED, 0, request);
                                close_client(sfds);
                                return;
                        }
			req_authenResvPort(request);
			break;

		case PBS_BATCH_StageIn:
			req_stagein(request);
			break;

		case PBS_BATCH_FailOver:
			req_failover(request);
			break;

		case PBS_BATCH_StatusRsc:
			req_stat_resc(request);
			break;

		case PBS_BATCH_MomRestart:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_NODE,
				LOG_INFO,
				request->rq_ind.rq_momrestart.rq_momhost,
				"Mom restarted on host");
			req_momrestart(request);
			break;
#else	/* MOM only functions */

		case PBS_BATCH_CopyFiles:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO,
				request->rq_ind.rq_cpyfile.rq_jobid,
				"copy file request received");
			/* don't time-out as copy may take long time */
			if (sfds != PBS_LOCAL_CONNECTION && !rpp)
				svr_conn[conn_idx].cn_authen |= PBS_NET_CONN_NOTIMEOUT;
			req_cpyfile(request);
			break;
		case PBS_BATCH_CopyFiles_Cred:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO,
				request->rq_ind.rq_cpyfile_cred.rq_copyfile.rq_jobid,
				"copy file cred request received");
			/* don't time-out as copy may take long time */
			if (sfds != PBS_LOCAL_CONNECTION && !rpp)
				svr_conn[conn_idx].cn_authen |= PBS_NET_CONN_NOTIMEOUT;
			req_cpyfile(request);
			break;

		case PBS_BATCH_DelFiles:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO,
				request->rq_ind.rq_cpyfile.rq_jobid,
				"delete file request received");
			req_delfile(request);
			break;
		case PBS_BATCH_DelFiles_Cred:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO,
				request->rq_ind.rq_cpyfile_cred.rq_copyfile.rq_jobid,
				"delete file cred request received");
			req_delfile(request);
			break;
		case PBS_BATCH_CopyHookFile:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_HOOK,
				LOG_INFO,
				request->rq_ind.rq_hookfile.rq_filename,
				"copy hook-related file request received");
			req_copy_hookfile(request);
			break;
		case PBS_BATCH_DelHookFile:
			log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_HOOK,
				LOG_INFO,
				request->rq_ind.rq_hookfile.rq_filename,
				"delete hook-related file request received");
			req_del_hookfile(request);
			break;

#endif
		default:
			req_reject(PBSE_UNKREQ, 0, request);
			close_client(sfds);
			break;
	}
	return;
}
Exemple #5
0
void
process_request(int sfds)
{
	int		      rc;
	struct batch_request *request;
	int		      conn_idx;

	time_now = time((time_t *)0);

	conn_idx = connection_find_actual_index(sfds);

	if (conn_idx == -1) {
		log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, LOG_ERR,
			"process_request", "did not find socket in connection table");
#ifdef WIN32
		(void)closesocket(sfds);
#else
		(void)close(sfds);
#endif
		return;
	}

	if ((request = alloc_br(0)) == NULL) {
		log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, LOG_ERR,
			"process_request", "Unable to allocate request structure");
		close_conn(sfds);
		return;
	}
	request->rq_conn = sfds;

	/*
	 * Read in the request and decode it to the internal request structure.
	 */

	if (get_connecthost(sfds, request->rq_host, PBS_MAXHOSTNAME)) {

		(void)sprintf(log_buffer, "%s: %lu", msg_reqbadhost,
			get_connectaddr(sfds));
		log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_REQUEST, LOG_DEBUG,
			"", log_buffer);
		req_reject(PBSE_BADHOST, 0, request);
		return;
	}
        
#ifndef PBS_MOM
	if (svr_conn[conn_idx].cn_active == FromClientDIS) {
		rc = dis_request_read(sfds, request);
	} else {
		log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, LOG_ERR,
			"process_req", "request on invalid type of connection");
		close_conn(sfds);
		free_br(request);
		return;
	}
#else	/* PBS_MOM */
	rc = dis_request_read(sfds, request);
#endif	/* PBS_MOM */

	if (rc == -1) {		/* End of file */
		close_client(sfds);
		free_br(request);
		return;

	} else if ((rc == PBSE_SYSTEM) || (rc == PBSE_INTERNAL)) {

		/* read error, likely cannot send reply so just disconnect */

		/* ??? not sure about this ??? */

		close_client(sfds);
		free_br(request);
		return;

	} else if (rc > 0) {

		/*
		 * request didn't decode, either garbage or  unknown
		 * request type, in ether case, return reject-reply
		 */

		req_reject(rc, 0, request);
		close_client(sfds);
		return;
	}
        
#ifndef PBS_MOM
#if defined(PBS_SECURITY) && (PBS_SECURITY == KRB5)
	strcpy(svr_conn[sfds].cn_physhost,request->rq_host);
	
        if (request->rq_type == PBS_BATCH_GSSAuthenUser) {
                log_event(PBSEVENT_DEBUG | PBSEVENT_FORCE, PBS_EVENTCLASS_SERVER, LOG_ERR, __func__,"Received GSSAuthenUser.");
            
                if (req_gssauthenuser(request,sfds) < 0) {
                        log_event(PBSEVENT_DEBUG | PBSEVENT_FORCE, PBS_EVENTCLASS_SERVER, LOG_ERR, __func__,"Authentication failed.");
                        req_reject(PBSE_BADCRED, 0, request);
                        return;
                }
            
                log_event(PBSEVENT_DEBUG | PBSEVENT_FORCE, PBS_EVENTCLASS_SERVER, LOG_ERR, __func__,"Authentication succeeded.");
        } else if ((svr_conn[sfds].cn_authen & PBS_NET_CONN_GSSAPIAUTH) != 0) {
		strcpy(request->rq_user,svr_conn[sfds].cn_username);
		strcpy(request->rq_host,svr_conn[sfds].cn_hostname);
		
	}
#endif
#endif

#ifndef PBS_MOM
	/* If the request is coming on the socket we opened to the  */
	/* scheduler,  change the "user" from "root" to "Scheduler" */

	if (request->rq_conn == scheduler_sock) {
		strncpy(request->rq_user, PBS_SCHED_DAEMON_NAME, PBS_MAXUSER);
		request->rq_user[PBS_MAXUSER] = '\0';
	}
#endif	/* PBS_MOM */

	(void)sprintf(log_buffer, msg_request, request->rq_type,
		request->rq_user, request->rq_host, sfds);
	log_event(PBSEVENT_DEBUG2, PBS_EVENTCLASS_REQUEST, LOG_DEBUG,
		"", log_buffer);

	/* is the request from a host acceptable to the server */
	if (request->rq_type == PBS_BATCH_AuthExternal) {
		rc = authenticate_external(conn_idx, request);
		if (rc == 0)
			reply_ack(request);
		else if (rc == -2)
			req_reject(PBSE_NOSUP, 0, request);
		else
			req_reject(PBSE_BADCRED, 0, request);
		return;
	}
        
#ifndef PBS_MOM
	int access_by_krb = 0;
	
#if defined(PBS_SECURITY) && (PBS_SECURITY == KRB5)
	if ((svr_conn[sfds].cn_authen & PBS_NET_CONN_GSSAPIAUTH) != 0) {
		
		if (server.sv_attr[(int)SRV_ATR_acl_krb_realm_enable].at_val.at_long) {
			
			if (acl_check(&server.sv_attr[(int)SRV_ATR_acl_krb_realms], svr_conn[sfds].cn_principal,ACL_Host) == 0) {
				req_reject(PBSE_BADHOST, 0, request);
				close_client(sfds);
				return;
			}
		}
		
		// this principal is allowed to access the server
		access_by_krb = 1;
	}
#endif
	
	if (access_by_krb == 0)
	if (server.sv_attr[(int)SRV_ATR_acl_host_enable].at_val.at_long) {
		/* acl enabled, check it; always allow myself	*/
		
		if ((acl_check(&server.sv_attr[(int)SRV_ATR_acl_hosts],
			request->rq_host, ACL_Host) == 0) &&
			(strcasecmp(server_host, request->rq_host) != 0)) {
				req_reject(PBSE_BADHOST, 0, request);
				close_client(sfds);
				return;
		}
	}

	/*
	 * determine source (user client or another server) of request.
	 * set the permissions granted to the client
	 */
	if (svr_conn[conn_idx].cn_authen & PBS_NET_CONN_FROM_PRIVIL) {

		/* request came from another server */

		request->rq_fromsvr = 1;
		request->rq_perm = ATR_DFLAG_USRD | ATR_DFLAG_USWR |
				   ATR_DFLAG_OPRD | ATR_DFLAG_OPWR |
				   ATR_DFLAG_MGRD | ATR_DFLAG_MGWR |
				   ATR_DFLAG_SvWR;

	} else {

		/* request not from another server */

		request->rq_fromsvr = 0;

		/*
		 * Client must be authenticated by a Authenticate User Request,
		 * if not, reject request and close connection.
		 * -- The following is retained for compat with old cmds --
		 * The exception to this is of course the Connect Request which
		 * cannot have been authenticated, because it contains the
		 * needed ticket; so trap it here.  Of course, there is no
		 * prior authentication on the Authenticate User request either,
		 * but it comes over a reserved port and appears from another
		 * server, hence is automatically granted authorization.

		 */

		if (request->rq_type == PBS_BATCH_Connect) {
			req_connect(request);
			return;
		}
       
		if ((svr_conn[conn_idx].cn_authen & PBS_NET_CONN_AUTHENTICATED) ==0) {
			rc = PBSE_BADCRED;
		} else {
			rc = authenticate_user(request, &svr_conn[conn_idx]);
		}
		if (rc != 0) {
			req_reject(rc, 0, request);
			if (rc == PBSE_BADCRED)
				close_client(sfds);
			return;
		}

		request->rq_perm =
			svr_get_privilege(request->rq_user, request->rq_host);
	}

	/* if server shutting down, disallow new jobs and new running */

	if (server.sv_attr[(int)SRV_ATR_State].at_val.at_long > SV_STATE_RUN) {
		switch (request->rq_type) {
			case PBS_BATCH_AsyrunJob:
			case PBS_BATCH_JobCred:
			case PBS_BATCH_UserCred:
			case PBS_BATCH_UserMigrate:
			case PBS_BATCH_MoveJob:
			case PBS_BATCH_QueueJob:
			case PBS_BATCH_RunJob:
			case PBS_BATCH_StageIn:
			case PBS_BATCH_jobscript:
				req_reject(PBSE_SVRDOWN, 0, request);
				return;
		}
	}


#else	/* THIS CODE FOR MOM ONLY */

	/* check connecting host against allowed list of ok clients */
	if (!addrfind(svr_conn[conn_idx].cn_addr)) {
		req_reject(PBSE_BADHOST, 0, request);
		close_client(sfds);
		return;
	}

	request->rq_fromsvr = 1;
	request->rq_perm = ATR_DFLAG_USRD | ATR_DFLAG_USWR |
			   ATR_DFLAG_OPRD | ATR_DFLAG_OPWR |
			   ATR_DFLAG_MGRD | ATR_DFLAG_MGWR |
			   ATR_DFLAG_SvWR | ATR_DFLAG_MOM;
#endif

	/*
	 * dispatch the request to the correct processing function.
	 * The processing function must call reply_send() to free
	 * the request struture.
	 */
        
        if (request->rq_type == PBS_BATCH_GSSAuthenUser)
            return;

	dispatch_request(sfds, request);
	return;
}
Exemple #6
0
/**
 * @brief
 * 		req_rerunjob - service the Rerun Job Request
 *
 *  @param[in,out]	preq	-	Job Request
 *  @param[in,out]	pjob	-	ptr to the subjob
 */
static void
req_rerunjob2(struct batch_request *preq, job *pjob)
{
	long	force = 0;
	struct  work_task *ptask;
	time_t  rerun_to;
	int	conn_idx;
	int rc;
	int is_mgr = 0;
	void *force_rerun = (void *)0;

	if (preq->rq_extend && (strcmp(preq->rq_extend, "force") == 0))
		force = 1;

	/* See if the request is coming from a manager */
	if (preq->rq_perm & (ATR_DFLAG_MGRD | ATR_DFLAG_MGWR))
		is_mgr = 1;

	/* the job must be rerunnable or force must be on */

	if ((pjob->ji_wattr[(int)JOB_ATR_rerunable].at_val.at_long == 0) &&
		(force == 0)) {
		req_reject(PBSE_NORERUN, 0, preq);
		return;
	}

	/* the job must be running */

	if (pjob->ji_qs.ji_state != JOB_STATE_RUNNING) {
		req_reject(PBSE_BADSTATE, 0, preq);
		return;
	}
	if ((pjob->ji_qs.ji_substate != JOB_SUBSTATE_RUNNING) && (force==0)) {
		req_reject(PBSE_BADSTATE, 0, preq);
		return;
	}

	/* Set the flag for post_rerun only when
	 * force is set and request is from manager */
	if (force == 1 && is_mgr == 1)
		force_rerun = (void *)1;

	/* ask MOM to kill off the job */

	rc = issue_signal(pjob, SIG_RERUN, post_rerun, force_rerun);

	/*
	 * If force is set and request is from a PBS manager,
	 * job is re-queued regardless of issue_signal to MoM
	 * was a success or failure.
	 * Eventually, when the mom updates server about the job,
	 * server sends a discard message to mom and job is
	 * then deleted from mom as well.
	 */
	if ((rc || is_mgr) && force == 1) {

		/* Mom is down and issue signal failed or
		 * request is from a manager and "force" is on,
		 * force the requeue */

		pjob->ji_qs.ji_substate = JOB_SUBSTATE_RERUN3;
		discard_job(pjob, "Force rerun", 1);
		force_reque(pjob);
		reply_ack(preq);
		return;

	}

	if (rc != 0) {
		req_reject(rc, 0, preq);
		return;
	}

	/* So job has run and is to be rerun (not restarted) */

	pjob->ji_qs.ji_svrflags = (pjob->ji_qs.ji_svrflags &
		~(JOB_SVFLG_CHKPT | JOB_SVFLG_ChkptMig)) |
	JOB_SVFLG_HASRUN;
	svr_setjobstate(pjob, JOB_STATE_RUNNING, JOB_SUBSTATE_RERUN);

	(void)sprintf(log_buffer, msg_manager, msg_jobrerun,
		preq->rq_user, preq->rq_host);
	log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_INFO,
		pjob->ji_qs.ji_jobid, log_buffer);

	/* The following means we've detected an outstanding rerun request  */
	/* for the same job which should not happen. But if it does, let's  */
	/* ack that previous request to also free up its request structure. */
	if (pjob->ji_rerun_preq != NULL) {
		reply_ack(pjob->ji_rerun_preq);
	}
	pjob->ji_rerun_preq = preq;

	/* put a timeout on the rerun request so that it doesn't hang 	*/
	/* indefinitely; if it does, the scheduler would also hang on a */
	/* requeue request  */
	time_now = time((time_t *)0);
	if ((server.sv_attr[(int)SRV_ATR_JobRequeTimeout].at_flags & ATR_VFLAG_SET) == 0) {
		rerun_to = time_now + PBS_DIS_TCP_TIMEOUT_RERUN;
	} else {
		rerun_to = time_now + server.sv_attr[(int)SRV_ATR_JobRequeTimeout].at_val.at_long;
	}
	ptask = set_task(WORK_Timed, rerun_to, timeout_rerun_request, pjob);
	if (ptask) {
		/* this ensures that the ptask created gets cleared in case */
		/* pjob gets deleted before the task is served */
		append_link(&pjob->ji_svrtask, &ptask->wt_linkobj, ptask);
	}

	/* set no-timeout flag on connection to client */
	if (preq->rq_conn != PBS_LOCAL_CONNECTION) {
		conn_idx = connection_find_actual_index(preq->rq_conn);
		if (conn_idx != -1)
			svr_conn[conn_idx].cn_authen |= PBS_NET_CONN_NOTIMEOUT;
	}

}