I'm more of a traditionalist, and prefer an interface something like this, if you really need add and delete at tthe head, middle, and tail of a list.

That is unless you have special performance requirements, where you really don't want to be calling "swiss army knife" functions.

Code:
struct anode
{
  struct anode *next;
  float x, y, z;
};


struct anode *add_node_after(struct anode **head, struct anode **tail, struct anode *after, float x, float y , float z); // Use NULL for after to add at the head of the list
int                 del_node(struct anode **head, struct anode **tail, struct anode *node_to_free);


int main ( void )
{
  // Head and tail pointers
  struct anode *head = NULL, *tail = NULL;

  // If you want, test the return value to check that a valid node was added. 
  add_node_after(&head, &tail, NULL,  1.0,  2.0,  3.0); // Add to the empty list
  add_node_after(&head, &tail, head,  4.0,  5.0,  6.0); // Add after head (and it is the new tail)
  add_node_after(&head, &tail, head,  7.0,  8.0,  9.0); // Add between head and tail
  add_node_after(&head, &tail, tail, 10.0, 11.0, 12.0); // Add at the very end
  add_node_after(&head, &tail, NULL, 13.0, 14.0, 15.0); // Add at the very start

  // Walk the list
  for(struct anode *node = head; node != NULL; node = node->next) {
    printf ( "(x,y,z) = (%f,%f,%f)\n", node->x, node->y, node->z );
  }

  // Delete all the nodes
  while (head != NULL)
    del_node(&head, &tail, head);

  return 0
}