[CIFS] Neaten cERROR and cFYI macros, reduce text space
[safe/jmp/linux-2.6] / fs / cifs / netmisc.c
index ef9c981..d35d528 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/netmisc.c
  *
- *   Copyright (c) International Business Machines  Corp., 2002
+ *   Copyright (c) International Business Machines  Corp., 2002,2008
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   Error mapping routines from Samba libsmb/errormap.c
@@ -29,9 +29,7 @@
 #include <linux/fs.h>
 #include <asm/div64.h>
 #include <asm/byteorder.h>
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 #include <linux/inet.h>
-#endif
 #include "cifsfs.h"
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -81,6 +79,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
        {ErrQuota, -EDQUOT},
        {ErrNotALink, -ENOLINK},
        {ERRnetlogonNotStarted, -ENOPROTOOPT},
+       {ERRsymlink, -EOPNOTSUPP},
        {ErrTooManyLinks, -EMLINK},
        {0, 0}
 };
@@ -116,10 +115,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
        {ERRusempx, -EIO},
        {ERRusestd, -EIO},
        {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
-       {ERRaccountexpired, -EACCES},
+       {ERRnoSuchUser, -EACCES},
+/*     {ERRaccountexpired, -EACCES},
        {ERRbadclient, -EACCES},
        {ERRbadLogonTime, -EACCES},
-       {ERRpasswordExpired, -EACCES},
+       {ERRpasswordExpired, -EACCES},*/
+       {ERRaccountexpired, -EKEYEXPIRED},
+       {ERRbadclient, -EACCES},
+       {ERRbadLogonTime, -EACCES},
+       {ERRpasswordExpired, -EKEYEXPIRED},
+
        {ERRnosupport, -EINVAL},
        {0, 0}
 };
@@ -128,30 +133,74 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
        {0, 0}
 };
 
-/* Convert string containing dotted ip address to binary form */
-/* returns 0 if invalid address */
-
-int
-cifs_inet_pton(int address_family, char *cp, void *dst)
+/*
+ * Convert a string containing text IPv4 or IPv6 address to binary form.
+ *
+ * Returns 0 on failure.
+ */
+static int
+cifs_inet_pton(const int address_family, const char *cp, void *dst)
 {
        int ret = 0;
 
        /* calculate length by finding first slash or NULL */
-       /* BB Should we convert '/' slash to '\' here since it seems already
-        * done before this */
-       if ( address_family == AF_INET ) {
-               ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
-       } else if ( address_family == AF_INET6 ) {
+       if (address_family == AF_INET)
+               ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL);
+       else if (address_family == AF_INET6)
                ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
-       }
-#ifdef CONFIG_CIFS_DEBUG2
-       cFYI(1, ("address conversion returned %d for %s", ret, cp));
-#endif
+
+       cFYI(DBG2, "address conversion returned %d for %s", ret, cp);
        if (ret > 0)
                ret = 1;
        return ret;
 }
 
+/*
+ * Try to convert a string to an IPv4 address and then attempt to convert
+ * it to an IPv6 address if that fails. Set the family field if either
+ * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to
+ * treat the part following it as a numeric sin6_scope_id.
+ *
+ * Returns 0 on failure.
+ */
+int
+cifs_convert_address(char *src, void *dst)
+{
+       int rc;
+       char *pct, *endp;
+       struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
+       struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;
+
+       /* IPv4 address */
+       if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) {
+               s4->sin_family = AF_INET;
+               return 1;
+       }
+
+       /* temporarily terminate string */
+       pct = strchr(src, '%');
+       if (pct)
+               *pct = '\0';
+
+       rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr);
+
+       /* repair temp termination (if any) and make pct point to scopeid */
+       if (pct)
+               *pct++ = '%';
+
+       if (!rc)
+               return rc;
+
+       s6->sin6_family = AF_INET6;
+       if (pct) {
+               s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0);
+               if (!*pct || *endp)
+                       return 0;
+       }
+
+       return rc;
+}
+
 /*****************************************************************************
 convert a NT status code to a dos class/code
  *****************************************************************************/
@@ -219,7 +268,8 @@ static const struct {
        ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
        ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
        ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
-       ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, {   /* mapping changed since shell does lookup on * and expects file not found */
+        /* mapping changed since shell does lookup on * expects FileNotFound */
+       ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, {
        ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
        ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
        ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
@@ -272,7 +322,7 @@ static const struct {
         from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
         during the session setup } */
        {
-       ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
+       ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */
        ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
        ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
        ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
@@ -287,10 +337,10 @@ static const struct {
        ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
        ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
        ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
-       ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
-       ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
+       ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
+       ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
        ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
-       ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
+       ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, {
        ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
        ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
        ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
@@ -587,7 +637,7 @@ static const struct {
        ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
        ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
        ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
-       ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
+       ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, {
        ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
        ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
        ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
@@ -713,6 +763,7 @@ static const struct {
        ERRDOS, ERRnoaccess, 0xc000028f}, {
        ERRDOS, ERRnoaccess, 0xc0000290}, {
        ERRDOS, ERRbadfunc, 0xc000029c}, {
+       ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
        ERRDOS, ERRinvlevel, 0x007c0001}, };
 
 /*****************************************************************************
@@ -736,7 +787,7 @@ cifs_print_status(__u32 status_code)
 
 
 static void
-ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
+ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
 {
        int i;
        if (ntstatus == 0) {
@@ -756,7 +807,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
 }
 
 int
-map_smb_to_linux_error(struct smb_hdr *smb)
+map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
 {
        unsigned int i;
        int rc = -EIO;  /* if transport error smb error may not be set */
@@ -773,7 +824,9 @@ map_smb_to_linux_error(struct smb_hdr *smb)
                /* translate the newer STATUS codes to old style SMB errors
                 * and then to POSIX errors */
                __u32 err = le32_to_cpu(smb->Status.CifsError);
-               if (cifsFYI & CIFS_RC)
+               if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED)))
+                       cifs_print_status(err);
+               else if (cifsFYI & CIFS_RC)
                        cifs_print_status(err);
                ntstatus_to_dos(err, &smberrclass, &smberrcode);
        } else {
@@ -784,27 +837,31 @@ map_smb_to_linux_error(struct smb_hdr *smb)
        /* old style errors */
 
        /* DOS class smb error codes - map DOS */
-       if (smberrclass == ERRDOS) {  /* 1 byte field no need to byte reverse */
+       if (smberrclass == ERRDOS) {
+               /* 1 byte field no need to byte reverse */
                for (i = 0;
                     i <
-                    sizeof (mapping_table_ERRDOS) /
-                    sizeof (struct smb_to_posix_error); i++) {
+                    sizeof(mapping_table_ERRDOS) /
+                    sizeof(struct smb_to_posix_error); i++) {
                        if (mapping_table_ERRDOS[i].smb_err == 0)
                                break;
-                       else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
+                       else if (mapping_table_ERRDOS[i].smb_err ==
+                                                               smberrcode) {
                                rc = mapping_table_ERRDOS[i].posix_code;
                                break;
                        }
                        /* else try next error mapping one to see if match */
                }
-       } else if (smberrclass == ERRSRV) {   /* server class of error codes */
+       } else if (smberrclass == ERRSRV) {
+               /* server class of error codes */
                for (i = 0;
                     i <
-                    sizeof (mapping_table_ERRSRV) /
-                    sizeof (struct smb_to_posix_error); i++) {
+                    sizeof(mapping_table_ERRSRV) /
+                    sizeof(struct smb_to_posix_error); i++) {
                        if (mapping_table_ERRSRV[i].smb_err == 0)
                                break;
-                       else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
+                       else if (mapping_table_ERRSRV[i].smb_err ==
+                                                               smberrcode) {
                                rc = mapping_table_ERRSRV[i].posix_code;
                                break;
                        }
@@ -813,8 +870,8 @@ map_smb_to_linux_error(struct smb_hdr *smb)
        }
        /* else ERRHRD class errors or junk  - return EIO */
 
-       cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!",
-                smberrcode, rc));
+       cFYI(1, "Mapping smb error code %d to POSIX err %d",
+                smberrcode, rc);
 
        /* generic corrective action e.g. reconnect SMB session on
         * ERRbaduid could be added */
@@ -829,14 +886,14 @@ map_smb_to_linux_error(struct smb_hdr *smb)
 unsigned int
 smbCalcSize(struct smb_hdr *ptr)
 {
-       return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+       return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
                2 /* size of the bcc field */ + BCC(ptr));
 }
 
 unsigned int
 smbCalcSize_LE(struct smb_hdr *ptr)
 {
-       return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+       return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) +
                2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr)));
 }
 
@@ -844,12 +901,12 @@ smbCalcSize_LE(struct smb_hdr *ptr)
 
 #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
 
-    /*
    * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
    * into Unix UTC (based 1970-01-01, in seconds).
    */
+/*
+ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
+ * into Unix UTC (based 1970-01-01, in seconds).
+ */
 struct timespec
-cifs_NTtimeToUnix(u64 ntutc)
+cifs_NTtimeToUnix(__le64 ntutc)
 {
        struct timespec ts;
        /* BB what about the timezone? BB */
@@ -857,7 +914,7 @@ cifs_NTtimeToUnix(u64 ntutc)
        /* Subtract the NTFS time offset, then convert to 1s intervals. */
        u64 t;
 
-       t = ntutc - NTFS_TIME_OFFSET;
+       t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
        ts.tv_nsec = do_div(t, 10000000) * 100;
        ts.tv_sec = t;
        return ts;
@@ -874,33 +931,32 @@ cifs_UnixTimeToNT(struct timespec t)
 static int total_days_of_prev_months[] =
 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
 
-
-__le64 cnvrtDosCifsTm(__u16 date, __u16 time)
-{
-       return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time)));
-}
-
-struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
+struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset)
 {
        struct timespec ts;
        int sec, min, days, month, year;
-       SMB_TIME * st = (SMB_TIME *)&time;
-       SMB_DATE * sd = (SMB_DATE *)&date;
+       u16 date = le16_to_cpu(le_date);
+       u16 time = le16_to_cpu(le_time);
+       SMB_TIME *st = (SMB_TIME *)&time;
+       SMB_DATE *sd = (SMB_DATE *)&date;
 
-       cFYI(1, ("date %d time %d", date, time));
+       cFYI(1, "date %d time %d", date, time);
 
        sec = 2 * st->TwoSeconds;
        min = st->Minutes;
        if ((sec > 59) || (min > 59))
-               cERROR(1, ("illegal time min %d sec %d", min, sec));
+               cERROR(1, "illegal time min %d sec %d", min, sec);
        sec += (min * 60);
        sec += 60 * 60 * st->Hours;
        if (st->Hours > 24)
-               cERROR(1, ("illegal hours %d", st->Hours));
+               cERROR(1, "illegal hours %d", st->Hours);
        days = sd->Day;
        month = sd->Month;
-       if ((days > 31) || (month > 12))
-               cERROR(1, ("illegal date, month %d day: %d", month, days));
+       if ((days > 31) || (month > 12)) {
+               cERROR(1, "illegal date, month %d day: %d", month, days);
+               if (month > 12)
+                       month = 12;
+       }
        month -= 1;
        days += total_days_of_prev_months[month];
        days += 3652; /* account for difference in days between 1980 and 1970 */
@@ -921,9 +977,9 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
                days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
        sec += 24 * 60 * 60 * days;
 
-       ts.tv_sec = sec;
+       ts.tv_sec = sec + offset;
 
-       /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */
+       /* cFYI(1, "sec after cnvrt dos to unix time %d",sec); */
 
        ts.tv_nsec = 0;
        return ts;