Ejemplo n.º 1
0
static GnmSolverResult *
run_solver (SolverState *state, GnmSolverParameters *param)
{
	GError *err = NULL;
	gboolean ok;
	GnmSheetRange sr;
	GOUndo *undo = NULL;
	GnmSolver *sol = NULL;
	GnmValue const *vinput;
	GtkWindow *top = GTK_WINDOW (gtk_widget_get_toplevel (state->dialog));
	GnmSolverResult *res = NULL;

	state->ref_count++;

	sol = gnm_solver_factory_functional (param->options.algorithm,
					     state->wbcg)
		? gnm_solver_factory_create (param->options.algorithm, param)
		: NULL;
	if (!sol) {
		go_gtk_notice_dialog (top, GTK_MESSAGE_ERROR,
				      _("The chosen solver is not functional."));
		goto fail;
	}

	gtk_notebook_set_current_page (GTK_NOTEBOOK (state->notebook), -1);

	state->run.solver = sol;

	vinput = gnm_solver_param_get_input (param);
	gnm_sheet_range_from_value (&sr, vinput);
	if (!sr.sheet) sr.sheet = param->sheet;
	undo = clipboard_copy_range_undo (sr.sheet, &sr.range);

	g_signal_connect_swapped (G_OBJECT (sol),
				  "notify::status",
				  G_CALLBACK (cb_notify_status),
				  state);
	g_signal_connect_swapped (G_OBJECT (sol),
				  "notify::reason",
				  G_CALLBACK (cb_notify_status),
				  state);
	cb_notify_status (state);

	g_signal_connect_swapped (G_OBJECT (sol),
				  "notify::result",
				  G_CALLBACK (cb_notify_result),
				  state);
	cb_notify_result (state);

	state->run.timer_source = g_timeout_add_seconds
		(1, (GSourceFunc)cb_timer_tick, state);
	cb_timer_tick (state);

	/* ---------------------------------------- */

	ok = gnm_solver_start (sol,
			       GNM_WBC (state->wbcg),
			       &err);
	if (ok) {
		state->run.in_main++;
		go_cmd_context_set_sensitive (GO_CMD_CONTEXT (state->wbcg), FALSE);
		gtk_main ();
		go_cmd_context_set_sensitive (GO_CMD_CONTEXT (state->wbcg), TRUE);
		state->run.in_main--;
		ok = gnm_solver_has_solution (sol);
	} else if (err) {
		gnm_solver_set_reason (sol, err->message);
	}
	g_clear_error (&err);

	remove_objective_value_source (state);
	remove_timer_source (state);

	/* ---------------------------------------- */

	if (ok) {
		GOUndo *redo;

		gnm_solver_store_result (sol);
		redo = clipboard_copy_range_undo (sr.sheet, &sr.range);

		if (param->options.program_report ||
		    param->options.sensitivity_report) {
			Workbook *wb = param->sheet->workbook;
			GOUndo *undo_report, *redo_report;

			undo_report = go_undo_binary_new
				(wb,
				 workbook_sheet_state_new (wb),
				 (GOUndoBinaryFunc)workbook_sheet_state_restore,
				 NULL,
				 (GFreeFunc)workbook_sheet_state_free);
			undo = go_undo_combine (undo, undo_report);

			create_report (sol, state);

			redo_report = go_undo_binary_new
				(wb,
				 workbook_sheet_state_new (wb),
				 (GOUndoBinaryFunc)workbook_sheet_state_restore,
				 NULL,
				 (GFreeFunc)workbook_sheet_state_free);
			redo = go_undo_combine (redo, redo_report);
		}

		cmd_generic (GNM_WBC (state->wbcg),
			     _("Running solver"),
			     undo, redo);
		res = g_object_ref (sol->result);
		undo = redo = NULL;
	}

fail:
	if (undo)
		g_object_unref (undo);

	if (state->run.solver) {
		g_object_unref (state->run.solver);
		state->run.solver = NULL;
	}

	unref_state (state);

	return res;
}
int
snmp_agent_parse(
        snmp_session *session,
        uint8 *indata,
        int inlength,
        uint8 *outdata,
        int *outlength
)
{
        uint8    msgtype, type;
        long      zero = 0;
        long      reqid, errstat, errindex, dummyindex;
        uint8    *out_auth, *out_header, *out_reqid;
        uint8    *startData = indata;
        int       startLength = inlength;
        long      version;
        uint8    *origdata = indata;
        int           origlen = inlength;
//      usecEntry *ue;
        int       packet_len, ret = 0;
#ifdef WEBADMIN
        int       newoutdata;   // add -- by arius 5/17/2000
        int       len;          // add -- by arius 5/17/2000
#endif WEBADMIN

        session->community_len = COMMUNITY_MAX_LEN;
        //get community name
        indata = snmp_parse_auth(indata, &inlength, community, &session->community_len, &version);

        if (indata == NULL){
//              increment_stat( SNMP_STAT_ENCODING_ERRORS );
                ERROR("bad auth encoding");
                return 0;
        }

#if 1 //ONLY SUPPORT VERSION 1
        if(version != SNMP_VERSION_1) {
                ERROR("wrong version");
                snmp_inbadversions++;
                return 0;
        }

#else ////////////////////////////////////////////
        if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) {
//              increment_stat( SNMP_STAT_ENCODING_ERRORS );
                ERROR("wrong version");
                snmp_inbadversions++;
                return 0;
        }

        if( version == SNMP_VERSION_2C || version == SNMP_VERSION_2 ) {
                if( version == SNMP_VERSION_2 ) {
                        ret = check_auth( session, origdata, origlen, indata - session->community_len, session->community_len, &ue );
                        *outlength = (SNMP_MAX_LEN < session->MMS) ? SNMP_MAX_LEN : session->MMS;
                        session->MMS = SNMP_MAX_LEN;
                } else if( version == SNMP_VERSION_2C ) {
                        ret = community_auth( session );
                        session->version = SNMP_VERSION_2C;
                }

                if( ret < 0 ) {
//                      increment_stat( -ret );
                        if( (indata=asn_parse_header(indata, &inlength, &msgtype))
                        &&  asn_parse_int(indata, &inlength, &type, &reqid, sizeof(reqid)) )
                        {
                                if( msgtype == REPORT_MSG ) return 0;
                                if( !(session->qoS & USEC_QOS_GENREPORT) ) return 0;
                                session->agentBoots = _agentBoots;
                                session->agentClock = _agentStartTime;
                                memcpy( session->agentID, _agentID, 12 );
                                session->MMS = SNMP_MAX_LEN;
                                create_report( session, outdata, outlength, -ret, reqid );
                                return 1;
                        } else {
                                return 0;
                        }
                } else if( ret > 0 ) {
//                      increment_stat( ret );
                        return 0;
                }

        } else  {
#endif  /////////////////////////////////////////////////////

        //VERSION 1
        if(community_auth( session )==0) return 0;
//      session->version = SNMP_VERSION_1;

#if 0 ////////
        }
#endif ///////

        indata = asn_parse_header(indata, &inlength, &msgtype);
        if (indata == NULL){
//              increment_stat( SNMP_STAT_ENCODING_ERRORS );
                ERROR("bad header");
                return 0;
        }

    // XXX: increment by total number of vars at correct place:
    snmp_intotalreqvars++;

        if(msgtype == GET_REQ_MSG)      snmp_ingetrequests++;
        else if (msgtype == GETNEXT_REQ_MSG) snmp_ingetnexts++;
        else if (msgtype ==     SET_REQ_MSG) snmp_insetrequests++;
        else return 0;

//   if (msgtype == GETBULK_REQ_MSG: //version 2

        // Request ID
        indata = asn_parse_int(indata, &inlength, &type, &reqid, sizeof(reqid));
        if (indata == NULL){
//              increment_stat( SNMP_STAT_ENCODING_ERRORS );
                ERROR("bad parse of reqid");
                return 0;
        }

        //Error Status
        indata = asn_parse_int(indata, &inlength, &type, &errstat, sizeof(errstat));
        if (indata == NULL){
//              increment_stat( SNMP_STAT_ENCODING_ERRORS );
                ERROR("bad parse of errstat");
                snmp_inasnparseerrors++;
                return 0;
        }

        //Error Index
    indata = asn_parse_int(indata, &inlength, &type, &errindex, sizeof(errindex));
    if (indata == NULL){
//              increment_stat( SNMP_STAT_ENCODING_ERRORS );
                ERROR("bad parse of errindex");
                return 0;
        }

     //
     // Now start cobbling together what is known about the output packet.
     // The final lengths are not known now, so they will have to be recomputed
     // later.
     //

    // setup for response
//Simon    time( (time_t *) &session->agentTime );
//Simon    session->agentClock = _agentStartTime;
//Simon    session->agentBoots = _agentBoots;
//Simon   memcpy( session->agentID, _agentID, 12 );

        out_auth = outdata;

        //Set Resp Community
        out_header = snmp_build_auth(out_auth, outlength,
                                     community,session->community_len,
                                     (long)SNMP_VERSION_1,0);
        if (out_header == NULL){
                ERROR("snmp_build_auth failed");
                snmp_inasnparseerrors++;
                return 0;
        }

        out_reqid = asn_build_sequence(out_header, outlength, (uint8)GET_RSP_MSG, 0);
        if (out_reqid == NULL){
                ERROR("out_reqid == NULL");
                return 0;
        }

        //Set Resp ID
        type = (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
        // return identical request id
        outdata = asn_build_int(out_reqid, outlength, type, &reqid, sizeof(reqid));
        if (outdata == NULL){
                ERROR("build reqid failed");
                return 0;
        }

    // assume that error status will be zero
        outdata = asn_build_int(outdata, outlength, type, &zero, sizeof(zero));
        if (outdata == NULL){
                ERROR("build errstat failed");
                return 0;
        }

    // assume that error index will be zero
        outdata = asn_build_int(outdata, outlength, type, &zero, sizeof(zero));
        if (outdata == NULL){
                ERROR("build errindex failed");
                return 0;
        }

#if 0 ///////////////////////////////////////////
        if (msgtype == GETBULK_REQ_MSG)
        errstat = bulk_var_op_list(indata, inlength, outdata, *outlength,
                                    errstat, errindex, &errindex );
    else
#endif 0 ////////////////////////////////////////

        errstat = parse_var_op_list(session, indata, inlength, outdata, *outlength,
                                    &errindex, msgtype, RESERVE1);

        if (msgtype== SET_REQ_MSG){
                if (errstat == SNMP_ERR_NOERROR)
                        errstat = parse_var_op_list(session, indata, inlength, outdata, *outlength,
                                        &errindex, msgtype, RESERVE2);
                if (errstat == SNMP_ERR_NOERROR){
                //
                //* SETS require 3-4 passes through the var_op_list.  The first two
                //* passes verify that all types, lengths, and values are valid
                //* and may reserve resources and the third does the set and a
                //* fourth executes any actions.  Then the identical GET RESPONSE
                //* packet is returned.
                //* If either of the first two passes returns an error, another
                //* pass is made so that any reserved resources can be freed.
                //*
              parse_var_op_list(session, indata, inlength, outdata, *outlength,
                                &dummyindex, msgtype, COMMIT);
              parse_var_op_list(session, indata, inlength, outdata, *outlength,
                                &dummyindex, msgtype, ACTION);
              if (create_identical(session, startData, out_auth, startLength, 0L, 0L )){
                  *outlength = packet_end - out_auth;
                  return 1;
              }
              return 0;
        } else {
              parse_var_op_list(session, indata, inlength, outdata, *outlength,
                                &dummyindex, msgtype, COMM_FREE);
        }
    }
    switch((short)errstat){
        case SNMP_ERR_NOERROR:
            // re-encode the headers with the real lengths
            *outlength = packet_end - out_header;
            packet_len = *outlength;
            outdata = asn_build_sequence(out_header, outlength, GET_RSP_MSG,
                                        packet_end - out_reqid);
// add --- By arius 5/17/2000
#ifdef WEBADMIN
newoutdata = packet_end - outdata;  // how many shifts
len = packet_end - out_reqid;
packet_end = outdata;               // save new pointer end of packet
outdata -= len;
out_reqid = out_reqid - newoutdata;
#endif WEBADMIN
// end of here
            if (outdata != out_reqid){
                ERROR("internal error: header");
                return 0;
            }

            *outlength = packet_end - out_auth;
            outdata = snmp_build_auth(out_auth, outlength,
                                          community, session->community_len,
                                          (long)SNMP_VERSION_1,
                                          packet_end - out_header );
// add --- By arius 5/17/2000
#ifdef WEBADMIN
out_header -= (packet_end - outdata);
packet_end = outdata;            // save new pointer end of packet
#endif WEBADMIN
// end of here
            *outlength = packet_end - out_auth;
#if 0
            // packet_end is correct for old SNMP.  This dichotomy needs to be fixed.
            if (session->version == SNMP_VERSION_2)
                packet_end = out_auth + packet_len;
#endif
            break;
        case SNMP_ERR_TOOBIG:
            snmp_intoobigs++;
#if notdone
            if (session->version == SNMP_VERSION_2){
                create_toobig(out_auth, *outlength, reqid, pi);
                break;
            } // else FALLTHRU
#endif
        case SNMP_ERR_NOACCESS:
        case SNMP_ERR_WRONGTYPE:
        case SNMP_ERR_WRONGLENGTH:
        case SNMP_ERR_WRONGENCODING:
        case SNMP_ERR_WRONGVALUE:
        case SNMP_ERR_NOCREATION:
        case SNMP_ERR_INCONSISTENTVALUE:
        case SNMP_ERR_RESOURCEUNAVAILABLE:
        case SNMP_ERR_COMMITFAILED:
        case SNMP_ERR_UNDOFAILED:
        case SNMP_ERR_AUTHORIZATIONERROR:
        case SNMP_ERR_NOTWRITABLE:
    case SNMP_ERR_INCONSISTENTNAME:
        case SNMP_ERR_NOSUCHNAME:
        case SNMP_ERR_BADVALUE:
        case SNMP_ERR_READONLY:
        case SNMP_ERR_GENERR:
            if (create_identical(session, startData, out_auth, startLength, errstat,
                                 errindex)){
                *outlength = packet_end - out_auth;
                return 1;
            }
            return 0;
        default:
            return 0;
    }

#if 0
    if( session->qoS & USEC_QOS_AUTH ) {
        md5Digest( out_auth, *outlength, outdata - (session->contextLen + 16),
            outdata - (session->contextLen + 16) );
    }
#endif

        return 1;
}