I am trying to get the krb5 service ticket for the cifs server using the below code. I am able to get the intial creds for the smb user. But when I try to get the cifs service ticket for the smb server, I am getting error PRINCIPAL_UNKNOWN error. In the packet trace, I noticed that TGS_REQ is sent with sname "krbtgt\cifs_server_name.domain_name" instead of cifs\cifs_server_name.domain_name. I am not sure what mistake I am making.. I constructed the service principal correctly( line 12-14) Not sure why TGS-REQ is send with sname krbtgt instead.
krb5_creds credentials;
krb5_creds* service_credentials;
krb5_principal user_principal = NULL;
krb5_principal service_principal = NULL;
krb5_ccache ccache;
krb5_get_init_creds_opt *options;
memset(&credentials, 0, sizeof(credentials));
char buf[100];
sprintf(buf, "%s#%s", smb2->user, smb2->domain);
ret = krb5_parse_name(context, buf, &user_principal);
sprintf(buf, "%s#%s", "cifs", smb2->target_name);
fprintf(stderr, "buff %s\n", buf);
ret = krb5_parse_name(context, buf, &service_principal);
if (ret != 0) {
fprintf(stderr, "krb5_parse_name %d\n", ret );
exit(-1);
}
ret = krb5_cc_default(context, &ccache);
if (ret != 0) {
fprintf(stderr, "krb5_parse_name %d\n", ret );
exit(-1);
}
ret = krb5_cc_initialize (context, ccache, user_principal);
if (ret != 0) {
fprintf(stderr, "krb5_cc_initialize %d\n", ret );
exit(-1);
}
ret = krb5_get_init_creds_opt_alloc(context, &options);
if (ret != 0) {
fprintf(stderr, "krb5_get_init_creds_opt_alloc %d\n", ret );
exit(-1);
}
ret = krb5_get_init_creds_opt_set_out_ccache(context, options, ccache);
if (ret != 0) {
fprintf(stderr, "krb5_get_init_creds_opt_set_out_ccache %d\n", ret );
exit(-1);
}
// Gets the realm name for the hostname
ret = krb5_get_init_creds_password(context, &credentials, user_principal,
smb2->password, NULL,
NULL, 0, NULL, options);
fprintf(stderr, "krb5_get_init_creds_password %d\n", ret);
if (ret != 0) {
fprintf(stderr, "krb5_get_init_creds_password %d\n", ret );
//exit(-1);
}
credentials.server = service_principal;
credentials.client = user_principal;
// krb5_tkt_creds_init(context, ccache, credentials, options, &)
ret = krb5_get_credentials(context, 0, ccache, &credentials, &service_credentials);
if (ret != 0) {
fprintf(stderr, "krb5_get_credentials %d\n", ret );
exit(-1);
}
fprintf(stderr, "----------------------------------------------------------krb5_get_credentials %d----------------------------------------------------------\n", ret);
Please help to resolve this issue.
Thanks
I found the problem after trial and error method. service principle should be cifs/cifs_server_name.domain_name not cifs#cifs_server_name.domain_name. Only user principle should be user#domain_name. After editing the below line, krb5_get_credentials() was able to get service ticket/
sprintf(buf, "%s/%s", "cifs", smb2->target_name);
Related
I'm building my own netcat style listener in C for a project that I'm working on.
The client (linux in this case) connects to the listener using netcat, and from the listener I'm able to send linux commands back. When running commands which give a small output (e.g. whoami, uname, pwd) the output comes back fine. However, when running a command that can give a substantial output (e.g. ls -la), I only get partial output until I send another command, which then means subsequent commands are executing the previous command. Screenshot:
Fig 1: Start of output
Fig 2: Entering another command to force output to finish
Fig 3: Now I'm one command behind, giving incorrect output.
Code as follows (includes/defines/other functions left out for brevity):
int main(int argc, char *argv[])
{
char readbuff[262144];
char user_input[1024] = "";
struct sockaddr_in srv, cln;
int bnd, checkrtr, len, lstn, new_sfd, rd, result, sfd, val;
if(argc != 2)
{
fprintf(stderr, "[*]Usage: %s <target_router>\n", argv[0]);
return -1;
}
check_router(argv[1]);
// Start a listener on port 8888
// Create the socket
sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd == -1)
{
fprintf(stderr, "\n[*]socket: %s (%d)", strerror(errno), errno);
return -1;
}
else
{
fprintf(stdout, "\n[*]Socket created.");
}
val = 1;
result = 0;
result = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
if(result == -1)
{
fprintf(stderr, "\n[*]setsockopt: %s (%d)", strerror(errno), errno);
}
else
{
fprintf(stdout, "\n[*]Address reuse set");
}
srv.sin_family = AF_INET;
srv.sin_addr.s_addr = inet_addr(IP);
srv.sin_port = htons(atoi(LPORT));
len = sizeof(srv);
bnd = bind(sfd, (struct sockaddr*)&srv, len);
if(bnd != 0)
{
fprintf(stderr, "\n[*]bind: %s (%d)", strerror(errno), errno);
return -1;
}
else
{
fprintf(stdout, "\n[*]Socket bound");
}
lstn = listen(sfd, 10);
if(lstn != 0)
{
fprintf(stderr, "\n[*]listen: %s (%d)", strerror(errno), errno);
return -1;
}
else
{
fprintf(stdout, "\n[*]Server listening on %s:%s", IP, LPORT);
}
socklen_t len_c = sizeof(cln);
new_sfd = accept(sfd, (struct sockaddr*)&cln, &len_c);
if(new_sfd == -1)
{
fprintf(stderr, "\n[*]accept: %s (%d)", strerror(errno), errno);
return -1;
}
else
{
char *ip_c = inet_ntoa(cln.sin_addr);
fprintf(stdout, "\n[*]New connection from client: %s:%d\n", ip_c, ntohs(cln.sin_port));
while(1)
{
memset(readbuff, 0x00, sizeof(readbuff));
memset(user_input, 0x00, sizeof(user_input));
fgets(user_input, sizeof(user_input), stdin);
if(user_input[0] == '\n')
{
continue;
}
int send_data = send(new_sfd, user_input, sizeof(user_input), 0);
if(send_data == -1)
{
fprintf(stderr, "\n[*]send: %s (%d)", strerror(errno), errno);
continue;
}
rd = read(new_sfd, readbuff, sizeof(readbuff));
fprintf(stdout, "\n size of rd: %d", rd);
fprintf(stdout, "\n size of readbuff: %ld", sizeof(readbuff));
if(rd > 0)
{
fprintf(stdout, "\n%s", readbuff);
}
else if(rd == 0)
{
fprintf(stdout, "\n[*]Client connection closed.\n");
continue;
//break;
}
else
{
fprintf(stderr, "\n[*]recv: %s (%d)", strerror(errno), errno);
continue;
}
}
}
}
Is anyone able to give me a reason why the output stops partway through please?
That's quite to be expected.
A single read can only read as much data as has been received so far (or otherwise it would need to bend time and space). The other end may also not have sent off everything they have to send by the time you issue read, so a single read won't be able to read everything either (because, well, it may not have been sent).
Since TCP is a stream protocol, you will need to devise a way to know how many bytes to expect for a single "message" from the other end, and read exactly that many bytes so you know you've gotten everything the other end has to say; I'd recommend some sort of Type-Length-Value scheme, even if you didn't need more than 1 type at present.
I am trying to implement an ssh client using libssh but output seems to just be an echo of whatever been sent main part of program is :
do {
printf("Enter Command or q to exit: ");
fgets(command, 100, stdin);
command[strlen(command)-1] = 0;
if (ssh_channel_write(channel, command, strlen(command)) != strlen(command)) {
fprintf(stderr, "Unable to execute command\n");
exit(1);
}
printf("Data Sent: %s\n", command);
sleep(1);
while ((bytes_recieved = ssh_channel_read_nonblocking(channel, output, 2024, 0))) {
if (bytes_recieved < 1) {
fprintf(stderr, "Error Reading Output or End Of Data\n");
break;
}
printf("Data Recieved(%d): %.*s\n", bytes_recieved, bytes_recieved, output);
}
}while (strcmp(command, "q")!=0 ||strcmp(command, "Q")!=0 );
first command result in what I guess the banner to be sent althought I guess the banner is supposed to be sent before connection , this is output for only the first command after that anything i type is just echod back.
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-40-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
* "If you've been waiting for the perfect Kubernetes dev solution for
macOS, the wait is over. Learn how to install Microk8s on macOS."
https://www.techrepublic.com/article/how-to-install-microk8s-on-macos/
65 updates can be installed immediately.
0 of these updates are security updates.
To see these additional updates run: apt list --upgradable
Your Hardware Enablement Stack (HWE) is supported until April 2025.
sshd_config files (server side) have been edited to include this as highlights:
AllowTcpForwarding no
PasswordAuthentication yes
PermitRootLogin prohibit-password
AllowUsers user_name
Whole code is here for anyone if he want's to use or test on it just change your username in ssh_options_set( ) part of the code.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <libssh/libssh.h>
int main(int argc, char* argv[])
{
printf("libssh version: %s\n", ssh_version(0));
if (argc < 2){
fprintf(stderr, "USAGE command hostname\n");
exit(1);
}
char* hostname = argv[1];
int port = 22;
ssh_session ssh = ssh_new();
ssh_options_set(ssh, SSH_OPTIONS_HOST, hostname);
ssh_options_set(ssh, SSH_OPTIONS_PORT, &port);
// TODO: Enable it in the future
int verbosity = SSH_LOG_PROTOCOL;
ssh_options_set(ssh, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
int error_code = ssh_connect(ssh);
if (error_code != SSH_OK){
fprintf(stderr, "Error creating connection with error %d", error_code);
exit(1);
}
printf("Connected to %s on port %d.\n", hostname, port);
printf("banner %s\n", ssh_get_serverbanner(ssh));
ssh_key key;
if(ssh_get_server_publickey(ssh, &key) != SSH_OK) {
fprintf(stderr,"Couldnt get server key\n");
exit(1);
}
unsigned char* hash;
size_t hash_len;
if(ssh_get_publickey_hash(key, SSH_PUBLICKEY_HASH_SHA1, &hash, &hash_len)!=SSH_OK){
fprintf(stderr, "Error Calculating Hash\n");
exit(1);
}
printf("Host public key hash:\n");
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA1, hash, hash_len);
ssh_key_free(key);
ssh_clean_pubkey_hash(&hash);
enum ssh_known_hosts_e known = ssh_session_is_known_server(ssh);
switch (known) {
case SSH_KNOWN_HOSTS_OK:printf("known Host\n");break;
case SSH_KNOWN_HOSTS_NOT_FOUND:printf("no host file\n");break;
case SSH_KNOWN_HOSTS_CHANGED:printf("Host Changed\n");break;
case SSH_KNOWN_HOSTS_ERROR:
printf("Host error. %s\n", ssh_get_error(ssh)); return 1;
case SSH_KNOWN_HOSTS_UNKNOWN: printf("Unknown Host verify please\n");break;
}
if(known == SSH_KNOWN_HOSTS_CHANGED){
printf("Server key changed Exiting\n");
exit(1);
}
if (
known == SSH_KNOWN_HOSTS_OTHER ||
known == SSH_KNOWN_HOSTS_UNKNOWN ||
known == SSH_KNOWN_HOSTS_NOT_FOUND)
{
printf("Do you want to trust this host\n");
char answer[10];
fgets(answer, 10, stdin);
if(answer[0] == 'y' || answer[0] == 'Y'){
ssh_session_update_known_hosts(ssh);
}else{
printf("Not trusting it\n");
exit(1);
}
}
ssh_options_set(ssh, SSH_OPTIONS_USER, "my_user");
printf("Enter password: ");
char pass[20];
fgets(pass, 20, stdin);
pass[strlen(pass)-1] = 0 ;
if(ssh_userauth_password(ssh, 0, pass) != SSH_AUTH_SUCCESS){
fprintf(stderr, "Unable to Authentication\n");
exit(1);
}else {
printf("Authentication successful!\n");
}
int err = ssh_userauth_publickey_auto(ssh, NULL, NULL);
if (err == SSH_AUTH_ERROR){
fprintf(stderr, "Unable to Authunticate\n");
exit(1);
}
ssh_channel channel = ssh_channel_new(ssh);
if(!channel){
fprintf(stderr, "Couldnt create a channel\n");
exit(1);
}
if(ssh_channel_open_session(channel) != SSH_OK){
fprintf(stderr, "Error Openning Session\n");
exit(1);
}
if (ssh_channel_request_pty(channel) != SSH_OK){
fprintf(stderr, "Can't initiate terminal\n");
exit(1);
}
if(ssh_channel_change_pty_size(channel, 80, 400) != SSH_OK){
fprintf(stderr, "Error Changing size of terminal\n");
exit(1);
}
if(ssh_channel_request_shell(channel) != SSH_OK){
fprintf(stderr, "Couldn't request a shell\n");
exit(1);
}
char command[100];
char output[2024];
int bytes_recieved;
do {
printf("Enter Command or q to exit: ");
fgets(command, 100, stdin);
command[strlen(command)-1] = 0;
if (ssh_channel_write(channel, command, strlen(command)) != strlen(command)) {
fprintf(stderr, "Unable to execute command\n");
exit(1);
}
printf("Data Sent: %s\n", command);
sleep(1);
while ((bytes_recieved = ssh_channel_read_nonblocking(channel, output, 2024, 0))) {
if (bytes_recieved < 1) {
fprintf(stderr, "Error Reading Output or End Of Data\n");
break;
}
printf("Data Recieved(%d): %.*s\n", bytes_recieved, bytes_recieved, output);
}
}while (strcmp(command, "q")!=0 ||strcmp(command, "Q")!=0 );
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(ssh);
ssh_free(ssh);
return 0;
}
I have written two process code both codes are copied below , let us assume sqlitep1.c refers to p1 and sqlitep2.c refers to p2
p1 constantly reads from database file sample.db and p2 writes to database file sample.db,
I executed one instances of p2 & p3 and one instances of p1, as per sqlite documentation, two process cannot simultaneously write to sqlite.
in code sqlitep2.c i have two version, one which opens connection and do write and then close (p2) and another version which opens connection and writes to db file and blocks with while(1), As shown in second version of sqlitep2.c which is executed as p3.
I first executed p3 and then p2, As per code p3 will block after writing, at this point I assume sqlite lock is not released as the connection is not closed.
But in my result I can see p2 is able to write without getting any busy error even though p3 has not released the lock.
Note : Executed in linux machine.
sqlitep1.c
#include <stdio.h>
#include </sqlite/sqlite3.h>
int main()
{
sqlite3_stmt *pSqlStmt = NULL;
sqlite3 *pSqlHandle = NULL;
int ret = SQLITE_ERROR;
char *pcSharedPath = "sample.db";
char* pcSqlQuery = NULL;
char *name = NULL;
int retry_count = 0;
while (1)
{
printf ("process 1.....\n");
printf ("-----------------------------\n\n");
ret = SQLITE_ERROR;
/*open connection to sqlite*/
while (ret != SQLITE_OK) {
printf ("process 1, open connection\n");
ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
if (ret != SQLITE_OK)
{
printf ("process 1, opening failed....\n");
if (ret == SQLITE_BUSY)
{
printf ("process 1, open connection busy error....\n");
}
}
sleep(1);
}
printf ("process 1, database connection opened...\n");
/* prepare query */
ret = SQLITE_ERROR;
pcSqlQuery = "SELECT * FROM EMP";
while (ret != SQLITE_OK)
{
ret = sqlite3_prepare_v2 (pSqlHandle, pcSqlQuery, -1, &pSqlStmt, NULL);
if (ret == SQLITE_BUSY) {
printf ("process 1, prepare busy error....\n");
}
if (ret == SQLITE_ERROR) {
printf("SQLITE_ERROR\n");
}
sleep(1);
}
printf ("process 1, prepare success...\n");
/* extract result from query */
while(1)
{
ret = sqlite3_step (pSqlStmt);
if (ret == SQLITE_DONE)
break;
if (ret != SQLITE_ROW) {
printf("process 1, no row exists...\n");
break;
}
name = sqlite3_column_text (pSqlStmt, 1);
printf ("%s \n", name);
}
/* finalize */
if (NULL != pSqlStmt)
{
ret = SQLITE_ERROR;
// while (ret != SQLITE_OK) {
ret = sqlite3_finalize (pSqlStmt);
printf ("process 1, Finalizing %d...\n", ret);
// }
pSqlStmt = NULL;
}
/* close sqlite connection */
ret = SQLITE_ERROR;
retry_count = 0;
while (ret != SQLITE_OK && retry_count != 5) {
ret = sqlite3_close(pSqlHandle);
printf("sqlite3_close %d...\n", ret);
retry_count++;
}
retry_count=0;
if (SQLITE_OK != ret) {
printf ("sqlite close failed....Exiting process 1...\n");
return 0;
}
}
}
first version of sqlitep2.c which does not block after write operation( no while(1))
#include <stdio.h>
#include </sqlite/sqlite3.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
sqlite3_stmt *pSqlStmt = NULL;
sqlite3 *pSqlHandle = NULL;
int ret = SQLITE_ERROR;
char *pcSharedPath = "sample.db";
char pcSqlQuery[100] = "";
char *name = NULL;
int i = atoi(argv[1]);
int retry_count = 0;
while (1)
{
printf ("process 2.....\n");
printf ("-----------------------------\n\n");
ret = SQLITE_ERROR;
/*open connection to sqlite*/
while (ret != SQLITE_OK) {
printf ("process 2, open connection\n");
ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
if (ret != SQLITE_OK)
{
printf ("process 2, opening failed %d....\n", ret);
if (ret == SQLITE_BUSY)
{
printf ("process 2, open connection busy error....\n");
}
}
usleep(10*1000);
}
printf ("process 2, database connection opened...\n");
sqlite3_busy_timeout(pSqlHandle, 1000);
/* prepare query */
ret = SQLITE_ERROR;
char name[50];
while (ret != SQLITE_OK && retry_count != 10)
{
pSqlStmt = NULL;
sqlite3_snprintf(50, name, "\"Sachin%d\"", i);
sqlite3_snprintf(100,pcSqlQuery, "INSERT INTO EMP VALUES (%d, %s)", i, name);
printf ("%s\n", pcSqlQuery);
ret = sqlite3_prepare_v2 (pSqlHandle, "INSERT INTO EMP(ID, NAME) VALUES (?1, ?2);", -1, &pSqlStmt, NULL);
sqlite3_bind_int(pSqlStmt, 1, i);
sqlite3_bind_text(pSqlStmt, 2, name, -1, SQLITE_STATIC);
if (ret == SQLITE_BUSY) {
printf ("process 2, prepare busy error....\n");
}
else {
if (ret == SQLITE_ERROR)
{
printf ("SQLITE_ERROR...\n");
}
ret = SQLITE_ERROR;
while (ret != SQLITE_OK) {
ret = sqlite3_step(pSqlStmt);
printf ("process 2, return from sqlite3_step : %d...\n", ret);
if (ret != SQLITE_DONE) {
printf ("process 2, insert error...\n");
} else if (ret == SQLITE_BUSY) {
printf("sqlite3_step busy error...\n");
} else {
i++;
ret = SQLITE_OK;
}
}
}
printf ("process 2, ret value of insert op %d\n ", ret);
usleep(10*1000);
retry_count++;
}
retry_count=0;
printf ("process 2, prepare success...\n");
/* finalize */
if (NULL != pSqlStmt)
{
ret = SQLITE_ERROR;
while (ret != SQLITE_OK) {
ret = sqlite3_finalize (pSqlStmt);
printf ("process 2, Finalizing %d...\n", ret);
}
pSqlStmt = NULL;
}
/* close sqlite connection */
ret = SQLITE_ERROR;
retry_count = 0;
ret = sqlite3_close(pSqlHandle);
while (ret != SQLITE_OK) {
ret = sqlite3_close(pSqlHandle);
printf("sqlite3_close %d...\n", ret);
retry_count++;
sleep(1);
}
retry_count=0;
pSqlHandle = NULL;
if (SQLITE_OK != ret) {
printf ("sqlite close failed....Exiting process 2...\n");
return 0;
}
sleep(1);
}
}
Second version of sqlitep2.c which has a infinite block while(1) after write operation, which means it is not releasing the lock.
#include <stdio.h>
#include </sqlite/sqlite3.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
sqlite3_stmt *pSqlStmt = NULL;
sqlite3 *pSqlHandle = NULL;
int ret = SQLITE_ERROR;
char *pcSharedPath = "sample.db";
char pcSqlQuery[100] = "";
char *name = NULL;
int i = atoi(argv[1]);
int retry_count = 0;
while (1)
{
printf ("process 2.....\n");
printf ("-----------------------------\n\n");
ret = SQLITE_ERROR;
/*open connection to sqlite*/
while (ret != SQLITE_OK) {
printf ("process 2, open connection\n");
ret = sqlite3_open_v2 (pcSharedPath, &(pSqlHandle), (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX), NULL);
if (ret != SQLITE_OK)
{
printf ("process 2, opening failed %d....\n", ret);
if (ret == SQLITE_BUSY)
{
printf ("process 2, open connection busy error....\n");
}
}
usleep(10*1000);
}
printf ("process 2, database connection opened...\n");
sqlite3_busy_timeout(pSqlHandle, 1000);
/* prepare query */
ret = SQLITE_ERROR;
char name[50];
while (ret != SQLITE_OK && retry_count != 10)
{
pSqlStmt = NULL;
sqlite3_snprintf(50, name, "\"Sachin%d\"", i);
sqlite3_snprintf(100,pcSqlQuery, "INSERT INTO EMP VALUES (%d, %s)", i, name);
printf ("%s\n", pcSqlQuery);
ret = sqlite3_prepare_v2 (pSqlHandle, "INSERT INTO EMP(ID, NAME) VALUES (?1, ?2);", -1, &pSqlStmt, NULL);
sqlite3_bind_int(pSqlStmt, 1, i);
sqlite3_bind_text(pSqlStmt, 2, name, -1, SQLITE_STATIC);
if (ret == SQLITE_BUSY) {
printf ("process 2, prepare busy error....\n");
}
else {
if (ret == SQLITE_ERROR)
{
printf ("SQLITE_ERROR...\n");
}
ret = SQLITE_ERROR;
while (ret != SQLITE_OK) {
ret = sqlite3_step(pSqlStmt);
printf ("process 2, return from sqlite3_step : %d...\n", ret);
if (ret != SQLITE_DONE) {
printf ("process 2, insert error...\n");
} else if (ret == SQLITE_BUSY) {
printf("sqlite3_step busy error...\n");
} else {
i++;
ret = SQLITE_OK;
}
}
}
printf ("process 2, ret value of insert op %d\n ", ret);
usleep(10*1000);
retry_count++;
}
while (1) {} // block here, DO NOT proceed further.
retry_count=0;
printf ("process 2, prepare success...\n");
/* finalize */
if (NULL != pSqlStmt)
{
ret = SQLITE_ERROR;
while (ret != SQLITE_OK) {
ret = sqlite3_finalize (pSqlStmt);
printf ("process 2, Finalizing %d...\n", ret);
}
pSqlStmt = NULL;
}
/* close sqlite connection */
ret = SQLITE_ERROR;
retry_count = 0;
ret = sqlite3_close(pSqlHandle);
while (ret != SQLITE_OK) {
ret = sqlite3_close(pSqlHandle);
printf("sqlite3_close %d...\n", ret);
retry_count++;
sleep(1);
}
retry_count=0;
pSqlHandle = NULL;
if (SQLITE_OK != ret) {
printf ("sqlite close failed....Exiting process 2...\n");
return 0;
}
sleep(1);
}
}
SQLite does locks around transactions, not open connections. Without an explicit transaction (which you don't appear to be doing) each SQL statement is a separate transaction that ends when the statement is executed. Your having an unfinalized statement means nothing, as "step" executed your INSERT and released the lock.
I'm having a problem with some openCL code I'm writing.
I've written a collection of utility functions to remove some boilerplate code from where I'm using it. The test method runs at the beginning and works absolutely fine, the code being below:
void openCLtest(char *arg_program, char *arg_device)
{
cl_int ret;
cl_device_id device_id = getDeviceId(atoi(arg_program), atoi(arg_device));
cl_context context = get_cl_context(&device_id);
cl_command_queue queue = get_cl_command_queue(&context, &device_id);
cl_kernel kernel = compileCLkernel(&context, &device_id, "src/hello.cl", "hello");
cl_mem memobj = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * sizeof(char), NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Allocate Buffer\n");
exit(1);
}
ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to set kernel Arg\n");
exit(1);
}
ret = clEnqueueTask(queue, kernel, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Enqueue Task\n");
exit(1);
}
ret = clFinish(queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to wait for finish\n");
exit(1);
}
char string[MEM_SIZE];
ret = clEnqueueReadBuffer(queue, memobj, CL_TRUE, 0, MEM_SIZE * sizeof(char), string, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to read buffer\n");
exit(1);
}
printf("CL Produced: %s\n", string);
ret = clFlush(queue);
ret = clFinish(queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Wait for test queue to finish\n");
exit(1);
}
ret = clReleaseKernel(kernel);
ret = clReleaseMemObject(memobj);
ret = clReleaseCommandQueue(queue);
ret = clReleaseContext(context);
}
This code works fine, and I then extracted the code into more functions which can be used for the real openCL I'm writing.
The same principle has been applied in the rest of the code, but this time, it doesn't work.
main:
openCLtest(argv[2], argv[3]); //This is the code above and works great
cl_device_id device_id = getDeviceId(atoi(argv[2]), atoi(argv[3]));
cl_context context = get_cl_context(&device_id);
cl_command_queue queue = get_cl_command_queue(&context, &device_id);
....
double *coords_3D = cl_extrude_coords(&device_id, &context, &queue, coords_2D, nodes, LAYERS, LAYER_HEIGHT);
cl_extrude_coords:
double *cl_extrude_coords(cl_device_id* device_id, cl_context* context, cl_command_queue* queue, double *coords, int nodes, int layers, double layer_height)
{
cl_int ret;
cl_kernel extrude_coords = compileCLkernel(context, device_id, "src/OpenCL_Kernels/extrude_coords.cl", "extrude_coords");
cl_mem coords_2d = clCreateBuffer(*context, CL_MEM_READ_ONLY, sizeof(coords) / sizeof(coords[0]), NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Create coords_2d CL Buffer %d\n", ret);
exit(1);
}
cl_mem result = clCreateBuffer(*context, CL_MEM_WRITE_ONLY, sizeof(double) * nodes * 3 * layers, NULL, &ret);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Create result CL Buffer %d\n", ret);
exit(1);
}
ret = clEnqueueWriteBuffer(*queue, coords_2d, CL_TRUE, 0, sizeof(coords) / sizeof(coords[0]), (const void *)&coords, 0, NULL, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed enqueue coords_2d write to buffer %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 0, sizeof(cl_mem), (void *)&coords_2d);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument coords_2d %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 1, sizeof(cl_mem), (void *)&result);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument result CL Buffer %d\n", ret);
exit(1);
}
ret = clSetKernelArg(extrude_coords, 2, sizeof(double), (void *)&layer_height);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Set kernel argument layers %d\n", ret);
exit(1);
}
size_t gWorkSize[] = {nodes, layers};
cl_event clEvent;
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, (const size_t *)&gWorkSize, NULL, 0, NULL, &clEvent);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Enqueue Extrude Coordinates Kernel\n");
exit(1);
}
double *res = (double *)malloc(sizeof(double) * nodes * 3 * layers);
ret = clFinish(*queue);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to wait for queue to finish in extrude_coords %d\n", ret);
exit(1);
}
ret = clEnqueueReadBuffer(*queue, result, CL_TRUE, 0, sizeof(double) * nodes * 3 * layers, (void *)res, 1, &clEvent, NULL);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to Enqueue the extrude_coords result buffer read %d\n", ret);
exit(1);
}
ret = clReleaseKernel(extrude_coords);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release kernel\n");
exit(1);
}
ret = clReleaseMemObject(coords_2d);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release result memory object\n");
exit(1);
}
ret = clReleaseMemObject(result);
if (ret != CL_SUCCESS)
{
fprintf(stderr, "Failed to release result memory object\n");
exit(1);
}
return res;
}
cl kernel:
#pragma OPENCL EXTENSION cl_khr_fp64: enable
__kernel void extrude_coords(__global const double * coords, __global double * res, const double layer_height){
uint i=get_global_id(0);
uint j=get_global_id(1);
uint layers=get_global_size(0);
res[3*(i*layers + j)] = coords[2*i];
res[3*(i*layers + j) + 1] = coords[2*i + 1];
res[3*(i*layers + j) + 2] = layer_height * j;
}
This function however, does not work, throwing the error below when clFinish(queue) is called.
Failed to wait for queue to finish in extrude_coords -36
Looking this up, I can see -36 is CL_INVALID_COMMAND_QUEUE. If I don't exit here, I then get an error thrown at the buffer read, error code -5, CL_OUT_OF_RESOURCES.
I'm not sure what is going wrong. The values of nodes and layers when this code is being tested are 151731 and 101 respectively. I'm not sure if that has something to do with it.
Does anyone have any ideas on what could be the issue and how to fix it, or even any suggestions on whether this structure for the code is a good idea. The plan was by passing the queue, context and device ID, each function can produce and execute its own kernel(s) to do something with the queue etc being released at the end of the program when they're no longer needed.
Any help would be appreciated, I've been stumped on this for several hours now.
EDIT:
I have since tried changinging the calling convention of clEnqueueNDRange in extrude_coords to
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, (const size_t *)&gWorkSize[0], NULL, 0, NULL, &clEvent);
as suggested in an answer but this does not work. Testing with printf("%d\n", &gWorkSize == &gWorkSize[0]); shows that the two pointers are functionally the same, so this is not the issue.
I then went on to modify the test openCL code to use clEnqueueNDRange instead of clEnqueueTask as follows:
size_t gWorkSize[] = {1, 1};
// ret = clEnqueueTask(queue, kernel, 0, NULL, NULL);
ret = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, (const size_t *)&gWorkSize, NULL, 0, NULL, NULL);
This still all works correctly, so something else is clearly wrong... I'm still not sure what...
The sizeof(coords) / sizeof(coords[0]) will not give the array size in C/C++. Best to use sizeof(coords)*elementsInCoords and pass in elementsInCoords. Alternatively, setup coords to be a std::vector<> and pass that around since you can get a data pointer out of it and the size as well.
Look at code:
size_t gWorkSize[] = {nodes, layers};
cl_event clEvent;
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, (const size_t *)&gWorkSize, NULL, 0, NULL, &clEvent);
&gWorkSize is of type size_t (*)[2], while argument must be of type const size_t*
Try this:
ret = clEnqueueNDRangeKernel(*queue, extrude_coords, 2, NULL, &gWorkSize[0], NULL, 0, NULL, &clEvent);
I am trying to write a c program to read data for morningstar sunsaver MPPT.
This is the simple program I found in net. But my program is unable to read data from register.
#include <stdlib.h>
#include <errno.h>
#include "src/modbus.h"
int main(void)
{
modbus_t *ctx;
uint16_t tab_reg[64];
int rc;
int i;
ctx = modbus_new_rtu("/dev/ttyS0", 115200, 'N',8,1);
if (ctx == NULL) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
for (i=0; i < rc; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
modbus_close(ctx);
modbus_free(ctx);
}
It does not work for me. I get the following error message:
Bad file descriptor
By reading the documentation from LibModBus, I think you're missing a call to modbus_connect.
Try connecting before reading registers:
ctx = modbus_new_rtu("/dev/ttyS0", 115200, 'N',8,1);
if (ctx == NULL) {
fprintf(stderr, "Creation failed: %s\n", modbus_strerror(errno));
return -1;
}
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
Also, remember to modbus_close and modbus_free your context before exiting due to further error conditions. For example:
rc = modbus_read_registers(ctx, 0, 10, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
modbus_close(ctx);
modbus_free(ctx);
return -1;
}
It turned out to be trying to read from wrong Serial port.
Reading from /dev/ttyS3 worked.
I later realize that serial port are from /dev/ttyS0 .. /dev/ttyS9