Reversing a linked list by iteration and recursion
Code Comments:
curr = malloc(sizeof(Node));

malloc() returns void* thus you need to cast it before assignment.
curr = (Node*) malloc(sizeof(Node));

Most (all I have seen) coding standards mention not to use this:
Node * head, * curr;
head = NULL;

I agree with them as it just makes things hard to read (thus maintain). So one variable per line. And initialize on declaration (where appropriate).
Node  *head = NULL;
Node  *curr;

OK. The next one is arguable (so feel free to use best judgement).
Personally I find that hard to read:
 if (!head-&gt;next)

I think it would be easier to read as:
if (head-&gt;next == NULL)

But surprisingly I normally I prefer using the ! when the object is a pointer (or bool). I think in this case it is because it is combined with testing a nested member of a structure it just does not look correct (but as I said it is an arguable case).
Edge Case
What happens if the list is empty?
Node * reverse_list(Node * head) {

  if (!head-&gt;next) //only one elem
    return head;

You have chosen the wrong edge case.
The one you should be checking is checking for NULL. A list of one node is no different than a list of many. The edge case with pointers is nearly always the NULL case.
Algorithm
Iterative
The code before your while loop looks like the code inside the while loop. This sort of suggests you can replace it with a do-while loop. Thus your iterative code should look more like this:
Node* reverse(Node* list)
{
    if (list == NULL)
    {   
        return NULL;
    }   

    Node*   last    = NULL;
    do  
    {   
        Node*   next    = list-&gt;next;
        list-&gt;next      = last;
        last            = list;
        list            = next;
    }   
    while(list != NULL);

    return last;
}

Recursive
Converting a loop into recursion requires an extra function to cope with the extra variable used for last. So the main recursion looks like this (it just calls the actually recursive function setting up the last parameter). You should have this wrapper function to help users of the code from calling the recursive part of the function incorrectly.
Node* r_reverse(Node* list)
{
    return r_reverseItem(NULL, list);
}

Now we can do the recursion. Again the edge case is still NULL.
Node* r_reverseItem(Node* last, Node* list)
{
    if (list == NULL)
    {   
        return last;
    }   

    Node*   next    = list-&gt;next;
    list-&gt;next      = last;
    return r_reverseItem(list,next);
}