2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * afs_util.c - miscellaneous AFS client utility functions
15 #include <afsconfig.h>
16 #include "afs/param.h"
20 #include "afs/sysincludes.h" /* Standard vendor system headers */
23 #if !defined(AFS_LINUX20_ENV)
26 #include <netinet/in.h>
29 #include "h/hashing.h"
31 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
32 #include <netinet/in_var.h>
33 #endif /* ! AFS_HPUX110_ENV */
34 #endif /* !defined(UKERNEL) */
36 #include "afsincludes.h" /* Afs-based standard headers */
37 #include "afs/afs_stats.h" /* afs statistics */
38 #include "hcrypto/md5.h"
40 #if defined(AFS_AIX_ENV)
41 #include <sys/fp_io.h>
44 afs_int32 afs_md5inum
= 0;
48 afs_cv2string(char *ttp
, afs_uint32 aval
)
54 AFS_STATCNT(afs_cv2string
);
70 /* not a generic strtoul replacement. for vol/vno/uniq, portable */
73 afs_strtoi_r(const char *str
, char **endptr
, afs_uint32
*ret
)
78 *endptr
= (char *)str
;
83 for (x
= (char *)str
; *x
>= '0' && *x
<= '9'; x
++) {
84 /* Check for impending overflow */
85 if (*ret
> 429496729) { /* ULONG_MAX/10 */
87 *endptr
= (char *)str
;
91 *ret
= (*ret
* 10) + (*x
- '0');
98 #ifndef afs_strcasecmp
100 afs_strcasecmp(const char *s1
, const char *s2
)
107 if (c1
>= 'A' && c1
<= 'Z')
109 if (c2
>= 'A' && c2
<= 'Z')
121 afs_strcat(char *s1
, char *s2
)
128 while ((*s1
++ = *s2
++));
133 #ifdef AFS_OBSD34_ENV
135 afs_strcpy(char *s1
, char *s2
)
140 while ((*s1
++ = *s2
++) != '\0');
147 afs_strchr(char *s
, int c
)
159 afs_strrchr(char *s
, int c
)
178 n
= afs_osi_Alloc(cc
);
186 print_internet_address(char *preamble
, struct srvAddr
*sa
, char *postamble
,
187 int flag
, int code
, struct rx_connection
*rxconn
)
189 struct server
*aserver
= sa
->server
;
193 AFS_STATCNT(print_internet_address
);
194 address
= ntohl(sa
->sa_ip
);
195 if (aserver
->flags
& SRVR_MULTIHOMED
) {
196 if (flag
== 1) { /* server down mesg */
197 if (!(aserver
->flags
& SRVR_ISDOWN
))
199 " (multi-homed address; other same-host interfaces maybe up)\n";
201 ptr
= " (all multi-homed ip addresses down for the server)\n";
202 } else if (flag
== 2) { /* server up mesg */
204 " (multi-homed address; other same-host interfaces may still be down)\n";
207 afs_warnall("%s%d.%d.%d.%d in cell %s%s (code %d)%s", preamble
, (address
>> 24),
208 (address
>> 16) & 0xff, (address
>> 8) & 0xff, (address
) & 0xff,
209 aserver
->cell
->cellName
, postamble
, code
, ptr
);
211 if (flag
== 1 && rxconn
) {
212 /* server was marked down, check Rx to see if this was possibly due to
213 * an ICMP error received from the network */
214 int errorigin
, errtype
, errcode
;
216 if (rx_GetNetworkError(rxconn
, &errorigin
, &errtype
, &errcode
, &errmsg
) == 0) {
217 const char *str1
= " (";
218 const char *str2
= ")";
220 errmsg
= str1
= str2
= "";
222 afs_warnall("afs: network error for %d.%d.%d.%d:%d: origin %d type %d code %d%s%s%s\n",
224 (address
>> 16) & 0xff,
225 (address
>> 8) & 0xff,
227 (int)ntohs(sa
->sa_portal
),
228 errorigin
, errtype
, errcode
, str1
, errmsg
, str2
);
231 } /*print_internet_address */
235 /* run everywhere, checking locks */
241 afs_warn("Looking for locked data structures.\n");
242 afs_warn("conn %p, volume %p, user %p, cell %p, server %p\n", &afs_xconn
,
243 &afs_xvolume
, &afs_xuser
, &afs_xcell
, &afs_xserver
);
246 AFS_STATCNT(afs_CheckLocks
);
248 for (i
= 0; i
< VCSIZE
; i
++) {
249 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= tvc
->hnext
) {
250 if (tvc
->f
.states
& CVInit
) continue;
251 #ifdef AFS_DARWIN80_ENV
252 if (vnode_isinuse(AFSTOV(tvc
), 0))
256 afs_warn("Stat cache entry at %p is held\n", tvc
);
257 if (CheckLock(&tvc
->lock
))
258 afs_warn("Stat entry at %p is locked\n", tvc
);
264 for (i
= 0; i
< afs_cacheFiles
; i
++) {
265 tdc
= afs_indexTable
[i
];
268 afs_warn("Disk entry %d at %p is held\n", i
, tdc
);
270 if (afs_indexFlags
[i
] & IFDataMod
)
271 afs_warn("Disk entry %d at %p has IFDataMod flag set.\n", i
,
278 struct sa_conn_vector
*tcv
;
279 for (i
= 0; i
< NSERVERS
; i
++) {
280 for (ts
= afs_servers
[i
]; ts
; ts
= ts
->next
) {
281 if (ts
->flags
& SRVR_ISDOWN
)
282 afs_warn("Server entry %p is marked down\n", ts
);
283 for (sa
= ts
->addr
; sa
; sa
= sa
->next_sa
) {
284 for (tcv
= sa
->conns
; tcv
; tcv
= tcv
->next
) {
286 afs_warn("conn at %p (server %x) is held\n", tcv
,
295 for (i
= 0; i
< NVOLS
; i
++) {
296 for (tv
= afs_volumes
[i
]; tv
; tv
= tv
->next
) {
297 if (CheckLock(&tv
->lock
))
298 afs_warn("volume at %p is locked\n", tv
);
300 afs_warn("volume at %p is held\n", tv
);
307 for (i
= 0; i
< NUSERS
; i
++) {
308 for (tu
= afs_users
[i
]; tu
; tu
= tu
->next
) {
309 if (CheckLock(&tu
->lock
))
310 afs_warn("user at %p is locked\n", tu
);
312 afs_warn("user at %lx is held\n", (unsigned long)tu
);
323 AFS_STATCNT(afs_noop
);
330 AFS_STATCNT(afs_badop
);
331 osi_Panic("afs bad vnode op");
336 * afs_data_pointer_to_int32() - returns least significant afs_int32 of the
337 * given data pointer, without triggering "cast truncates pointer"
338 * warnings. We use this where we explicitly don't care whether a
339 * pointer is truncated -- it loses information where a pointer is
340 * larger than an afs_int32.
344 afs_data_pointer_to_int32(const void *p
)
347 afs_int32 i32
[sizeof(void *) / sizeof(afs_int32
)];
351 int i32_sub
; /* subscript of least significant afs_int32 in ip.i32[] */
356 /* used to determine the byte order of the system */
359 char c
[sizeof(int) / sizeof(char)];
365 /* little-endian system */
368 /* big-endian system */
369 i32_sub
= (sizeof ip
.i32
/ sizeof ip
.i32
[0]) - 1;
374 return ip
.i32
[i32_sub
];
377 static_inline afs_int32
378 afs_calc_inum_md5(afs_int32 cell
, afs_int32 volume
, afs_int32 vnode
)
380 afs_int32 ino
= 0, vno
= vnode
;
387 MD5_Update(&ct
, &cell
, 4);
388 MD5_Update(&ct
, &volume
, 4);
389 MD5_Update(&ct
, &vnode
, 4);
390 MD5_Final(digest
, &ct
);
392 /* Userspace may react oddly to an inode number of 0 or 1, so keep
393 * reading more of the md5 digest if we get back one of those.
394 * Make sure not to read beyond the end of the digest; if we somehow
395 * still have a 0, we will fall through to the non-md5 calculation. */
397 (ino
== 0 || ino
== 1) &&
398 offset
+ sizeof(ino
) <= sizeof(digest
);
401 memcpy(&ino
, &digest
[offset
], sizeof(ino
));
402 ino
^= (ino
^ vno
) & 1;
403 ino
&= 0x7fffffff; /* Assumes 32 bit ino_t ..... */
410 afs_calc_inum(afs_int32 cell
, afs_int32 volume
, afs_int32 vnode
)
414 ino
= afs_calc_inum_md5(cell
, volume
, vnode
);
416 if (ino
== 0 || ino
== 1) {
417 ino
= (volume
<< 16) + vnode
;
419 ino
&= 0x7fffffff; /* Assumes 32 bit ino_t ..... */