Following is the function I wrote to capture IPv6 multicast data coming on multicast address ff02::1 and port 9154.
This code works fine on Windows Vista and Windows 7. But I am unable to capture the same traffic for Windows 8 (none of the winsock functions returns error for Win8).
Using netstat I am able to verify that my application is using this port.
Can any one help?
void func()
{
int multicastChannel = 0;
char multicastIP[] = "FF02::1";
char multicastPort[] = "9154";
ADDRINFO* multicastAddr = NULL;
ADDRINFO* localAddr = NULL;
ADDRINFO hints = { 0 };
struct ipv6_mreq multicastRequest6;
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST;
if ( getaddrinfo(multicastIP, NULL, &hints, &multicastAddr) != 0 )
{
printf("getaddrinfo() failed");
return;
}
hints.ai_family = multicastAddr->ai_family;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
if ( getaddrinfo(NULL, multicastPort, &hints, &localAddr) != 0 )
{
printf("getaddrinfo() failed");
return;
}
multicastChannel = socket(localAddr->ai_family, localAddr->ai_socktype, 0);
if ( bind(multicastChannel, localAddr->ai_addr, localAddr->ai_addrlen) != 0 )
{
printf("bind() failed");
return;
}
memcpy(&multicastRequest6.ipv6mr_multiaddr,
&((struct sockaddr_in6*)(multicastAddr->ai_addr))->sin6_addr,
sizeof(multicastRequest6.ipv6mr_multiaddr));
multicastRequest6.ipv6mr_interface = 0;
if ( setsockopt(multicastChannel,
IPPROTO_IPV6,
IPV6_ADD_MEMBERSHIP,
(char*) &multicastRequest6,
sizeof(multicastRequest6)) != 0 )
{
ERROR_ReportError("setsockopt() failed");
}
freeaddrinfo(localAddr);
freeaddrinfo(multicastAddr);
ioctlsocket(multicastChannel, FIONBIO, &arg);
sockaddr_in6 fromAddr;
while(1)
{
read = recvfrom(multicastChannel,
data,
1500,
0,
(struct sockaddr*)&fromAddr,
&sizeof(sockaddr_in6);
if (read > 0) {
function();
}
}
}
Related
#define CA "/mnt/key/ca.crt"
#define CLIENT_KEY "/mnt/key/client.key"
#define CLIENT_CRT "/mnt/key/client.crt"
void onConnectFailure(void *context, MQTTAsync_failureData *response)
{
finished = 1;
printf("[CS55]Connect failed, rc %d\n", response ? response->code : 0);
delay(1000);
connect_server();
}
void connect_server()
{
if (MQTTAsync_connect(client, &conn_opts) != MQTTASYNC_SUCCESS)
{
printf("[CS55]connect_server()\n");
finished = 1;
}
}
void mqtt_connect()//连接
{
MQTTAsync_SSLOptions ssl_opts = MQTTAsync_SSLOptions_initializer;
pthread_mutex_init(&serial_mute, NULL); //互斥锁
MQTTAsync_create(&client, mqtt_addr, client_id, MQTTCLIENT_PERSISTENCE_NONE, NULL);
MQTTAsync_setCallbacks( //设置回调
client,
NULL,
connlost,
msgarrvd,
NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.onSuccess = onConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.username = username;
conn_opts.password = password;
conn_opts.context = client;
ssl_opts.struct_version = 5;
ssl_opts.sslVersion = MQTT_SSL_VERSION_TLS_1_2;
ssl_opts.verify = true;
ssl_opts.keyStore = CLIENT_KEY;
ssl_opts.trustStore = CLIENT_CRT;
ssl_opts.enableServerCertAuth = true;
ssl_opts.CApath = CA;
conn_opts.ssl = &ssl_opts;
// ssl_opts.enabledCipherSuites = "TLSv1";
int rc;
if ((rc = MQTTAsync_connect(client, &conn_opts))!= MQTTASYNC_SUCCESS)
{
printf("[CS55]MQTTAsync_connect return %d\n",rc);
finished = 1;
}
// connect_server(); //开始请求连接服务器
while (subscribe_fail != 1) //while(订阅成功)
{
delay(1000); //延迟1000ms
}
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
disc_opts.onSuccess = onDisconnect;
rc = MQTTAsync_disconnect(client, &disc_opts);
if (rc != MQTTASYNC_SUCCESS)
{
//printf("Failed to start disconnect, return code %d\n", rc);
}
MQTTAsync_destroy(&client);
}
log:
[CS55]Connect failed, rc -1
[CS55]Connect failed, rc -1
[CS55]Connect failed, rc -1
[CS55]Connect failed, rc -1
After I start the program, I will execute the callback function onConnectFailure, and then print the log of connection failure all the time. After debugging for a long time, I don't know where the problem is. I may need help。
I tried to add certificate authentication in mqtt, but I couldn't connect to the server. I didn't find a reference use case. If so, please share it with me
connopts.ssl = &ssl_opts;
connopts.ssl->trustStore = CA;
connopts.ssl->privateKey = CLIENT_KEY;
connopts.ssl->keyStore = CLIENT_CRT;
connopts.ssl->enableServerCertAuth = ture;
connopts.ssl->verify = true;
Refer to the above code, pay attention to using SSL protocol when connecting to the server ssl://11.22.33.44 :8883。
I have a small C program where I am trying to bind to a socket at a certain ip:port. Here it the program -
int main ()
{
int udp_fd = -1;
struct sockaddr_in sockaddr;
char *ip = (char *)"xx.yyy.zzz.aaa";
int port = 1234;
udp_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_fd == -1) {
printf("Could not create socket\n");
return -1;
}
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = inet_addr(ip);
sockaddr.sin_port = htons(port);
if (bind(udp_fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1) {
printf("Could not bind to %s: %d: %d: %d\n", ip, port, errno, udp_fd);
return -1;
}
if (fcntl(udp_fd, F_SETFL, O_NONBLOCK | O_ASYNC) < 0) {
printf("Error setting socket as non-blocking \n");
return -1;
}
return 0;
}
This fails with EADDRNOTAVAIL
define EADDRNOTAVAIL 99 /* Cannot assign requested address */
I try to connect to the same server from another device that is on the same network as the other device that fails the bind and it is successful.
There are no firewalls enabled on the failing device.
You are trying to bind your socket to a non-local IP address.
You don't generally need to bind to a specific IP address at all. Change:
sockaddr.sin_addr.s_addr = inet_addr(ip);
to
sockaddr.sin_addr.s_addr = INADDR_ANY;
I have a client that connects to LDAP server using TLS. For this connection, I want to enable CRL check and reject the connection only if any server/client certificates are revoked.
In special cases (like CRL missing, CRL expired) I want to ignore the error and establish the connection.
So I though to overwrite the default SSL verify call back to ignore the specific errors.
But the call back is not called at all. Always only default call-back is called.
Here is my call back:
static int verify_callback(int ok, X509_STORE_CTX *ctx)
{
X509* cert = X509_STORE_CTX_get_current_cert(ctx);
if (ok)
return ok;
int sslRet = X509_STORE_CTX_get_error(ctx);
const char* err = NULL;
switch (sslRet)
{
case X509_V_ERR_UNABLE_TO_GET_CRL:
case X509_V_ERR_CRL_HAS_EXPIRED:
case X509_V_ERR_CRL_NOT_YET_VALID:
printf( "CRL: Verification failed... but ignored : %d\n", sslRet);
return 1;
default:
err = X509_verify_cert_error_string(sslRet);
if (err)
printf( "CRL: Failed to verify : %s\n",err);
return 0;
}
return sslRet;
}
Default verify call-back is overwritten using the ldap call-back set option:
void ldap_tls_cb(LDAP * ld, SSL * ssl, SSL_CTX * ctx, void * arg)
{
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER , verify_callback);
printf("verify call back is set...\n");
return;
}
Main Program:
int main( int argc, char **argv )
{
LDAP *ldap;
int auth_method = LDAP_AUTH_SIMPLE; //LDAP_AUTH_SASL
int ldap_version = LDAP_VERSION3;
char *ldap_host = "10.104.40.35";
int ldap_port = 389;
if ( (ldap = ldap_init(ldap_host, ldap_port)) == NULL ) {
perror( "ldap_init failed" );
return( EXIT_FAILURE );
}
int result = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option failed!");
return(EXIT_FAILURE);
}
int requireCert = LDAP_OPT_X_TLS_DEMAND;
result = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &requireCert);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option - req cert -failed!");
return(EXIT_FAILURE);
}
result = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, "/etc/certs/Cert.pem");
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option - cert file - failed!");
return(EXIT_FAILURE);
}
int crlvalue = LDAP_OPT_X_TLS_CRL_ALL;
result =ldap_set_option(NULL, LDAP_OPT_X_TLS_CRLCHECK, &crlvalue);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option failed!");
return(EXIT_FAILURE);
}
int debug = 7;
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
result = ldap_set_option(ldap, LDAP_OPT_X_TLS_CONNECT_CB, (void *)ldap_tls_cb);
if (result != LDAP_SUCCESS) {
fprintf(stderr, "ldap_set_option(LDAP_OPT_X_TLS_CONNECT_CB): %s\n", ldap_err2string(result));
return(1);
}
int msgidp = 0;
result = ldap_start_tls(ldap,NULL,NULL,&msgidp);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "start tls failed!");
return result;
} else {
printf("Start tls success.\n");
}
LDAPMessage *resultm;
struct timeval timeout;
result = ldap_result(ldap, msgidp, 0, &timeout, &resultm );
if ( result == -1 || result == 0 ) {
printf("ldap_result failed;retC=%d \n", result);
return result;
}
result = ldap_parse_extended_result(ldap, resultm, NULL, NULL, 0 );
if ( result == LDAP_SUCCESS ) {
result = ldap_install_tls (ldap);
printf("installing tls... %s\n", ldap_err2string(result));
}
int request_id = 0;
result = ldap_sasl_bind(ldap, "", LDAP_SASL_SIMPLE, NULL, 0, 0, &request_id);
if ( result != LDAP_SUCCESS ) {
fprintf(stderr, "ldap_x_bind_s: %s\n", ldap_err2string(result));
printf("LDAP bind error .. %d\n", result);
return(EXIT_FAILURE);
} else {
printf("LDAP connection successful.\n");
}
ldap_unbind(ldap);
return(EXIT_SUCCESS);
}
can someone help to check why my verify call-back is not called?
I think you need to set the callback on the SSL object directly instead of the context, so
void ldap_tls_cb(LDAP * ld, SSL * ssl, SSL_CTX * ctx, void * arg)
{
SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_callback);
printf("verify call back is set...\n");
return;
}
The reason for this is that the SSL handle has already been initialised by the time your connect callback is called (see the OpenLDAP code), and
it's too late to set this callback through the context at that point:
If no special callback was set before, the default callback for the underlying ctx is used, that was valid at the time ssl was created with SSL_new(3).
OpenLDAP can be built with GnuTLS, so you may need to check that it's using OpenSSL before setting the callback. The LDAP_OPT_X_TLS_PACKAGE option could be used for this (note that I haven't tested this code):
char* package = NULL;
int result = ldap_get_option(NULL, LDAP_OPT_X_TLS_PACKAGE, (void *)&package);
if (result != LDAP_OPT_SUCCESS) {
ldap_perror(ldap, "ldap_get_option failed!");
return(EXIT_FAILURE);
} else {
if (strcmp(package, "OpenSSL") == 0) {
// Set your callback
}
ldap_memfree(package);
}
I am getting status code 404 for the below code snippet.
Note: please add <HOSTNAME> when you are trying to figure out the issue.
HINTERNET m_hConnect;
HINTERNET m_hSession;
HINTERNET m_hRequest;
m_hSession = WinHttpOpen(userAgent,
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
if (!m_hSession) {
printf("WinHttpOpen:Error %d has occurred.",GetLastError());
return 0;
}
// connect to the IPP server on the given port
m_hConnect = WinHttpConnect( m_hSession, <HOSTNAME>, 443, 0);
if (!m_hConnect) {
printf("WinHttpConnect: Error %d has occurred.",GetLastError());
return 0;
}
// Create an HTTP Request handle.
m_hRequest = WinHttpOpenRequest(m_hConnect, L"POST" ,L"/ipp",
L"HTTP/1.1", WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,WINHTTP_FLAG_SECURE);
if (!m_hRequest) {
printf("WinHttpOpenRequest:Error %d has occurred.",GetLastError());
return 0;
}
DWORD secureflags = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_CN_INVALID |SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
BOOL bResult= WinHttpSetOption(m_hRequest, WINHTTP_OPTION_SECURITY_FLAGS, (LPVOID)&secureflags, sizeof(secureflags));
if (!bResult) {
printf("WinHttpSetOption:Error %d has occurred.",GetLastError());
return 0;
}
bResult = WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS,0,WINHTTP_NO_REQUEST_DATA,0,0,0);
if (!bResult) {
printf("WinHttpSendRequest:Error %d has occurred.",GetLastError());
return 0;
}
if( !WinHttpReceiveResponse( m_hRequest, NULL ) )
{
if( GetLastError( ) == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED )
{
HCERTSTORE hMyStore = 0;
PCCERT_CONTEXT pCertContext = 0;
WCHAR szCertName[256]={0};
//MY is the store the certificate is in.
hMyStore = CertOpenSystemStore( 0, TEXT("MY") );
if( hMyStore )
{
pCertContext = CertFindCertificateInStore( hMyStore,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_STR,
(LPVOID) szCertName, //Subject string in the certificate.
NULL );
if( pCertContext )
{
WinHttpSetOption( m_hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
(LPVOID) pCertContext,
sizeof(CERT_CONTEXT) );
CertFreeCertificateContext( pCertContext );
}
CertCloseStore( hMyStore, 0 );
// NOTE: Application should now resend the request.
bResult = WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS,0,WINHTTP_NO_REQUEST_DATA,0,0,0);
if (!bResult) {
printf("WinHttpSendRequest:Error %d has occurred.",GetLastError());
return 0;
}
}
}
}
DWORD dwStatusCode = 0;
DWORD dwSize = sizeof(DWORD);
BOOL bResults = true;
bResults = WinHttpQueryHeaders( m_hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwStatusCode, &dwSize, NULL );
Result: I am getting status code of 404. I am not able to figure out why it is happening.
Using WinINet, I have followed the same procedure, I am getting status code of 200, which is success. But my requirement is to use only WinHttp.
This is not a mystery. It is happening because the resource you request was not found.
Either:
The URL you used was incorrect, or
The mapping of URLs to resources at the server isn't correct.
I'm the beginner in socket programming. I want to receive udp packets continuously from the port. For that I created socket and using bind and recv calls I have done with my program. In a buffer I'm storing the udp packets. How to receive packet by packet. How to put condition for particular time interval? Thanks in advance.
static int recvData = 1;
sockID = socket(AF_INET, SOCK_DGRAM, 0);
if(sockID < 0)
{
printf("Socket creation error\n");
WSACleanup();
}
else
{
printf("Socket Created\n");
}
fepAddr.sin_family = AF_INET;
fepAddr.sin_port = htons(inputData.portNo);
fepAddr.sin_addr.s_addr = inet_addr(inputData.destIPAddr);
if (bind(sockID, (struct sockaddr *)&fepAddr, sizeof(fepAddr)) == SOCKET_ERROR)
{
printf("bind() failed: %ld.\n", WSAGetLastError());
closesocket(sockID);
return 0;
}
else
{
printf("bind() is OK!\n");
}
memset(udpBuf,sizeof(udpBuf),0);
while (recvData)
{
printf("receiving data\n");
recvResult = recvfrom( sockID, udpBuf, sizeof(udpBuf), 0,(struct sockaddr *)&fepAddr, &sock_len);
fprintf(udp, "%s", udpBuf);
//fwrite(udpBuf, sizeof(udpBuf), 1, udp);
recvData-- ;
}
exit:
if(udp)
{
fclose(udp);
udp = 0;
}
//shutdown socket
closesocket(sockID);
fclose(udp);
recvfrom() receives UDP data packet-by-packet. If a given packet is too large, recvfrom() will return an error. As for timing, you can use select() to know when the socket is readable.
Try something like this:
sockID = socket(AF_INET, SOCK_DGRAM, 0);
if (sockID == INVALID_SOCKET)
{
printf("Socket creation error\n");
goto exit;
}
printf("Socket Created\n");
memset(&fepAddr, 0, sizeof(fepAddr));
fepAddr.sin_family = AF_INET;
fepAddr.sin_port = htons(inputData.portNo);
fepAddr.sin_addr.s_addr = inet_addr(inputData.destIPAddr);
if (bind(sockID, (struct sockaddr *)&fepAddr, sizeof(fepAddr)) == SOCKET_ERROR)
{
printf("bind() failed: %ld.\n", WSAGetLastError());
goto exit;
}
printf("bind() is OK!\n");
memset(udpBuf, 0, sizeof(udpBuf));
printf("receiving data\n");
while (...)
{
printf(".");
recvResult = recvfrom(sockID, udpBuf, sizeof(udpBuf), 0, (struct sockaddr *)&fepAddr, &addr_len);
if (recvResult == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("\nrecvfrom() failed: %ld.\n", WSAGetLastError());
goto exit;
}
fd_set fd;
FD_ZERO(&fd);
FD_SET(sockID, &fd);
timeval t;
t.tv_sec = ...; // seconds
t.tv_usec = ...; // microseconds
selectResult = select(0, &fd, NULL, NULL, &t);
if (selectResult == SOCKET_ERROR)
{
printf("\nselect() failed: %ld.\n", WSAGetLastError());
goto exit;
}
if (selectResult == 0)
{
printf("\nsocket timed out.\n");
goto exit;
}
continue;
}
if (recvResult > 0)
fwrite(udpBuf, recvResult, 1, udp);
}
exit:
if (udp != 0)
{
fclose(udp);
udp = 0;
}
if (sockID != INVALID_SOCKET)
{
closesocket(sockID);
sockID = INVALID_SOCKET;
}