[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 845
  • Last Modified:

UDP broadcasting from kernel

How to send broad cast message from myne kernel module?
Have wrote a piece of code, but it is not working :(
___________________________________________________
      // Initial properties
      int iRet;

      // Creating socket
      struct socket *pWorkingSocket = NULL;
      iRet = sock_create(PF_INET, SOCK_DGRAM, 0, &pWorkingSocket);
      if (iRet) {
            printk("Cannot create the socket...\n");
            return -1;
      }

      // Allocating memory for remote address
      struct sockaddr_in *pAddress;
      pAddress = kmalloc(sizeof(struct sockaddr_in), GFP_KERNEL);
      if (pAddress == NULL) {
            printk("Cannot allocate kernel memory (ERROR: %d)...\n", -ENOMEM);
            return -ENOMEM;
      }
      memset(pAddress, 0, sizeof(pAddress));
      pAddress->sin_family = AF_INET;
      pAddress->sin_port = htons(DRIVER_SERVICE_PORT);
      pAddress->sin_addr.s_addr = htonl(INADDR_BROADCAST);

      // Connecting socket to remote address
      iRet = pWorkingSocket->ops->connect(pWorkingSocket,
                  (struct sockaddr *) pAddress,
                  sizeof(struct sockaddr), O_RDWR);
      if (iRet) {
            printk("Cannot connect to the remote PC (ERROR: %d)...\n", iRet);
            goto out;
      }
___________________________________________________
It shows me "Cannot connect to the remote PC".
0
-Thespian-
Asked:
-Thespian-
  • 28
  • 24
1 Solution
 
Duncan RoeSoftware DeveloperCommented:
Is this a homework assignment by any chance?
What message number did your printk show?
UDP is connectionless, I'm not surprised the connect failed.
If I were you, I'd get this running as a user-space program first. Then convert it into a kernel module once you're sure the logic is right.
0
 
-Thespian-Author Commented:
Nope, it is not a homework.
This code works good, if I put the target IP instead "htonl(INADDR_BROADCAST);".
Can u give a sample of non connecton code with sending message?
0
 
Duncan RoeSoftware DeveloperCommented:
With UDP, use sendto() instead of connect(), send(). Use recvfrom() in preferance to recv(), which shows you from which IP a message came.
Yes now I've looked, I see from the man page that you can use connect() with SOCK_DGRAM. But maybe not to the broadcast address (which would always fail for a SOCK_STREAM socket anyway).
As I said, try it in userspace first - it's so much easier to debug.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
-Thespian-Author Commented:
I am talking about kernel. There is no sendto() function (can't find symbol). There we have sock_sendmsg().
0
 
Duncan RoeSoftware DeveloperCommented:
There is a userspace sendmsg - maybe sock_sendmsg() is its equivalent in kernel. Like sendto(), sendmsg() can specify a destination address as well as a message.
0
 
-Thespian-Author Commented:
there is sock_sendmsg, but no sock_sendto
0
 
Duncan RoeSoftware DeveloperCommented:
I'm hoping sock_sendmsg is like userspace sendmsg - sendmsg() is an alternative to sendto(). Have a look at "man sendmsg".
0
 
-Thespian-Author Commented:
sendmsg need connect or bind. sendto - don't need it...
0
 
Duncan RoeSoftware DeveloperCommented:
Doesn't kernel have a bind? user-space connect is "overloaded" for SOCK_DGRAM to have an unusual meaning as per man page - but bind is always bind. It associates the local end of the socket with a particular NIC
0
 
-Thespian-Author Commented:
yes. can u show me the full sample code of how can I send broadcast UDP messages and addressed messages?
0
 
Duncan RoeSoftware DeveloperCommented:
I don't have sample code - I suggest you try it out in userland restricting yourself to calls available in kernel space, then port it once it's working.
1. bind to a NIC
2. do a sendmsg - params similar to connect & send, except you set them up in a struct.
0
 
-Thespian-Author Commented:
it is already working, but I can not send broadcast. Even if it is in userspace....
0
 
Duncan RoeSoftware DeveloperCommented:
Post the userspace source that can't send broadcasts. We can take it from there.
0
 
-Thespian-Author Commented:
/******************************************************************************
 * Sending message to selected socket
 * Parameters:
 *   sock - initialized socket
 *   Buffer - data to send
 *   Lenght - size of data to send
 *   bConfirm - set to 1 if u want the confirmation from server
 */
size_t SendBuffer(struct socket *sock,
                  const char *Buffer, size_t Length,
                  int bConfirm)
{
      // Set the iovec structure
      struct iovec iov;
      memset(&iov, 0, sizeof(iov));
      iov.iov_base = (char*) Buffer;
      iov.iov_len = (__kernel_size_t) Length;

      struct msghdr msg;
      memset(&msg, 0, sizeof(msg));
      msg.msg_iov = &iov;
      msg.msg_iovlen = 1;
      msg.msg_flags = MSG_NOSIGNAL;
/*
      if (bConfirm != 1)
            msg.msg_flags = MSG_NOSIGNAL;//0 MSG_DONTWAIT;
      else
            msg.msg_flags = MSG_CONFIRM;
*/
      mm_segment_t oldfs = get_fs(); set_fs(KERNEL_DS);
      int len = sock_sendmsg(sock, &msg, (size_t)(Length));
      set_fs(oldfs);

      log_info("Sended message. Original size: %d. Sended size: %d", Length, len);

      if (bConfirm == 1)
      {
            char* ptr = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
            int ret = RecvBuffer(sock, ptr, BUFFER_LENGTH, 1);
            if (ret != 1 || ptr[0] != 'Y')
                  ret = 0;
            kfree(ptr);
            if (ret == 1)
                  log_info("Message synchronized.");
            else
                  log_warn("Message not synchronized.");
      }

      return len;
}
0
 
-Thespian-Author Commented:
int sendUDPMessage(const char* sIP, char* cBuffer, int iBufferLength, int bConfirm)
{
      int ret = 0;
      // Initial properties
      int iRet;

      // Creating socket
      struct socket *pWorkingSocket = NULL;
      iRet = sock_create(PF_INET, SOCK_DGRAM, 0, &pWorkingSocket);
      if (iRet) {
            printk("Cannot create the socket...\n");
            return -1;
      }

      // Allocating memory for remote address
      struct sockaddr_in *pAddress;
      pAddress = kmalloc(sizeof(struct sockaddr_in), GFP_KERNEL);
      if (pAddress == NULL) {
            printk("Cannot allocate kernel memory (ERROR: %d)...\n", -ENOMEM);
            return -ENOMEM;
      }
      memset(pAddress, 0, sizeof(pAddress));
      pAddress->sin_family = AF_INET;
      pAddress->sin_port = htons(MOD_SERVICE_PORT);
      if (sIP == NULL) {
            pAddress->sin_addr.s_addr = htonl(INADDR_BROADCAST);
/*            int one = 1;
            iRet = setsockopt(pWorkingSocket, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));
            if (iRet) {
                  printk("Cannot create broadcasting (ERROR: %d)...\n", iRet);
                  goto out;
            }*/
      } else {
            pAddress->sin_addr.s_addr = IP2InetAddr(sIP);
      }

      // Connecting socket to remote address
      iRet = pWorkingSocket->ops->connect(pWorkingSocket,
                  (struct sockaddr *) pAddress,
                  sizeof(struct sockaddr), O_RDWR);
      if (iRet) {
            printk("Cannot connect to the remote PC (ERROR: %d)...\n", iRet);
            goto out;
      }

      ret = SendBuffer(pWorkingSocket, cBuffer, iBufferLength, bConfirm);

out:      sock_release(pWorkingSocket);
      kfree(pAddress);
      return ret;
}
0
 
Duncan RoeSoftware DeveloperCommented:
Hi -Thespian- , I thought from your comment earlier that you had a userspace version? I'd prefer if you would post that, but I guess I can work with the kernel one (will port to userland though).
0
 
Duncan RoeSoftware DeveloperCommented:
Please post source for RecvBuffer to save me fuessing - thanks ... Duncan.
0
 
Duncan RoeSoftware DeveloperCommented:
fuessing - guessing. Why can't I see 'em before I post? Dunno
0
 
Duncan RoeSoftware DeveloperCommented:
Well, my userspace program drew a blank. I can send UDP to a host but not to the broadcast address. When I try to do that, I get "Permission denied", even running as root. Perhaps it's just something you can't do with UDP protocol, at least from userspace - is that why you're doing it in the kernel?
Mind you I *did* get different errors until I did everything else right - bind the socket with a sending port, specify a nonzero port to send to (otherwise you get "Invalid argument"). Maybe something would work, but I'm out of ideas.
FWIW, here's the code. You can change values as you wish with gdb - saves having to write a UI

00:59:45$ cat bcast.c
//SIOCGIFADDR
// ((struct sockaddr_in)ifr.ifr_ifru.ifru_broadaddr).sin_addr
/*
gcc -Wall -Wstrict-prototypes -Wmissing-prototypes -g3 bcast.c -o bcast
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

/* For test purposes, let's say we know which interface we want to use */

static char*ifname="eth0";

/* Message to broadcast */

char*Buffer="Hi there Tiger";

int main(int argc,char**argv)
{
  struct ifreq ifr;
  int s;
  struct msghdr msg;
  struct iovec iov;
  struct sockaddr addr;
 
  if((s=socket(PF_INET, SOCK_DGRAM, 0))==-1)
  {
    fprintf(stderr,"%s. (PF_INET, SOCK_DGRAM, 0 (socket)\n",
      strerror(errno));
    exit(1);
  }                             /* if((s=socket(PF_INET, SOCK_DGRAM, 0)0==-1) */
  snprintf(ifr.ifr_name,sizeof ifr.ifr_name,"%s",ifname);
  if(ioctl(s,SIOCGIFADDR,&ifr))
  {
    fprintf(stderr,"%s. SIOCGIFADDR %s (ioctl)\n",strerror(errno),
      ifr.ifr_name);
    exit(1);
  }                                /* if(ioctl(SIOCGIFADDR,&ifr)) */
  memcpy(&addr,&ifr.ifr_ifru.ifru_addr,sizeof(struct sockaddr));
  ((struct sockaddr_in*)&addr)->sin_port=htons(12345);
  if(bind(s,&addr,sizeof addr))
  {
    fprintf(stderr,"%s. (bind)\n",strerror(errno));
    exit(1);
  }
  if(ioctl(s,SIOCGIFBRDADDR,&ifr))
  {
    fprintf(stderr,"%s. SIOCGIFBRDADDR %s (ioctl)\n",strerror(errno),
      ifr.ifr_name);
    exit(1);
  }                                /* if(ioctl(SIOCGIFBRDADDR,&ifr)) */
  memset(&iov, 0, sizeof(iov));
  iov.iov_base = (char*) Buffer;
  iov.iov_len = strlen(Buffer);
  memset(&msg,0,sizeof msg);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_flags = 0;
  msg.msg_name=&ifr.ifr_ifru.ifru_broadaddr;
  msg.msg_namelen=sizeof ifr.ifr_ifru.ifru_broadaddr;
  ((struct sockaddr_in*)msg.msg_name)->sin_port=htons(12345);
  if(sendmsg(s,&msg,0)==-1)
  {
    fprintf(stderr,"%s. (sendmsg)\n",strerror(errno));
    exit(1);
  }                                /* if(sendmsg(s,&msg,0)==-1) */
  return 0;
}                                  /* int main(int argc,char**argv) */
0
 
Duncan RoeSoftware DeveloperCommented:
I tried adding MSG_DONTROUTE to the flags arg (which you'd certainly want to do) but still get "Permission denied", even as root.
I guess you could use a packet socket - the MAC has to be the broadcast address (6 bytes of 0xff)  (or 1st byte 7f(?)). The source address of your NIC can be had from an ioctl similar to those above. Build the UDP packet according to RFC768
0
 
Duncan RoeSoftware DeveloperCommented:
Got it. From reading kernel source, I found that you must set socket option SO_BROADCAST (userspace) or SOCK_BROADCAST (kernel), otherwise you will get EPERM (as I did). Also in the source I could see where it insists on a nonzero destination port. And I could see it do a bind() for you if you haven't already done one (so you don't care about the sending port). The following userspace program sends UDP broadcasts - even as an ordinary user - I'll leave it to you to translate it for the kernel:

20:23:00$ cat bcast.c
/*
gcc -Wall -Wstrict-prototypes -Wmissing-prototypes -g3 bcast.c -o bcast
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

/* For test purposes, let's say we know which interface we want to use */

static char*ifname="eth0";

/* Message to broadcast */

char*Buffer="Hi there Tiger";

int main(int argc,char**argv)
{
  struct ifreq ifr;
  int s;
  struct msghdr msg;
  struct iovec iov;
  int flags=MSG_DONTROUTE;
  int optval=1;
 
  if((s=socket(PF_INET, SOCK_DGRAM, 0))==-1)
  {
    fprintf(stderr,"%s. (PF_INET, SOCK_DGRAM, 0 (socket)\n",
      strerror(errno));
    exit(1);
  }                             /* if((s=socket(PF_INET, SOCK_DGRAM, 0)0==-1) */
  snprintf(ifr.ifr_name,sizeof ifr.ifr_name,"%s",ifname);
  if(ioctl(s,SIOCGIFBRDADDR,&ifr))
  {
    fprintf(stderr,"%s. SIOCGIFBRDADDR %s (ioctl)\n",strerror(errno),
      ifr.ifr_name);
    exit(1);
  }                                /* if(ioctl(SIOCGIFBRDADDR,&ifr)) */
  if(setsockopt(s,SOL_SOCKET,SO_BROADCAST,&optval,sizeof optval))
  {
    fprintf(stderr,"%s. SO_BROADCAST (setsockopt)\n",strerror(errno));
    exit(1);
  }
  memset(&iov, 0, sizeof(iov));
  iov.iov_base = (char*) Buffer;
  iov.iov_len = strlen(Buffer);
  memset(&msg,0,sizeof msg);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_flags = 0;
  msg.msg_name=&ifr.ifr_ifru.ifru_broadaddr;
  msg.msg_namelen=sizeof ifr.ifr_ifru.ifru_broadaddr;
  ((struct sockaddr_in*)msg.msg_name)->sin_port=htons(2);
  if(sendmsg(s,&msg,flags)==-1)
  {
    fprintf(stderr,"%s. (sendmsg)\n",strerror(errno));
    exit(1);
  }                                /* if(sendmsg(s,&msg,0)==-1) */
  return 0;
}                                  /* int main(int argc,char**argv) */
0
 
-Thespian-Author Commented:
Thank you for reply, but I have discovered this too, and the problem is: setsockopt - no symbol found (after I start my kernel module). And I need this module to start without kernel recompilation:((

Also, maybe, u can help, how can I get the sender IP, when I receive the message (will inc points to 500 for this).

Thanks.
0
 
Duncan RoeSoftware DeveloperCommented:
Oh yes it was in your posted code, but commented out. Would it be available from pWorkingSocket->ops? In kernel source I see sk->sk_prot->setsockopt - maybe you could try that.
You should be using rcvmsg() to receive UDP packets (in userland you could use that or recvfrom()) - either way the sender's address is there as a sockaddr (*msg.name will get filled in)
0
 
-Thespian-Author Commented:
>Oh yes it was in your posted code, but commented out. Would it be available from pWorkingSocket->ops? In kernel source I see sk->sk_prot->setsockopt - maybe you could try that.
  thanks. will try in the evening.


>You should be using rcvmsg() to receive UDP packets (in userland you could use that or recvfrom()) - either way the sender's address is there as a sockaddr (*msg.name will get filled in)
  I was discovering it, but msg.namesize shows `16` and msg.name was `null`
0
 
Duncan RoeSoftware DeveloperCommented:
msg.name is a I-O arg. Before calling sendmsg, set it to point to a buffer lenth sizeof sockaddr. Set namesize to sizeof sockaddr. On return, the buffer addressed by msg.name will be filled in.
0
 
Duncan RoeSoftware DeveloperCommented:
I meant, before calling rcvmsg....
It's getting late here :)
0
 
-Thespian-Author Commented:
>msg.name is a I-O arg. Before calling sendmsg, set it to point to a buffer lenth sizeof sockaddr. Set namesize to sizeof sockaddr. On return, the buffer addressed by msg.name will be filled in.

ah... thanks. will try today or tomorrow. will reply u up to the tomorrow same time.
0
 
-Thespian-Author Commented:
Thanks, for msg help. It works. I have increased points. Please, give me some time to test broadcasting.
0
 
-Thespian-Author Commented:
Have a problem with "sock->sk->sk_prot->ioctl(sock,SIOCGIFBRDADDR,&ifr)" string. The first parameter must be int, but it is pointer. I can't find the int field in socket structure. Also, mabe it is undefined because I don't make connect or bind.:((
0
 
Duncan RoeSoftware DeveloperCommented:
The first parameter to ioctl is always a file unit number. In this case it should be he file unit number associated with sock.
0
 
-Thespian-Author Commented:
:( hmm.. what should I put there from my code?
0
 
Duncan RoeSoftware DeveloperCommented:
In the kernel, inet_ioctl takes a pointer to struct sock and implements SIOCGIFBRDADDR.
0
 
Duncan RoeSoftware DeveloperCommented:
BTW, did you really mean sock->sk->sk_prot->ioctl or sock-->sk_prot->ioctl?
0
 
-Thespian-Author Commented:
really.

>In the kernel, inet_ioctl takes a pointer to struct sock and implements SIOCGIFBRDADDR.
  it works, but I have a problem with "setsockopt" :(
  there is no "inet_setsockopt" symbol.:(
0
 
Duncan RoeSoftware DeveloperCommented:
That's correct. You want udp_setsockopt()
0
 
-Thespian-Author Commented:
udp_setsockopt symbol unknown too...:(
it's 4:40AM here. So will check for your response in 8hours (will be sleeping).
0
 
Duncan RoeSoftware DeveloperCommented:
Oops - udp_setsockopt() is static. On the basis od "really", you want sock->sk->sk_prot->setsockopt. Also in the kernel source I can see sock->ops->setsockopt, so maybe that will work. One of them should, I guess.
0
 
Duncan RoeSoftware DeveloperCommented:
Was 11:40 AM here. I'll check around 9PM or so. Sleep well :)
0
 
-Thespian-Author Commented:
it shows me "Error SIOCGIFBRDADDR (ERROR: -14)." :(
my code:
_________________________________________________________
size_t SendBuffer(struct socket *sock,
                  const char *Buffer, size_t Length,
                  int bConfirm, int bBroadcast)
{
      // Set the iovec structure
      struct iovec iov;
      memset(&iov, 0, sizeof(iov));
      iov.iov_base = (char*) Buffer;
      iov.iov_len = (__kernel_size_t) Length;

      struct msghdr msg;
      memset(&msg, 0, sizeof(msg));
      msg.msg_iov = &iov;
      msg.msg_iovlen = 1;
      msg.msg_flags = MSG_NOSIGNAL;
      if (bBroadcast == 1)
      {
            struct ifreq ifr;
            snprintf(ifr.ifr_name,sizeof ifr.ifr_name,"%s",ifname);
            int iRet;
            iRet = inet_ioctl(sock,SIOCGIFBRDADDR,&ifr);
            if(iRet != 0)
            {
                  log_warn("Error SIOCGIFBRDADDR (ERROR: %d).", iRet);
            }
            else
            {
                  int optval = 1;
                  iRet = sock->ops->setsockopt(sock,
                        SOL_SOCKET, SOCK_BROADCAST, &optval, sizeof optval);
                  if(iRet != 0)
                  {
                        log_warn("Error setsockopt (ERROR: %d).", iRet);
                  } else {
                        msg.msg_name=&ifr.ifr_ifru.ifru_broadaddr;
                        msg.msg_namelen=sizeof ifr.ifr_ifru.ifru_broadaddr;
                        ((struct sockaddr_in*)msg.msg_name)->sin_port=htons(MOD_SERVICE_PORT);
                  }
            }
      }

      if (bConfirm != 1)
            msg.msg_flags = MSG_NOSIGNAL;//0 MSG_DONTWAIT;
      else
            msg.msg_flags = MSG_CONFIRM;

      mm_segment_t oldfs = get_fs(); set_fs(KERNEL_DS);
      int len = sock_sendmsg(sock, &msg, (size_t)(Length));
      set_fs(oldfs);

      log_info("Sended message. Original size: %d. Sended size: %d", Length, len);
/*
      if (bConfirm == 1)
      {
            char* ptr = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
            int ret = RecvBuffer(sock, ptr, BUFFER_LENGTH, 1);
            if (ret != 1 || ptr[0] != 'Y')
                  ret = 0;
            kfree(ptr);
            if (ret == 1)
                  log_info("Message synchronized.");
            else
                  log_warn("Message not synchronized.");
      }
*/
      return len;
}


int sendUDPMessage(const char* sIP, char* cBuffer, int iBufferLength, int bConfirm)
{
      int ret = 0;
      // Initial properties
      int iRet;

      // Creating socket
      struct socket *pWorkingSocket = NULL;
      iRet = sock_create(PF_INET, SOCK_DGRAM, 0, &pWorkingSocket);
      if (iRet) {
            printk("Cannot create the socket...\n");
            return -1;
      }

      // Allocating memory for remote address
      struct sockaddr_in *pAddress = NULL;
      int bBroadcast = 0;
      if (sIP != NULL)
      {
            pAddress = kmalloc(sizeof(struct sockaddr_in), GFP_KERNEL);
            if (pAddress == NULL) {
                  printk("Cannot allocate kernel memory (ERROR: %d)...\n", -ENOMEM);
                  return -ENOMEM;
            }
            memset(pAddress, 0, sizeof(pAddress));
            pAddress->sin_family = AF_INET;
            pAddress->sin_port = htons(MOD_SERVICE_PORT);
            pAddress->sin_addr.s_addr = IP2InetAddr(sIP);
            // Connecting socket to remote address
            iRet = pWorkingSocket->ops->connect(pWorkingSocket,
                        (struct sockaddr *) pAddress,
                        sizeof(struct sockaddr), O_RDWR);
            if (iRet) {
                  printk("Cannot connect to the remote PC (ERROR: %d)...\n", iRet);
                  goto out;
            }
      } else {
            bBroadcast = 1;
      }

      ret = SendBuffer(pWorkingSocket, cBuffer, iBufferLength, bConfirm, bBroadcast);

out:      sock_release(pWorkingSocket);
      if (pAddress != NULL)
            kfree(pAddress);
      return ret;
}
0
 
Duncan RoeSoftware DeveloperCommented:
From  /usr/src/linux/include/asm-generic/errno-base.h:
#define EFAULT          14      /* Bad address */
So either sock is a bad pointer or there's something seriously wrong with ifr.name.
What is ifname? I don't see a dcl for it in your code.
0
 
-Thespian-Author Commented:
as u said earlier it is "eth0"
0
 
-Thespian-Author Commented:
this function takes int as first param - descriptor of a socket, but I give it a pointer:(
0
 
Duncan RoeSoftware DeveloperCommented:
/usr/src/linux/net/ipv4/af_inet.c:745:int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
0
 
-Thespian-Author Commented:
maybe, the error is in ifr?
0
 
Duncan RoeSoftware DeveloperCommented:
You must have linux source, you could be looking up some of this stuff as easily as I.
Ok it looks like ioctl() is a user call:
inet_ioctl calls devinet_ioctl to implement SIOCGIFBRDADDR.
devinet uses copy_from_user() to fetch the ifr struct. I.e. it is taking the address and verifying it to be in userspace - which it isn't because it's in kernel space.
What you need to do is copy the relevant lines from devinet.c to accomplish what you want.
0
 
Duncan RoeSoftware DeveloperCommented:
At a guess, I'd say something like this should do the trick:

int junk(struct sockaddr_in *sin)
{
  struct in_ifaddr **ifap = NULL;
  struct in_ifaddr *ifa = NULL;
  int ret = -ENODEV;
  struct in_device *in_dev;
  struct net_device *dev;

#ifdef CONFIG_KMOD
  dev_load(ifname);
#endif
  rtnl_lock();
  if ((dev = __dev_get_by_name(ifname)) == NULL)
    goto done;
  if ((in_dev = __in_dev_get_rtnl(dev)) != NULL)
  {
    for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next)
      if (!strcmp(ifname, ifa->ifa_label))
        break;
  }
  ret = -EADDRNOTAVAIL;
  if (!ifa)
    goto done;
  sin->sin_addr.s_addr = ifa->ifa_broadcast;
  ret = 0;
done:
  rtnl_unlock();
  return ret;
}                                  /* int junk() */
0
 
-Thespian-Author Commented:
> You must have linux source, you could be looking up some of this stuff as easily as I.
I have it. And trying to seek by myself. But I am new to linux, so don't knew how to find aproparate *.h file:(. Even I don't knew how to debug:(.

int junk() - I don't understand what it is doing.. What it for?
0
 
-Thespian-Author Commented:
have find out what it does...
but have a compilation error: "error: dereferencing pointer to incomplete type"
on lines:
    for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next)
and
    sin->sin_addr.s_addr = ifa->ifa_broadcast;
0
 
Duncan RoeSoftware DeveloperCommented:
You need the header file that defines struct in_ifaddr. It will be one of the headers included by devinet_ioctl.c
I use this shell script to find variables in the current dir & below (tidied up recently in answer to another EE Qn): hope you find it useful:

#!/bin/sh
#set -x

# Runs the show
main()
{
  try_gnu_args
  set_personality || exit 1

# Had to inline the next bit, coz it uses shift & args are local to functions
if [ -z "$1" ];then
  echo "Usage: $j <string> [<grep option>,...]" >&2
  exit 1
else
  k="$1"
  shift
fi

do_the_grep "$@"
}

# Sets fiddly gnu arg iff we have gnu grep
try_gnu_args()
{
  grep --version >/dev/null 2>&1
  [ $? -eq 0 ] && n=-noleaf || n=
}

# Check for good invocation.
# sfl is designed to be symlinked to - which synlink is used determines behaviour.
# list of symlinks:
# lrwxrwxrwx  1 dunc users    3 2004-09-30 22:12 afl -> sfl
# lrwxrwxrwx  1 dunc users    3 2004-09-30 22:12 aflc -> sfl
# lrwxrwxrwx  1 dunc users    3 2004-09-30 22:12 afll -> sfl
# lrwxrwxrwx  1 dunc users    3 2004-09-30 22:12 afllc -> sfl
# -rwxr-xr-x  1 dunc users 1183 2006-05-04 07:59 sfl
# lrwxrwxrwx  1 root root     3 2004-09-30 22:12 sflc -> sfl
# lrwxrwxrwx  1 root root     3 2004-09-30 22:12 sfll -> sfl
# lrwxrwxrwx  1 root root     3 2004-09-30 22:12 sfllc -> sfl
# lrwxrwxrwx  1 root root     3 2004-09-30 22:12 ufl -> sfl
# lrwxrwxrwx  1 root root     3 2004-09-30 22:12 uflc -> sfl
# lrwxrwxrwx  1 root root     3 2004-09-30 22:12 ufll -> sfl
# lrwxrwxrwx  1 root root     3 2004-09-30 22:12 ufllc -> sfl
set_personality()
{
  j=`basename $0`
  case $j in
  u*)
    f='.. -maxdepth 2 -mindepth 2'
    w=w
    ;;
  s*)
    f=.
    w=w
    ;;
  a*)
    f=.
    w=""
    ;;
  *)
    echo bad symlink of sfl to $j
    return 1
    ;;
  esac
  case $j in
  ?fl)
    i=''
    ;;
  ?fll)
    i=''
    f="$f -follow"
    ;;
  ?flc)
    i=i
    ;;
  ?fllc)
    i=i
    f="$f -follow"
    ;;
  *)
    echo bad symlink of sfl to $j
    return 1
    ;;
  esac
  return 0
}

# Actually do the gep
do_the_grep()
{
  find $f $n -depth -type f \( \
    -name "*.c" \
    -o -name "*.cpp" \
    -o -name "*.cxx" \
    -o -name "*.cc" \
    -o -name "*.f" \
    -o -name "*.for" \
    -o -name "*.S" \
    -o -name "*.h" \
    -o -name "*.java" \
    -o -name "*.exp" \
    -o -name "*.tcl" \
    -o -name "*.expect" \
    -o -name "*.pl" \
    -o -iname "makefile" \
    -o -name "make-file" \
    -o -name "*.i" \
    -o -name "*.l" \
    -o -name "*.lex" \
    -o -name "*.y" \
    -o -name "*.yacc" \
    -o -name "*.sh" \
    \) -print|xargs -n 32 -r -e grep -${i}s${w}n "$@" -- "$k" /dev/null
}
main "$@"


After installing, you could enter "sfl in_ifaddr" or "sfl in_ifaddr|grep struct" &c. I did that already, but hope you'll agree it's more useful to have the tool rather than the answer.
0
 
Duncan RoeSoftware DeveloperCommented:
Hi -Thespian- , what's happening? It's several days since my last answer. Is it all working now? Do you have further questions?
0
 
-Thespian-Author Commented:
Sorry. This thing is not working.:(( And I don't knew what to ask. Please, give me the time up to Mon or Tue.
0
 
-Thespian-Author Commented:
Sorry for my pause...
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 28
  • 24
Tackle projects and never again get stuck behind a technical roadblock.
Join Now