void process_request(int sfds) { int rc; struct batch_request *request; conn_t *conn; time_now = time(NULL); conn = get_conn(sfds); if (!conn) { 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 (conn->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 the request is coming on the socket we opened to the */ /* scheduler, change the "user" from "root" to "Scheduler" */ if (find_sched_from_sock(request->rq_conn) != NULL) { 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, 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 if (server.sv_attr[(int)SRV_ATR_acl_host_enable].at_val.at_long) { /* acl enabled, check it; always allow myself */ struct pbsnode *isanode = NULL; if ((server.sv_attr[SRV_ATR_acl_host_moms_enable].at_flags & ATR_VFLAG_SET) && (server.sv_attr[(int)SRV_ATR_acl_host_moms_enable].at_val.at_long == 1)) { isanode = find_nodebyaddr(get_connectaddr(sfds)); if ((isanode != NULL) && (isanode->nd_state & INUSE_DELETED)) isanode = NULL; } if (isanode == NULL) { 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 (conn->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 ((conn->cn_authen & PBS_NET_CONN_AUTHENTICATED) ==0) { rc = PBSE_BADCRED; } else { rc = authenticate_user(request, conn); } 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(conn->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. */ dispatch_request(sfds, request); return; }
void req_modifyjob(struct batch_request *preq) { int add_to_am_list = 0; /* if altered during sched cycle */ int bad = 0; int jt; /* job type */ int newstate; int newsubstate; resource_def *outsideselect = NULL; job *pjob; svrattrl *plist; resource *presc; resource_def *prsd; int rc; int running = 0; int sendmom = 0; char hook_msg[HOOK_MSG_SIZE]; int mod_project = 0; pbs_sched *psched; switch (process_hooks(preq, hook_msg, sizeof(hook_msg), pbs_python_set_interrupt)) { case 0: /* explicit reject */ reply_text(preq, PBSE_HOOKERROR, hook_msg); return; case 1: /* explicit accept */ if (recreate_request(preq) == -1) { /* error */ /* we have to reject the request, as 'preq' */ /* may have been partly modified */ strcpy(hook_msg, "modifyjob event: rejected request"); log_event(PBSEVENT_ERROR, PBS_EVENTCLASS_HOOK, LOG_ERR, "", hook_msg); reply_text(preq, PBSE_HOOKERROR, hook_msg); return; } break; case 2: /* no hook script executed - go ahead and accept event*/ break; default: log_event(PBSEVENT_DEBUG2, PBS_EVENTCLASS_HOOK, LOG_INFO, "", "modifyjob event: accept req by default"); } if (pseldef == NULL) /* do one time to keep handy */ pseldef = find_resc_def(svr_resc_def, "select", svr_resc_size); pjob = chk_job_request(preq->rq_ind.rq_modify.rq_objname, preq, &jt); if (pjob == NULL) return; if ((jt == IS_ARRAY_Single) || (jt == IS_ARRAY_Range)) { req_reject(PBSE_IVALREQ, 0, preq); return; } psched = find_sched_from_sock(preq->rq_conn); /* allow scheduler to modify job */ if (psched == NULL) { /* provisioning job is not allowed to be modified */ if ((pjob->ji_qs.ji_state == JOB_STATE_RUNNING) && (pjob->ji_qs.ji_substate == JOB_SUBSTATE_PROVISION)) { req_reject(PBSE_BADSTATE, 0, preq); return; } } /* cannot be in exiting or transit, exiting has already be checked */ if (pjob->ji_qs.ji_state == JOB_STATE_TRANSIT) { req_reject(PBSE_BADSTATE, 0, preq); return; } plist = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); if (plist == NULL) { /* nothing to do */ reply_ack(preq); return; } /* * Special checks must be made: * if during a scheduling cycle and certain attributes are altered, * make a note of the job to prevent it from being run now; * if job is running, only certain attributes/resources can be * altered. */ if (pjob->ji_qs.ji_state == JOB_STATE_RUNNING) { running = 1; } while (plist) { int i; i = find_attr(job_attr_def, plist->al_name, JOB_ATR_LAST); /* * Is the attribute being altered one which could change * scheduling (ATR_DFLAG_SCGALT set) and if a scheduling * cycle is in progress, then set flag to add the job to list * of jobs which cannot be run in this cycle. * If the scheduler itself sends a modify job request, * no need to delay the job until next cycle. */ if ((psched == NULL) && (scheduler_jobs_stat) && (job_attr_def[i].at_flags & ATR_DFLAG_SCGALT)) add_to_am_list = 1; /* Is the attribute modifiable in RUN state ? */ if (i < 0) { reply_badattr(PBSE_NOATTR, 1, plist, preq); return; } if ((running == 1) && ((job_attr_def[i].at_flags & ATR_DFLAG_ALTRUN) == 0)) { reply_badattr(PBSE_MODATRRUN, 1, plist, preq); return; } if (i == (int)JOB_ATR_resource) { prsd = find_resc_def(svr_resc_def, plist->al_resc, svr_resc_size); if (prsd == 0) { reply_badattr(PBSE_UNKRESC, 1, plist, preq); return; } /* is the specified resource modifiable while */ /* the job is running */ if (running) { if ((prsd->rs_flags & ATR_DFLAG_ALTRUN) == 0) { reply_badattr(PBSE_MODATRRUN, 1, plist, preq); return; } sendmom = 1; } /* should the resource be only in a select spec */ if (prsd->rs_flags & ATR_DFLAG_CVTSLT && !outsideselect && plist->al_atopl.value && plist->al_atopl.value[0]) { /* if "-lresource" is set and has non-NULL value, ** remember as potential bad resource ** if this appears along "select". */ outsideselect = prsd; } } if (strcmp(plist->al_name, ATTR_project) == 0) { mod_project = 1; } else if ((strcmp(plist->al_name, ATTR_runcount) == 0) && ((plist->al_flags & ATR_VFLAG_HOOK) == 0) && (plist->al_value != NULL) && (plist->al_value[0] != '\0') && ((preq->rq_perm & (ATR_DFLAG_MGWR | ATR_DFLAG_OPWR)) == 0) && (atol(plist->al_value) < \ pjob->ji_wattr[(int)JOB_ATR_runcount].at_val.at_long)) { sprintf(log_buffer, "regular user %s@%s cannot decrease '%s' attribute value from %ld to %ld", preq->rq_user, preq->rq_host, ATTR_runcount, pjob->ji_wattr[(int)JOB_ATR_runcount].at_val.at_long, atol(plist->al_value)); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_ERR, pjob->ji_qs.ji_jobid, log_buffer); req_reject(PBSE_PERM, 0, preq); return; } plist = (svrattrl *)GET_NEXT(plist->al_link); } if (outsideselect) { presc = find_resc_entry(&pjob->ji_wattr[(int)JOB_ATR_resource], pseldef); if (presc && ((presc->rs_value.at_flags & ATR_VFLAG_DEFLT) == 0)) { /* select is not a default, so reject qalter */ resc_in_err = strdup(outsideselect->rs_name); req_reject(PBSE_INVALJOBRESC, 0, preq); return; } } /* modify the jobs attributes */ bad = 0; plist = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); rc = modify_job_attr(pjob, plist, preq->rq_perm, &bad); if (rc) { if (pjob->ji_clterrmsg) reply_text(preq, rc, pjob->ji_clterrmsg); else reply_badattr(rc, bad, plist, preq); return; } /* If certain attributes modified and if in scheduling cycle */ /* then add to list of jobs which cannot be run in this cycle */ if (add_to_am_list) am_jobs_add(pjob); /* see req_runjob() */ /* check if project attribute was requested to be modified to */ /* be the default project value */ if (mod_project && (pjob->ji_wattr[(int)JOB_ATR_project].at_flags & \ ATR_VFLAG_SET)) { if (strcmp(pjob->ji_wattr[(int)JOB_ATR_project].at_val.at_str, PBS_DEFAULT_PROJECT) == 0) { sprintf(log_buffer, msg_defproject, ATTR_project, PBS_DEFAULT_PROJECT); #ifdef NAS /* localmod 107 */ log_event(PBSEVENT_DEBUG4, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); #else log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); #endif /* localmod 107 */ } } if (pjob->ji_wattr[(int)JOB_ATR_resource].at_flags & ATR_VFLAG_MODIFY) { presc = find_resc_entry(&pjob->ji_wattr[(int)JOB_ATR_resource], pseldef); if (presc && (presc->rs_value.at_flags & ATR_VFLAG_DEFLT)) { /* changing Resource_List and select is a default */ /* clear "select" so it is rebuilt inset_resc_deflt */ pseldef->rs_free(&presc->rs_value); } } /* Reset any defaults resource limit which might have been unset */ if ((rc = set_resc_deflt((void *)pjob, JOB_OBJECT, NULL)) != 0) { req_reject(rc, 0, preq); return; } /* if job is not running, may need to change its state */ if (pjob->ji_qs.ji_state != JOB_STATE_RUNNING) { svr_evaljobstate(pjob, &newstate, &newsubstate, 0); (void)svr_setjobstate(pjob, newstate, newsubstate); } else { (void)job_save(pjob, SAVEJOB_FULL); } (void)sprintf(log_buffer, msg_manager, msg_jobmod, preq->rq_user, preq->rq_host); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); /* if a resource limit changed for a running job, send to MOM */ if (sendmom) { rc = relay_to_mom(pjob, preq, post_modify_req); if (rc) req_reject(rc, 0, preq); /* unable to get to MOM */ return; } reply_ack(preq); }