diff -r -u motion-3.2.3/netcam.c motion-3.2.3-ipv6/netcam.c --- motion-3.2.3/netcam.c 2005-08-13 01:26:57.000000000 +0200 +++ motion-3.2.3-ipv6/netcam.c 2007-12-31 02:22:11.000000000 +0100 @@ -577,27 +577,27 @@ */ static int netcam_connect(netcam_context_ptr netcam, struct timeval *timeout) { - struct sockaddr_in server; /* for connect */ - struct addrinfo *res; /* for getaddrinfo */ + struct addrinfo *res, *ressave, hints; /* for getaddrinfo */ int ret; int saveflags; int back_err; socklen_t len; fd_set fd_w; struct timeval selecttime; + char portname[100]; + + snprintf(portname, sizeof(portname), "%u", netcam->connect_port); /* Assure any previous connection has been closed */ netcam_disconnect(netcam); - /* create a new socket */ - if ((netcam->sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - motion_log(netcam->cnt, LOG_ERR, 1, - "Attempting to create socket"); - return -1; - } - /* lookup the hostname given in the netcam URL */ - if ((ret = getaddrinfo(netcam->connect_host, NULL, NULL, &res)) - != 0) { + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG; + + if (getaddrinfo(netcam->connect_host, portname, &hints, &res) != 0) + { motion_log(netcam->cnt, LOG_ERR, 0, "getaddrinfo() failed (%s): %s", netcam->connect_host, @@ -606,79 +606,101 @@ return -1; } - /* - * Fill the hostname details into the 'server' structure and - * attempt to connect to the remote server - */ - memset(&server, 0, sizeof(server)); - memcpy(&server, res->ai_addr, sizeof(server)); - freeaddrinfo(res); - - server.sin_family = AF_INET; - server.sin_port = htons(netcam->connect_port); - if (timeout) - netcam->timeout = *timeout; + ressave = res; + netcam->sock = -1; + + while (res) + { + /* create a new socket */ + netcam->sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + while (1) + { + if (netcam->sock < 0) { + motion_log(netcam->cnt, LOG_ERR, 1, + "Attempting to create socket"); + netcam->sock = -1; + break; + } + + if (timeout) + netcam->timeout = *timeout; - if ((setsockopt(netcam->sock, SOL_SOCKET, SO_RCVTIMEO, - &netcam->timeout, sizeof(netcam->timeout))) < 0) { - motion_log(netcam->cnt, LOG_ERR, 1, "setsockopt() failed"); - netcam_disconnect(netcam); - return -1; - } + if ((setsockopt(netcam->sock, SOL_SOCKET, SO_RCVTIMEO, + &netcam->timeout, sizeof(netcam->timeout))) < 0) { + motion_log(netcam->cnt, LOG_ERR, 1, "setsockopt() failed"); + netcam_disconnect(netcam); + netcam->sock = -1; + break; + } - /* - * Unfortunately, the SO_RCVTIMEO does not affect the 'connect' - * call, so we need to be quite a bit more clever. We want to - * use netcam->timeout, so we set the socket non-blocking and - * then use a 'select' system call to control the timeout. - */ + /* + * Unfortunately, the SO_RCVTIMEO does not affect the 'connect' + * call, so we need to be quite a bit more clever. We want to + * use netcam->timeout, so we set the socket non-blocking and + * then use a 'select' system call to control the timeout. + */ - if ((saveflags = fcntl(netcam->sock, F_GETFL, 0)) < 0) { - motion_log(netcam->cnt, LOG_ERR, 1, "fcntl(1) on socket"); - close(netcam->sock); - netcam->sock = -1; - return -1; - } - /* Set the socket non-blocking */ - if (fcntl(netcam->sock, F_SETFL, saveflags | O_NONBLOCK) < 0) { - motion_log(netcam->cnt, LOG_ERR, 1, "fcntl(2) on socket"); - close(netcam->sock); - netcam->sock = -1; - return -1; - } - /* Now the connect call will return immediately */ - ret = connect(netcam->sock, (struct sockaddr *) &server, - sizeof(server)); - back_err = errno; /* save the errno from connect */ - - /* Restore the normal socket flags */ - if (fcntl(netcam->sock, F_SETFL, saveflags) < 0) { - motion_log(netcam->cnt, LOG_ERR, 1, "fcntl(3) on socket"); - close(netcam->sock); - netcam->sock = -1; - return -1; - } + if ((saveflags = fcntl(netcam->sock, F_GETFL, 0)) < 0) { + motion_log(netcam->cnt, LOG_ERR, 1, "fcntl(1) on socket"); + close(netcam->sock); + netcam->sock = -1; + break; + } + /* Set the socket non-blocking */ + if (fcntl(netcam->sock, F_SETFL, saveflags | O_NONBLOCK) < 0) { + motion_log(netcam->cnt, LOG_ERR, 1, "fcntl(2) on socket"); + close(netcam->sock); + netcam->sock = -1; + break; + } + /* Now the connect call will return immediately */ + ret = connect(netcam->sock, res->ai_addr, (unsigned int)res->ai_addrlen); + back_err = errno; /* save the errno from connect */ + + /* Restore the normal socket flags */ + if (fcntl(netcam->sock, F_SETFL, saveflags) < 0) { + motion_log(netcam->cnt, LOG_ERR, 1, "fcntl(3) on socket"); + close(netcam->sock); + netcam->sock = -1; + break; + } - /* If the connect failed with anything except EINPROGRESS, error */ - if ((ret < 0) && (back_err != EINPROGRESS)) { - motion_log(netcam->cnt, LOG_ERR, 1, "connect() failed (%d)", - back_err); - close(netcam->sock); - netcam->sock = -1; - return -1; + /* If the connect failed with anything except EINPROGRESS, error */ + if ((ret < 0) && (back_err != EINPROGRESS)) { + motion_log(netcam->cnt, LOG_ERR, 1, "connect() failed (%d)", + back_err); + close(netcam->sock); + netcam->sock = -1; + break; + } + + /* Now we do a 'select' with timeout to wait for the connect */ + FD_ZERO(&fd_w); + FD_SET(netcam->sock, &fd_w); + selecttime.tv_sec = CONNECT_TIMEOUT; + selecttime.tv_usec = 0; + ret = select(FD_SETSIZE, NULL, &fd_w, NULL, &selecttime); + + if (ret == 0) { /* 0 means timeout */ + motion_log(netcam->cnt, LOG_ERR, 0, "timeout on connect()"); + close(netcam->sock); + netcam->sock = -1; + break; + } + + } + + /* We have a working connected socket thus get out of this loop */ + if (netcam->sock >= 0) break; + + res = res->ai_next; } - /* Now we do a 'select' with timeout to wait for the connect */ - FD_ZERO(&fd_w); - FD_SET(netcam->sock, &fd_w); - selecttime.tv_sec = CONNECT_TIMEOUT; - selecttime.tv_usec = 0; - ret = select(FD_SETSIZE, NULL, &fd_w, NULL, &selecttime); - - if (ret == 0) { /* 0 means timeout */ - motion_log(netcam->cnt, LOG_ERR, 0, "timeout on connect()"); - close(netcam->sock); - netcam->sock = -1; + freeaddrinfo(ressave); + + if (netcam->sock < 0) + { + motion_log(netcam->cnt, LOG_ERR, 0, "Could not establish a connection"); return -1; } diff -r -u motion-3.2.3/webcam.c motion-3.2.3-ipv6/webcam.c --- motion-3.2.3/webcam.c 2005-08-10 08:19:07.000000000 +0200 +++ motion-3.2.3-ipv6/webcam.c 2007-12-31 03:06:21.000000000 +0100 @@ -29,6 +29,9 @@ #include "webcam.h" #include "motion.h" +#include +#include +#include /* This function sets up a TCP/IP socket for incomming requests. It is called only during * initiatization of Motion from the function webcam_init @@ -38,35 +41,56 @@ */ int http_bindsock(struct context *cnt, int port, int local) { - int sl, optval=1; - struct sockaddr_in sin; - - if ((sl=socket(PF_INET, SOCK_STREAM, 0))<0) { - motion_log(cnt, LOG_ERR, 1, "socket()"); + int sl, optval=1, n; + struct addrinfo hints, *res, *ressave; + char portnumber[100]; + + snprintf(portnumber, sizeof(portnumber), "%u", port); + + memset(&hints, 0, sizeof(struct addrinfo)); + /* Use the AI_PASSIVE flag, which indicates we are using this address for a listen() */ + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + n = getaddrinfo(local ? "localhost" : NULL, portnumber, &hints, &res); + if (n < 0) { + motion_log(cnt, LOG_ERR, 1, "getaddrinfo() error, couldn't not listen because of that"); return -1; } - memset(&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_family=AF_INET; - sin.sin_port=htons(port); - - if (local) - sin.sin_addr.s_addr=htonl(INADDR_LOOPBACK); - else - sin.sin_addr.s_addr=htonl(INADDR_ANY); - - setsockopt(sl, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - - if (bind(sl, (struct sockaddr *)&sin, sizeof(struct sockaddr_in))==-1) { - motion_log(cnt, LOG_ERR, 1, "bind()"); - close(sl); - return -1; - } + ressave = res; - if (listen(sl, DEF_MAXWEBQUEUE)==-1) { - motion_log(cnt, LOG_ERR, 1, "listen()"); - close(sl); - return -1; + while (res) { + /* create socket */ + if ((sl=socket(res->ai_family, res->ai_socktype, res->ai_protocol))<0) { + motion_log(cnt, LOG_ERR, 1, "socket()"); + sl = -1; + res = res->ai_next; + continue; + } + + /* Reuse Address */ + setsockopt(sl, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + + if (bind(sl, res->ai_addr, (unsigned int)res->ai_addrlen)==-1) { + motion_log(cnt, LOG_ERR, 1, "bind()"); + close(sl); + sl = -1; + res = res->ai_next; + continue; + } + + if (listen(sl, DEF_MAXWEBQUEUE)==-1) { + motion_log(cnt, LOG_ERR, 1, "listen()"); + close(sl); + sl = -1; + res = res->ai_next; + continue; + } + + /* Got a working socket */ + break; } return sl; @@ -77,8 +101,8 @@ { int sc; unsigned long i; - struct sockaddr_in sin; - socklen_t addrlen=sizeof(struct sockaddr_in); + struct sockaddr_storage sin; + socklen_t addrlen=sizeof(sin); if ((sc=accept(sl, (struct sockaddr *)&sin, &addrlen))>=0) { i=1; @@ -220,7 +244,7 @@ "Connection: close\r\n" "Max-Age: 0\r\n" "Expires: 0\r\n" - "Cache-Control: no-cache, private\r\n" + "Cache-Control: no-store, no-cache, private, must-revalidate\r\n" "Pragma: no-cache\r\n" "Content-Type: multipart/x-mixed-replace; boundary=--BoundaryString\r\n\r\n"; diff -r -u motion-3.2.3/webhttpd.c motion-3.2.3-ipv6/webhttpd.c --- motion-3.2.3/webhttpd.c 2005-08-16 22:06:07.000000000 +0200 +++ motion-3.2.3-ipv6/webhttpd.c 2007-12-31 02:49:00.000000000 +0100 @@ -46,8 +46,7 @@ "Connection: close\r\n" "Max-Age: 0\r\n" "Expires: 0\r\n" - "Cache-Control: no-cache\r\n" - "Cache-Control: private\r\n" + "Cache-Control: no-store, no-cache, must-revalidate, private\r\n" "Pragma: no-cache\r\n" "Content-type: text/html\r\n\r\n"; @@ -57,8 +56,7 @@ "Connection: close\r\n" "Max-Age: 0\r\n" "Expires: 0\r\n" - "Cache-Control: no-cache\r\n" - "Cache-Control: private\r\n" + "Cache-Control: no-store, no-cache, must-revalidate, private\r\n" "Pragma: no-cache\r\n" "Content-type: text/plain\r\n\r\n"; @@ -1898,8 +1896,8 @@ int acceptnonblocking(int serverfd, int timeout) { int curfd; - socklen_t namelen = sizeof(struct sockaddr_in); - struct sockaddr_in client; + struct sockaddr_storage client; + socklen_t namelen = sizeof(client); struct timeval tm; fd_set fds; @@ -1926,12 +1924,13 @@ void httpd_run(struct context **cnt) { - int sd, client_socket_fd; + int sd, client_socket_fd, n; int client_sent_quit_message = 1, val=1; int closehttpd = 0; - struct sockaddr_in servAddr; + struct addrinfo hints, *res, *ressave; struct sigaction act; char *authentication=NULL; + char portnumber[100]; /* Initialize the mutex */ pthread_mutex_init(&httpd_mutex, NULL); @@ -1944,35 +1943,52 @@ sigaction(SIGPIPE,&act,NULL); sigaction(SIGCHLD,&act,NULL); - /* create socket */ - sd = socket(AF_INET, SOCK_STREAM, 0); - if (sd<0) { - motion_log(cnt[0], LOG_ERR, 1, "httpd socket"); + memset(&hints, 0, sizeof(struct addrinfo)); + /* PASSIVE as we are going to listen */ + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + snprintf(portnumber, sizeof(portnumber), "%u", cnt[0]->conf.control_port); + + n = getaddrinfo(cnt[0]->conf.control_localhost ? "localhost" : NULL, portnumber, &hints, &res); + if (n < 0) + { + motion_log(cnt[0], LOG_ERR, 1, "getaddrinfo() for httpd socket failed"); return; } - /* bind server port */ - servAddr.sin_family = AF_INET; - if (cnt[0]->conf.control_localhost) - servAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - else - servAddr.sin_addr.s_addr = htonl(INADDR_ANY); - servAddr.sin_port = htons(cnt[0]->conf.control_port); + ressave = res; - /* Reuse Address */ - - setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( int ) ) ; + while (res) + { + /* create socket */ + if ((sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol))<0) { + motion_log(cnt[0], LOG_ERR, 1, "httpd socket"); + sd = -1; + res = res->ai_next; + continue; + } - if (bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) { - motion_log(cnt[0], LOG_ERR, 1, "httpd bind()"); - close(sd); - return ; - } + /* Reuse Address */ + setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( int ) ) ; - if (listen(sd,5) == -1){ - motion_log(cnt[0], LOG_ERR, 1, "httpd listen()"); - close(sd); - return; + if (bind(sd, (struct sockaddr *) res->ai_addr, (unsigned int)res->ai_addrlen)==-1) { + motion_log(cnt[0], LOG_ERR, 1, "httpd bind()"); + close(sd); + sd = -1; + res = res->ai_next; + } + + if (listen(sd,5) == -1) { + motion_log(cnt[0], LOG_ERR, 1, "httpd listen()"); + close(sd); + sd = -1; + res = res->ai_next; + } + + /* Got a working socket */ + break; } motion_log(cnt[0], LOG_DEBUG, 0, "motion-httpd/"VERSION" running, accepting connections");