Blaisorblade <[EMAIL PROTECTED]> writes:

> On Friday 13 October 2006 05:33, Nic James Ferrier wrote:
>> I've patched the ipv4 stack so that it does proc registration of the
>> IP address for an iface.
> Take a look at /proc/net/if_inet6, generated by 

I did take a look at that. It seems to be done a bit
differently. There's what looks like a cleaner interface to config.

I may be a confident C hacker, but I'm not going to start refactoring
the ipv4 stack with my first patch /8->



>> I'm using kernel ioctl calls (correctly surrounded by get_fs/set_fs
>> calls) to get the interface data.
>
>> All the interface data is returned at 16 bits.
> I.e. that's the seq_printf string, right?

Yes. The data passed to the seq_printf string has had 16 bits chopped
off it.

It looks to me like the data is getting lost in the conversion from
kernel space to user space which occurs at the end of the ioctl
wrapper.


> I know you're beginning to write kernel code and this is not even a finished 
> patch, however I'm commenting _various_ improvable aspects of the work. Do 
> not worry for that.

Any comments are *very* welcome.

I've attached a cleaner copy of my patch with my debug and sketch code
removed. It's down to the bear essentials which is a call to ioctl to
retrieve the address only getting 16 bits of the necessary data.


> Also, for mainline acceptance I guess they'd prefer to bypass ioctl and 
> access 
> directly the needed fields.

The ipv4 config and dhcp code uses the ioctl stuff which is why I
did. I wasn't sure about this... I think it makes more sense for the
kernel to be able to access the fields directly as well. And it's the
ioctl that seems to be causing the problem. However, if you don't need
the ioctl why does the ipv4 config code call it?


> Beyond that, I've found your bug. You can cast a (struct sockaddr*) to a 
> (struct sockaddr_in*), but your doing a worse cast; since ifr_addr is a 
> struct sockaddr, 

I don't think I'm doing that:

  ifreq.ifr_addr 

  is the same as:  ifreq.ifr_ifru.ifru_addr 

  which is a:  struct sockaddr

So ifreq.ifr_addr.sa_data is a sockaddr_in right?


> the _below_ version is correct:
> if_addr = (struct sockaddr_in *) ir.ifr_addr;

This doesn't compile.


> This is goto out_ipaddress (the naming is misleading, ok, but compare with 
> the 
> above goto).

Yes... sorry, that is an ommision from a previous edit.

-- 
Nic Ferrier
http://www.tapsellferrier.co.uk   for all your tapsell ferrier needs

--- /scp:[EMAIL PROTECTED]:/var/local/virtualmachine/kernels/linux-2.6.17.1/net/ipv4/proc.c
+++ /var/local/src/linux-2.6.17.1/net/ipv4/proc.c
@@ -44,6 +44,77 @@
 #include <net/sock.h>
 #include <net/raw.h>
 
+
+//// New IP Address proc interface
+#include <asm/uaccess.h>
+#include <linux/if.h>
+
+static int ipaddress_dev_ioctl(struct ifreq *ir, unsigned int cmd)
+{
+	int res;
+        mm_segment_t oldfs;
+
+	oldfs = get_fs();
+	set_fs(get_ds());
+	res = devinet_ioctl(cmd, (struct ifreq __user *) ir);
+	set_fs(oldfs);
+	return res;
+}
+
+static int ipaddress_seq_show(struct seq_file *seq, void *v)
+{
+        struct ifreq ir;
+        struct sockaddr_in * if_addr;
+        uint32_t local;
+
+        memset(&ir, 0, sizeof(ir));
+        strcpy(ir.ifr_ifrn.ifrn_name, "eth0");
+
+        ipaddress_dev_ioctl(&ir, SIOCGIFADDR);
+
+        if_addr = (struct sockaddr_in *) ir.ifr_addr.sa_data;
+        local = if_addr->sin_addr.s_addr;
+
+        seq_printf(seq, "eth0: %u\n", local);        
+
+        /*
+        ipaddress_dev_ioctl(&ir, SIOCGIFNETMASK);
+        if_addr = (struct sockaddr_in *) ir.ifr_addr.sa_data;
+        mask = if_addr->sin_addr.s_addr;
+
+        ipaddress_dev_ioctl(&ir, SIOCGIFBRDADDR);
+        if_addr = (struct sockaddr_in *) ir.ifr_addr.sa_data;
+        broadcast = if_addr->sin_addr.s_addr;
+
+        ipaddress_dev_ioctl(&ir, SIOCGIFDSTADDR);
+        if_addr = (struct sockaddr_in *) ir.ifr_addr.sa_data;
+        destination = if_addr->sin_addr.s_addr;
+
+        seq_printf(seq, "ethx: %u %u %u %u\n",
+                   local,
+                   mask,
+                   broadcast,
+                   destination);
+        */
+        return 0;
+}
+
+static int ipaddress_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ipaddress_seq_show, NULL);
+}
+
+static struct file_operations ipaddress_seq_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = ipaddress_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+//// End new IP Address proc interface
+
+
 static int fold_prot_inuse(struct proto *proto)
 {
 	int res = 0;
@@ -65,7 +136,7 @@
 		   fold_prot_inuse(&tcp_prot), atomic_read(&tcp_orphan_count),
 		   tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated),
 		   atomic_read(&tcp_memory_allocated));
-	seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
+ 	seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
 	seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
 	seq_printf(seq,  "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
 		   atomic_read(&ip_frag_mem));
@@ -365,8 +436,14 @@
 
 	if (!proc_net_fops_create("sockstat", S_IRUGO, &sockstat_seq_fops))
 		goto out_sockstat;
+
+        if (!proc_net_fops_create("ipaddress", S_IRUGO, &ipaddress_seq_fops))
+                goto out_ipaddress;
+
 out:
 	return rc;
+out_ipadress:
+        proc_net_remove("sockstat");
 out_sockstat:
 	proc_net_remove("snmp");
 out_snmp:

Diff finished.  Sat Oct 14 12:29:27 2006
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
User-mode-linux-user mailing list
User-mode-linux-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-user

Reply via email to