diff --git a/share/libc/sys/socket.h b/share/libc/sys/socket.h
index f440e7fba8c91ba66bd5b4874b992a93aa9c5735..ddd988809200e62411824aaa1f6319b035b23287 100644
--- a/share/libc/sys/socket.h
+++ b/share/libc/sys/socket.h
@@ -443,11 +443,10 @@ extern int listen(int sockfd, int backlog);
  */
 extern ssize_t recv(int sockfd, void * buf, size_t len, int flags);
 
-
 /*@
   requires valid_sockfd: 0 <= sockfd < __FC_MAX_OPEN_SOCKETS;
   requires valid_buffer_length: \valid((char *)buf+(0 .. len-1));
-  requires valid_addrbuf_or_null: (\valid(addrbuf_len) &&
+  requires valid_addrbuf_or_null:initialization: (\valid(addrbuf_len) &&
                                    \initialized(addrbuf_len) &&
                                    \valid((char *)addrbuf+(0 .. *addrbuf_len-1)))
                                   || (addrbuf == \null && addrbuf_len == \null);
@@ -503,7 +502,23 @@ extern ssize_t recvmsg(int sockfd, struct msghdr *hdr, int flags);
   ensures error_or_chars_sent: \result == -1 || 0 <= \result <= len;
  */
 extern ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-extern ssize_t sendmsg(int, const struct msghdr *, int);
+
+/*@
+  requires available_sockfd: 0 <= sockfd < __FC_MAX_OPEN_SOCKETS;
+  requires valid_message: \valid_read(message);
+  requires valid_msg_iov:
+    \valid_read(message->msg_iov+(0 .. message->msg_iovlen - 1));
+  assigns __fc_sockfds[sockfd]
+    \from __fc_sockfds[sockfd],
+          indirect:*message,
+          indirect:message->msg_iov[0 .. message->msg_iovlen - 1],
+          indirect:flags;
+  assigns \result \from indirect:sockfd, indirect:__fc_sockfds[sockfd],
+          indirect:*message,
+          indirect:message->msg_iov[0 .. message->msg_iovlen - 1];
+  ensures error_or_chars_sent: \result == -1 || 0 <= \result;
+ */
+extern ssize_t sendmsg(int sockfd, const struct msghdr *message, int flags);
 
 /*@
   requires available_sockfd: 0 <= sockfd < __FC_MAX_OPEN_SOCKETS;
diff --git a/share/libc/unistd.h b/share/libc/unistd.h
index 5979b51c4d998f8883c3d332861a36a51cd86688..4dd08614227cf0105780abb9016bf80b60a1e613 100644
--- a/share/libc/unistd.h
+++ b/share/libc/unistd.h
@@ -947,7 +947,21 @@ extern char        *getwd(char *);
 extern int          isatty(int fd);
 
 extern int          lchown(const char *, uid_t, gid_t);
-extern int          link(const char *, const char *);
+
+/*@ //missing: may assign to errno: EACCES, EEXIST, ELOOP, EMLINK, ENAMETOOLONG,
+    //                              ENOENT, ENOSPC, ENOTDIR, EPERM, EROFS,
+    //                              EXDEV, EBADF, ENOTDIR, EINVAL;
+    // missing: assigns 'filesystem' \from path1[0..strlen(path1)],
+    //                                     path2[0..strlen(path2)];
+    // missing: assigns \result \from 'paths in filesystem'
+  requires valid_path: valid_read_string(path1);
+  requires valid_path: valid_read_string(path2);
+  assigns \result \from indirect:path1[0 .. strlen(path1)],
+                        indirect:path2[0 .. strlen(path2)];
+  ensures result_ok_or_error: \result == 0 || \result == -1;
+ */
+extern int          link(const char *path1, const char *path2);
+
 extern int          lockf(int, int, off_t);
 
 /*@ //missing: may assign to errno: EBADF, EINVAL, EOVERFLOW, ESPIPE, ENXIO (Linux);
@@ -1108,7 +1122,7 @@ extern useconds_t   ualarm(useconds_t, useconds_t);
   // missing: assigns 'filesystem' \from path[0..];
   // missing: assigns \result \from 'filesystem';
   requires valid_string_path: valid_read_string(path);
-  assigns \result \from path[0..];
+  assigns \result \from indirect:path[0..strlen(path)];
   ensures result_ok_or_error: \result == 0 || \result == -1;
  */
 extern int          unlink(const char *path);
diff --git a/tests/libc/oracle/fc_libc.0.res.oracle b/tests/libc/oracle/fc_libc.0.res.oracle
index 96ad940d69778adf1aee7a90d46c4d25b63c46c2..e6cd5c1976c5f1ee699bb4d9bc33852458d258ef 100644
--- a/tests/libc/oracle/fc_libc.0.res.oracle
+++ b/tests/libc/oracle/fc_libc.0.res.oracle
@@ -14,8 +14,6 @@
 [eva] ====== VALUES COMPUTED ======
 [eva:final-states] Values at end of function main:
   
-[kernel] FRAMAC_SHARE/libc/sys/socket.h:451: Warning: 
-  clause with '\initialized' must contain name 'initialization'
 /* Generated by Frama-C */
 #include "__fc_builtin.c"
 #include "__fc_builtin.h"
diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle
index 566c5af75a06db659d7b28cacb1c2f2a69a9640d..4ada2331e0413447eb3e48baaf2895c7e2c5edd6 100644
--- a/tests/libc/oracle/fc_libc.1.res.oracle
+++ b/tests/libc/oracle/fc_libc.1.res.oracle
@@ -3098,6 +3098,16 @@ extern uid_t getuid(void);
  */
 extern int isatty(int fd);
 
+/*@ requires valid_path: valid_read_string(path1);
+    requires valid_path: valid_read_string(path2);
+    ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
+    assigns \result;
+    assigns \result
+      \from (indirect: *(path1 + (0 .. strlen{Old}(path1)))),
+            (indirect: *(path2 + (0 .. strlen{Old}(path2))));
+ */
+extern int link(char const *path1, char const *path2);
+
 /*@ requires valid_fd: 0 ≤ fd < 1024;
     requires valid_whence: whence ≡ 0 ∨ whence ≡ 1 ∨ whence ≡ 2;
     ensures result_error_or_offset: \result ≡ -1 ∨ 0 ≤ \result;
@@ -3218,7 +3228,7 @@ extern char *ttyname(int fildes);
 /*@ requires valid_string_path: valid_read_string(path);
     ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1;
     assigns \result;
-    assigns \result \from *(path + (0 ..));
+    assigns \result \from (indirect: *(path + (0 .. strlen{Old}(path))));
  */
 extern int unlink(char const *path);
 
@@ -4772,7 +4782,7 @@ extern ssize_t recv(int sockfd, void *buf, size_t len, int flags);
 /*@ requires valid_sockfd: 0 ≤ sockfd < 1024;
     requires valid_buffer_length: \valid((char *)buf + (0 .. len - 1));
     requires
-      valid_addrbuf_or_null:
+      valid_addrbuf_or_null: initialization:
         (\valid(addrbuf_len) ∧ \initialized(addrbuf_len) ∧
          \valid((char *)addrbuf + (0 .. *addrbuf_len - 1))) ∨
         (addrbuf ≡ \null ∧ addrbuf_len ≡ \null);
@@ -4854,6 +4864,24 @@ extern ssize_t recvmsg(int sockfd, struct msghdr *hdr, int flags);
  */
 extern ssize_t send(int sockfd, void const *buf, size_t len, int flags);
 
+/*@ requires available_sockfd: 0 ≤ sockfd < 1024;
+    requires valid_message: \valid_read(message);
+    requires
+      valid_msg_iov:
+        \valid_read(message->msg_iov + (0 .. message->msg_iovlen - 1));
+    ensures error_or_chars_sent: \result ≡ -1 ∨ 0 ≤ \result;
+    assigns __fc_sockfds[sockfd], \result;
+    assigns __fc_sockfds[sockfd]
+      \from __fc_sockfds[sockfd], (indirect: *message),
+            (indirect: *(message->msg_iov + (0 .. message->msg_iovlen - 1))),
+            (indirect: flags);
+    assigns \result
+      \from (indirect: sockfd), (indirect: __fc_sockfds[sockfd]),
+            (indirect: *message),
+            (indirect: *(message->msg_iov + (0 .. message->msg_iovlen - 1)));
+ */
+extern ssize_t sendmsg(int sockfd, struct msghdr const *message, int flags);
+
 /*@ requires available_sockfd: 0 ≤ sockfd < 1024;
     requires buf_len_ok: \valid_read((char *)buf + (0 .. len - 1));
     ensures
diff --git a/tests/libc/oracle/socket_h.res.oracle b/tests/libc/oracle/socket_h.res.oracle
index 1b50d5781ffd4b976d3805c528190ddde6247bf0..f46e7a13fd1552f6249cbd35da7871aa2c345fd1 100644
--- a/tests/libc/oracle/socket_h.res.oracle
+++ b/tests/libc/oracle/socket_h.res.oracle
@@ -82,7 +82,7 @@
 [eva] socket_h.c:31: 
   function recvfrom: precondition 'valid_buffer_length' got status valid.
 [eva] socket_h.c:31: 
-  function recvfrom: precondition 'valid_addrbuf_or_null' got status valid.
+  function recvfrom: precondition 'valid_addrbuf_or_null,initialization' got status valid.
 [eva] Done for function recvfrom
 [eva] socket_h.c:35: assertion got status valid.
 [eva] computing for function recvfrom <- main.
@@ -92,7 +92,7 @@
 [eva] socket_h.c:37: 
   function recvfrom: precondition 'valid_buffer_length' got status valid.
 [eva] socket_h.c:37: 
-  function recvfrom: precondition 'valid_addrbuf_or_null' got status valid.
+  function recvfrom: precondition 'valid_addrbuf_or_null,initialization' got status valid.
 [eva:invalid-assigns] socket_h.c:37: 
   Completely invalid destination for assigns clause *addrbuf_len. Ignoring.
 [eva:invalid-assigns] socket_h.c:37: 
diff --git a/tests/libc/oracle/sys_socket_h.res.oracle b/tests/libc/oracle/sys_socket_h.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..bd668507be702ce8fb2db931063de1a8cea31f2a
--- /dev/null
+++ b/tests/libc/oracle/sys_socket_h.res.oracle
@@ -0,0 +1,65 @@
+[kernel] Parsing sys_socket_h.c (with preprocessing)
+[eva] Analyzing a complete application starting at main
+[eva] Computing initial state
+[eva] Initial state computed
+[eva:initial-state] Values of globals at initialization
+  dest ∈ [--..--]
+  v ∈ [--..--]
+[eva] sys_socket_h.c:26: Call to builtin strlen
+[eva] sys_socket_h.c:26: 
+  function strlen: precondition 'valid_string_s' got status valid.
+[eva] computing for function socket <- main.
+  Called from sys_socket_h.c:40.
+[eva] using specification for function socket
+[eva] Done for function socket
+[eva] computing for function sendmsg <- main.
+  Called from sys_socket_h.c:42.
+[eva] using specification for function sendmsg
+[eva] sys_socket_h.c:42: 
+  function sendmsg: precondition 'available_sockfd' got status valid.
+[eva] sys_socket_h.c:42: 
+  function sendmsg: precondition 'valid_message' got status valid.
+[eva] sys_socket_h.c:42: 
+  function sendmsg: precondition 'valid_msg_iov' got status valid.
+[eva] Done for function sendmsg
+[eva] sys_socket_h.c:43: assertion 'valid' got status valid.
+[eva] computing for function sendmsg <- main.
+  Called from sys_socket_h.c:47.
+[eva] sys_socket_h.c:47: 
+  function sendmsg: precondition 'available_sockfd' got status valid.
+[eva] sys_socket_h.c:47: 
+  function sendmsg: precondition 'valid_message' got status valid.
+[eva:alarm] sys_socket_h.c:47: Warning: 
+  function sendmsg: precondition 'valid_msg_iov' got status invalid.
+[eva] Done for function sendmsg
+[eva] Recording results for main
+[eva] done for function main
+[eva] ====== VALUES COMPUTED ======
+[eva:final-states] Values at end of function main:
+  __fc_sockfds[0..1023] ∈ [--..--]
+  __fc_socket_counter ∈ [--..--]
+  d1 ∈ {{ "message" }}
+  s1.a ∈ {42}
+    .b ∈ {65}
+    .[bits 40 to 63] ∈ {0}
+  s2.p ∈ {0}
+    .d ∈ {3.125}
+  n ∈ {501}
+  d ∈ {5.5}
+  iov[0].iov_base ∈ {{ "message" }}
+     [0].iov_len ∈ {7}
+     [1].iov_base ∈ {{ (void *)&s1 }}
+     [1].iov_len ∈ {8}
+     [2].iov_base ∈ {{ (void *)&s2 }}
+     [2].iov_len ∈ {12}
+     [3].iov_base ∈ {{ (void *)&n }}
+     [3].iov_len ∈ {4}
+     [4].iov_base ∈ {{ (void *)&d }}
+     [4].iov_len ∈ {8}
+  msg{.msg_name; .msg_namelen} ∈ {0}
+     .msg_iov ∈ {{ &iov[0] }}
+     .msg_iovlen ∈ {5; 6}
+     {.msg_control; .msg_controllen; .msg_flags} ∈ UNINITIALIZED
+  sockfd ∈ [-1..1023]
+  r ∈ [-1..2147483647]
+  __retres ∈ {0; 1}
diff --git a/tests/libc/sys_socket_h.c b/tests/libc/sys_socket_h.c
new file mode 100644
index 0000000000000000000000000000000000000000..77aeabb54afb2eb690f4cfdd5df1149aed570a9d
--- /dev/null
+++ b/tests/libc/sys_socket_h.c
@@ -0,0 +1,51 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+struct s1 {
+  int a;
+  char b;
+};
+
+struct s2 {
+  int *p;
+  double d;
+};
+
+volatile struct sockaddr_in dest;
+volatile int v;
+
+int main() {
+  char *d1 = "message";
+  struct s1 s1 = {42, 'A'};
+  struct s2 s2 = {0, 3.125};
+  int n = 501;
+  double d = 5.5;
+  struct iovec iov[5];
+  iov[0].iov_base = d1;
+  iov[0].iov_len = strlen(d1);
+  iov[1].iov_base = &s1;
+  iov[1].iov_len = sizeof(struct s1);
+  iov[2].iov_base = &s2;
+  iov[2].iov_len = sizeof(struct s2);
+  iov[3].iov_base = &n;
+  iov[3].iov_len = sizeof(int);
+  iov[4].iov_base = &d;
+  iov[4].iov_len = sizeof(double);
+  struct msghdr msg;
+   msg.msg_name = 0;
+   msg.msg_namelen = 0;
+   msg.msg_iov = iov;
+   msg.msg_iovlen = 5;
+   int sockfd = socket(AF_INET, SOCK_STREAM, 0);
+   if (sockfd < 0) return 1;
+   int r = sendmsg(sockfd, &msg, 0);
+   //@ assert valid: r == -1 || r >= 0;
+
+   msg.msg_iovlen = 6; // invalid length
+   if (v) {
+     sendmsg(sockfd, &msg, 0); // must fail
+     //@ assert unreachable: \false;
+   }
+   return 0;
+}
diff --git a/tests/metrics/oracle/libc.json b/tests/metrics/oracle/libc.json
index de14067e7a65d53a82dd943adb71c6cb31536f68..4216280930594e36a24f4db3ea2baca79bd5ee12 100644
--- a/tests/metrics/oracle/libc.json
+++ b/tests/metrics/oracle/libc.json
@@ -87,6 +87,7 @@
     { "isspace": { "calls": 0, "address_taken": false } },
     { "isupper": { "calls": 0, "address_taken": false } },
     { "isxdigit": { "calls": 0, "address_taken": false } },
+    { "link": { "calls": 0, "address_taken": false } },
     { "lseek": { "calls": 0, "address_taken": false } },
     { "pathconf": { "calls": 0, "address_taken": false } },
     { "pclose": { "calls": 0, "address_taken": false } },