Re: about ipv6...

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jonathan Khoo wrote:
> 
> Hi guys,
> 
> I hacked part of the route.c under /net/ipv6. I made modifications to
> ip6_route_output, trying to change the destination address, so that a
> different interface will be chosen. This will then affect the hash_val
> that will be calculated under neigh_lookup (ndisc.c) used for neighbour
> discovery.
> 
> I tested the codes listed below in the user-land and everything is okay.
> However, when I merged it into the kernel and it always goes into kernel
> panic at the memcpy statement. I must apologize as I am not well versed
> with c and always made silly mistakes over pointers. I would appreciate
> it if anyone can help point out my errors.
> 
> Thanks in advance.
> Jon.
> 
> The codes are basically:
> 
> struct in6_addr *daddr;
> 
> my_function(daddr);
> 
> ....
> 
> (in another file)
> void my_function(struct in6_addr *addr)
> {
>   struct in6_addr *newaddr;
>   ....
>   memcpy(&(*addr), &(*newaddr), sizeof(struct in6_addr));

This is equivalent to

   memcpy(addr, newaddr, sizeof(struct in6_addr));

Note that with memcpy, the first argument is the *destination*
address. So you are copying the contents of a random memory
block (whatever is pointed to by the uninitialized "newaddr")
over the address passed in "addr". This is certainly not what
you want :-)

First, if you want to make a copy of the struct pointed to
by "addr", you need a place to put it, so you must either
declare a struct in6_addr on the stack, or else declare
a pointer (as you've done) and malloc() storage for it to
point to. I'll do both:

void my_function(struct in6_addr *addr)
{
  struct in6_addr newstruct;
  struct in6_addr *newaddr;

  /* Local copy... */
  memcpy(&newstruct, addr, sizeof(struct in6_addr));
  
  /* Heap copy... */
  newaddr = (struct in6_addr*)malloc(sizeof(struct in6_addr));
  memcpy(newaddr,addr,sizeof(struct in6_addr));

  /*...*/

  /* return &newstruct; WRONG! Don't do this. */
  return newaddr; /* And don't forget to free(newaddr) when you're done.
*/
}


Note that you cannot successfully return &newstruct from
my_function(), since its storage is allocated in the stack
frame in which my_function() executes, and will therefore
be destroyed (logically) when my_function() returns to its
caller (you might get such code to *appear* to work under
a limited set of circumstances, but it's wrong: as soon as
some function call needs to re-use the stack space on which
newstruct was allocated, it will be destroyed). You *can*
return newaddr, the address of an in6_addr allocated on the
heap -- but you must be sure to free the malloc'd memory when
you are done with it, or else you have a memory leak.

A thorough understanding of exactly how functions are
called, stack frames constructed, and free storage
managed is absolutely critical to successful coding
in C, especially at the kernel level. Don't leave home
without it.

HTH,

-- Joe

-- 
"I should like to close this book by sticking out any part of my neck
 which is not yet exposed, and making a few predictions about how the
 problem of quantum gravity will in the end be solved."
 --- Physicist Lee Smolin, "Three Roads to Quantum Gravity"
--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
IRC Channel:   irc.openprojects.net / #kernelnewbies
Web Page:      http://www.kernelnewbies.org/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux