Pcap_inject sends too many messages - c

I am trying to send authenticate messages to an access point, but when I do that it sends 15 authenticate messages to the AP, whereby the AP doesn't respond. I use a Mac OS X and the libpcap library.
Here is my code:
int inject(char *src_mac, char *dst_mac)
{
int i, rc;
char *device, *packet;
char error[PCAP_ERRBUF_SIZE];
pcap_t *handle;
device = pcap_lookupdev(error);
handle = pcap_create(device, error);
check(device != NULL, "Failed to find a device!");
check(handle != NULL, "Failed to create handle!");
rc = pcap_set_rfmon(handle, 1);
check(rc == 0, "Failed to set monitor mode!");
rc = pcap_set_promisc(handle, 1);
check(rc == 0, "Failed to set promiscuous mode!");
rc = pcap_activate(handle);
check(rc == 0, "Failed to activate handle!");
rc = pcap_datalink(handle);
check(rc == DLT_IEEE802_11_RADIO, "Failed to use the correct format!");
packet = radiotap_setup(src_mac, dst_mac,\
dst_mac, 0xb0);
rc = pcap_inject(handle, packet,\
RADIO_LEN + sizeof(ieee80211_hdr));
check(rc != -1, "Failed to send packet!");
pcap_close(handle);
return 1;
error:
pcap_close(handle);
return -1;
}
char *radiotap_setup(char *dst_mac, char *src_mac, char *bssid_mac, int fc)
{
int i, radio_len;
unsigned int shost_mac[6], dhost_mac[6], bhost_mac[6];
static char packet[RADIO_LEN + sizeof(ieee80211_hdr)];
ieee80211_hdr ieeeh;
ieeeh.fc = fc;
ieeeh.dur = 314;
sscanf(src_mac, "%x:%x:%x:%x:%x:%x", &shost_mac[0], &shost_mac[1],\
&shost_mac[2], &shost_mac[3], &shost_mac[4], &shost_mac[5]);
sscanf(dst_mac, "%x:%x:%x:%x:%x:%x", &dhost_mac[0], &dhost_mac[1],\
&dhost_mac[2], &dhost_mac[3], &dhost_mac[4], &dhost_mac[5]);
sscanf(bssid_mac, "%x:%x:%x:%x:%x:%x", &bhost_mac[0], &bhost_mac[1],\
&bhost_mac[2], &bhost_mac[3], &bhost_mac[4], &bhost_mac[5]);
for (i = 0; i != 6; i++) {
ieeeh.src[i] = (unsigned char)shost_mac[i];
ieeeh.dest[i] = (unsigned char)dhost_mac[i];
ieeeh.bssid[i] = (unsigned char)bhost_mac[i];
}
ieeeh.seq = rand();
ieeeh.rc = 1792;
radio_len = RADIO_LEN;
memcpy(&packet[2], &radio_len, 2);
memcpy(packet + RADIO_LEN, &ieeeh,\
sizeof(ieee80211_hdr));
return packet;
}
When I execute the code I get this on Wireshark:
Wireshark output

Related

VFIO interrupts using eventfd: can eventfd semaphore behaviour be maintained?

I have a program running on a QEMU VM. The program running inside this VM gets notified by a program on the host via interrupts and using QEMU ivshmem. The program on the host creates an eventfd and sends this file descriptor to QEMU when the VM starts. The program in the guest then opens a VFIO group device and sets an interrupt request fd on this device. We can then add the interrupt fd to epoll and epoll_wait to wait for notifications from the host.
The thing is that I want a 1-1 matching between the times the host writes to the eventfd and the number of events that are signaled in epoll_wait. For this I decided to use EFD_SEMAPHORE for the evenfds on the host and the guest. From my understanding, every time I write an 8 byte integer with value 1, the eventfd_counter is incremented by 1. Then every time the eventfd is read, the counter is decremented by 1 (different from a regular eventfd where each read clears the whole counter). For some reason, I am not getting the desired behaviour, so I was wondering if either eventfds with the EFD_SEMAPHORE flags are not properly supported by VFIO or QEMUs ivshmem.
Below is a simplified version of the parts I think are relevant and how I setup the notification system. I hope the code below is not too verbose. I tried to reduce the number of irrelevant parts (there is too much other code in the middle that is not particularly relevant to the problem) but not 100% sure what might be relevant or not.
Code host uses to signal guest
int ivshmem_uxsocket_send_int(int fd, int64_t i)
{
int n;
struct iovec iov = {
.iov_base = &i,
.iov_len = sizeof(i),
};
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = NULL,
.msg_controllen = 0,
.msg_flags = 0,
};
if ((n = sendmsg(fd, &msg, 0)) != sizeof(int64_t))
{
return -1;
}
return n;
}
int ivshmem_uxsocket_sendfd(int uxfd, int fd, int64_t i)
{
int n;
struct cmsghdr *chdr;
/* Need to pass at least one byte of data to send control data */
struct iovec iov = {
.iov_base = &i,
.iov_len = sizeof(i),
};
/* Allocate a char array but use a union to ensure that it
is aligned properly */
union {
char buf[CMSG_SPACE(sizeof(fd))];
struct cmsghdr align;
} cmsg;
memset(&cmsg, 0, sizeof(cmsg));
/* Add control data (file descriptor) to msg */
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = &cmsg,
.msg_controllen = sizeof(cmsg),
.msg_flags = 0,
};
/* Set message header to describe ancillary data */
chdr = CMSG_FIRSTHDR(&msg);
chdr->cmsg_level = SOL_SOCKET;
chdr->cmsg_type = SCM_RIGHTS;
chdr->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(chdr), &fd, sizeof(fd));
if ((n = sendmsg(uxfd, &msg, 0)) != sizeof(i))
{
return -1;
}
return n;
}
/* SETUP IVSHMEM WITH QEMU AND PASS THE EVENTFD USED TO
NOTIFY THE GUEST */
int ivshmem_uxsocket_accept()
{
int ret;
int cfd, ifd, nfd;
int64_t version = IVSHMEM_PROTOCOL_VERSION;
uint64_t hostid = HOST_PEERID;
int vmid = 0
/* Accept connection from qemu ivshmem */
if ((cfd = accept(uxfd, NULL, NULL)) < 0)
{
return -1;
}
/* Send protocol version as required by qemu ivshmem */
ret = ivshmem_uxsocket_send_int(cfd, version);
if (ret < 0)
{
return -1;
}
/* Send vm id to qemu */
ret = ivshmem_uxsocket_send_int(cfd, vmid);
if (ret < 0)
{
return -1;
}
/* Send shared memory fd to qemu */
ret = ivshmem_uxsocket_sendfd(cfd, shm_fd, -1);
if (ret < 0)
{
return -1;
}
/* Eventfd used by guest to notify host */
if ((nfd = eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK)) < 0)
{
return -1;
}
/* Ivshmem protocol requires to send host id
with the notify fd */
ret = ivshmem_uxsocket_sendfd(cfd, nfd, hostid);
if (ret < 0)
{
return -1;
}
/* THIS IS THE EVENTFD OF INTEREST TO US: USED BY HOST
TO NOTIFY GUEST */
if ((ifd = eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK)) < 0)
{
return -1;
}
ret = ivshmem_uxsocket_sendfd(cfd, ifd, vmid);
if (ret < 0)
{
return -1;
}
if (epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev) < 0)
{
return -1;
}
return 0;
}
/* NOW EVERY TIME WE WANT TO NOTIFY THE GUEST
WE CALL THE FOLLOWING FUNCTION */
int notify_guest(int fd)
{
int ret;
uint64_t buf = 1;
ret = write(fd, &buf, sizeof(uint64_t));
if (ret < sizeof(uint64_t))
{
return -1;
}
return 0;
}
Code guest uses to receive notifications from host
/* THIS FUNCTION SETS THE IRQ THAT RECEIVES THE
NOTIFICATIONS FROM THE HOST */
int vfio_set_irq(int dev)
{
int fd;
struct vfio_irq_set *irq_set;
char buf[sizeof(struct vfio_irq_set) + sizeof(int)];
if ((fd = eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK)) < 0)
{
return -1;
}
irq_set = (struct vfio_irq_set *) buf;
irq_set->argsz = sizeof(buf);
irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
irq_set->index = 2;
irq_set->start = 0;
irq_set->count = 1;
memcpy(&irq_set->data, &fd, sizeof(int));
if (ioctl(dev, VFIO_DEVICE_SET_IRQS, irq_set) < 0)
{
return -1;
}
return irq_fd;
}
/* The guest sets up the ivshmem region from QEMU and sets the
interrupt request. */
int vfio_init()
{
int cont, group, irq_fd;
struct epoll_event ev;
struct vfio_group_status g_status = { .argsz = sizeof(g_status) };
struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
/* Create vfio container */
if ((cont = open("/dev/vfio/vfio", O_RDWR)) < 0)
{
return -1;
}
/* Check API version of container */
if (ioctl(cont, VFIO_GET_API_VERSION) != VFIO_API_VERSION)
{
return -1;
}
if (!ioctl(cont, VFIO_CHECK_EXTENSION, VFIO_NOIOMMU_IOMMU))
{
return -1;
}
/* Open the vfio group */
if((group = open(VFIO_GROUP, O_RDWR)) < 0)
{
return -1;
}
/* Test if group is viable and available */
ioctl(group, VFIO_GROUP_GET_STATUS, &g_status);
if (!(g_status.flags & VFIO_GROUP_FLAGS_VIABLE))
{
return -1;
}
/* Add group to container */
if (ioctl(group, VFIO_GROUP_SET_CONTAINER, &cont) < 0)
{
return -1;
}
/* Enable desired IOMMU model */
if (ioctl(cont, VFIO_SET_IOMMU, VFIO_NOIOMMU_IOMMU) < 0)
{
return -1;
}
/* Get file descriptor for device */
if ((dev = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, VFIO_PCI_DEV)) < 0)
{
return -1;
}
/* Get device info */
if (ioctl(dev, VFIO_DEVICE_GET_INFO, &device_info) < 0)
{
return -1;
}
/* Set interrupt request fd */
if ((irq_fd = vfio_set_irq(dev)) < 0)
{
return -1
}
/* Add interrupt request fd to interest list */
if (vfio_subscribe_irq() < 0)
{
return -1;
}
/* Do other shm setup stuff not related to the interrupt
request */
ev.events = EPOLLIN;
ev.data.ptr = EP_NOTIFY;
ev.data.fd = irq_fd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, irq_fd, &ev) != 0)
{
return -1;
}
return 0;
}
int ivshmem_drain_evfd(int fd)
{
int ret;
uint64_t buf;
ret = read(fd, &buf, sizeof(uint64_t));
if (ret == 0)
{
return -1;
}
return ret;
}
/* I should get every notification from the host here,
but it seems that not all notifications are going
through. The number of calls to notify_guest does not
match the number of events received from epoll_wait
here */
int notify_poll()
{
int i, n;
struct epoll_event evs[32];
n = epoll_wait(epfd, evs, 32, 0);
for (i = 0; i < n; i++)
{
if (evs[i].events & EPOLLIN)
{
/* Drain evfd */
drain_evfd(irq_fd);
/* Handle notification ... */
handle();
}
}
}

C programm hangs when recv() not expected amount of bytes

I have server side app in C that must read data and process it. Now it handles two messages: send screenshot to client and click mouse. When debugging I found that it receives 16 bytes when client ask a screenshot, but when I send click mouse message, server receives 32 bytes and hangs. Why is that happening and how to process all incoming packets correctly? I'am pretty new at winsock and there not much explaning informations or example how to handle data in wild. Here's the main code of server:
struct coord
{
int x;
int y;
};
struct send_packet
{
int magic;
int cmd;
coord Coords;
};
struct recv_packet
{
int magic;
int code;
int length;
BYTE body[0];
};
do
{
ZeroMemory(&buff, BUFLEN);
int numRcvBytes = 0;
while (numRcvBytes < sizeof(send_packet))
{
iResult = recv(ClientSocket, buff + numRcvBytes, BUFLEN, 0);
//if (iResult <= 0)
// closesocket(ClientSocket);
if (iResult == SOCKET_ERROR)
{
printf("Error %d", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
}
numRcvBytes += iResult;
}
numRcvBytes = 0;
if (iResult > 0)
{
send_packet *pkt;
pkt = (send_packet *)buff;
printf("magc %d cmd %d\n", pkt->magic, pkt->cmd);
printf("Received %d %s\n", iResult, buff);
printf("m:%d c:%d x:%d y:%d\n", pkt->magic, pkt->cmd, pkt->Coords.x, pkt->Coords.y);
int command = pkt->cmd;
recv_packet *rcv_pkt;
int buff_size = 0;
BYTE *data_buffer = NULL;
int size;
int coordX;
int coordY;
wchar_t message[512];
switch (command)
{
case GET_SCREEN:
data_buffer = GetScreeny(75, &buff_size);
rcv_pkt = (recv_packet *)malloc(sizeof(recv_packet)+buff_size);
rcv_pkt->magic = MAGIC;
rcv_pkt->code = 0;
rcv_pkt->length = buff_size;
memcpy(rcv_pkt->body, data_buffer, buff_size);
size = sizeof(rcv_pkt->magic) + sizeof(rcv_pkt->code) + sizeof(rcv_pkt->length) + buff_size;
if (send(ClientSocket, (char *)rcv_pkt, size, 0) == SOCKET_ERROR)
{
printf("Error %d\n", WSAGetLastError());
closesocket(ClientSocket);
//WSACleanup();
//return 1;
}
free(rcv_pkt);
break;
case CLICK_MOUSE:
coordX = pkt->Coords.x;
coordY = pkt->Coords.y;
//wsprintf(message, L"x:%d y:%d", coordX, coordY);
//MessageBox(NULL, message, NULL, MB_OK);
MoveMouse(coordX, coordY);
ClickMouse();
break;
default:
break;
}
/*
char send_buff[1024+1] = "";
ZeroMemory(&send_buff, 1025);
memset(send_buff, 'A', 1024);
recv_packet *rcv_pkt = (recv_packet *)malloc(sizeof(recv_packet)+1024+1);
//recv_packet rcv_pkt = { 0 };
rcv_pkt->magic = MAGIC;
rcv_pkt->code = 0;
rcv_pkt->length = strlen(send_buff)+1;
memcpy(rcv_pkt->body, send_buff, 1025);
int size = sizeof(rcv_pkt->magic) + sizeof(rcv_pkt->code) + sizeof(rcv_pkt->length) + 1024 + 1;
//printf("%d", size);
//getchar();
//return 0;
*/
}
} while (iResult > 0);
I would appreciate any help! Thank you.
You should only read one message at a time. If there are 2 messages available in the socket, your current code will read both but only handle the first.
Change your read to:
iResult = recv(ClientSocket, buff + numRcvBytes, sizeof(send_packet) - numRcvBytes, 0);
Even better would be to extract the receiving to a separate function:
int recvBytes(int socket, size_t numBytes, void *buffer) {
int numRcvBytes = 0;
while (numRcvBytes < numBytes)
{
iResult = recv(socket, buff + numRcvBytes, numBytes - numRcvBytes, 0);
if (iResult == SOCKET_ERROR)
{
// Leave cleanup to caller
return SOCKET_ERROR;
}
numRcvBytes += iResult;
}
return numRcvBytes;
}

client get segmentation fault when attach to shared memory

Hi i want to implement a client-server program that communicates with each other via shared memory.
in the server side i have two threads. a writer thread and a reader thread. the writer thread puts some data into the queue and the reader thread reads from it and passes the data to the client side via shared memory.each client that has shmid can attach itself to it and read data from it...
right now i get segmentation fault at client side when it comes to attach to shared memory.
here is my code:
server side:
typedef struct shared_mem {
char imgDir[100];
int client_id;
int read_client;
sem_t shm_sem;
}shared_mem;
shared_mem *shared;
int main(int argc , char *argv[])
{
pthread_t writer_t, reader_t;
queue_t = (struct Queue*) malloc(sizeof(Queue));
queue_t->head = 0;
queue_t->tail = 0;
sem_init(&queue_t->empty, 0, QUEUE_SIZE);
sem_init(&queue_t->full, 1, 0);
int shmid;
key_t key;
key =3434;
//Create the segment and set permissions.
if ((shmid = shmget(key, sizeof(struct shared_mem), IPC_CREAT | 0666)) < 0)
{
perror("shmget error");
if(errno==EEXIST)
{
fprintf(stderr,"shared memory exist... ");
exit(1);
}
}
fprintf(stdout,"shared mem created with id: %d\n",shmid);
if( pthread_create( &reader_t , NULL , reader_thread , &shmid) < 0)
{
perror("could not create reader thread");
return 1;
}
puts("reader thread assigned");
if( pthread_create( &writer_t , NULL , writer_thread , NULL) < 0)
{
perror("could not create writer thread");
return 1;
}
puts("writer thread assigned");
pthread_join(reader_t, NULL);
pthread_join(writer_t, NULL);
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
//---------
void *reader_thread(void * id)
{
char imgPath[100];
FILE *image_fd;
char * img_filename;
char imgBuf[1024];
int readed_img_data;
char imgcount[10];
char * shm_addr;
int shm_id = *((int *)id);
shared = (struct shared_mem *) shmat(shm_id, NULL, 0);
if ((int) shared == -1)
{
printf("*** shmat error (server) ***\n");
exit(1);
}
memset(shared, 0, sizeof(struct shared_mem));
sem_init(&shared->shm_sem, 1, 1);
shared->read_client = 0;
shared->client_id = 1;
//printf("shared address: %s", &shared);
while (1)
{
printf("Here in thread reader!\n");
sem_wait(&queue_t->full);
sem_wait(&shared->shm_sem);
if (queue_t->tail != queue_t->head)
{
memmove(imgPath,queue_t->imgAddr[queue_t->head],strlen(queue_t->imgAddr[queue_t->head])-1);
imgPath[strlen(queue_t->imgAddr[queue_t->head])-1] = '\0';
queue_t->head = (queue_t->head + 1) % QUEUE_SIZE;
}
sem_post(&queue_t->empty);
printf("imagepath size: %d...\n",sizeof(imgPath));
memcpy(&shared->imgDir, &imgPath, sizeof(imgPath));
printf("shared contents: %s\n",(char *) &shared->imgDir);
shared->read_client = 0;
sem_post(&shared->shm_sem);
} //end while
if(shmdt(shm_addr) != 0)
fprintf(stderr, "Could not close memory segment.\n");
return 0;
}
clientSide():
typedef struct shared_mem {
char imgDir[100];
int client_id;
int read_client;
sem_t shm_sem;
}shared_mem;
shared_mem *shared;
int main(int argc , char *argv[])
{
char server_data[1024];
int server_data_len = 1024;
char imgDir[100]= "client_/"; // directory where client store image
char imgPath[100]; // image address which client pop from shared memory
char *imgFilename;
char imgcount[10] = "";
int readed_img_data;
int shmid;
key_t key;
key = 3434;
shmid = shmget(key, sizeof(struct shared_mem), 0666);
printf("get shmid: %d\n ", shmid);
if ((shared = (struct shared_mem *) shmat(shmid, NULL, 0)) == (void *) -1)
{
perror("shmat error");
return 1;
}
shared->client_id = 0;
sprintf(imgDir,"%s", shared->imgDir);
//keep communicating with server
while(1)
{
printf("\nReceiving new file...\n");
sem_wait(&shared->shm_sem);
memcpy(&imgPath, &shared->imgDir, 100);
memcpy(&read_client, &shared->read_client, 4);
if (read_client == 0)
read_client = 1;
memcpy(&shared->read_client, &read_client, 4);
sem_post(&shared->shm_sem);
FILE * Client_img = fopen(imgPath,"r");
if (!Client_img)
printf("%s not created!", imgPath);
fseek(Client_img, 0, SEEK_END); // seek to end of file
long size = ftell(Client_img); // get current file pointer
rewind(Client_img);
printf("size: %ld", size);
imgFilename= strrchr(imgPath,'/');
if(imgFilename)
++imgFilename;
else
{
imgFilename = (char*)malloc(100 * sizeof(char));
memmove(imgFilename,imgPath, strlen(imgPath));
}
strcat(imgDir, imgFilename);
printf("imgDir:%s", imgDir);
FILE * written_img = fopen(imgDir, "wa");
int read_sz = fread(server_data, sizeof(char), size, Client_img);
int write_sz = fwrite(server_data, sizeof(char), read_sz, written_img);
fclose(Client_img);
fclose(written_img);
}//while
if(shmdt(shm) != 0)
fprintf(stderr, "Could not close memory segment.\n");
return 0;
}

ODBC driver manager Error while calling SQLDriverConnect

I am trying to connect to my driver using SQLDriverConnect. Here is my program.
#include"stdio.h"
#include"stdlib.h"
#include"windows.h"
#include"sqlext.h"
#include"string.h"
#include"sqltypes.h"
#include"conio.h"
SQLHENV henv = (SQLHENV) NULL;
typedef struct
{
SDWORD pfNativeError[1];
SWORD pcbErrorMsg[1];
SWORD cbErrorMsgMax;
UCHAR *szErrorMsg;
UCHAR *szSqlState;
}ERR_INFO;
RETCODE odbc_Error(SQLHENV hEnv, SQLHDBC hDbc, SQLHSTMT hStmt);
RETCODE odbc_Error(SQLHENV hEnv,SQLHDBC hDbc,SQLHSTMT hStmt)
{
char *szBuf;
int pt_ch ='.' ;
int brac_ch =']' ;
ERR_INFO *Err;
RETCODE st = 0;
Err = (ERR_INFO *)malloc (sizeof(ERR_INFO));
Err->szErrorMsg = (UCHAR* )malloc(200);
Err->szSqlState = (UCHAR* )malloc(50);
szBuf = (char *)malloc(600);
memset (Err->szErrorMsg,'\0',200);
memset (Err->szSqlState,'\0',50);
memset (szBuf,'\0',600);
if (hStmt)
st = SQLGetDiagRec(SQL_HANDLE_STMT,hStmt,1,Err->szSqlState,
Err->pfNativeError, Err->szErrorMsg,150,Err->pcbErrorMsg);
else if (hDbc)
st = SQLGetDiagRec(SQL_HANDLE_DBC,hDbc,1,Err->szSqlState,
Err->pfNativeError, Err->szErrorMsg,150,Err->pcbErrorMsg);
else if (hEnv)
st = SQLGetDiagRec(SQL_HANDLE_ENV,hEnv,1,Err->szSqlState,
Err->pfNativeError, Err->szErrorMsg,150,Err->pcbErrorMsg);
if ((st == SQL_SUCCESS) || (st == SQL_SUCCESS_WITH_INFO))
{
sprintf(szBuf," %s - [%s]\n", (char *)Err->szErrorMsg, Err->szSqlState);
printf("%s \n",szBuf);
}
free(Err->szErrorMsg);
free(Err->szSqlState);
free(Err);
free(szBuf);
return SQL_SUCCESS;
}
#define ARRAY_SIZE 8
#define MAX_BINDPARAM1 17
#define DRVC_LEN 1024
struct // We have to support bit, tinyint, binary, varbinary, long varbinary
{
SQLSMALLINT SQLType[MAX_BINDPARAM1];
} CDataArgToSQL1 =
{
SQL_CHAR,SQL_VARCHAR,SQL_DECIMAL,SQL_NUMERIC,SQL_SMALLINT,SQL_INTEGER,SQL_REAL,
SQL_FLOAT,SQL_DOUBLE,SQL_DATE,SQL_TIME,SQL_TIMESTAMP,SQL_LONGVARCHAR,SQL_BIGINT,
SQL_CHAR,SQL_VARCHAR,SQL_LONGVARCHAR
};
int main()
{
int j =0;
int i = 0;
int k=0;
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt[1900];
SQLRETURN retcode;
SQLPOINTER rgbValue = &i;
SQLRETURN st = 0;
SQLPOINTER ValuePtr = NULL;
SQLHWND hwnd=NULL;
char buf[450];
int len;
char query[400]={'\0'};
char connstr[DRVC_LEN]={'\0'};
char szConnStrOut[DRVC_LEN];
SWORD cbConnStrOut;
printf("\n\tUsing Data Source :Vivek \n\n");
printf("Test Negative Functionality of SQLDriverConnect: only \n");
strcpy(connstr,"DSN=VIV_OFF32_64A;UID=super.super;PWD=nedops;");
retcode = SQLAllocEnv(&henv);
if (retcode != SQL_SUCCESS)
{
printf("Error in Connection\n");
odbc_Error(henv,hdbc,NULL);
getch();
}
retcode = SQLAllocConnect(henv, &hdbc);
if (retcode != SQL_SUCCESS)
{
printf("Error in Connection\n");
odbc_Error(henv,hdbc,NULL);
getch();
}
retcode = SQLDriverConnect(hdbc,hwnd,(SQLCHAR*)connstr,SQL_NTS,(SQLCHAR*)szConnStrOut,DRVC_LEN,&cbConnStrOut,SQL_DRIVER_PROMPT);
if (retcode != SQL_SUCCESS)
{
printf("Error in Connection\n");
odbc_Error(henv,hdbc,NULL);
getch();
}
SQLDisconnect(hdbc);
SQLFreeConnect(hdbc);
SQLFreeEnv(henv);
}
When i use SQL_DRIVER_NOPROMP,SQL_DRIVER_COMPLETE or SQL_DRIVER_COMPLETE_REQUIRED i got succeess.
my goal is to prompt an window using SQLDriverConnect.
You need to supply a window handle to SQLDriverConnect and you are just passing NULL.
Without a window handle how is it going to display a dialogue.
There are ways to get a window handle if you are running this in a console.
As an aside you are mixing old ODBC APIs with new ones e.g., SQLAllocConnect/SQLGetDiagxxx and SQLDriverConnect. If this is a new application you are better writing it using at least the ODBC 3 API so you'd be using SQLAllocHandle, SQLFreeHandle and SQLSetEnvAttr to ask for ODBC 3 behaviour.

Using nl80211.h to scan access points

I'm trying to use nl80211.h for scanning access points for a simple WLAN manager. I can't find any example code and only documentation I can find is kerneldoc. I have been trying to study from iw and wpa_supplicant source but it's rather complex.
This is only documentation I can find:
NL80211_CMD_GET_SCAN get scan results
NL80211_CMD_TRIGGER_SCAN trigger a new scan with the given parameters
NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
probe requests at CCK rate or not.
How can I scan access points with nl80211? I think I need to use enum nl80211_commands {NL80211_CMD_GET_SCAN NL80211_CMD_TRIGGER_SCAN}. How can I use them?
I know this is an old question but I ran across it while I was trying to do the same thing. Being new to C and libnl I struggled to get a simple C program to just spit out access points. I'm posting this here for others who were also trying to write a simple program. iw was a great reference but it was challenging following the code around since it does so much more than scan for access points.
/*
* scan_access_points.c: Prints all detected access points with wlan0 using NL80211 (netlink).
*
* Only works on network interfaces whose drivers are compatible with Netlink. Test this by running `iw list`.
*
* Since only privileged users may submit NL80211_CMD_TRIGGER_SCAN, you'll have to run the compiled program as root.
*
* Build with: gcc $(pkg-config --cflags --libs libnl-genl-3.0) scan_access_points.c
*
* Raspbian prerequisites:
* sudo apt-get install libnl-genl-3-dev
*
* Resources:
* http://git.kernel.org/cgit/linux/kernel/git/jberg/iw.git/tree/scan.c
* http://stackoverflow.com/questions/21601521/how-to-use-the-libnl-library-to-trigger-nl80211-commands
* http://stackoverflow.com/questions/23760780/how-to-send-single-channel-scan-request-to-libnl-and-receive-single-
*
* Expected output (as root):
* NL80211_CMD_TRIGGER_SCAN sent 36 bytes to the kernel.
* Waiting for scan to complete...
* Got NL80211_CMD_NEW_SCAN_RESULTS.
* Scan is done.
* NL80211_CMD_GET_SCAN sent 28 bytes to the kernel.
* 47:be:34:f0:bb:be, 2457 MHz, NETGEAR16
* 6b:db:ed:85:ef:42, 2432 MHz, NETGEAR31
* d8:06:ef:a7:f9:80, 2412 MHz, ATT912
* a7:0d:af:0a:19:08, 2462 MHz, ATT185
*
* Expected output (without root):
* NL80211_CMD_TRIGGER_SCAN sent 36 bytes to the kernel.
* Waiting for scan to complete...
* error_handler() called.
* WARNING: err has a value of -1.
* ERROR: nl_recvmsgs() returned -28 (Operation not permitted).
* do_scan_trigger() failed with -28.
*
*/
#include <errno.h>
#include <netlink/errno.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <linux/nl80211.h>
struct trigger_results {
int done;
int aborted;
};
struct handler_args { // For family_handler() and nl_get_multicast_id().
const char *group;
int id;
};
static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) {
// Callback for errors.
printf("error_handler() called.\n");
int *ret = arg;
*ret = err->error;
return NL_STOP;
}
static int finish_handler(struct nl_msg *msg, void *arg) {
// Callback for NL_CB_FINISH.
int *ret = arg;
*ret = 0;
return NL_SKIP;
}
static int ack_handler(struct nl_msg *msg, void *arg) {
// Callback for NL_CB_ACK.
int *ret = arg;
*ret = 0;
return NL_STOP;
}
static int no_seq_check(struct nl_msg *msg, void *arg) {
// Callback for NL_CB_SEQ_CHECK.
return NL_OK;
}
static int family_handler(struct nl_msg *msg, void *arg) {
// Callback for NL_CB_VALID within nl_get_multicast_id(). From http://sourcecodebrowser.com/iw/0.9.14/genl_8c.html.
struct handler_args *grp = arg;
struct nlattr *tb[CTRL_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *mcgrp;
int rem_mcgrp;
nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
if (!tb[CTRL_ATTR_MCAST_GROUPS]) return NL_SKIP;
nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) { // This is a loop.
struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp), nla_len(mcgrp), NULL);
if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]) continue;
if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]), grp->group,
nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]))) {
continue;
}
grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
break;
}
return NL_SKIP;
}
int nl_get_multicast_id(struct nl_sock *sock, const char *family, const char *group) {
// From http://sourcecodebrowser.com/iw/0.9.14/genl_8c.html.
struct nl_msg *msg;
struct nl_cb *cb;
int ret, ctrlid;
struct handler_args grp = { .group = group, .id = -ENOENT, };
msg = nlmsg_alloc();
if (!msg) return -ENOMEM;
cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb) {
ret = -ENOMEM;
goto out_fail_cb;
}
ctrlid = genl_ctrl_resolve(sock, "nlctrl");
genlmsg_put(msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
ret = -ENOBUFS;
NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
ret = nl_send_auto_complete(sock, msg);
if (ret < 0) goto out;
ret = 1;
nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret);
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, family_handler, &grp);
while (ret > 0) nl_recvmsgs(sock, cb);
if (ret == 0) ret = grp.id;
nla_put_failure:
out:
nl_cb_put(cb);
out_fail_cb:
nlmsg_free(msg);
return ret;
}
void mac_addr_n2a(char *mac_addr, unsigned char *arg) {
// From http://git.kernel.org/cgit/linux/kernel/git/jberg/iw.git/tree/util.c.
int i, l;
l = 0;
for (i = 0; i < 6; i++) {
if (i == 0) {
sprintf(mac_addr+l, "%02x", arg[i]);
l += 2;
} else {
sprintf(mac_addr+l, ":%02x", arg[i]);
l += 3;
}
}
}
void print_ssid(unsigned char *ie, int ielen) {
uint8_t len;
uint8_t *data;
int i;
while (ielen >= 2 && ielen >= ie[1]) {
if (ie[0] == 0 && ie[1] >= 0 && ie[1] <= 32) {
len = ie[1];
data = ie + 2;
for (i = 0; i < len; i++) {
if (isprint(data[i]) && data[i] != ' ' && data[i] != '\\') printf("%c", data[i]);
else if (data[i] == ' ' && (i != 0 && i != len -1)) printf(" ");
else printf("\\x%.2x", data[i]);
}
break;
}
ielen -= ie[1] + 2;
ie += ie[1] + 2;
}
}
static int callback_trigger(struct nl_msg *msg, void *arg) {
// Called by the kernel when the scan is done or has been aborted.
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct trigger_results *results = arg;
//printf("Got something.\n");
//printf("%d\n", arg);
//nl_msg_dump(msg, stdout);
if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) {
printf("Got NL80211_CMD_SCAN_ABORTED.\n");
results->done = 1;
results->aborted = 1;
} else if (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
printf("Got NL80211_CMD_NEW_SCAN_RESULTS.\n");
results->done = 1;
results->aborted = 0;
} // else probably an uninteresting multicast message.
return NL_SKIP;
}
static int callback_dump(struct nl_msg *msg, void *arg) {
// Called by the kernel with a dump of the successful scan's data. Called for each SSID.
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
char mac_addr[20];
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct nlattr *bss[NL80211_BSS_MAX + 1];
static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
[NL80211_BSS_TSF] = { .type = NLA_U64 },
[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
[NL80211_BSS_BSSID] = { },
[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
[NL80211_BSS_INFORMATION_ELEMENTS] = { },
[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
[NL80211_BSS_STATUS] = { .type = NLA_U32 },
[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
[NL80211_BSS_BEACON_IES] = { },
};
// Parse and error check.
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
if (!tb[NL80211_ATTR_BSS]) {
printf("bss info missing!\n");
return NL_SKIP;
}
if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy)) {
printf("failed to parse nested attributes!\n");
return NL_SKIP;
}
if (!bss[NL80211_BSS_BSSID]) return NL_SKIP;
if (!bss[NL80211_BSS_INFORMATION_ELEMENTS]) return NL_SKIP;
// Start printing.
mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
printf("%s, ", mac_addr);
printf("%d MHz, ", nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
print_ssid(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
printf("\n");
return NL_SKIP;
}
int do_scan_trigger(struct nl_sock *socket, int if_index, int driver_id) {
// Starts the scan and waits for it to finish. Does not return until the scan is done or has been aborted.
struct trigger_results results = { .done = 0, .aborted = 0 };
struct nl_msg *msg;
struct nl_cb *cb;
struct nl_msg *ssids_to_scan;
int err;
int ret;
int mcid = nl_get_multicast_id(socket, "nl80211", "scan");
nl_socket_add_membership(socket, mcid); // Without this, callback_trigger() won't be called.
// Allocate the messages and callback handler.
msg = nlmsg_alloc();
if (!msg) {
printf("ERROR: Failed to allocate netlink message for msg.\n");
return -ENOMEM;
}
ssids_to_scan = nlmsg_alloc();
if (!ssids_to_scan) {
printf("ERROR: Failed to allocate netlink message for ssids_to_scan.\n");
nlmsg_free(msg);
return -ENOMEM;
}
cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb) {
printf("ERROR: Failed to allocate netlink callbacks.\n");
nlmsg_free(msg);
nlmsg_free(ssids_to_scan);
return -ENOMEM;
}
// Setup the messages and callback handler.
genlmsg_put(msg, 0, 0, driver_id, 0, 0, NL80211_CMD_TRIGGER_SCAN, 0); // Setup which command to run.
nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index); // Add message attribute, which interface to use.
nla_put(ssids_to_scan, 1, 0, ""); // Scan all SSIDs.
nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids_to_scan); // Add message attribute, which SSIDs to scan for.
nlmsg_free(ssids_to_scan); // Copied to `msg` above, no longer need this.
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback_trigger, &results); // Add the callback.
nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); // No sequence checking for multicast messages.
// Send NL80211_CMD_TRIGGER_SCAN to start the scan. The kernel may reply with NL80211_CMD_NEW_SCAN_RESULTS on
// success or NL80211_CMD_SCAN_ABORTED if another scan was started by another process.
err = 1;
ret = nl_send_auto(socket, msg); // Send the message.
printf("NL80211_CMD_TRIGGER_SCAN sent %d bytes to the kernel.\n", ret);
printf("Waiting for scan to complete...\n");
while (err > 0) ret = nl_recvmsgs(socket, cb); // First wait for ack_handler(). This helps with basic errors.
if (err < 0) {
printf("WARNING: err has a value of %d.\n", err);
}
if (ret < 0) {
printf("ERROR: nl_recvmsgs() returned %d (%s).\n", ret, nl_geterror(-ret));
return ret;
}
while (!results.done) nl_recvmsgs(socket, cb); // Now wait until the scan is done or aborted.
if (results.aborted) {
printf("ERROR: Kernel aborted scan.\n");
return 1;
}
printf("Scan is done.\n");
// Cleanup.
nlmsg_free(msg);
nl_cb_put(cb);
nl_socket_drop_membership(socket, mcid); // No longer need this.
return 0;
}
int main() {
int if_index = if_nametoindex("wlan0"); // Use this wireless interface for scanning.
// Open socket to kernel.
struct nl_sock *socket = nl_socket_alloc(); // Allocate new netlink socket in memory.
genl_connect(socket); // Create file descriptor and bind socket.
int driver_id = genl_ctrl_resolve(socket, "nl80211"); // Find the nl80211 driver ID.
// Issue NL80211_CMD_TRIGGER_SCAN to the kernel and wait for it to finish.
int err = do_scan_trigger(socket, if_index, driver_id);
if (err != 0) {
printf("do_scan_trigger() failed with %d.\n", err);
return err;
}
// Now get info for all SSIDs detected.
struct nl_msg *msg = nlmsg_alloc(); // Allocate a message.
genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0); // Setup which command to run.
nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index); // Add message attribute, which interface to use.
nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, callback_dump, NULL); // Add the callback.
int ret = nl_send_auto(socket, msg); // Send the message.
printf("NL80211_CMD_GET_SCAN sent %d bytes to the kernel.\n", ret);
ret = nl_recvmsgs_default(socket); // Retrieve the kernel's answer. callback_dump() prints SSIDs to stdout.
nlmsg_free(msg);
if (ret < 0) {
printf("ERROR: nl_recvmsgs_default() returned %d (%s).\n", ret, nl_geterror(-ret));
return ret;
}
return 0;
}
nl80211.h only provides these enums for you to use with the real wireless library (which is libnl). You can use libnl by downloading it and including it in your c program: http://www.carisma.slowglass.com/~tgr/libnl/
Then with nl80211.h included, you can use all the enums that are defined with the commands defined in libnl.

Resources