54e8ce366496bef65388545e33759d40ba6040fd
[openafs.git] / src / afs / afs_util.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 /*
11  * afs_util.c - miscellaneous AFS client utility functions
12  *
13  * Implements:
14  */
15 #include <afsconfig.h>
16 #include "afs/param.h"
17
18 RCSID
19     ("$Header$");
20
21 #include "afs/stds.h"
22 #include "afs/sysincludes.h"    /* Standard vendor system headers */
23
24 #if !defined(UKERNEL)
25 #if !defined(AFS_LINUX20_ENV)
26 #include <net/if.h>
27 #endif
28 #include <netinet/in.h>
29
30 #ifdef AFS_SGI62_ENV
31 #include "h/hashing.h"
32 #endif
33 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN60_ENV)
34 #include <netinet/in_var.h>
35 #endif /* ! AFS_HPUX110_ENV */
36 #endif /* !defined(UKERNEL) */
37
38 #include "afsincludes.h"        /* Afs-based standard headers */
39 #include "afs/afs_stats.h"      /* afs statistics */
40
41 #if     defined(AFS_SUN56_ENV)
42 #include <inet/led.h>
43 #include <inet/common.h>
44 #if     defined(AFS_SUN58_ENV)
45 #include <netinet/ip6.h>
46 #endif
47 #include <inet/ip.h>
48 #endif
49
50 #if     defined(AFS_AIX_ENV)
51 #include <sys/fp_io.h>
52 #endif
53
54 afs_int32 afs_new_inum = 0;
55
56 #ifndef afs_cv2string
57 char *
58 afs_cv2string(char *ttp, afs_uint32 aval)
59 {
60     register char *tp = ttp;
61     register int i;
62     int any;
63
64     AFS_STATCNT(afs_cv2string);
65     any = 0;
66     *(--tp) = 0;
67     while (aval != 0) {
68         i = aval % 10;
69         *(--tp) = '0' + i;
70         aval /= 10;
71         any = 1;
72     }
73     if (!any)
74         *(--tp) = '0';
75     return tp;
76
77 }                               /*afs_cv2string */
78 #endif
79
80 #ifndef afs_strcasecmp
81 int
82 afs_strcasecmp(char *s1, char *s2)
83 {
84     while (*s1 && *s2) {
85         char c1, c2;
86
87         c1 = *s1++;
88         c2 = *s2++;
89         if (c1 >= 'A' && c1 <= 'Z')
90             c1 += 0x20;
91         if (c2 >= 'A' && c2 <= 'Z')
92             c2 += 0x20;
93         if (c1 != c2)
94             return c1 - c2;
95     }
96
97     return *s1 - *s2;
98 }
99 #endif
100
101 #ifndef afs_strcat
102 char *
103 afs_strcat(char *s1, char *s2)
104 {
105     char *os1;
106
107     os1 = s1;
108     while (*s1++);
109     --s1;
110     while ((*s1++ = *s2++));
111     return (os1);
112 }
113 #endif
114
115 #ifdef AFS_OBSD34_ENV
116 char *
117 afs_strcpy(char *s1, char *s2)
118 {
119     char *os1;
120
121     os1 = s1;
122     while ((*s1++ = *s2++) != '\0');
123     return os1;
124 }
125 #endif
126
127 #ifndef afs_strchr
128 char *
129 afs_strchr(char *s, int c)
130 {
131     char *p;
132
133     for (p = s; *p; p++)
134         if (*p == c)
135             return p;
136     return NULL;
137 }
138 #endif
139
140 char *
141 afs_strdup(char *s)
142 {
143     char *n;
144     int cc;
145
146     cc = strlen(s) + 1;
147     n = (char *)afs_osi_Alloc(cc);
148     if (n)
149         memcpy(n, s, cc);
150
151     return n;
152 }
153
154 void
155 print_internet_address(char *preamble, struct srvAddr *sa, char *postamble,
156                        int flag)
157 {
158     register struct server *aserver = sa->server;
159     char *ptr = "\n";
160     afs_uint32 address;
161
162     AFS_STATCNT(print_internet_address);
163     address = ntohl(sa->sa_ip);
164     if (aserver->flags & SRVR_MULTIHOMED) {
165         if (flag == 1) {        /* server down mesg */
166             if (!(aserver->flags & SRVR_ISDOWN))
167                 ptr =
168                     " (multi-homed address; other same-host interfaces maybe up)\n";
169             else
170                 ptr = " (all multi-homed ip addresses down for the server)\n";
171         } else if (flag == 2) { /* server up mesg */
172             ptr =
173                 " (multi-homed address; other same-host interfaces may still be down)\n";
174         }
175     }
176     afs_warn("%s%d.%d.%d.%d in cell %s%s%s", preamble, (address >> 24),
177              (address >> 16) & 0xff, (address >> 8) & 0xff, (address) & 0xff,
178              aserver->cell->cellName, postamble, ptr);
179     afs_warnuser("%s%d.%d.%d.%d in cell %s%s%s", preamble, (address >> 24),
180                  (address >> 16) & 0xff, (address >> 8) & 0xff,
181                  (address) & 0xff, aserver->cell->cellName, postamble, ptr);
182
183 }                               /*print_internet_address */
184
185
186
187 /* * * * * * *
188  * this code badly needs to be cleaned up...  too many ugly ifdefs.
189  * XXX
190  */
191 #if 0
192 void
193 afs_warn(char *a, long b, long c, long d, long e, long f, long g, long h,
194          long i, long j)
195 #else
196 void
197 afs_warn(a, b, c, d, e, f, g, h, i, j)
198      char *a;
199 #if defined( AFS_USE_VOID_PTR)
200      void *b, *c, *d, *e, *f, *g, *h, *i, *j;
201 #else
202      long b, c, d, e, f, g, h, i, j;
203 #endif
204 #endif
205 {
206     AFS_STATCNT(afs_warn);
207
208     if (afs_showflags & GAGCONSOLE) {
209 #if defined(AFS_AIX_ENV)
210         struct file *fd;
211
212         /* cf. console_printf() in oncplus/kernext/nfs/serv/shared.c */
213         if (fp_open
214             ("/dev/console", O_WRONLY | O_NOCTTY | O_NDELAY, 0666, 0, FP_SYS,
215              &fd) == 0) {
216             char buf[1024];
217             ssize_t len;
218             ssize_t count;
219
220             sprintf(buf, a, b, c, d, e, f, g, h, i, j);
221             len = strlen(buf);
222             fp_write(fd, buf, len, 0, UIO_SYSSPACE, &count);
223             fp_close(fd);
224         }
225 #else
226         printf(a, b, c, d, e, f, g, h, i, j);
227 #endif
228     }
229 }
230
231 #if 0
232 void
233 afs_warnuser(char *a, long b, long c, long d, long e, long f, long g, long h,
234              long i, long j)
235 #else
236 void
237 afs_warnuser(a, b, c, d, e, f, g, h, i, j)
238      char *a;
239      long b, c, d, e, f, g, h, i, j;
240 #endif
241 {
242     AFS_STATCNT(afs_warnuser);
243     if (afs_showflags & GAGUSER) {
244 #ifdef AFS_GLOBAL_SUNLOCK
245         int haveGlock = ISAFS_GLOCK();
246         if (haveGlock)
247             AFS_GUNLOCK();
248 #endif /* AFS_GLOBAL_SUNLOCK */
249
250         uprintf(a, b, c, d, e, f, g, h, i, j);
251
252 #ifdef AFS_GLOBAL_SUNLOCK
253         if (haveGlock)
254             AFS_GLOCK();
255 #endif /* AFS_GLOBAL_SUNLOCK */
256     }
257 }
258
259
260 /* run everywhere, checking locks */
261 void
262 afs_CheckLocks(void)
263 {
264     register int i;
265
266     afs_warn("Looking for locked data structures.\n");
267     afs_warn("conn %lx, volume %lx, user %lx, cell %lx, server %lx\n", &afs_xconn,
268              &afs_xvolume, &afs_xuser, &afs_xcell, &afs_xserver);
269     {
270         register struct vcache *tvc;
271         AFS_STATCNT(afs_CheckLocks);
272
273         for (i = 0; i < VCSIZE; i++) {
274             for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
275                 if (tvc->states & CVInit) continue;
276 #ifdef  AFS_OSF_ENV
277                 if (VREFCOUNT(tvc) > 1)
278 #else /* AFS_OSF_ENV */
279 #ifdef AFS_DARWIN80_ENV
280                 if (vnode_isinuse(AFSTOV(tvc), 0))
281 #else
282                 if (VREFCOUNT(tvc))
283 #endif
284 #endif
285                     afs_warn("Stat cache entry at %x is held\n", tvc);
286                 if (CheckLock(&tvc->lock))
287                     afs_warn("Stat entry at %x is locked\n", tvc);
288             }
289         }
290     }
291     {
292         register struct dcache *tdc;
293         for (i = 0; i < afs_cacheFiles; i++) {
294             tdc = afs_indexTable[i];
295             if (tdc) {
296                 if (tdc->refCount)
297                     afs_warn("Disk entry %d at %x is held\n", i, tdc);
298             }
299             if (afs_indexFlags[i] & IFDataMod)
300                 afs_warn("Disk entry %d at %x has IFDataMod flag set.\n", i,
301                          tdc);
302         }
303     }
304     {
305         struct srvAddr *sa;
306         struct server *ts;
307         struct conn *tc;
308         for (i = 0; i < NSERVERS; i++) {
309             for (ts = afs_servers[i]; ts; ts = ts->next) {
310                 if (ts->flags & SRVR_ISDOWN)
311                     printf("Server entry %lx is marked down\n", (unsigned long)ts);
312                 for (sa = ts->addr; sa; sa = sa->next_sa) {
313                     for (tc = sa->conns; tc; tc = tc->next) {
314                         if (tc->refCount)
315                             afs_warn("conn at %x (server %x) is held\n", tc,
316                                      sa->sa_ip);
317                     }
318                 }
319             }
320         }
321     }
322     {
323         struct volume *tv;
324         for (i = 0; i < NVOLS; i++) {
325             for (tv = afs_volumes[i]; tv; tv = tv->next) {
326                 if (CheckLock(&tv->lock))
327                     afs_warn("volume at %x is locked\n", tv);
328                 if (tv->refCount)
329                     afs_warn("volume at %x is held\n", tv);
330             }
331         }
332     }
333     {
334         struct unixuser *tu;
335
336         for (i = 0; i < NUSERS; i++) {
337             for (tu = afs_users[i]; tu; tu = tu->next) {
338                 if (tu->refCount)
339                     printf("user at %lx is held\n", (unsigned long)tu);
340             }
341         }
342     }
343     afs_warn("Done.\n");
344 }
345
346
347 int
348 afs_noop(void)
349 {
350     AFS_STATCNT(afs_noop);
351 #ifdef  AFS_OSF30_ENV
352     return (EOPNOTSUPP);
353 #else
354     return EINVAL;
355 #endif
356 }
357
358 int
359 afs_badop(void)
360 {
361     AFS_STATCNT(afs_badop);
362     osi_Panic("afs bad vnode op");
363     return 0;
364 }
365
366 /*
367  * afs_data_pointer_to_int32() - returns least significant afs_int32 of the
368  * given data pointer, without triggering "cast truncates pointer"
369  * warnings.  We use this where we explicitly don't care whether a
370  * pointer is truncated -- it loses information where a pointer is
371  * larger than an afs_int32.
372  */
373
374 afs_int32
375 afs_data_pointer_to_int32(const void *p)
376 {
377     union {
378         afs_int32 i32[sizeof(void *) / sizeof(afs_int32)];
379         const void *p;
380     } ip;
381
382     int i32_sub;                /* subscript of least significant afs_int32 in ip.i32[] */
383
384     /* set i32_sub */
385
386     {
387         /* used to determine the byte order of the system */
388
389         union {
390             char c[sizeof(int) / sizeof(char)];
391             int i;
392         } ci;
393
394         ci.i = 1;
395         if (ci.c[0] == 1) {
396             /* little-endian system */
397             i32_sub = 0;
398         } else {
399             /* big-endian system */
400             i32_sub = (sizeof ip.i32 / sizeof ip.i32[0]) - 1;
401         }
402     }
403
404     ip.p = p;
405     return ip.i32[i32_sub];
406 }
407
408 #ifdef AFS_LINUX20_ENV
409
410 struct afs_md5 {
411     unsigned int sz[2];
412     afs_int32 counter[4];
413     unsigned char save[64];
414 };
415
416 static void AFS_MD5_Init (struct afs_md5 *m);
417 static void AFS_MD5_Update (struct afs_md5 *m, const void *p, size_t len);
418 static void AFS_MD5_Final (void *res, struct afs_md5 *m); /* u_int32 res[4] */
419
420 #define A m->counter[0]
421 #define B m->counter[1]
422 #define C m->counter[2]
423 #define D m->counter[3]
424 #define X data
425
426 static void
427 AFS_MD5_Init (struct afs_md5 *m)
428 {
429     m->sz[0] = 0;
430     m->sz[1] = 0;
431     D = 0x10325476;
432     C = 0x98badcfe;
433     B = 0xefcdab89;
434     A = 0x67452301;
435 }
436
437 #define F(x,y,z) ((x & y) | (~x & z))
438 #define G(x,y,z) ((x & z) | (y & ~z))
439 #define H(x,y,z) (x ^ y ^ z)
440 #define I(x,y,z) (y ^ (x | ~z))
441
442 static inline afs_uint32
443 cshift (afs_uint32 x, unsigned int n)
444 {
445     return ((x << n) | (x >> (32 - n)));
446 }
447
448 #define DOIT(a,b,c,d,k,s,i,OP) \
449 a = b + cshift(a + OP(b,c,d) + X[k] + (i), s)
450
451 #define DO1(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,F)
452 #define DO2(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,G)
453 #define DO3(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,H)
454 #define DO4(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,I)
455
456 static inline void
457 calc (struct afs_md5 *m, afs_uint32 *data)
458 {
459     afs_uint32 AA, BB, CC, DD;
460     
461     AA = A;
462     BB = B;
463     CC = C;
464     DD = D;
465     
466     /* Round 1 */
467     
468     DO1(A,B,C,D,0,7,0xd76aa478);
469     DO1(D,A,B,C,1,12,0xe8c7b756);
470     DO1(C,D,A,B,2,17,0x242070db);
471     DO1(B,C,D,A,3,22,0xc1bdceee);
472     
473     DO1(A,B,C,D,4,7,0xf57c0faf);
474     DO1(D,A,B,C,5,12,0x4787c62a);
475     DO1(C,D,A,B,6,17,0xa8304613);
476     DO1(B,C,D,A,7,22,0xfd469501);
477     
478     DO1(A,B,C,D,8,7,0x698098d8);
479     DO1(D,A,B,C,9,12,0x8b44f7af);
480     DO1(C,D,A,B,10,17,0xffff5bb1);
481     DO1(B,C,D,A,11,22,0x895cd7be);
482     
483     DO1(A,B,C,D,12,7,0x6b901122);
484     DO1(D,A,B,C,13,12,0xfd987193);
485     DO1(C,D,A,B,14,17,0xa679438e);
486     DO1(B,C,D,A,15,22,0x49b40821);
487     
488     /* Round 2 */
489     
490     DO2(A,B,C,D,1,5,0xf61e2562);
491     DO2(D,A,B,C,6,9,0xc040b340);
492     DO2(C,D,A,B,11,14,0x265e5a51);
493     DO2(B,C,D,A,0,20,0xe9b6c7aa);
494     
495     DO2(A,B,C,D,5,5,0xd62f105d);
496     DO2(D,A,B,C,10,9,0x2441453);
497     DO2(C,D,A,B,15,14,0xd8a1e681);
498     DO2(B,C,D,A,4,20,0xe7d3fbc8);
499     
500     DO2(A,B,C,D,9,5,0x21e1cde6);
501     DO2(D,A,B,C,14,9,0xc33707d6);
502     DO2(C,D,A,B,3,14,0xf4d50d87);
503     DO2(B,C,D,A,8,20,0x455a14ed);
504     
505     DO2(A,B,C,D,13,5,0xa9e3e905);
506     DO2(D,A,B,C,2,9,0xfcefa3f8);
507     DO2(C,D,A,B,7,14,0x676f02d9);
508     DO2(B,C,D,A,12,20,0x8d2a4c8a);
509     
510     /* Round 3 */
511     
512     DO3(A,B,C,D,5,4,0xfffa3942);
513     DO3(D,A,B,C,8,11,0x8771f681);
514     DO3(C,D,A,B,11,16,0x6d9d6122);
515     DO3(B,C,D,A,14,23,0xfde5380c);
516     
517     DO3(A,B,C,D,1,4,0xa4beea44);
518     DO3(D,A,B,C,4,11,0x4bdecfa9);
519     DO3(C,D,A,B,7,16,0xf6bb4b60);
520     DO3(B,C,D,A,10,23,0xbebfbc70);
521     
522     DO3(A,B,C,D,13,4,0x289b7ec6);
523     DO3(D,A,B,C,0,11,0xeaa127fa);
524     DO3(C,D,A,B,3,16,0xd4ef3085);
525     DO3(B,C,D,A,6,23,0x4881d05);
526     
527     DO3(A,B,C,D,9,4,0xd9d4d039);
528     DO3(D,A,B,C,12,11,0xe6db99e5);
529     DO3(C,D,A,B,15,16,0x1fa27cf8);
530     DO3(B,C,D,A,2,23,0xc4ac5665);
531     
532     /* Round 4 */
533     
534     DO4(A,B,C,D,0,6,0xf4292244);
535     DO4(D,A,B,C,7,10,0x432aff97);
536     DO4(C,D,A,B,14,15,0xab9423a7);
537     DO4(B,C,D,A,5,21,0xfc93a039);
538     
539     DO4(A,B,C,D,12,6,0x655b59c3);
540     DO4(D,A,B,C,3,10,0x8f0ccc92);
541     DO4(C,D,A,B,10,15,0xffeff47d);
542     DO4(B,C,D,A,1,21,0x85845dd1);
543     
544     DO4(A,B,C,D,8,6,0x6fa87e4f);
545     DO4(D,A,B,C,15,10,0xfe2ce6e0);
546     DO4(C,D,A,B,6,15,0xa3014314);
547     DO4(B,C,D,A,13,21,0x4e0811a1);
548     
549     DO4(A,B,C,D,4,6,0xf7537e82);
550     DO4(D,A,B,C,11,10,0xbd3af235);
551     DO4(C,D,A,B,2,15,0x2ad7d2bb);
552     DO4(B,C,D,A,9,21,0xeb86d391);
553     
554     A += AA;
555     B += BB;
556     C += CC;
557     D += DD;
558 }
559
560 /*
561  * From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu>
562  */
563
564 #if defined(AFSBIG_ENDIAN)
565 static inline afs_uint32
566 swap_u_int32_t (afs_uint32 t)
567 {
568     afs_uint32 temp1, temp2;
569     
570     temp1   = cshift(t, 16);
571     temp2   = temp1 >> 8;
572     temp1  &= 0x00ff00ff;
573     temp2  &= 0x00ff00ff;
574     temp1 <<= 8;
575     return temp1 | temp2;
576 }
577 #endif
578
579 struct x32{
580     unsigned int a:32;
581     unsigned int b:32;
582 };
583
584 static void
585 AFS_MD5_Update (struct afs_md5 *m, const void *v, size_t len)
586 {
587     const unsigned char *p = v;
588     size_t old_sz = m->sz[0];
589     size_t offset;
590     
591     m->sz[0] += len * 8;
592     if (m->sz[0] < old_sz)
593         ++m->sz[1];
594     offset = (old_sz / 8)  % 64;
595     while(len > 0){
596         size_t l = MIN(len, 64 - offset);
597         memcpy(m->save + offset, p, l);
598         offset += l;
599         p += l;
600         len -= l;
601         if(offset == 64){
602 #if defined(AFSBIG_ENDIAN)
603             int i;
604             afs_uint32 current[16];
605             struct x32 *us = (struct x32*)m->save;
606             for(i = 0; i < 8; i++){
607                 current[2*i+0] = swap_u_int32_t(us[i].a);
608                 current[2*i+1] = swap_u_int32_t(us[i].b);
609             }
610             calc(m, current);
611 #else
612             calc(m, (afs_uint32*)m->save);
613 #endif
614             offset = 0;
615         }
616     }
617 }
618
619 static void
620 AFS_MD5_Final (void *res, struct afs_md5 *m)
621 {
622     unsigned char zeros[72];
623     unsigned offset = (m->sz[0] / 8) % 64;
624     unsigned int dstart = (120 - offset - 1) % 64 + 1;
625     
626     *zeros = 0x80;
627     memset (zeros + 1, 0, sizeof(zeros) - 1);
628     zeros[dstart+0] = (m->sz[0] >> 0) & 0xff;
629     zeros[dstart+1] = (m->sz[0] >> 8) & 0xff;
630     zeros[dstart+2] = (m->sz[0] >> 16) & 0xff;
631     zeros[dstart+3] = (m->sz[0] >> 24) & 0xff;
632     zeros[dstart+4] = (m->sz[1] >> 0) & 0xff;
633     zeros[dstart+5] = (m->sz[1] >> 8) & 0xff;
634     zeros[dstart+6] = (m->sz[1] >> 16) & 0xff;
635     zeros[dstart+7] = (m->sz[1] >> 24) & 0xff;
636     AFS_MD5_Update (m, zeros, dstart + 8);
637     {
638         int i;
639         unsigned char *r = (unsigned char *)res;
640         
641         for (i = 0; i < 4; ++i) {
642             r[4*i]   = m->counter[i] & 0xFF;
643             r[4*i+1] = (m->counter[i] >> 8) & 0xFF;
644             r[4*i+2] = (m->counter[i] >> 16) & 0xFF;
645             r[4*i+3] = (m->counter[i] >> 24) & 0xFF;
646         }
647     }
648 }
649
650 afs_int32 afs_calc_inum (afs_int32 volume, afs_int32 vnode)
651
652     afs_int32 ino;
653     char digest[16];
654     struct afs_md5 ct;
655     
656     if (afs_new_inum) {
657         AFS_MD5_Init(&ct);
658         AFS_MD5_Update(&ct, &volume, 4);
659         AFS_MD5_Update(&ct, &vnode, 4);
660         AFS_MD5_Final(digest, &ct);
661         memcpy(&ino, digest, sizeof(ino_t));
662     } else {
663         ino = (volume << 16) + vnode;
664         ino &= 0x7fffffff;      /* Assumes 32 bit ino_t ..... */
665     }
666     return ino;
667 }
668
669 #else
670
671 afs_int32 afs_calc_inum (afs_int32 volume, afs_int32 vnode)
672 {
673     return (volume << 16) + vnode;
674 }
675
676 #endif