plan9fox/sys/src/ape/lib/bsd/bind.c
cinap_lenrek e8c1d0fe7c ape: check *alen before copying in getpeername(), getsockname() and accept()
*alen has to be initialized to the size of the buffer
by the caller, and we are supposed to put the real
size of the address in there, but not copy more than
the original *alen value (truncate).
2013-04-02 01:40:29 +02:00

75 lines
1.3 KiB
C

/* posix */
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <signal.h>
/* socket extensions */
#include <sys/uio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
/* plan 9 */
#include "lib.h"
#include "sys9.h"
#include "priv.h"
int
bind(int fd, void *a, int alen)
{
int n, len, cfd, port;
struct sockaddr *sa;
Rock *r;
char msg[128];
/* assign the address */
r = _sock_findrock(fd, 0);
if(r == 0){
errno = ENOTSOCK;
return -1;
}
sa = (struct sockaddr*)a;
if(sa->sa_family != r->domain){
errno = EAFNOSUPPORT;
return -1;
}
if(alen > sizeof(r->addr)){
errno = ENAMETOOLONG;
return -1;
}
memmove(&r->addr, a, alen);
/* the rest is IP sepecific */
if (r->domain != PF_INET && r->domain != PF_INET6)
return 0;
cfd = open(r->ctl, O_RDWR);
if(cfd < 0){
errno = EBADF;
return -1;
}
port = _sock_inport(&r->addr);
if(port > 0)
snprintf(msg, sizeof msg, "bind %d", port);
else
strcpy(msg, "bind *");
n = write(cfd, msg, strlen(msg));
if(n < 0){
errno = EOPNOTSUPP; /* Improve error reporting!!! */
close(cfd);
return -1;
}
close(cfd);
if(port <= 0)
_sock_ingetaddr(r, &r->addr, 0, "local");
return 0;
}