How to decide if two ip are on the same subnet or not?
The only input is the ip address and the subnet mask!
What is the optimal way, using C/C++, to compute if two ip have the same subnet?
bool checkForSubnetEquality(in_addr_t ipA, in_addr_t ipB, uint32_t subnetMask) {
return (ipA & subnetMask) == (ipB & subnetMask);
}
typedef unsigned char BYTE;
Bool CheckForSubnetParity(
BYTE[] _In_ iPAddress1,
BYTE[] _In_ iPAddress2,
BYTE[] _In_ subNetMask
) {
BYTE[] NetworkPrefix1 = new BYTE[4];
BYTE[] NetWorkPrefix2 = new BYTE[4];
Bool Result = true;
for ( int x = 0; x < 4; x++)
{
NetworkPrefix1[x] = iPAddress1[x] && subNetMask[x];
NetworkPrefix2[x] = iPAddress2[x] && subNetMask[x];
if ( NetworkPrefix1[x] != NetworkPrefix2[x] )
{
Result = false;
}
}
return Result;
}
You can apply 'xor' operation to both IP's using their mask and compare them after that. If they're identical, then both IP addresses in the same subnet.
Let's look at the 172.16.2.4/255.255.0.0 and 172.16.1.69/255.255.0.0
After 'xor' you'll get '172.16.0.0' for both addresses, so they are in the same subnet.
Regards.
Related
I'm currently trying to detect if a machine has a specific NVME SSD installed. On my machine, the file name is: SCSI#Disk&Ven_NVMe&Prod_XPG_SPECTRIX_S40#5&1363da6c&0&000000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
What would be a reliable way to detect this universally on any machine? I don't know if any of these fields are unique to each machine, and I'm not very familiar with Windows' API.
when disk type hardware is detected, kernel create device for it (really 2 device usually PDO and FDO attached to it) and register well known interface GUID_DEVINTERFACE_DISK (by call IoRegisterDeviceInterface ). as result Symbolic Link will be created under \GLOBAL?? directory. we can got all registered disk interfaces via CM_Get_Device_Interface_ListW.
SCSI#Disk&Ven_NVMe&Prod_XPG_SPECTRIX_S40# obvious unique and will be the same anywhere for this device.
so code can be next
CONFIGRET Is_XPG_SPECTRIX_S40_Present(PBOOL pb)
{
CONFIGRET cr;
ULONG cb = 0, rcb;
union {
PVOID buf;
PZZWSTR Buffer;
};
static volatile UCHAR guz = 0;
PVOID stack = alloca(guz);
do
{
cr = CM_Get_Device_Interface_List_SizeW(&rcb, const_cast<GUID*>(&GUID_DEVINTERFACE_DISK), 0, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (cr != CR_SUCCESS)
{
break;
}
if (cb < (rcb *= sizeof(WCHAR)))
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);// /RTCs must be off
}
cr = CM_Get_Device_Interface_ListW(const_cast<GUID*>(&GUID_DEVINTERFACE_DISK),
0, Buffer, cb, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
} while (cr == CR_BUFFER_SMALL);
if (cr == CR_SUCCESS)
{
while (*Buffer)
{
if (wcsstr(Buffer, L"\\SCSI#Disk&Ven_NVMe&Prod_XPG_SPECTRIX_S40#"))
{
*pb = TRUE;
break;
}
Buffer += wcslen(Buffer) + 1;
}
}
return cr;
}
I am reading and writing to an RFID tag using MFRC522.h
I can currently read the UID of a card and dump it to "UIDChar"
The UID of a card typically is 8 characters.
UID Example: 467EE9A9
I can use the mfrc522.MIFARE_SetUid function to write this UID to a new card. In order to do this I have to set the newUID to:
0x46,0x7E,0xE9,0xA9f
I have written this into my code.
What I am wanting to do is convert the UID string into a byte array so that I can use that in place of my manually written 0x46,0x7E,0xE9,0xA9.
I use the convert function to convert the UID into that format.
It can that be displayed with "buf".
Serial.println(buf);
Now my problem. If I replace the
byte newUid[] = {0x46,0x7E,0xE9,0xA9f};
with
byte newUid[] = {buf};
I get the error
invalid conversion from 'char*' to 'byte {aka unsigned char}'
How can I set my "newUid" as "buf"?
#define SS_PIN 0 //D2
#define RST_PIN 2 //D1
#include <SPI.h>
#include <MFRC522.h>
/* For RFID */
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
char buf[40]; // For string to byte array convertor
void convert(char *s)
{
int i, j, k;
buf[0] = 0x0;
for (j = 0, i = 0, k = 0; j < strlen(s); j++)
{
if (i++ == 0) {
buf[k++] = '0';
buf[k++] = 'x';
}
buf[k++] = s[j];
if (i == 2) {
if(j != strlen(s) -1) buf[k++] = ',';
i = 0;
}
}
buf[k] = 0x0;
}
void clone() {
/* RFID Read */
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent())
{
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
{
return;
}
//Show UID on serial monitor
Serial.println();
Serial.print(" UID tag :");
// Very basic UID dump
unsigned int hex_num;
hex_num = mfrc522.uid.uidByte[0] << 24;
hex_num += mfrc522.uid.uidByte[1] << 16;
hex_num += mfrc522.uid.uidByte[2] << 8;
hex_num += mfrc522.uid.uidByte[3];
// Get UID
int NFC_id = (int)hex_num;
Serial.print(NFC_id, HEX);
// Convert UID to string using an int and a base (hexadecimal)
String stringUID = String(NFC_id, HEX);
char UIDChar[10];
stringUID.toCharArray(UIDChar,10);
delay(1000);
Serial.println();
// Convert to uppercase
for (int i = 0; i < strlen(UIDChar); i++ )
{
if ( UIDChar[i] == NULL ) break;
UIDChar[i] = toupper(UIDChar[i]);
}
//Serial.print( &UIDChar[0] );
Serial.println();
convert(UIDChar);
Serial.println(buf);
/* RFID Write */
// Set new UID
// Change your UID hex string to 4 byte array
// I get error if I use byte newUid[] = {buf};
/* ERROR HERE */
byte newUid[] = {0x46,0x7E,0xE9,0xA9};
if ( mfrc522.MIFARE_SetUid(newUid, (byte)4, true) ) {
Serial.println( "Wrote new UID to card." );
}
// Halt PICC and re-select it so DumpToSerial doesn't get confused
mfrc522.PICC_HaltA();
if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
return;
}
// Dump the new memory contents
Serial.println( "New UID and contents:" );
mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}
void setup() {
Serial.begin ( 115200 );
/* RFID */
SPI.begin(); // Initiate SPI bus
mfrc522.PCD_Init(); // Initiate MFRC522
clone();
}
void loop() {
}
When you write
byte newUid[] = {buf};
you are trying to initialise newUid with a single element (there's only one item inside your {}), and that element is buf, which is a char* (or a char[]). That's why you get the error - you are trying to assign an array with one char* to a variable whose elements are bytes.
Without reading your full code in detail, I don't know why you are trying to do this assignment, rather than just use your buf array as it is. But to fix the problem, you probably just want to use
byte* newUid = buf;
Currently my android bluetooth device receive character one by one. Is it possible for me to receive one shot together without one by one ? Thanks for advice.
For example incoming data:
abcd but incoming one by 1 like a b c d
how to make it like:
abcd incoming abcd straight away.
I need to change this line code?
message = txtReceived.getText().toString() + (char)data;}
This is my current code.
btnSend.setOnClickListener(this);
int delay = 1000; // delay in ms
int period = 100; // repeat in ms
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
if (flag)
{
final byte data = read();
readMessageHandler.post(new Runnable()
{
public void run()
{
String message;
if (data != 1){
/* if(txtReceived.getText().toString().equals("ON") || txtReceived.getText().toString().equals("OFF"))
{
txtReceived.setText("");
}*/
message = txtReceived.getText().toString() + (char)data;}
else{
message = "";}
txtReceived.setText(message);
}
});
}
}
}, delay, period);
private byte read()
{
byte dataRead = 0;
try
{
dataRead = (byte) inputStream.read();
}
catch(IOException readException)
{
toastText = "Failed to read from input stream: " + readException.getMessage();
Toast.makeText(Blood_Pressure.this, toastText, Toast.LENGTH_SHORT).show();
}
return dataRead;
}
The problem is that inputstream.read returns only one byte of data, hence, you are reading byte-by-byte.
You can send the size of message before the message and then send the message.
You can modify the code to something like this.
{
...
// assuming size is within the range of integer
byte[] sizeOfIncomingData = new byte[4];
inputStream.read(sizeOfIncomingdata, 0, 4);
int size = getIntFromByteArray(sizeOfIncomingData);
byte[] dataBuffer = new byte[size];
inputStream.read(dataBuffer, 0, size);
String message = new String(dataBuffer, "UTF-8");
}
private int getIntFromByteArray(byte[] bytes)
{
return (bytes[0] & 0xFF) << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}
I'm working on decryption of encrypted MS Excel(RC4 encryption with SHA1),password is already known.In vs2010,I've could decrypt it correctly,however,my program hasto work under both Win and linux.And I have no idea to get the encryption key under linux right now,which is something like below under Win:
int getEncrypKey(HCRYPTKEY *hKey, int blocknum)
{
//------------------------H0 = H(salt, password)-----
BYTE *pbSaltandPwdHash = NULL;
DWORD dwSaltandPwdLen = 0;
pbSaltandPwdHash = SHA1_2(psalt, 16, ppwd, strlen(pwd)/2, &dwSaltandPwdLen);
printf("SHA1 of SaltandPwd:\n");
for(DWORD i = 0 ; i < dwSaltandPwdLen ; i++) {
printf("%2.2x ",pbSaltandPwdHash[i]);
}
printf("\n");
//------------------------H0 = H(salt, password)-----
//------------------------Hfinal = H(H0, block)-----
HCRYPTHASH hHash1 = 0;
CryptCreateHash( hCryptProv, CALG_SHA1, 0, 0, &hHash1) ;
CryptHashData( hHash1, pbSaltandPwdHash, dwSaltandPwdLen, 0) ;
CryptHashData( hHash1, (unsigned char*)&blocknum, sizeof(blocknum), 0) ;
//------------------------Hfinal = H(H0, block)-----
CryptDeriveKey(hCryptProv, CALG_RC4, hHash1, 0x00280000, hKey);
if(hHash1 != 0) CryptDestroyHash(hHash1);
if(pbSaltandPwdHash != NULL) free(pbSaltandPwdHash);
return 0;
}
I knew how to get H0 under linux,but I dont know how to get the hHash1 and hKey.
This post sounds like it does the same thing: Implement Windows CryptoAPI CryptDeriveKey Using OpenSSL APIs
A more general way of generating hashes in openssl is below:
Before you do anything:
#include <ssl/evp.h>
int main(int argc, char argv[]) // or in an "initialise" type function
{
OpenSSL_add_all_digests()
...
}
Then to generate the hash (error checking omitted):
const EVP_MD *digest;
EVP_MD_CTX context;
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len;
digest = EVP_get_digestbyname("sha1"); /* choose the hash type here */
EVP_MD_CTX_init(&context);
EVP_DigestInit_ex(&contxt, digest, NULL);
EVP_DigestUpdate(&context, pbSaltandPwdHash, dwSaltandPwdLen);
EVP_DigestUpdate(&context, &blocknum, sizeof(blocknum));
EVP_DigestFinal_ex(&context, hash, &hash_len);
EVP_MD_CTX_cleanup(&context);
/* Now use hash and hash_len as required */
I want to calculate the broadcast address for:
IP: 192.168.3.1
Subnet: 255.255.255.0
= 192.168.3.255
in C.
I know the way (doing fancy bitwise OR's between the inversed IP and subnet), but my problem is I come from the green fields of MacOSX Cocoa programing.
I looked into the source of ipcal, but wasn't able to integrate it into my code base. There must be a simple ten lines of code somewhere on the internet, I just can't find it.
Could someone point me to a short code example of how to do it in C?
Just calculate:
broadcast = ip | ( ~ subnet )
(Broadcast = ip-addr or the inverted subnet-mask)
The broadcast address has a 1 bit where the subnet mask has a 0 bit.
I understand that the OP had at least a vague understanding of the bit-level arithmetic but was lost on converting the strings to numbers and its inverse. here's a working (with minimal testing anyway) example, using froh42's calculation.
jcomeau#aspire:~/rentacoder/jcomeau/freifunk$ cat inet.c; make inet; ./inet 192.168.3.1 255.255.255.0
#include <arpa/inet.h>
#include <stdio.h>
int main(int argc, char **argv) {
char *host_ip = argc > 1 ? argv[1] : "127.0.0.1";
char *netmask = argc > 2 ? argv[2] : "255.255.255.255";
struct in_addr host, mask, broadcast;
char broadcast_address[INET_ADDRSTRLEN];
if (inet_pton(AF_INET, host_ip, &host) == 1 &&
inet_pton(AF_INET, netmask, &mask) == 1)
broadcast.s_addr = host.s_addr | ~mask.s_addr;
else {
fprintf(stderr, "Failed converting strings to numbers\n");
return 1;
}
if (inet_ntop(AF_INET, &broadcast, broadcast_address, INET_ADDRSTRLEN) != NULL)
printf("Broadcast address of %s with netmask %s is %s\n",
host_ip, netmask, broadcast_address);
else {
fprintf(stderr, "Failed converting number to string\n");
return 1;
}
return 0;
}
cc inet.c -o inet
Broadcast address of 192.168.3.1 with netmask 255.255.255.0 is 192.168.3.255
Could it be?
unsigned broadcast(unsigned ip,unsigned subnet){
unsigned int bits = subnet ^ 0xffffffff;
unsigned int bcast = ip | bits;
return bcast;
}
Edit: I considered that both ip and subnet are without "."
Here is how to do it in C#. for example using ip 10.28.40.149 with netmask 255.255.252.0 returns 10.28.43.255 which is the correct broadcast address. thanks to some code from here
private static string GetBroadcastAddress(string ipAddress, string subnetMask) {
//determines a broadcast address from an ip and subnet
var ip = IPAddress.Parse(ipAddress);
var mask = IPAddress.Parse(subnetMask);
byte[] ipAdressBytes = ip.GetAddressBytes();
byte[] subnetMaskBytes = mask.GetAddressBytes();
if (ipAdressBytes.Length != subnetMaskBytes.Length)
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
for (int i = 0; i < broadcastAddress.Length; i++) {
broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));
}
return new IPAddress(broadcastAddress).ToString();
}
ok whom will look for this code in the future. I have spend sometimes today as I needed this, here is the full code and it works :) simply copy and paste it and then import the required dlls.
private IPAddress CalculateBroadCastAddress(IPAddress currentIP, IPAddress ipNetMask)
{
string[] strCurrentIP = currentIP.ToString().Split('.');
string[] strIPNetMask = ipNetMask.ToString().Split('.');
ArrayList arBroadCast = new ArrayList();
for (int i = 0; i < 4; i++)
{
int nrBCOct = int.Parse(strCurrentIP[i]) | (int.Parse(strIPNetMask[i]) ^ 255);
arBroadCast.Add(nrBCOct.ToString());
}
return IPAddress.Parse(arBroadCast[0] + "." + arBroadCast[1] +
"." + arBroadCast[2] + "." + arBroadCast[3]);
}
private IPAddress getIP()
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip;
}
}
return null;
}
private IPAddress getSubnetMask()
{
NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
IPAddress ip = getIP();
foreach (NetworkInterface interf in Interfaces)
{
UnicastIPAddressInformationCollection UnicastIPInfoCol = interf.GetIPProperties().UnicastAddresses;
foreach (UnicastIPAddressInformation UnicatIPInfo in UnicastIPInfoCol)
{
if (UnicatIPInfo.Address.Equals(ip))
return UnicatIPInfo.IPv4Mask;
}
}
return null;
}
Then just call it like :
IPAddress broadcastip = CalculateBroadCastAddress(getIP(), getSubnetMask());
Happy coding :)