How to give to a client specific ip address in C - c

I am trying to implement a simple client and server in C and I can't find online an example how to set a specific IP address to the client. This is what I got so far:
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
<some code to handle error>
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(<addressOfTheServer>);
address.sin_port = htons(<portToConnectToServer>);
len = sizeof(address);
int result = connect(sockfd, (struct sockaddr *)&address, len);
On the server side I check for the client IP Address and I always get 127.0.0.1
I want to change it something different.

If you want your client to connect using a specific network interface (say, because you have multiple network cards), then you first need to call bind(2) on that interface's IP address before connecting. For example, if you have two network interfaces with IP addresses 192.168.1.100 and 10.101.151.100, then to connect using the 192.168.1.100 address you could do this:
// Error checking omitted for expository purposes
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
// Bind to a specific network interface (and optionally a specific local port)
struct sockaddr_in localaddr;
localaddr.sin_family = AF_INET;
localaddr.sin_addr.s_addr = inet_addr("192.168.1.100");
localaddr.sin_port = 0; // Any local port will do
bind(sockfd, (struct sockaddr *)&localaddr, sizeof(localaddr));
// Connect to the remote server
struct sockaddr_in remoteaddr;
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_addr.s_addr = inet_addr(server_ip);
remoteaddr.sin_port = htons(server_port);
connect(sockfd, (struct sockaddr *)&remoteaddr, sizeof(remoteaddr));

OK so I put the solution together with getting the ip address off of the computer as well:
/*dl_senderprog.c - debian linux send to server a client, datagram*/
/***********************************************************************
140203 lets see if we can bind to a port
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# vi senderprog_bind.c
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# gcc -g senderprog_bind.c -o senderprog_bind
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# ./senderprog_bind
Sender:Client-Usage: ./senderprog_bind <hostname> <message>
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# ./senderprog_bind 10.0.1.26 "dot,33,22"
MY IP address:10.0.1.242: on port: 1043
Sender: Client-gethostname() is OK...
Sender: Client-socket() sockfd is OK...
Sender: Using port: 14950
Sender: Client-sendto() is OK...
Sender: sent 9 bytes to 10.0.1.26
Sender: Client-sockfd successfully closed!
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# # it worked!!!!!
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
/* the port users will be connecting to 14950 is the port on the windows machine
that I have the server running on */
#define TOPORT 14950
#define MYPORT 1043
void my_ip( char *myniccard, char *myipaddr) {
int fd;
struct ifreq ifr;
myipaddr[0]=0;
fd = socket(AF_INET, SOCK_DGRAM, 0);
/* I want to get an IPv4 IP address */
ifr.ifr_addr.sa_family = AF_INET;
/* I want IP address attached to "eth0" */
//strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
strncpy(ifr.ifr_name, myniccard, IFNAMSIZ-1);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
/* display result */
sprintf(myipaddr,"%s"
, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
printf("MY IP address:%s: on port: %d\n", myipaddr, MYPORT);
} // my_ip
int main(int argc, char *argv[ ])
{
int sockfd;
/* connectors address information */
struct sockaddr_in their_addr;
struct sockaddr_in localaddr;
char myipaddressm[22]; //buffer for ip address
char *myniccardm ="eth0"; // check with ipconfig for correct ethernet port
struct hostent *he;
int numbytes;
if (argc != 3) {
fprintf(stderr, "Sender:Client-Usage: %s <hostname> <message>\n", argv[0]);
exit(1);
}
my_ip(myniccardm, myipaddressm);
/* get the host info */
if ((he = gethostbyname(argv[1])) == NULL) {
perror("Sender: Client-gethostbyname() error lol!");
exit(1);
}
else
printf("Sender: Client-gethostname() is OK...\n");
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Sender: Client-socket() error lol!");
exit(1);
}
else
printf("Sender: Client-socket() sockfd is OK...\n");
// Bind to a specific network interface
// (this is unusual, as you normally do not want a specific
// port for the client, but we have a specific server in
// this case that will not accept connects unless its on
// a specific port )
localaddr.sin_family = AF_INET;
localaddr.sin_addr.s_addr = inet_addr(myipaddressm);
localaddr.sin_port = htons(MYPORT); // Any local port will do
bind(sockfd, (struct sockaddr *)&localaddr, sizeof(localaddr));
/* host byte order */
their_addr.sin_family = AF_INET;
/* short, network byte order */
printf("Sender: Using port: %d\n",TOPORT);
their_addr.sin_port = htons(TOPORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
/* zero the rest of the struct */
memset(&(their_addr.sin_zero), '\0', 8);
if((numbytes = sendto(sockfd, argv[2],
strlen(argv[2]),
0,
(struct sockaddr *)&their_addr,
sizeof(struct sockaddr))) == -1) {
perror("Sender: Client-sendto() error lol!");
exit(1);
}
else
printf("Sender: Client-sendto() is OK...\n");
printf("Sender: sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr));
if (close(sockfd) != 0)
printf("Sender: Client-sockfd closing is failed!\n");
else
printf("Sender: Client-sockfd successfully closed!\n");
return 0;
}//main
/*******************************************EOF***********************/
I've run this on my debian linux embedded arm ts-7500 single board computer.

Related

socket binding failed (address already in use, even with SO_REUSEADDR)

I am working in a simple socket project. I would like to know:
why error messages appear before telnet localhost 5678?
why SO_REUSEADDR (between socket() and bind()) don't work, and what else I should try?
Code Output Message:
bind error
Error opening file: Address already in use
telnet localhost 5678
[+]Server Socket is created.
main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#define BUFSIZE 1024 // Buffer Size
#define PORT 5678
int main() {
printf("telnet localhost 5678\n");
int rfd; // socket descriptor
int clientfd; // client descriptor
struct sockaddr_in client; // Client Socket address
socklen_t client_len; // Length of Client Data
char input[BUFSIZE]; // Client Data -> Server
int bytes_read; // Client Bytes
// 1. socket() = create a socket, SOCK_STREAM = TCP
rfd = socket(AF_INET, SOCK_STREAM, 0);
if (rfd < 0) {
fprintf(stderr, "socket error\n");
exit(-1);
}
printf("[+]Server Socket is created.\n");
// optional
int enable = 1;
if (setsockopt(rfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
fprintf(stderr, "setsockopt(SO_REUSEADDR) failed");
//Initialize the server address by the port and IP
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET; // Internet address family: v4 address
server.sin_addr.s_addr = INADDR_ANY; // Server IP address
server.sin_port = htons(PORT); // Server port
// 2. bind() = bind the socket to an address
int brt = bind(rfd, (struct sockaddr *) &server, sizeof(server));
if (brt < 0) {
int errnum;
errnum = errno;
fprintf(stderr, "bind error\n");
fprintf(stderr, "Error opening file: %s\n", strerror(errnum));
exit(-1);
}
printf("[+]Bind to port %d\n", PORT);
// 3. listen() = listen for connections
int lrt = listen(rfd, 50);
if (lrt < 0) {
printf("listen error\n");
exit(-1);
}
if (lrt == 0) {
printf("[+]Listening....\n");
}
// non-stop loop
while (1) {
// 4. accept() = accept a new connection on socket from client
clientfd = accept(rfd, (struct sockaddr *) &client, &client_len);
if (clientfd < 0) {
fprintf(stderr, "accept failed with error %d\n");
exit(-1);
}
printf("Client connected\n");
...
close(clientfd);
printf("Client disconnected\n");
}
close(rfd);
}
I'm assuming that you are using Linux. If you want to rebind to an address, you should use SO_REUSEPORT not SO_REUSEADDR. Name is really misleading. But make sure that you know how it works and whether you really want to use it or not.
You can check difference here: How do SO_REUSEADDR and SO_REUSEPORT differ?

Multicasting on Ubuntu

My situation is as follows:
I have a windows machine running a UDP Multicast server that is broadcasting packets. I wrote a window client that is able to capture these packets without a problem on a separate windows machine that is connected to the network. I ran into a few firewall problems on the windows machines, but worked that out.
Now, I have an ubuntu 12.04 version of the client; however, my program isn't finding these packets. I ran through all the suggestions provided by other stack overflow posts and some google threads:
when I am running my client, netstat -g shows the IP address of the multicast network
I set the rp_filter to 0 using sysctl
I can see the packets when using tcpdump -i wlan0
Added a route (sudo route add -net 224.0.0.0 netmask 224.0.0.0 wlan0)
For step four, this is a wireless connection established over wlan0, so I add the route on wlan0. Similarly, wlan0's rp_filter=0.
Now, for the code. From the print statements and error checking. I am seeing that I am successfully binding, joining the multicast group, creating the buffer, etc... Then it just blocks at the recvfrom() function call.
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <fstream>
#pragma warning( disable : 4996 )
#define MAX_PACKETSIZE 100000 // max size of packet (actual packet size is dynamic)
bool IPAddress_StringToAddr(char *szNameOrAddress, struct in_addr *Address);
void Unpack(char* pData);
#define MULTICAST_ADDRESS "239.255.42.99" // IANA, local network
#define PORT_COMMAND 1510
#define PORT_DATA 1511
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
typedef int SOCKET;
SOCKET DataSocket;
int main(int argc, char* argv[])
{
int retval;
char szMyIPAddress[128] = "";
in_addr MyAddress, MultiCastAddress;
int optval = 0x100000;
int optval_size = 4;
// client address
if(argc>1)
{
strcpy(szMyIPAddress, argv[1]); // specified on command line
IPAddress_StringToAddr(szMyIPAddress, &MyAddress);
}
else
{ printf("usage: ./client [local_ip_address]\n"); return 0; }
MultiCastAddress.s_addr = inet_addr(MULTICAST_ADDRESS);
printf("Client: %s\n", szMyIPAddress);
printf("Multicast Group: %s\n", MULTICAST_ADDRESS);
// create a "Data" socket
printf("Create Socket.\n");
DataSocket = socket(AF_INET, SOCK_DGRAM, 0);
// allow multiple clients on same machine to use address/port
int value = 1;
printf("Set SO_REUSEADDR sockopt.\n");
retval = setsockopt(DataSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value));
if (retval == SOCKET_ERROR)
{
close(DataSocket);
return -1;
}
//bind
struct sockaddr_in MySocketAddr;
memset(&MySocketAddr, 0, sizeof(MySocketAddr));
MySocketAddr.sin_family = AF_INET;
MySocketAddr.sin_port = htons(PORT_DATA);
MySocketAddr.sin_addr = MyAddress;
printf("Bind Socket.\n");
if (bind(DataSocket, (struct sockaddr *)&MySocketAddr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
printf("[PacketClient] bind failed.\n");
return 0;
}
// join multicast group
struct ip_mreq Mreq;
Mreq.imr_multiaddr = MultiCastAddress;
Mreq.imr_interface = MyAddress;
printf("Join multicast group.\n");
retval = setsockopt(DataSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&Mreq, sizeof(Mreq));
if (retval == SOCKET_ERROR)
{
printf("[PacketClient] join failed.\n");
return -1;
}
// create a 1MB buffer
printf("Create 1MB Buffer.\n");
setsockopt(DataSocket, SOL_SOCKET, SO_RCVBUF, (char *)&optval, 4);
getsockopt(DataSocket, SOL_SOCKET, SO_RCVBUF, (char *)&optval, (socklen_t*)&optval_size);
if (optval != 0x100000)
{
printf("[PacketClient] ReceiveBuffer size = %d\n", optval);
}
//listening
printf("Listening...\n");
char szData[20000];
int addr_len = sizeof(struct sockaddr);
sockaddr_in TheirAddress;
while (1)
{
// Block until we receive a datagram from the network (from anyone including ourselves)
int nDataBytesReceived = recvfrom(DataSocket, szData, sizeof(szData), 0, (sockaddr *)&TheirAddress, (socklen_t*)&addr_len);
Unpack(szData);
}
return 0;
}
// convert ipp address string to addr
bool IPAddress_StringToAddr(char *szNameOrAddress, struct in_addr *Address)
{
int retVal;
struct sockaddr_in saGNI;
char hostName[256];
char servInfo[256];
u_short port;
port = 0;
// Set up sockaddr_in structure which is passed to the getnameinfo function
saGNI.sin_family = AF_INET;
saGNI.sin_addr.s_addr = inet_addr(szNameOrAddress);
saGNI.sin_port = htons(port);
// getnameinfo
if ((retVal = getnameinfo((sockaddr *)&saGNI, sizeof(sockaddr), hostName, 256, servInfo, 256, NI_NUMERICSERV)) != 0)
{
printf("[PacketClient] GetHostByAddr failed.\n");
return false;
}
Address->s_addr = saGNI.sin_addr.s_addr;
return true;
}
void Unpack(char* pData)
{
printf("Begin Packet\n-------\n");
}
Any suggestions are appreciated. Here is the question I used as a reference when trying to fix this problem: UDP socket (multicast) not receiving data (Ubuntu)
I paste my answer here instead writing it in comments.
As I understood you have windows machines on both sides, successfully broadcasting udp packets and now you want to replace them with ubuntu machines. And the machines are receiving the packets, but your client isn't notified.
Maybe this will help
SOL_SOCKET is for the socket layer, IPPROTO_IP for the IP layer, etc... For multicast programming, level will always be IPPROTO_IP
Here is the working code for simplified RIPv2 protocol that sends and reives multicast traffic without an problem.
int setup_sender_connection(struct in_addr interface_addr){
//create socket
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock<0){
die("Creating Socket");
}
//set outgoing interface
if(setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &interface_addr, sizeof(interface_addr))<0){
die("Setting outgoing interface");
}
//disable loopback
u_char loop = 0;
if(setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop))<0){
die("Disabling loopback");
}
//allow reusing of port
int reuse = 1;
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0){
die("Allowing reuse");
}
//bind to this port
struct sockaddr_in saddr;
bzero(&saddr, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(520);
saddr.sin_addr = interface_addr;
if(bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in))<0){
die("Binding");
}
return sock;
}
void join_group(int sock, struct in_addr interface_addr){
//join gorup
struct ip_mreq mreq;
bzero(&mreq, sizeof(struct ip_mreq));
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_IP); /* IP multicast address of group */
mreq.imr_interface = interface_addr; /* local IP address of interface */
if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))<0){
die("Joining group");
}
}
void die(char *error){
perror(error);
exit(1);
}

Server on different ip's

I'm trying to create TCP Server that should run on a machine with multiple NIC's (eth0, eth1). Each NIC has its own IP from the network and I basically want to be able to connect to the servers running on each of the IP's at the same time. However currently I am able only to connect (netcat) to the first interface IP eth0 and when I try with eth1 I get a "Connection refused" even when I have the server only running on eth1.
I'm not sure if it is a problem with my server code (below). I bind to the required interface with setsockopt() and also use the interface IP (retrieved via ioctl), and netstat shows that the server is listening on the correct ip:port, however I am not able to connect to the one on eth1.
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 255
struct in_addr getIfIp(char* ifName)
{
int sockfd;
struct ifreq ifr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifName, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
fprintf(stderr, "ioctl failed\n");
}
close(sockfd);
return ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr;
}
int startServer(char* ifName, unsigned short port)
{
int sock_descriptor, conn_desc;
struct sockaddr_in serv_addr, client_addr;
socklen_t size = sizeof(client_addr);
char buff[MAX_SIZE];
if (ifName == NULL || port == 0) {
fprintf(stderr, "invalid server parameters\n");
return -1;
}
sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
if(sock_descriptor < 0) {
fprintf(stderr, "Failed creating socket\n");
return sock_descriptor;
}
if (setsockopt(sock_descriptor, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName)) < 0) {
fprintf(stderr, "Failed setting socket option\n");
return -1;
}
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; // AddressFamily = Internet address
serv_addr.sin_addr = getIfIp(ifName);//INADDR_ANY;
serv_addr.sin_port = htons(port);
// bind the address to the socket file descriptor
if (bind(sock_descriptor, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
fprintf(stderr, "Failed to bind\n");
return -1;
} else {
printf("bound to %s\n", inet_ntoa(serv_addr.sin_addr));
}
// Now start listening
if (listen(sock_descriptor, 0) < 0){
fprintf(stderr, "Listen failed");
return -1;
} else {// max queue of pending connections
printf("Listening on port %hu ...\n", port);
}
conn_desc = accept(sock_descriptor, (struct sockaddr *)&client_addr, &size);
if (conn_desc == -1) {
fprintf(stderr, "Failed accepting connection\n");
} else {
fprintf(stderr, "Connected\n");
}
close(conn_desc);
close(sock_descriptor);
return 0;
}
Any help with this would be appreciated.
[EDIT]
As mentioned in my comment, one funny thing I noticed is that once I connect to either of the interfaces I can only connect to this interface again and connect attempts to the other fail (for both eth0 and eth1) until a reboot.
Also I guess I would go ahead with INADDR_ANY for now but would really like to hear if anyone could shed some light as to why I can't connect to separate listeners (with my code here) in this case?
To have the socket listen on any interface use INADDR_ANY as listener address ...
serv_addr.sin_addr = INADDR_ANY;
and remove the call to setsockopt().
I'm not sure whether a back-log size of 0 makes sense. Also the code misses to test the outcome of the call to listen().
Finally int size should be socklen_t size.

Specifying port number on client side

How can I make sure that my client uses a particular port to connect to server in a typical server client program. Like in server side we are using a port number in bind system call and then listen on that particular port, is there any way we can specify the port number on the client side and uses the same port to connect to server. Server = 3456 ,
Client = 7834 ( I want to specify this port number so that client uses 7834 for connection). I am trying in C and Unix platform.
You do this on the client side exactly as you do it on the server side - using bind(). It's just that the client calls connect() after bind() instead of calling listen().
Note that you will only be able to run one instance of the client on each machine if you do this, and your server might see a different client port anyway if there are network middleboxes using address translation between the client and server.
The client program can set sockaddr...sin_port and then call bind() before connecting and it will get, subject to availability, the requested outgoing port.
The server can verify this port is set manually by calling getpeername() and checking it.
As others have said though, you dont really need to set the outgoing port usually, unless you have something weird going on, or specific requirements.
It's similar with server side, usually we do
local_addr.sin_port = htons(INADDR_ANY);
because port number is not important. Instead, you can use
local_addr.sin_port = htons(src_port); /Use the src_port as you like
And then call bind
Here is a working solution that runs in debian linux on the ts-7500 sbc. it should port pretty easy. This solution also looks up the ip address of the client machine automatically.
/*dl_senderprog.c - debian linux send to server a client, datagram*/
/***********************************************************************
140203 lets see if we can bind to a port
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# vi senderprog_bind.c
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# gcc -g senderprog_bind.c -o senderprog_bind
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# ./senderprog_bind
Sender:Client-Usage: ./senderprog_bind <hostname> <message>
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# ./senderprog_bind 10.0.1.26 "dot,33,22"
MY IP address:10.0.1.242: on port: 1043
Sender: Client-gethostname() is OK...
Sender: Client-socket() sockfd is OK...
Sender: Using port: 14950
Sender: Client-sendto() is OK...
Sender: sent 9 bytes to 10.0.1.26
Sender: Client-sockfd successfully closed!
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
ts7500:/var/www/jon/uvir_sensor_lab/source/socket# # it worked!!!!!
ts7500:/var/www/jon/uvir_sensor_lab/source/socket#
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <net/if.h>
/* the port users will be connecting to 14950 is the port on the windows machine
that I have the server running on */
#define TOPORT 14950
#define MYPORT 1043
void my_ip( char *myniccard, char *myipaddr) {
int fd;
struct ifreq ifr;
myipaddr[0]=0;
fd = socket(AF_INET, SOCK_DGRAM, 0);
/* I want to get an IPv4 IP address */
ifr.ifr_addr.sa_family = AF_INET;
/* I want IP address attached to "eth0" */
//strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
strncpy(ifr.ifr_name, myniccard, IFNAMSIZ-1);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
/* display result */
sprintf(myipaddr,"%s"
, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
printf("MY IP address:%s: on port: %d\n", myipaddr, MYPORT);
} // my_ip
int main(int argc, char *argv[ ])
{
int sockfd;
/* connectors address information */
struct sockaddr_in their_addr;
struct sockaddr_in localaddr;
char myipaddressm[22]; //buffer for ip address
char *myniccardm ="eth0"; // check with ipconfig for correct ethernet port
struct hostent *he;
int numbytes;
if (argc != 3) {
fprintf(stderr, "Sender:Client-Usage: %s <hostname> <message>\n", argv[0]);
exit(1);
}
my_ip(myniccardm, myipaddressm);
/* get the host info */
if ((he = gethostbyname(argv[1])) == NULL) {
perror("Sender: Client-gethostbyname() error lol!");
exit(1);
}
else
printf("Sender: Client-gethostname() is OK...\n");
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Sender: Client-socket() error lol!");
exit(1);
}
else
printf("Sender: Client-socket() sockfd is OK...\n");
// Bind to a specific network interface
// (this is unusual, as you normally do not want a specific
// port for the client, but we have a specific server in
// this case that will not accept connects unless its on
// a specific port )
localaddr.sin_family = AF_INET;
localaddr.sin_addr.s_addr = inet_addr(myipaddressm);
localaddr.sin_port = htons(MYPORT); // Any local port will do
bind(sockfd, (struct sockaddr *)&localaddr, sizeof(localaddr));
/* host byte order */
their_addr.sin_family = AF_INET;
/* short, network byte order */
printf("Sender: Using port: %d\n",TOPORT);
their_addr.sin_port = htons(TOPORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
/* zero the rest of the struct */
memset(&(their_addr.sin_zero), '\0', 8);
if((numbytes = sendto(sockfd, argv[2],
strlen(argv[2]),
0,
(struct sockaddr *)&their_addr,
sizeof(struct sockaddr))) == -1) {
perror("Sender: Client-sendto() error lol!");
exit(1);
}
else
printf("Sender: Client-sendto() is OK...\n");
printf("Sender: sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr));
if (close(sockfd) != 0)
printf("Sender: Client-sockfd closing is failed!\n");
else
printf("Sender: Client-sockfd successfully closed!\n");
return 0;
}//main
/*******************************************EOF***********************/

Global IPv6 adrress is unable to bind on Solaris

I am trying to bring up a sample code for IPv6 server on Solaris. When i give link local address, it is working fine. But when i give global address, it is failing to bind. Please tell me, that can we use global IPv6 address on Solaris ?
This is my code ....
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* the port users will be connecting to */
#define MYPORT 9000
/* how many pending connections queue will hold */
#define BACKLOG 10
int main(int argc, char *argv[ ])
{
/* listen on sock_fd, new connection on new_fd */
int sockfd, new_fd;
/* my address information */struct sockaddr_in6 their_addr;
socklen_t sin_size;
//struct sigaction sa;
int yes = 1;
if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
{
perror("Server-socket() error lol!");
return 0;//exit(1);
}
else
printf("Server-socket() sockfd is OK...\n");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Server-setsockopt() error lol!");
return 0;//exit(1);
}else
printf("Server-setsockopt is OK...\n");
/* host byte order */
my_addr.sin6_family = AF_INET6;
/* short, network byte order */
my_addr.sin6_port = htons(MYPORT);
/* automatically fill with my IP */
inet_pton(AF_INET6,"2345:1111:aaaa::500",&my_addr.sin6_addr);
//inet_pton(AF_INET6,"fe80::203:baff:fe50:cbe5",&my_addr.sin6_addr);
my_addr.sin6_scope_id=5;
/* zero the rest of the struct */
if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
perror("Server-bind() error");
return 0;//exit(1);
}
else
printf("Server-bind() is OK...\n");
if(listen(sockfd, BACKLOG) == -1)
{
perror("Server-listen() error");
return 0;//exit(1);
}
printf("Server-listen() is OK...Listening...\n");
sin_size = sizeof(struct sockaddr_in6);
if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
{
perror("Server-accept() error");
//continue;
}
else
printf("Server-accept() is OK...\n");
printf("Server-new socket, new_fd is OK...\n");
printf("Server: Got connection from \n");
/* this is the child process */
/* child doesn’t need the listener */
char buf[1024];
int numbytes=0;
if((numbytes = recv(new_fd, buf, 1024, 0)) == -1)
{
perror("recv()");
return 1;//exit(1);
}
else
printf("Client-The recv() is OK...\n");
buf[numbytes] = '\0';printf("Client-Received: %s", buf);
if(send(new_fd, "This is a test string from server!\n", 37, 0) == -1)
perror("Server-send() error lol!");
/* parent doesn’t need this*/
close(new_fd);
printf("Server-new socket, new_fd closed successfully...\n");
return 0;
}
Thank you ....
Is 2345:1111:aaaa::500 configured on any of your interfaces? This is required before you can bind to that address.
2345:1111:aaaa::500 is the netmask, the IP is fe80::203:baff:fe50:cbe5
I think you will need scope id (2) to bind() to work, since it´s a Link-Local IPv6 address.
Malleus
I am not sure about on the Solaris, but on Windows 7 it requires Administrator priviledges to bind a socket to a global or multicast address.
Can you run your test with elevated priviledges?
-Jesse

Resources