Retrieve server IP address using gethostbyname() - sockets

I'm trying to retrieve the server IP address using gethostbyname(required from me)
here is the part of the client application for connecting to the server
struct hostent *SN = gethostbyname(argv[1]);
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portNum);
server_addr.sin_addr.s_addr = htonl(*SN->h_addr); //I have a doubt about this line
int serverfd=0;
serverfd = connect(SocketD, (struct sockaddr*) &server_addr,
sizeof(server_addr));
where argv[1] is the name of the server, currently localhost.
I tried also this line of code
server_addr.sin_addr = *(struct in_addr*)SN->h_addr;
Could anyone please tell me what is wrong with my code?

Related

Retrieving source address in a recvmmsg UDP socket

I am receiving multiple messages through a socket using:
result = recvmmsg(socket_, &messages_[0], MAX_NUM_MSG, MSG_WAITFORONE, NULL);
And I want get the source address and port, but I am getting an error in the struct assignment when I try:
msg = &messages_[0];
***struct sockaddr *src = &msg->msg_hdr.msg_name;***
srcport = ntohs(src->sin_port);
srcaddr = ntohl(src->sin_addr.s_addr);
invalid conversion from ‘void**’ to ‘sockaddr*'
The recvmmsg system call is an extension of recvmsg. As described in recvmsg: The msg_name field points to a caller-allocated buffer that is used to return the source address
That means you should preallocate memory space for msg_name by yourself, and also you should specify msg_namelen, please try:
sockaddr_in addrs[MAX_NUM_MSG];
for (int i = 0; i < MAX_NUM_MSG; ++i) {
messages_[i].msg_hdr.msg_name = &addrs[i];
messages_[i].msg_hdr.msg_namelen = sizeof(sockaddr_in);
}
So that you can access address when you have at least one message by doing (Remember to use sockaddr_in but not sockaddr):
struct sockaddr_in *src = messages_[0].msg_hdr.msg_name;

Get ip address of client from the server

I'm trying to get the ip address of each of my clients that connect to my server. I save this into fields of a struct which I sent to a thread. I'm noticing that sometimes I get the right ip and sometimes the wrong one. My first peer to connect usually has an incorrect ip...
The problem is that inet_ntoa() returns a pointer to static memory that is overwritten each time you call inet_ntoa(). You need to make a copy of the data before calling inet_ntoa() again:
struct peerInfo{
char ip[16];
int socket;
};
while((newsockfd = accept(sockfd,(struct sockaddr *)&clt_addr, &addrlen)) > 0)
{
struct peerInfo *p = (struct peerInfo *) malloc(sizeof(struct peerInfo));
strncpy(p->ip, inet_ntoa(clt_addr.sin_addr), 16);
p->socket = newsockfd;
printf("A peer connection was accepted from %s:%hu\n", p->ip, ntohs(clt_addr.sin_port));
if (pthread_create(&thread_id , NULL, peer_handler, (void*)p) < 0)
{
syserr("could not create thread\n");
free(p);
return 1;
}
printf("Thread created for the peer.\n");
pthread_detach(thread_id);
}
if (newsockfd < 0)
{
syserr("Accept failed.\n");
}
From http://linux.die.net/man/3/inet_ntoa:
The inet_ntoa() function converts the Internet host address in, given
in network byte order, to a string in IPv4 dotted-decimal notation.
The string is returned in a statically allocated buffer, which
subsequent calls will overwrite.
Emphasis added.

Raw socket multicasting

I have a raw socket I have bound to eth2.
#define DEVICE_NAME "eth2"
// open a socket
int Socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (Socket < 0)
{
perror("socket() error");
return -1;
}
// create a interface request structure
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
// set the interface name
strncpy(ifr.ifr_name, DEVICE_NAME, IFNAMSIZ);
// get interface index
ioctl(Socket, SIOCGIFINDEX, &ifr);
int Socket_Index = ifr.ifr_ifindex;
// bind the socket to the interface
struct sockaddr_ll Socket_Addr;
Socket_Addr.sll_family = AF_PACKET;
Socket_Addr.sll_protocol = htons(ETH_P_ALL);
Socket_Addr.sll_ifindex = Socket_Index;
bind(Socket, (struct sockaddr *)&Socket_Addr, sizeof(Socket_Addr));
// add multicast addresses to the socket, based on Unit Number
struct packet_mreq mreq;
mreq.mr_ifindex = Socket_Index;
mreq.mr_type = PACKET_MR_MULTICAST;
mreq.mr_alen = ETH_ALEN;
memcpy(mreq.mr_address, Addresses[UNITS_1_2], ETH_ALEN);
setsockopt(Socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
memcpy(mreq.mr_address, Addresses[UNIT_3], ETH_ALEN);
setsockopt(Socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
Where Addresses[UNITS_1_2] resolves to 03:00:00:01:04:00 and Addresses[UNIT_3] resolves to 02:00:00:01:04:01.
The socket is only receiving the multicast packets, and not the unicast ones. While debugging I started tcpdump and low-and-behold going to promiscuous mode did the trick.
My question is: Can I receive both multicast and unicast packets on the same raw socket without promiscuous mode? I have tried adding 02:00:00:01:04:01 to eth0s mac addresses using maddr, with no luck.
Sneaking from gabhijit: Try adding
Socket_Addr.sll_pkttype = PACKET_HOST | PACKET_MULTICAST;

CFSocketSendData won't send Data?

I am a newbie to objective C networking. I have put together the code below for a simple WOL application. I can successfully create a socket, and then set an address (I only am able to set the local machine address but thats another question).
However when trying to send the data using CFSocketSendData, it does not send the data(Data not sent message displayed).
Am I using CFSocketSendData correctly, or is there a problem elsewhere?
Any help will be greatly appreciated, thanks.
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT); //port
inet_aton(IP, &addr.sin_addr);//IP is the network IP of the machine e.g 192.168.0.2
NSData *address = [NSData dataWithBytes: &addr length: sizeof(addr)];
if (CFSocketSetAddress(WOLsocket, (CFDataRef)address) != kCFSocketSuccess){
NSLog(#"Address could not be set!");
}
else{
NSLog(#"Address set");
char ethadd []= "helloworld";
CFDataRef Data = CFDataCreate(NULL, (const UInt8*)ethadd, sizeof(ethadd));
if (CFSocketSendData(WOLsocket, NULL, Data, 0) < 0){
NSLog(#"Data could not be sent!");
}
else NSLog(#"Data Sent");
}
You didn't include the CFSocketCreate(...) code in your snippet, but I assume that you chose the defaults, the PF_INET family and the TCP protocol.
With the TCP protocol, setting the address is not enough, you need to establish a
connection to your destination endpoint.
First call the function...
CFSocketConnectToAddress (WOLsocket, address, 10.0);
then send your data...
CFSocketSendData(WOLsocket, NULL, Data, 0)

local vs remote socket connections on iphone

I want to send OSC messages from iphone to another programme (max/msp) by creating and connecting to a udp socket. this works from the iphone simulator, i.e. when both apps are running on the same computer but not when i install the app on the phone itself.
I think the problem could be with specifying the IP of the remote computer. I am using the sockaddr_in struct to specify IP and port info. when i run the code in the simulator it is fine to specify the IP as INADDR_ANY:
sin_addr.s_addr = INADDR_ANY;
when i run it on the device i'm trying to convert my IP into a hexidecimal number and specifying that instead of INADDR_ANY. This doesn't work for either the simulator or the device.
The console shows that the the socket is connecting and sending data fine but the remote programme (max/msp) doesn't receive any data at all.
I have tried importing the right frameworks so that it should work on both device and simulator.
the full code follows:
import "UDPSocketCreate.h"
#implementation UDPSocketCreate
-(id)init
{
in_addr_t myAddress = 0xC0A80145;
if(self =[super init])
{
//addr is an instance variable of type struct sockaddr_in
memset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = PF_INET;
addr.sin_port = htons(3333);
addr.sin_addr.s_addr = myAddress;INADDR_ANY
connectAddr = CFDataCreate(NULL, (unsigned char *)&addr, sizeof(addr));
OSC_initBuffer(&myOSCBuff, sizeof(packetBuffer), packetBuffer);
NSString *address = #"/test";
const char *utf8Address = [address UTF8String];
int addressResult = OSC_writeAddress(&myOSCBuff, (char*)utf8Address);
}
return self;
}
CFSocketRef udpSocket;
// this method is called from app delegate after init
-(void)createUDPSocketRef
{
udpSocket = CFSocketCreate(NULL, PF_INET, SOCK_DGRAM, IPPROTO_UDP, kCFSocketWriteCallBack, myCallBack, NULL);
if(udpSocket == NULL)
{
NSLog(#"socket create failed");
return;
}
CFRunLoopSourceRef runLoopSrceRef = CFSocketCreateRunLoopSource(NULL, udpSocket, 1);
CFRunLoopRef rl = CFRunLoopGetCurrent();
CFRunLoopAddSource(rl, runLoopSrceRef, kCFRunLoopCommonModes);
}
// pressing a button on the UI triggers this method
-(void)bang
{
int myInt = 1;
int writeRestult = OSC_writeIntArg(&myOSCBuff, myInt);
int buffDoneResult;
if (buffDoneResult = OSC_isBufferDone(&myOSCBuff))
{
NSLog(#"valid message in buff");
char *pack = OSC_getPacket(&myOSCBuff);
int packSize = OSC_packetSize(&myOSCBuff);
CFDataRef OSCPacketWithAddressTest = CFDataCreate(NULL, pack, packSize);
CFSocketError sendError = CFSocketSendData(udpSocket, connectAddr, OSCPacketWithAddressTest, 30);
NSLog(#"send error: %d", sendError);
}
OSC_resetBuffer(&myOSCBuff);
NSString *address = #"/test";
const char *utf8Address = [address UTF8String];
int addressResult = OSC_writeAddress(&myOSCBuff, (char*)utf8Address);
}
#end
any help would be greatly appreciated
Change;
in_addr_t myAddress = 0xC0A80145
to
in_addr_t myAddress = inet_addr("192.168.1.2");
or whatever that IP is.
S.
Unless I misunderstood you are trying to connect with INADDR_ANY as server address. INADDR_ANY is only for listening server to tell the IP stack that it wants to listen on any network interface (versus a specific interface on a multi-homed machine.) The client needs explicit server address of the server to send packets to. Look into inet_pton function for how to convert IP address from character string to network representation.