Add a limit for number of fns.
[doldaconnect.git] / daemon / ui.c
index 09a6dcf..0e7fba1 100644 (file)
@@ -23,6 +23,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/ip6.h>
+#include <arpa/inet.h>
 #include <errno.h>
 #include <string.h>
 #include <stdarg.h>
@@ -315,6 +316,7 @@ static int haspriv(struct uidata *data, int perm)
 static void cmd_connect(struct socket *sk, struct uidata *data, int argc, wchar_t **argv)
 {
     int valid;
+    struct in6_addr mv4lo;
     
     if(confgetint("ui", "onlylocal"))
     {
@@ -324,7 +326,12 @@ static void cmd_connect(struct socket *sk, struct uidata *data, int argc, wchar_
            valid = ((struct sockaddr_in *)sk->remote)->sin_addr.s_addr == INADDR_LOOPBACK;
            break;
        case AF_INET6:
-           valid = !memcmp(&((struct sockaddr_in6 *)sk->remote)->sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback));
+           inet_pton(AF_INET6, "::ffff:127.0.0.1", &mv4lo);
+           valid = 0;
+           if(!memcmp(&((struct sockaddr_in6 *)sk->remote)->sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback)))
+               valid = 1;
+           if(!memcmp(&((struct sockaddr_in6 *)sk->remote)->sin6_addr, &mv4lo, sizeof(in6addr_loopback)))
+               valid = 1;
            break;
        default:
            valid = 0;
@@ -430,19 +437,20 @@ static void cmd_login(struct socket *sk, struct uidata *data, int argc, wchar_t
        if(data->uid == -1)
        {
            sq(sk, 0, L"506", L"Authentication error", NULL);
-           flog(LOG_INFO, "user %ls authenticated successfully, but no account existed", data->username);
+           flog(LOG_INFO, "user %ls authenticated successfully from %s, but no account existed", data->username, formataddress(sk->remote, sk->remotelen));
            logout(data);
        } else if((data->userinfo == NULL) || (data->userinfo->perms & PERM_DISALLOW)) {
            sq(sk, 0, L"506", L"Authentication error", NULL);
-           flog(LOG_INFO, "user %ls authenticated successfully, but was not authorized", data->username);
+           flog(LOG_INFO, "user %ls authenticated successfully from %s, but was not authorized", data->username, formataddress(sk->remote, sk->remotelen));
            logout(data);
        } else {
            sq(sk, 0, L"200", L"Welcome", NULL);
-           flog(LOG_INFO, "%ls (UID %i) logged in", data->username, data->uid);
+           flog(LOG_INFO, "%ls (UID %i) logged in from %s", data->username, data->uid, formataddress(sk->remote, sk->remotelen));
        }
        break;
     case AUTH_DENIED:
        sq(sk, 0, L"506", L"Authentication error", L"%%ls", (data->auth->text == NULL)?L"":(data->auth->text), NULL);
+       flog(LOG_INFO, "authentication failed for %ls from %s", data->username, formataddress(sk->remote, sk->remotelen));
        logout(data);
        break;
     case AUTH_PASS:
@@ -503,19 +511,20 @@ static void cmd_pass(struct socket *sk, struct uidata *data, int argc, wchar_t *
        if(data->uid == -1)
        {
            sq(sk, 0, L"506", L"Authentication error", NULL);
-           flog(LOG_INFO, "user %ls authenticated successfully, but no account existed", data->username);
+           flog(LOG_INFO, "user %ls authenticated successfully from %s, but no account existed", data->username, formataddress(sk->remote, sk->remotelen));
            logout(data);
        } else if((data->userinfo == NULL) || (data->userinfo->perms & PERM_DISALLOW)) {
            sq(sk, 0, L"506", L"Authentication error", NULL);
-           flog(LOG_INFO, "user %ls authenticated successfully, but was not authorized", data->username);
+           flog(LOG_INFO, "user %ls authenticated successfully from %s, but was not authorized", data->username, formataddress(sk->remote, sk->remotelen));
            logout(data);
        } else {
            sq(sk, 0, L"200", L"Welcome", NULL);
-           flog(LOG_INFO, "%ls (UID %i) logged in", data->username, data->uid);
+           flog(LOG_INFO, "%ls (UID %i) logged in from %s", data->username, data->uid, formataddress(sk->remote, sk->remotelen));
        }
        break;
     case AUTH_DENIED:
        sq(sk, 0, L"506", L"Authentication error", L"%%ls", (data->auth->text == NULL)?L"":(data->auth->text), NULL);
+       flog(LOG_INFO, "authentication failed for %ls from %s", data->username, formataddress(sk->remote, sk->remotelen));
        logout(data);
        break;
     case AUTH_PASS:
@@ -558,15 +567,24 @@ static void cmd_fnetconnect(struct socket *sk, struct uidata *data, int argc, wc
     char *buf;
     int err;
     struct fnetnode *fn;
+    struct wcspair *args;
     
     haveargs(3);
     havepriv(PERM_FNETCTL);
+    for(i = 0, fn = fnetnodes; fn != NULL; i++, fn = fn->next);
+    if((confgetint("fnet", "maxnodes") > 0) && (i >= confgetint("fnet", "maxnodes"))) {
+       sq(sk, 0, L"515", L"Too many fnetnodes connected already", NULL);
+       return;
+    }
     if((buf = icwcstombs(argv[2], NULL)) == NULL)
     {
        sq(sk, 0, L"504", L"Could not convert data to locale charset", NULL);
        return;
     }
-    fn = fnetinitconnect(argv[1], buf);
+    args = NULL;
+    for(i = 3; i < argc - 1; i += 2)
+       newwcspair(argv[i], argv[i + 1], &args);
+    fn = fnetinitconnect(argv[1], buf, args);
     err = errno;
     free(buf);
     if(fn == NULL)
@@ -577,11 +595,6 @@ static void cmd_fnetconnect(struct socket *sk, struct uidata *data, int argc, wc
            sq(sk, 0, L"509", L"Could not parse the address", L"%%s", strerror(err), NULL);
        return;
     }
-    for(i = 3; i < argc - 1; i += 2)
-    {
-       if(!wcscmp(argv[i], L"nick"))
-           fnetsetnick(fn, argv[i + 1]);
-    }
     linkfnetnode(fn);
     fnetsetname(fn, argv[2]);
     putfnetnode(fn);
@@ -599,7 +612,7 @@ static void cmd_lsnodes(struct socket *sk, struct uidata *data, int argc, wchar_
     }
     for(fn = fnetnodes; fn != NULL; fn = fn->next)
     {
-       sq(sk, (fn->next != NULL)?1:0, L"200", L"%%i", fn->id, fn->fnet->name, (fn->name == NULL)?L"":fn->name, L"%%i", fn->numpeers, L"%%i", fn->state, NULL);
+       sq(sk, (fn->next != NULL)?1:0, L"200", L"%%i", fn->id, fn->fnet->name, (fn->name == NULL)?L"":fn->name, L"%%i", fn->numpeers, L"%%i", fn->state, L"%%ls", fn->pubid, NULL);
     }
 }
 
@@ -745,7 +758,7 @@ static void cmd_download(struct socket *sk, struct uidata *data, int argc, wchar
            {
                transfersethash(transfer, parsehash(argv[i + 1]));
            } else {
-               transferaddarg(transfer, argv[i], argv[i + 1]);
+               newwcspair(argv[i], argv[i + 1], &transfer->args);
            }
        }
     }
@@ -1164,7 +1177,7 @@ static void cmd_filtercmd(struct socket *sk, struct uidata *data, int argc, wcha
 static void cmd_lstrarg(struct socket *sk, struct uidata *data, int argc, wchar_t **argv)
 {
     struct transfer *transfer;
-    struct transarg *ta;
+    struct wcspair *ta;
     
     haveargs(2);
     havepriv(PERM_TRANS);
@@ -1183,7 +1196,7 @@ static void cmd_lstrarg(struct socket *sk, struct uidata *data, int argc, wchar_
        sq(sk, 0, L"201", L"Transfer has no arguments", NULL);
     } else {
        for(ta = transfer->args; ta != NULL; ta = ta->next)
-           sq(sk, ta->next != NULL, L"200", L"%%ls", ta->rec, L"%%ls", ta->val, NULL);
+           sq(sk, ta->next != NULL, L"200", L"%%ls", ta->key, L"%%ls", ta->val, NULL);
     }
 }
 
@@ -1205,6 +1218,18 @@ static void cmd_hashstatus(struct socket *sk, struct uidata *data, int argc, wch
     sq(sk, 0, L"200", L"%%i", total, L"tth", L"%%i", hashed, NULL);
 }
 
+static void cmd_transstatus(struct socket *sk, struct uidata *data, int argc, wchar_t **argv)
+{
+    wchar_t *buf1, *buf2;
+    
+    havepriv(PERM_TRANS);
+    buf1 = swprintf2(L"%lli", bytesdownload);
+    buf2 = swprintf2(L"%lli", bytesupload);
+    sq(sk, 0, L"200", L"%%ls", buf1, L"%%ls", buf2, NULL);
+    free(buf1);
+    free(buf2);
+}
+
 #undef haveargs
 #undef havepriv
 
@@ -1240,6 +1265,7 @@ static struct command commands[] =
     {L"filtercmd", cmd_filtercmd},
     {L"lstrarg", cmd_lstrarg},
     {L"hashstatus", cmd_hashstatus},
+    {L"transstatus", cmd_transstatus},
     {NULL, NULL}
 };
 
@@ -1903,7 +1929,7 @@ static int transferdestroyed(struct transfer *transfer, void *uudata)
     for(data = actives; data != NULL; data = data->next)
     {
        if(haspriv(data, PERM_TRANS) && data->notify.b.tract && ((transfer->owner == 0) || (transfer->owner == data->uid)))
-           newnotif(data, 617, NOTIF_ID, transfer->id, NOTIF_END);
+           newnotif(data, 617, NOTIF_ID, transfer->id, NOTIF_STR, (transfer->exitstatus == NULL)?L"":(transfer->exitstatus), NOTIF_END);
     }
     return(0);
 }
@@ -2017,41 +2043,11 @@ static void preinit(int hup)
     }
 }
 
-#ifdef HAVE_IPV6
-static struct sockaddr *getnameforport(int port, socklen_t *len)
-{
-    static struct sockaddr_in6 addr;
-    
-    memset(&addr, 0, sizeof(addr));
-    addr.sin6_family = AF_INET6;
-    addr.sin6_port = htons(port);
-    addr.sin6_addr = in6addr_any;
-    if(len != NULL)
-       *len = sizeof(addr);
-    return((struct sockaddr *)&addr);
-}
-#else
-static struct sockaddr *getnameforport(int port, socklen_t *len)
-{
-    static struct sockaddr_in addr;
-    
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(port);
-    if(len != NULL)
-       *len = sizeof(addr);
-    return((struct sockaddr *)&addr);
-}
-#endif
-
 static int portupdate(struct configvar *var, void *uudata)
 {
-    struct sockaddr *addr;
-    socklen_t addrlen;
     struct socket *newsock;
     
-    addr = getnameforport(var->val.num, &addrlen);
-    if((uisocket = netcslistenlocal(SOCK_STREAM, addr, addrlen, uiaccept, NULL)) == NULL)
+    if((uisocket = netcstcplisten(var->val.num, 1, uiaccept, NULL)) == NULL)
     {
        flog(LOG_WARNING, "could not create new UI socket, reverting to old: %s", strerror(errno));
        return(0);
@@ -2064,8 +2060,6 @@ static int portupdate(struct configvar *var, void *uudata)
 
 static int init(int hup)
 {
-    struct sockaddr *addr;
-    socklen_t addrlen;
     struct uiuser *user, *next;
     
     if(hup)
@@ -2081,8 +2075,7 @@ static int init(int hup)
     {
        if(uisocket != NULL)
            putsock(uisocket);
-       addr = getnameforport(confgetint("ui", "port"), &addrlen);
-       if((uisocket = netcslistenlocal(SOCK_STREAM, addr, addrlen, uiaccept, NULL)) == NULL)
+       if((uisocket = netcstcplisten(confgetint("ui", "port"), 1, uiaccept, NULL)) == NULL)
        {
            flog(LOG_CRIT, "could not create UI socket: %s", strerror(errno));
            return(1);