Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 05 Jan 2000 13:31:28 -0500
From:      "Douglas B. Quayle" <dquayle@slk.com>
To:        Matt Gostick <matt@crazylogic.net>
Cc:        freebsd-questions@freebsd.org
Subject:   Re: ioctl programming probs
Message-ID:  <38738E00.2A1B98AE@slk.com>
References:  <Pine.BSF.4.10.9912282005040.40430-100000@thunk.crazylogic.net>

next in thread | previous in thread | raw e-mail | index | archive | help
I had a friend who asked me for something similar, so I'll give you the code
I wrote for him.
This was build on a 3.2-RELEASE box.

What I didn't know how to do, I learned
from http://ccnga.uwaterloo.ca/~mvlioy/stuff/ipc_adv_tut.txt and Unix Network
Programming.

I would recommend compiling as follows:
    g++ -Wall -ansi -ggdb main.cc

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <iostream.h>

extern "C"
{
#include <errno.h>
#include <unistd.h>

#include <netdb.h>

#include <sys/param.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <net/if.h>
#include <netinet/in.h>
}

union netaddr_t
{
  unsigned long l;
  unsigned char b[sizeof(long)];
};

template <class errcode_t>
class error
{
  errcode_t ec;
  int err;
  unsigned long ln;

public:
  error(errcode_t excpt, unsigned long l = 0, int errn = errno) :
    ec(excpt), err(errn), ln(l) { }
  error(const error<errcode_t> &e) : ec(e.ec), err(e.err), ln(e.ln) { }
  ~error(void) { }

  inline errcode_t code(void) const { return ec; }
  inline int operator()(void) const { return err; }
  inline unsigned long line(void) const { return ln; }
};

enum err_t { Socket, Bind, IoCtl };

typedef error<err_t> err;
typedef struct hostent hostent_t;
typedef struct ifconf ifconf_t;
typedef struct ifreq ifreq_t;
typedef struct protoent protoent_t;
typedef struct sockaddr sock_t;
typedef struct sockaddr_in sockin_t;

static const char *const TCP = "tcp";
static const short PORT = 3123;
static const int SOCK_FAMILY = AF_INET, SOCK_MODE = SOCK_DGRAM;
static const int SOCK_PROT = 0;

int main(int argc, char **argv)
{
  char ifcbuf[1024] = { 0 };
  int result = 0, fd = -1, i = 1;
  ifconf_t ifc = { sizeof(ifcbuf), { ifcbuf  }};
  ifreq_t *ifr = 0;
  netaddr_t netaddr = { 0 };
  sock_t dest;
  sockin_t sin;

  try
    {
      if((fd = socket(SOCK_FAMILY, SOCK_MODE, SOCK_PROT)) < 0)
 throw err(Socket, __LINE__);

      if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &i, sizeof(int)) < 0)
 throw err(Socket, __LINE__);

      memset((void *) &sin, 0, sizeof(sockin_t));
      sin.sin_family = SOCK_FAMILY, sin.sin_port = htons(PORT),
 sin.sin_addr.s_addr = htonl(INADDR_ANY);

      if(bind(fd, (sock_t *) &sin, sizeof(sockin_t)) < 0)
 throw err(Bind, __LINE__);

      if(ioctl(fd, SIOCGIFCONF, (char *) &ifc) < 0)
 throw err(IoCtl, __LINE__);

      for(i = ifc.ifc_len / sizeof(ifreq_t), ifr = ifc.ifc_req; --i >= 0;
   ifr++)
 {
   if(ioctl(fd, SIOCGIFFLAGS, (char *) ifr) < 0)
     continue;

   if(ifr -> ifr_flags & IFF_BROADCAST)
     {
       if(ioctl(fd, SIOCGIFADDR, (char *) ifr) < 0)
  throw err(IoCtl, __LINE__);
       else
  {
    memcpy((void *) &dest, (const void *) &ifr -> ifr_broadaddr,
    sizeof(sock_t));

    netaddr.l = ((sockin_t *) &dest) -> sin_addr.s_addr;

    cout << "Interface " << (short) netaddr.b[0] << "." <<
      (short) netaddr.b[1] << "." <<
      (short) netaddr.b[2] << "." <<
      (short) netaddr.b[3] << '\t';
  }

       if(ioctl(fd, SIOCGIFBRDADDR, (char *) ifr) < 0)
  throw err(IoCtl, __LINE__);
       else
  {
    memcpy((void *) &dest, (const void *) &ifr -> ifr_broadaddr,
    sizeof(sock_t));

    netaddr.l = ((sockin_t *) &dest) -> sin_addr.s_addr;

    cout << "Broadcast " << (short) netaddr.b[0] << "." <<
      (short) netaddr.b[1] << "." <<
      (short) netaddr.b[2] << "." <<
      (short) netaddr.b[3] << endl;
  }
     }
 }
    }
  catch(const err e)
    {
      switch(e.code())
 {
 case Bind: cerr << "Bind error "; break;
 case Socket: cerr << "Socket error "; break;
 case IoCtl: cerr << "Socket control error "; break;
 }

      cerr << "at " << e.line() << endl << strerror(e()) << endl;
    }

  if(fd >= 0)
    close(fd);

  return result;
}



Matt Gostick wrote:

> I'm trying to make a simple little program that gets the ip address of a
> given interface.  I'm using ioctl to do this and am having a wierd problem
> that I can't figure out.  Any help is appretiated.
>
> >From what I understand about ioctl ... the below program should display
> the interface name, ip address, destination address and the broadcast
> address.  Unfortuanely it's not.  It's not crashing ... it just always
> prints:
>
> name      : lo0
> addr      : 16.2.0.0
> dstaddr   : 16.2.0.0
> broadaddr : 16.2.0.0
>
> I've tried this on two different FreeBSD-3.2 machines with the same
> result, even the same IP's.  I've even tried switching the interface
> names to something different, and am still getting the same IP's.
>
> I have searched newsgroups and mailing lists only to come up with no
> solution.  I was hoping that those familiar with ioctl under FreeBSD will
> spot my mistake in a couple of seconds... :)  I'm new to it so any help is
> very much appretiated.
>
> /* --<get_if_ip.c>------------------------------------- */
>
> #include <stdio.h>
> #include <sys/types.h>
> #include <sys/ioctl.h>
> #include <sys/socket.h>
> #include <net/if.h>
>
> int main (void) {
>   int fd;
>   struct ifreq ifr;
>
>   /* open a socket to use for ioctl */
>   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
>     perror("socket");
>     return -1;
>   }
>
>   strcpy(ifr.ifr_name, "lo0");
>
>   /* get if address */
>   if (ioctl(fd, SIOCGIFADDR, &ifr, sizeof(ifr)) == -1) {
>     close(fd);
>     perror("ioctl");
>     return -1;
>   }
>
>   printf("name      : %s\n", ifr.ifr_name);
>   printf("addr      : %s\n", inet_ntoa(ifr.ifr_addr));
>   printf("dstaddr   : %s\n", inet_ntoa(ifr.ifr_dstaddr));
>   printf("broadaddr : %s\n", inet_ntoa(ifr.ifr_broadaddr));
>
>   close(fd);
>   return 0;
> }
>
> /* --<end get_if_ip.c>---------------------------------- */
>
> Thanks,
> Matt
>
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-questions" in the body of the message






To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?38738E00.2A1B98AE>