aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Puiu <stefan.puiu@gmail.com>2012-04-23 08:15:01 +1200
committerMichael Kerrisk <mtk.manpages@gmail.com>2012-04-23 08:15:01 +1200
commit4c49bf908c48f4548cda4826efd897ce04d1c976 (patch)
treee293b8061301b2f0ecf66a23239e775e616956f9
parentdf21098dee6cddac7ceb9961573c47705b48c3c4 (diff)
downloadman-pages-4c49bf908c48f4548cda4826efd897ce04d1c976.tar.gz
send.2: Document EACCES error case for UDP
It seems sendto() can return EACCES for UDP as well; the current man page in git only says it can return EACCES for Unix sockets. I was able to make sendto() return EACCES if I try to send from 192.168.1.1/24 to 192.168.1.0. I think the relevant code (in kernel 2.6.38, but also present in 2.6.7 and 2.6.32, the 2 kernels we use) is this (net/ipv4/udp.c, udp_sendmsg()): 910 err = -EACCES; 911 if ((rt->rt_flags & RTCF_BROADCAST) && 912 !sock_flag(sk, SOCK_BROADCAST)) 913 goto out; So I guess if the kernel finds a route to the destination and it's a broadcast route (and the socket doesn't have the broadcast flag), then it returns EACCES. I can verify the behavior with a very simple program (attached). I've run it on my Ubuntu 10.10 (2.6.35 kernel) and got this: stefan@spuiu-vml2:~/src/test/broadcast$ ./broadcast_test 10.205.20.94 10.205.20.1 sendto() returned 4 stefan@spuiu-vml2:~/src/test/broadcast$ ./broadcast_test 10.205.20.94 10.205.20.0 sendto() returned negative, errno: 13/Permission denied (10.205.20.94 is my local IP, of course). ===== #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <stdlib.h> int main(int argc, char **argv) { int sock; if (argc < 2) { printf("Usage: %s local_address destination_address\n", argv[0]); exit(1); } sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { perror("socket"); return -1; } struct sockaddr_in local_addr; local_addr.sin_family = AF_INET; local_addr.sin_port = htons(1234); local_addr.sin_addr.s_addr = inet_addr(argv[1]); int ret = bind(sock, (struct sockaddr *) &local_addr, sizeof(local_addr)); if (ret < 0) { perror("bind"); return -1; } struct sockaddr_in remote_addr; remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(1234); remote_addr.sin_addr.s_addr = inet_addr(argv[2]); ret = sendto(sock, "blah", 4, 0, (struct sockaddr *)&remote_addr, sizeof(remote_addr)); if (ret < 0) { printf("sendto() returned negative, errno: %d/%m\n", errno); } else { printf("sendto() returned %d\n", ret); } return 0; } ===== Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
-rw-r--r--man2/send.25
1 files changed, 4 insertions, 1 deletions
diff --git a/man2/send.2 b/man2/send.2
index eaeeb3aee3..6f71300786 100644
--- a/man2/send.2
+++ b/man2/send.2
@@ -35,7 +35,7 @@
.\" Modified Oct 2003 by aeb
.\" Modified 2004-07-01 by mtk
.\"
-.TH SEND 2 2012-02-27 "Linux" "Linux Programmer's Manual"
+.TH SEND 2 2012-04-23 "Linux" "Linux Programmer's Manual"
.SH NAME
send, sendto, sendmsg \- send a message on a socket
.SH SYNOPSIS
@@ -288,6 +288,9 @@ or search permission is denied for one of the directories
the path prefix.
(See
.BR path_resolution (7).)
+.sp
+(For UDP sockets) An attempt was made to send to a
+network/broadcast address as though it was a unicast address.
.TP
.BR EAGAIN " or " EWOULDBLOCK
.\" Actually EAGAIN on Linux