On Friday 13 October 2006 05:33, Nic James Ferrier wrote: > I know this is not UML specific... but maybe the kernel hackers here > can answer this anyway, since I'm doing it to make life with UMLs > easier. > > 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
> Currently I'm just getting the details for eth0. > > 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? > I've put printk's in the kernel side of the code and there I can see > the values are 32 bit. The values you pass to seq printf, right? Actually IMHO not - I guess printk() used different data. > So it seems that in the conversion from kernel space to user space > half the information is being lost. > > Anyone know anything about that? See below, there's the analsys. > Here's my patch to create /proc/net/ipaddress in case anyone's > interested in half the data: 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. > --- old/linux-2.6.17.1/net/ipv4/proc.c > +++ new/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()); Nah, this line should be set_fs(KERNEL_DS) - grep for examples, I've always used KERNEL_DS there and it's the only one that makes sense. Also, for mainline acceptance I guess they'd prefer to bypass ioctl and access directly the needed fields. Btw, on linux-kernel@ or on linux-netdev@ (cc'ing here) you might also ask why this info is missing. > + 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; > + struct sockaddr_in * local_addr; > + uint32_t local; > + uint32_t mask; > + uint32_t broadcast; > + uint32_t destination; > + > + memset(&ir, 0, sizeof(ir)); > + strcpy(ir.ifr_ifrn.ifrn_name, "eth0"); Ok, that will be fixed afterwards - that file (the ipv6 one, see above) iterates between addrs correctly. Note also that one interface can be associated to multiple address, even without using aliases, if you use the "ip" command (which uses probably even a different kernel level API - I remember that ifconfig and friends use an in-kernel emulation of the old API - but since the data model is different it is just an emulation). > + > + ipaddress_dev_ioctl(&ir, SIOCGIFADDR); > + local_addr = if_addr = (struct sockaddr_in *) ir.ifr_addr.sa_data; But local_addr is redundant, right? 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, the _below_ version is correct: if_addr = (struct sockaddr_in *) ir.ifr_addr; The way you do it, if_addr is 2 + the correct value - i.e. 16 bit are cut away. Unless in kernel they use different conventions (then show it me and I'll agree). > + local = if_addr->sin_addr.s_addr; > + > + 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; Here you should use ifr_broadaddr, and so on... look directly at struct ifreq definition. That is an union so what you do happens to work, but this detail is not part of the API, so don't cheat ;-). > + 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); > + //inet_ntoa(local_addr->sin_addr)); > + 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_sockstat; This is goto out_ipaddress (the naming is misleading, ok, but compare with the above goto). > + > out: > return rc; > +out_ipadress: > + proc_net_remove("sockstat"); > out_sockstat: > proc_net_remove("snmp"); > out_snmp: -- Inform me of my mistakes, so I can keep imitating Homer Simpson's "Doh!". Paolo Giarrusso, aka Blaisorblade http://www.user-mode-linux.org/~blaisorblade Chiacchiera con i tuoi amici in tempo reale! http://it.yahoo.com/mail_it/foot/*http://it.messenger.yahoo.com ------------------------------------------------------------------------- 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