Why can't this program connect to the socket?
I know that WSAStartup fails, but I can't figure out how to use it.
#include "StdAfx.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <string.h>
#include <errno.h>
#pragma comment(lib, "ws2_32.lib")
int sockd;
#define SocketErrno (WSAGetLastError())
#define bcopy(src,dest,len) memmove(dest,src,len)
typedef signed char int8;
typedef signed long int32;
inline int WriteInt8(char *buf, int pos, int8 value) { buf[pos] = (int8)(value); return 1; }
inline int WriteInt32(char *buf, int pos, int32 value) { buf[pos] = (int8)(value >> 24); buf[pos+1] = (int8)(value >> 16); buf[pos+2] = (int8)(value >> 8); buf[pos+3] = (int8)(value); return 4; }
inline int WriteASCII(char *start_buf, int pos, const char *start, int length) { int startPos = 0; char *buf = &start_buf[pos]; for (int i = 0; i < length; ++i) { buf[i] = start[startPos]; if (start[startPos]) ++startPos; } return length; }
size_t writen(int fd, const char *vptr, size_t n)
{
size_t nleft;
size_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0)
{
if ( (nwritten = writen(fd, ptr, nleft)) <= 0)
{
if (errno == EINTR)
nwritten = 0;
else
return(-1);
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
bool login(char *Username, char *Password, int characterID)
{
char buffer[8192];
int pos = 0;
pos += WriteInt8(buffer, pos, 0x91u);
pos += WriteInt8(buffer, pos, 58);
pos += WriteInt8(buffer, pos, 0xFFu);
pos += WriteInt8(buffer, pos, 55);
pos += WriteInt8(buffer, pos, 40);
pos += WriteASCII(buffer, pos, Username, 30);
pos += WriteASCII(buffer, pos, Password, 30);
if( writen(sockd, buffer, 65) < 65)
return false;
WriteInt8(buffer, 0, 0x5D);
WriteInt32(buffer, 65, characterID);
if( writen(sockd, buffer, 73) < 73)
return false;
return true;
}
bool connect(char *ServerAddress, int ServerPort)
{
struct sockaddr_in servaddr;
if ( (sockd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
return false;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(ServerPort);
if ( inet_pton(AF_INET, ServerAddress, &servaddr.sin_addr) <= 0 )
return false;
if ( connect(sockd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
return false;
char seed[4] = { 0x3au, 0xFFu, 55, 40 };
if( writen(sockd, seed, 4) < 0)
return false;
return true;
}
int main(int argc, char * argv[])
{
bool wArgs = true;
if (argc == 1)
{
wArgs = false;
}
else if (argc != 4)
{
printf("USAGE: %s User Password CharacterNumber\n", argv[0]);
return 51;
}
printf("stuff");
char *user = new char[20];
char *pass = new char[20];
int pg;
if (wArgs)
{
user = argv[1];
pass = argv[2];
pg = atoi(argv[3]);
}
else
{
printf("*****************************************\n\nUser: ");
scanf("%s", user);
printf("Pass: ");
scanf("%s", pass);
printf("Character Number: ");
scanf("%d", &pg);
printf("\n*****************************************\n");
}
if (!connect("ip hidden,port hidden))
{
printf("Error at socket(): %ld\n", WSAGetLastError());
return 1;
}
if (!login(user, pass, pg))
return 103;
char version[12] = { 0xBDu, 0x00u, 0x0Cu, 0x36u, 0x2Eu, 0x30u, 0x2Eu, 0x31u, 0x2Eu, 0x31u, 0x30u, 0x00 };
if ( writen(sockd, version, 12) < 0 )
return 105;
for(;;)
{
//12 00 09 24 32 31 20 30 00 ...l.....$21 0.
char refresh[9] = { 0x12, 0x00, 0x09, 0x24, 0x32, 0x31, 0x20, 0x30, 0x00 };
if( writen(sockd, refresh, 9) < 0)
return 104;
Sleep(40);
}
return 1;
}
10093 is WSANOTINITIALISED, which means WSAStartup() has not been called yet. The documentation for WSAStartup is pretty clear, if a bit verbose, and even includes a fairly complete example.
You must call WSAStartup before using any other Winsock functions:
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
You may also want to checkout out the WinSock FAQ when learning to do WinSock programming.
Related
I got an error:
dereferencing pointer to incomplete type 'struct ip'
138| u_int8_t icmp_Type = icmp_package->icmp_type;
I've made some research, found some similar topics on this, but nothing helped. The problem probably is with icmp.
The program works like traceroute in a Linux terminal.
None of these seem to work to fix it:
adding -D_GNU_SOURCE to gcc command
adding __USE_BSD
Does anyone know how to solve it?
Compiling on Linux with gcc -std=c17
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
int receive_from(int sockfd, char recipient[20], int PID, int TTL, char response[20]);
void print_as_bytes (unsigned char* buff, ssize_t length)
{
for (ssize_t i = 0; i < length; i++, buff++)
printf ("%.2x ", *buff);
}
void print_row(int RCV_NUM, int avg, int TTL, char responses[3][20])
{
if(TTL < 10)
printf(" ");
printf("%d", TTL);
if(RCV_NUM == 0)
{
printf("*\n");
} else {
printf(" %s", responses[0]);
if(strcmp(responses[0], responses[1]) != 0)
printf(" %s", responses[1]);
if(strcmp(responses[0], responses[2]) != 0 && strcmp(responses[1], responses[2]) != 0)
printf(" %s", responses[2]);
if(RCV_NUM < 3)
printf(" ???\n");
else
printf(" %d ms", avg);
}
}
int receive(int sockfd, char recipient[20], int PID, int TTL)
{
int DEST_REACHED = 0;
char responses[3][20] = {"", "", ""};
struct timeval time;
gettimeofday(&time, NULL);
long long start = ((long long)time.tv_sec * 1000) + (time.tv_usec / 1000);
fd_set descriptors;
FD_ZERO(&descriptors);
FD_SET(sockfd, &descriptors);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
int time_passed = 0;
int which = 0;
while(which < 3)
{
int ready = select (sockfd+1, &descriptors, NULL, NULL, &tv);
if(ready < 0)
{
fprintf(stderr, "traceroute: select error: %s\n", strerror(errno));
which++;
}
if(ready > 0)
{
gettimeofday(&time, NULL);
long long timeNow = ((long long)time.tv_sec * 1000) + (time.tv_usec / 1000);
time_passed += timeNow - start;
int result = receive_from(sockfd, recipient, PID, TTL, responses[which]);
if(result == -1)
{
fprintf(stderr, "traceroute: Package missed\n");
which++;
continue;
}
if(result == 1)
{
DEST_REACHED = 1;
}
which++;
if(which == 3)
{ break; }
}
if(ready == 0)
{
which++;
}
}
int avg;
int RCV_NUM = 3;
if(which < 3)
{
RCV_NUM = which;
} else {
avg = time_passed / 3;
}
print_row(RCV_NUM, avg, TTL, responses);
return DEST_REACHED;
}
int receive_from(int sockfd, char recipient[20], int PID, int TTL, char response[20])
{
struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
u_int8_t buffer[IP_MAXPACKET];
ssize_t packet_len = recvfrom (sockfd, buffer, IP_MAXPACKET, 0, (struct sockaddr*)&sender, &sender_len);
if (packet_len < 0) {
fprintf(stderr, "recvfrom error: %s\n", strerror(errno));
return EXIT_FAILURE;
}
char sender_ip_str[20];
inet_ntop(AF_INET, &(sender.sin_addr), sender_ip_str, sizeof(sender_ip_str));
printf ("Received IP packet with ICMP content from: %s\n", sender_ip_str);
struct ip* ip_header = (struct ip*) buffer;
ssize_t ip_header_len = 4 * ip_header->ip_hl;
struct icmp* icmp_package = (struct icmp*)((uint8_t *)ip_header + ip_header_len);
u_int8_t icmp_Type = icmp_package->icmp_type;
u_int8_t icmp_Code = icmp_package->icmp_code;
//We reached the destination point
if(icmp_Type == 0 && icmp_Code == 0)
{
if(icmp_package->icmp_hun.ih_idseq.icd_id == (u_int16_t) PID && icmp_package->icmp_hun.ih_idseq.icd_id == (u_int16_t) TTL)
{
inet_ntop(AF_INET, &(sender.sin_addr), response, 20);
return 1;
}
}
//Time Exceeded - we are not yet in the destination point
if(icmp_Type == 11 && icmp_Code == 0)
{
struct ip* ip_header_md = (struct ip *)((uint8_t *)icmp_package + 8);
struct icmp* icmp_package_md = (struct icmp *)((uint8_t *)ip_header_md + (*ip_header_md).ip_hl * 4);
if(icmp_package_md->icmp_hun.ih_idseq.icd_id == (u_int16_t) PID && icmp_package_md->icmp_hun.ih_idseq.icd_id == (u_int16_t) TTL)
{
inet_ntop(AF_INET, &(sender.sin_addr), response, 20);
return 0;
}
}
//Błąd
return -1;
}
I am using bluez enquiry mode to scan bluetooth client with RSSI.I am using c code enquiry_with _rssi.I am using CSR4.0 bluetooth dongle and not able to scan.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
static void print_result(const bdaddr_t *bdaddr, char has_rssi, int rssi,int sock)
{
char addr[18];
char name[248] = { 0 };
ba2str(bdaddr, addr);
memset(name, 0, sizeof(name));
if (hci_read_remote_name(sock, bdaddr, sizeof(name), name, 0) < 0)
strcpy(name, "[unknown]");
printf("%17s \t", addr);
printf("%s \t", name);
if(has_rssi)
printf(" RSSI:%d", rssi);
else
printf(" RSSI:n/a");
printf("\n");
fflush(NULL);
}
static void scanner_start()
{
int dev_id, sock = 0;
struct hci_filter flt;
inquiry_cp cp;
unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr;
hci_event_hdr *hdr;
char canceled = 0;
inquiry_info_with_rssi *info_rssi;
inquiry_info *info;
int results, i, len;
struct pollfd p;
dev_id = hci_get_route(NULL);
sock = hci_open_dev( dev_id );
if (dev_id < 0 || sock < 0) {
perror("Can't open socket");
return;
}
hci_filter_clear(&flt);
hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
hci_filter_set_event(EVT_INQUIRY_RESULT, &flt);
hci_filter_set_event(EVT_INQUIRY_RESULT_WITH_RSSI, &flt);
hci_filter_set_event(EVT_INQUIRY_COMPLETE, &flt);
if (setsockopt(sock, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
perror("Can't set HCI filter");
return;
}
if (hci_send_cmd(sock, OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE,
WRITE_INQUIRY_MODE_RP_SIZE, &cp) < 0) {
perror("Can't set inquiry mode");
return;
}
memset (&cp, 0, sizeof(cp));
cp.lap[2] = 0x9e;
cp.lap[1] = 0x8b;
cp.lap[0] = 0x33;
cp.num_rsp = 0;
cp.length = 0x30;
printf("Starting inquiry with RSSI...\n");
if (hci_send_cmd (sock, OGF_LINK_CTL, OCF_INQUIRY, INQUIRY_CP_SIZE,&cp) < 0) {
perror("Can't start inquiry");
return;
}
p.fd = sock;
p.events = POLLIN | POLLERR | POLLHUP;
while(!canceled) {
p.revents = 0;
/* poll the BT device for an event */
if (poll(&p, 1, -1) > 0) {
len = read(sock, buf, sizeof(buf));
if (len < 0)
continue;
else if (len == 0)
break;
printf("len= %d \n",len);
hdr = (void *) (buf + 1);
ptr = buf + (1 + HCI_EVENT_HDR_SIZE);
results = ptr[0];
printf("results %d \n",results);
switch (hdr->evt)
{
case EVT_INQUIRY_RESULT:
for (i = 0; i < results; i++) {
info = (void *)ptr + (sizeof(*info) * i) + 1;
print_result(&info->bdaddr, 0, 0,sock);
}
break;
case EVT_INQUIRY_RESULT_WITH_RSSI:
for (i = 0; i < results; i++) {
info_rssi = (void *)ptr + (sizeof(*info_rssi) * i) + 1;
print_result(&info_rssi->bdaddr, 1, info_rssi->rssi,sock);
}
break;
case EVT_INQUIRY_COMPLETE:
canceled = 1;
break;
}
}
}
close(sock);
}
int main(int argc, char **argv)
{
scanner_start();
return 0;
}
[lsusb,i have two bluetooth adaptor,down hci0 and up hci1][1]
compile above code but not able to search any client
when i execute the command sudo hciconfig hci1 inqmode 1,then it scan one client and stucks,not able to scan other device
i hope CSR4.0 support Enquiry with RSSI,and features of CSR4.0,you can see in 4 and 5 image.
So,where is the problem,why it stucks after scan one devices.
The codes are as follows. I want to enumerate all the ips. Part of the codes are used to my GUI, i am sure that the error has no relevance with them.
void udpchat1::getNameAndIp() {
struct hostent *host;
struct in_addr *ptr;
DWORD dwScope = RESOURCE_CONTEXT;
NETRESOURCE *NetResource = NULL;
HANDLE hEnum;
WNetOpenEnum(dwScope, NULL, NULL, NULL, &hEnum);
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData);
ui.IpListWidget->clear();
names.clear();
ui.chatIpLabel->setText("1111111111111");
sendAble = false;
// flag = false;
if (hEnum)
{
DWORD Count = 0xFFFFFFFF;
DWORD BufferSize = 10240;
LPVOID Buffer = new char[10240];
WNetEnumResource(hEnum, &Count, Buffer, &BufferSize);
NetResource = (NETRESOURCE*)Buffer;
char szHostName[200];
for (unsigned int i = 0; i < BufferSize / sizeof(NETRESOURCE); i++, NetResource++)
{
if (NetResource->dwUsage == RESOURCEUSAGE_CONTAINER && NetResource->dwType == RESOURCETYPE_ANY)
{
if (NetResource->lpRemoteName)
{
CString strFullName = NetResource->lpRemoteName;
if (0 == strFullName.Left(2).Compare(_T("\\\\")))
strFullName = strFullName.Right(strFullName.GetLength() - 2);
gethostname(szHostName, strlen(szHostName));
USES_CONVERSION;
char *pchar = T2A(strFullName);
host = gethostbyname(pchar);
if (host == NULL) continue;
ptr = (struct in_addr *) host->h_addr_list[0];
std::string str = "";
for (int n = 0; n < 4; n++)
{
CString addr;
if (n > 0)
{
str += ".";
}
int value = (unsigned int)((unsigned char*)host->h_addr_list[0])[n];
char p[20];
sprintf(p, "%d", value);
str.append(p);
}
names.insert(std::pair<std::string, std::string>(host->h_name, str));
ui.IpListWidget->addItem(QString::fromStdString(host->h_name));
//std::cout << "IP:" << str << " Name:" << host->h_name << std::endl;
}
}
}
delete Buffer;
WNetCloseEnum(hEnum);
}
WSACleanup();
}
I used debugging, and i found the program can not get in to this if statement.
if (NetResource->lpRemoteName)
Here is a screenshot of the debug inspector.
I'm trying to zip/unzip folders using libarchive. But, I couldn't know how to use it?
Include these:
#include <archive.h>
#include <archive_entry.h>
And compile with:
gcc -Wall -o test test.c -lz -lbz2 -larchive
So all together it should look something like this
#include <sys/types.h>
#include <sys/stat.h>
#include <archive.h>
#include <archive_entry.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int
copy_data(struct archive *ar, struct archive *aw)
{
int r;
const void *buff;
size_t size;
off_t offset;
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r < ARCHIVE_OK)
return (r);
r = archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_OK) {
fprintf(stderr, "%s\n", archive_error_string(aw));
return (r);
}
}
}
static int
extract(const char *filename)
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if ((r = archive_read_open_filename(a, filename, 10240)))
return 1;
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(a));
if (r < ARCHIVE_WARN)
return 1;
r = archive_write_header(ext, entry);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
else if (archive_entry_size(entry) > 0) {
r = copy_data(a, ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_finish_entry(ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
return 0;
}
int main ( int argc, const char **argv )
{
return extract (argv[1]);;
}
Perhaps this link will help? Examples from LibArchive Wiki
For example, here is the code they give to write files to an archive:
void
write_archive(const char *outname, const char **filename)
{
struct archive *a;
struct archive_entry *entry;
struct stat st;
char buff[8192];
int len;
int fd;
a = archive_write_new();
archive_write_add_filter_gzip(a);
archive_write_set_format_pax_restricted(a); // Note 1
archive_write_open_filename(a, outname, 10240);
while (*filename) {
stat(*filename, &st);
entry = archive_entry_new(); // Note 2
archive_entry_set_pathname(entry, *filename);
archive_entry_set_size(entry, st.st_size); // Note 3
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_perm(entry, 0644);
archive_write_header(a, entry);
fd = open(*filename, O_RDONLY);
len = read(fd, buff, sizeof(buff));
while ( len > 0 ) {
archive_write_data(a, buff, len);
len = read(fd, buff, sizeof(buff));
}
close(fd);
archive_entry_free(entry);
filename++;
}
archive_write_close(a); // Note 4
archive_write_free(a); // Note 5
}
int main(int argc, const char **argv)
{
const char *outname;
argv++;
outname = argv++;
write_archive(outname, argv);
return 0;
}
I am playing with SOCKS5 proxy ( TOR ). I am able to estabilish connection but now I dont know how to send and receive data to/from destination. Thanks for help. Code:
#include <stdio.h>
#include <WinSock2.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32.lib")
#define PUT_BYTE(ptr,data) (*(unsigned char*)ptr = data)
int main()
{
WORD wVersionRequested = MAKEWORD(2,0);
WSADATA wsaData;
if(WSAStartup(wVersionRequested,&wsaData) != 0 )
{
return 1;
}
int fd = socket( AF_INET, SOCK_STREAM, 0);
if (fd < 0)
return 1;
struct sockaddr_in destaddr;
destaddr.sin_addr.s_addr = inet_addr("xx.xx.xx.xx");
int dest_port = 80;
struct sockaddr_in saddr;
saddr.sin_port = htons(9150);
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int rv = connect( fd, (struct sockaddr *)&saddr, sizeof(saddr));
if(rv < SOCKET_ERROR)
return 1;
char buf[256], *ptr;
ptr = buf;
PUT_BYTE( ptr++,5);
PUT_BYTE( ptr++,1);
PUT_BYTE(ptr++,0x00);
send(fd,buf,ptr-buf,0);
recv(fd,buf,2,0);
if ( (buf[0] != 5) || buf[1] == 0xFF )
{
return 1;
}
ptr = buf;
PUT_BYTE(ptr++,5);
PUT_BYTE(ptr++,1);
PUT_BYTE(ptr++,0);
PUT_BYTE(ptr++,1);
memcpy( ptr, &destaddr.sin_addr.s_addr,sizeof(destaddr.sin_addr));
ptr += sizeof(destaddr.sin_addr);
PUT_BYTE(ptr++,dest_port>>8);
PUT_BYTE(ptr++,dest_port&0xFF);
send(fd,buf,ptr-buf,0);
recv(fd,buf,4,0);
if(buf[1] != 0x00)
{
return 1;
}
ptr = buf + 4;
switch ( buf[3] ) {
case 1:
recv( fd, ptr, 4+2,0 );
break;
case 3:
recv( fd, ptr, 1 ,0);
recv( fd, ptr+1, *(unsigned char*)ptr + 2,0);
break;
case 4:
recv( fd, ptr, 16+2,0 );
break;
}
printf("Succes!");
//How to send and receive data now? Now we are connected on port 80 and for example I want to send http get request and receive the answer.
return 0;
}
How to send and receive data now? Now we are connected on port 80 and for example I want to send http get request and receive the answer.
Once you have successfully authenticated with the proxy and told it where to connect to, then you simply send/recv your desired data (in this case, the HTTP data) using the existing connection to the proxy, as if you had connected to the target server directly and not to a proxy. Once the proxy session is established, all subsequent sends/receives are transparent to your app.
Update: You might also want to clean up your code so it is easier to read, fix your existing broken error handling, and add some additional error handling that is missing:
#include <stdio.h>
#include <WinSock2.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32.lib")
#include <pshpack1.h>
struct socks5_ident_req
{
unsigned char Version;
unsigned char NumberOfMethods;
unsigned char Methods[256];
};
struct socks5_ident_resp
{
unsigned char Version;
unsigned char Method;
};
struct socks5_req
{
unsigned char Version;
unsigned char Cmd;
unsigned char Reserved;
unsigned char AddrType;
union {
in_addr IPv4;
in6_addr IPv6;
struct {
unsigned char DomainLen;
char Domain[256];
};
} DestAddr;
unsigned short DestPort;
};
struct socks5_resp
{
unsigned char Version;
unsigned char Reply;
unsigned char Reserved;
unsigned char AddrType;
union {
in_addr IPv4;
in6_addr IPv6;
struct {
unsigned char DomainLen;
char Domain[256];
};
} BindAddr;
unsigned short BindPort;
};
#include <poppack.h>
bool sendData(SOCKET fd, void *data, int len)
{
char *ptr = (char *) data;
while (len > 0)
{
int sent = send(fd, ptr, len, 0);
if (sent <= 0)
{
printf("send() error: %d", WSAGetLastError());
return false;
}
ptr += sent;
len -= sent;
}
return true;
}
int recvData(SOCKET fd, void *data, int len, bool disconnectOk = false)
{
char *ptr = (char *) data;
int total = 0;
while (len > 0)
{
int recvd = recv(fd, ptr, len, 0);
if (recvd < 0)
{
printf("recv() error: %d", WSAGetLastError());
return -1;
}
if (recvd == 0)
{
if (disconnectOk)
break;
printf("disconnected");
return -1;
}
ptr += recvd;
len -= recvd;
total -= recvd;
}
return total;
}
bool socksLogin(SOCKET fd)
{
socks5_ident_req req;
socks5_ident_req resp;
req.Version = 5;
req.NumberOfMethods = 1;
req.Methods[0] = 0x00;
// add other methods as needed...
if (!sendData(fd, &req, 2+req.NumberOfMethods))
return false;
if (recvData(fd, &resp, sizeof(resp)) == -1)
return false;
if (resp.Version != 5)
{
printf("SOCKS v5 identification failed");
return false;
}
if (resp.Method == 0xFF)
{
printf("SOCKS v5 authentication failed");
return false;
}
/*
if (resp.Method != 0x00)
{
// authenticate as needed...
}
*/
return true;
}
bool socksRequest(SOCKET fd, const socks5_req &req, socks5_resp &resp)
{
memset(&resp, 0, sizeof(resp));
if (!sendData(fd, &req, 4))
return false;
switch (req.AddrType)
{
case 1:
{
if (!sendData(fd, &(req.DestAddr.IPv4), sizeof(in_addr)))
return false;
break;
}
case 3:
{
if (!sendData(fd, &(req.DestAddr.DomainLen), 1))
return false;
if (!sendData(fd, req.DestAddr.Domain, req.DestAddr.DomainLen))
return false;
break;
}
case 4:
{
if (!sendData(fd, &(req.DestAddr.IPv6), sizeof(in6_addr)))
return false;
break;
}
default:
{
printf("SOCKS 5 requesting unknown address type");
return false;
}
}
unsigned short port = htons(req.DestPort);
if (!sendData(fd, &port, 2))
return false;
if (recvData(fd, &resp, 4) == -1)
return false;
switch (resp.AddrType)
{
case 1:
{
if (recvData(fd, &(resp.BindAddr.IPv4), sizeof(in_addr)) == -1)
return false;
break;
}
case 3:
{
if (recvData(fd, &(resp.BindAddr.DomainLen), 1) == -1)
return false;
if (recvData(fd, resp.BindAddr.Domain, resp.BindAddr.DomainLen) == -1)
return false;
break;
}
case 4:
{
if (recvData(fd, &(resp.BindAddr.IPv6), sizeof(in6_addr)) == -1)
return false;
break;
}
default:
{
printf("SOCKS 5 bound to unknown address type");
return false;
}
}
if (recvData(fd, &port, 2, 0) == -1)
return false;
resp.BindPort = ntohs(port);
return true;
}
bool socksConnect(SOCKET fd, const in_addr &dest, unsigned short port)
{
socks5_req req;
socks5_resp resp;
req.Version = 5;
req.Cmd = 1;
req.Reserved = 0;
req.AddrType = 1;
req.DestAddr.IPv4 = dest;
req.DestPort = port;
if (!socksRequest(fd, req, resp))
return false;
if (resp.Reply != 0x00)
{
printf("SOCKS v5 connect failed, error: 0x%02X", resp.Reply);
return false;
}
return true;
}
int main()
{
WSADATA wsaData;
int rv = WSAStartup(MAKEWORD(2,0), &wsaData);
if (rv != 0)
{
printf("WSAStartup() error: %d", rv);
return 1;
}
SOCKET fd = socket( AF_INET, SOCK_STREAM, 0);
if (fd == INVALID_SOCKET)
{
printf("socket() error: %d", WSAGetLastError());
return 1;
}
struct sockaddr_in saddr;
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
saddr.sin_port = htons(9150);
if (connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)) != 0)
{
printf("connect() error: %d", WSAGetLastError());
return 1;
}
if (!socksLogin(fd))
return 1;
if (!socksConnect(fd, inet_addr("xx.xx.xx.xx"), 80))
return 1;
printf("Success!");
// now send/receive desired data as needed using existing fd ...
return 0;
}
I wrote a modern C++ implementation for sending and receiving data through a SOCKS5 proxy server, with SOCKS5's User/Pass Authentication too (along with Anonymous mode) and also with remote and local DNS resolution options (for more privacy).
Take a look: https://github.com/harsath/SOCKS5-Proxy-Handler
(Disclaimer: I am the author of the linked repository).
Olof, the routines you are using are notoriously difficult. If your goal is to actually get something working, I would recommend that you use a tool that has been built on top of these low-level routines.
The best one is curl. At the curl website, they compare themselves with the other tools you could consider: http://curl.haxx.se/docs/comparison-table.html
Edit: all right, so you voted down my answer. Go and look at the source code for torsocks, which tries to use these routines. Compile it and try to run it. Does it work? No. Look at the source code. Try to run the test suite. Does it work? No. Look at the routines they call. Many are deprecated. Can you even figure out which routines are deprecated?
If you look around, you will see that the people who are able to actually transfer data over Tor are using curl.