diff options
Diffstat (limited to 'linden/indra/llcommon/lluuid.cpp')
-rw-r--r-- | linden/indra/llcommon/lluuid.cpp | 923 |
1 files changed, 923 insertions, 0 deletions
diff --git a/linden/indra/llcommon/lluuid.cpp b/linden/indra/llcommon/lluuid.cpp new file mode 100644 index 0000000..7e4eb50 --- /dev/null +++ b/linden/indra/llcommon/lluuid.cpp | |||
@@ -0,0 +1,923 @@ | |||
1 | /** | ||
2 | * @file lluuid.cpp | ||
3 | * | ||
4 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
5 | * | ||
6 | * Copyright (c) 2000-2008, Linden Research, Inc. | ||
7 | * | ||
8 | * Second Life Viewer Source Code | ||
9 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
10 | * to you under the terms of the GNU General Public License, version 2.0 | ||
11 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
12 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
13 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
14 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
15 | * | ||
16 | * There are special exceptions to the terms and conditions of the GPL as | ||
17 | * it is applied to this Source Code. View the full text of the exception | ||
18 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
19 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
20 | * | ||
21 | * By copying, modifying or distributing this software, you acknowledge | ||
22 | * that you have read and understood your obligations described above, | ||
23 | * and agree to abide by those obligations. | ||
24 | * | ||
25 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
26 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
27 | * COMPLETENESS OR PERFORMANCE. | ||
28 | * $/LicenseInfo$ | ||
29 | */ | ||
30 | |||
31 | #include "linden_common.h" | ||
32 | |||
33 | // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes. | ||
34 | #if LL_WINDOWS | ||
35 | # undef WIN32_LEAN_AND_MEAN | ||
36 | # include <winsock2.h> | ||
37 | # include <windows.h> | ||
38 | #endif | ||
39 | |||
40 | #include "lldefs.h" | ||
41 | #include "llerror.h" | ||
42 | |||
43 | #include "lluuid.h" | ||
44 | #include "llerror.h" | ||
45 | #include "llrand.h" | ||
46 | #include "llmd5.h" | ||
47 | #include "llstring.h" | ||
48 | #include "lltimer.h" | ||
49 | |||
50 | const LLUUID LLUUID::null; | ||
51 | const LLTransactionID LLTransactionID::tnull; | ||
52 | |||
53 | /* | ||
54 | |||
55 | NOT DONE YET!!! | ||
56 | |||
57 | static char BASE85_TABLE[] = { | ||
58 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | ||
59 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', | ||
60 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', | ||
61 | 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', | ||
62 | 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', | ||
63 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', | ||
64 | 'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*', | ||
65 | '+', '-', ';', '[', '=', '>', '?', '@', '^', '_', | ||
66 | '`', '{', '|', '}', '~', '\0' | ||
67 | }; | ||
68 | |||
69 | |||
70 | void encode( char * fiveChars, unsigned int word ) throw( ) | ||
71 | { | ||
72 | for( int ix = 0; ix < 5; ++ix ) { | ||
73 | fiveChars[4-ix] = encodeTable[ word % 85]; | ||
74 | word /= 85; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | To decode: | ||
79 | unsigned int decode( char const * fiveChars ) throw( bad_input_data ) | ||
80 | { | ||
81 | unsigned int ret = 0; | ||
82 | for( int ix = 0; ix < 5; ++ix ) { | ||
83 | char * s = strchr( encodeTable, fiveChars[ ix ] ); | ||
84 | if( s == 0 ) throw bad_input_data(); | ||
85 | ret = ret * 85 + (s-encodeTable); | ||
86 | } | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | void LLUUID::toBase85(char* out) | ||
91 | { | ||
92 | U32* me = (U32*)&(mData[0]); | ||
93 | for(S32 i = 0; i < 4; ++i) | ||
94 | { | ||
95 | char* o = &out[i*i]; | ||
96 | for(S32 j = 0; j < 5; ++j) | ||
97 | { | ||
98 | o[4-j] = BASE85_TABLE[ me[i] % 85]; | ||
99 | word /= 85; | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | unsigned int decode( char const * fiveChars ) throw( bad_input_data ) | ||
105 | { | ||
106 | unsigned int ret = 0; | ||
107 | for( S32 ix = 0; ix < 5; ++ix ) | ||
108 | { | ||
109 | char * s = strchr( encodeTable, fiveChars[ ix ] ); | ||
110 | ret = ret * 85 + (s-encodeTable); | ||
111 | } | ||
112 | return ret; | ||
113 | } | ||
114 | */ | ||
115 | |||
116 | #define LL_USE_JANKY_RANDOM_NUMBER_GENERATOR 0 | ||
117 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR | ||
118 | /** | ||
119 | * @brief a global for | ||
120 | */ | ||
121 | static U64 sJankyRandomSeed(LLUUID::getRandomSeed()); | ||
122 | |||
123 | /** | ||
124 | * @brief generate a random U32. | ||
125 | */ | ||
126 | U32 janky_fast_random_bytes() | ||
127 | { | ||
128 | sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223); | ||
129 | return (U32)sJankyRandomSeed; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * @brief generate a random U32 from [0, val) | ||
134 | */ | ||
135 | U32 janky_fast_random_byes_range(U32 val) | ||
136 | { | ||
137 | sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223); | ||
138 | return (U32)(sJankyRandomSeed) % val; | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * @brief generate a random U32 from [0, val) | ||
143 | */ | ||
144 | U32 janky_fast_random_seeded_bytes(U32 seed, U32 val) | ||
145 | { | ||
146 | seed = U64L(1664525) * (U64)(seed) + U64L(1013904223); | ||
147 | return (U32)(seed) % val; | ||
148 | } | ||
149 | #endif | ||
150 | |||
151 | // Common to all UUID implementations | ||
152 | void LLUUID::toString(std::string& out) const | ||
153 | { | ||
154 | out = llformat( | ||
155 | "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", | ||
156 | (U8)(mData[0]), | ||
157 | (U8)(mData[1]), | ||
158 | (U8)(mData[2]), | ||
159 | (U8)(mData[3]), | ||
160 | (U8)(mData[4]), | ||
161 | (U8)(mData[5]), | ||
162 | (U8)(mData[6]), | ||
163 | (U8)(mData[7]), | ||
164 | (U8)(mData[8]), | ||
165 | (U8)(mData[9]), | ||
166 | (U8)(mData[10]), | ||
167 | (U8)(mData[11]), | ||
168 | (U8)(mData[12]), | ||
169 | (U8)(mData[13]), | ||
170 | (U8)(mData[14]), | ||
171 | (U8)(mData[15])); | ||
172 | } | ||
173 | |||
174 | // *TODO: deprecate | ||
175 | void LLUUID::toString(char *out) const | ||
176 | { | ||
177 | std::string buffer; | ||
178 | toString(buffer); | ||
179 | strcpy(out,buffer.c_str()); /* Flawfinder: ignore */ | ||
180 | } | ||
181 | |||
182 | void LLUUID::toCompressedString(std::string& out) const | ||
183 | { | ||
184 | char bytes[UUID_BYTES+1]; | ||
185 | memcpy(bytes, mData, UUID_BYTES); /* Flawfinder: ignore */ | ||
186 | bytes[UUID_BYTES] = '\0'; | ||
187 | out.assign(bytes, UUID_BYTES); | ||
188 | } | ||
189 | |||
190 | // *TODO: deprecate | ||
191 | void LLUUID::toCompressedString(char *out) const | ||
192 | { | ||
193 | memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */ | ||
194 | out[UUID_BYTES] = '\0'; | ||
195 | } | ||
196 | |||
197 | std::string LLUUID::getString() const | ||
198 | { | ||
199 | return asString(); | ||
200 | } | ||
201 | |||
202 | std::string LLUUID::asString() const | ||
203 | { | ||
204 | std::string str; | ||
205 | toString(str); | ||
206 | return str; | ||
207 | } | ||
208 | |||
209 | BOOL LLUUID::set(const char* in_string, BOOL emit) | ||
210 | { | ||
211 | return set(ll_safe_string(in_string)); | ||
212 | } | ||
213 | |||
214 | BOOL LLUUID::set(const std::string& in_string, BOOL emit) | ||
215 | { | ||
216 | BOOL broken_format = FALSE; | ||
217 | |||
218 | // empty strings should make NULL uuid | ||
219 | if (in_string.empty()) | ||
220 | { | ||
221 | setNull(); | ||
222 | return TRUE; | ||
223 | } | ||
224 | |||
225 | if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */ | ||
226 | { | ||
227 | // I'm a moron. First implementation didn't have the right UUID format. | ||
228 | // Shouldn't see any of these any more | ||
229 | if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */ | ||
230 | { | ||
231 | if(emit) | ||
232 | { | ||
233 | llinfos << "Warning! Using broken UUID string format" << llendl; | ||
234 | } | ||
235 | broken_format = TRUE; | ||
236 | } | ||
237 | else | ||
238 | { | ||
239 | // Bad UUID string. Spam as INFO, as most cases we don't care. | ||
240 | if(emit) | ||
241 | { | ||
242 | llinfos << "Bad UUID string: " << in_string << llendl; | ||
243 | } | ||
244 | setNull(); | ||
245 | return FALSE; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | U8 cur_pos = 0; | ||
250 | S32 i; | ||
251 | for (i = 0; i < UUID_BYTES; i++) | ||
252 | { | ||
253 | if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) | ||
254 | { | ||
255 | cur_pos++; | ||
256 | if (broken_format && (i==10)) | ||
257 | { | ||
258 | // Missing - in the broken format | ||
259 | cur_pos--; | ||
260 | } | ||
261 | } | ||
262 | |||
263 | mData[i] = 0; | ||
264 | |||
265 | if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) | ||
266 | { | ||
267 | mData[i] += (U8)(in_string[cur_pos] - '0'); | ||
268 | } | ||
269 | else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f')) | ||
270 | { | ||
271 | mData[i] += (U8)(10 + in_string[cur_pos] - 'a'); | ||
272 | } | ||
273 | else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F')) | ||
274 | { | ||
275 | mData[i] += (U8)(10 + in_string[cur_pos] - 'A'); | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | if(emit) | ||
280 | { | ||
281 | llwarns << "Invalid UUID string character" << llendl; | ||
282 | } | ||
283 | setNull(); | ||
284 | return FALSE; | ||
285 | } | ||
286 | |||
287 | mData[i] = mData[i] << 4; | ||
288 | cur_pos++; | ||
289 | |||
290 | if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) | ||
291 | { | ||
292 | mData[i] += (U8)(in_string[cur_pos] - '0'); | ||
293 | } | ||
294 | else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f')) | ||
295 | { | ||
296 | mData[i] += (U8)(10 + in_string[cur_pos] - 'a'); | ||
297 | } | ||
298 | else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F')) | ||
299 | { | ||
300 | mData[i] += (U8)(10 + in_string[cur_pos] - 'A'); | ||
301 | } | ||
302 | else | ||
303 | { | ||
304 | if(emit) | ||
305 | { | ||
306 | llwarns << "Invalid UUID string character" << llendl; | ||
307 | } | ||
308 | setNull(); | ||
309 | return FALSE; | ||
310 | } | ||
311 | cur_pos++; | ||
312 | } | ||
313 | |||
314 | return TRUE; | ||
315 | } | ||
316 | |||
317 | BOOL LLUUID::validate(const std::string& in_string) | ||
318 | { | ||
319 | BOOL broken_format = FALSE; | ||
320 | if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */ | ||
321 | { | ||
322 | // I'm a moron. First implementation didn't have the right UUID format. | ||
323 | if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */ | ||
324 | { | ||
325 | broken_format = TRUE; | ||
326 | } | ||
327 | else | ||
328 | { | ||
329 | return FALSE; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | U8 cur_pos = 0; | ||
334 | for (U32 i = 0; i < 16; i++) | ||
335 | { | ||
336 | if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) | ||
337 | { | ||
338 | cur_pos++; | ||
339 | if (broken_format && (i==10)) | ||
340 | { | ||
341 | // Missing - in the broken format | ||
342 | cur_pos--; | ||
343 | } | ||
344 | } | ||
345 | |||
346 | if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) | ||
347 | { | ||
348 | } | ||
349 | else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f')) | ||
350 | { | ||
351 | } | ||
352 | else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F')) | ||
353 | { | ||
354 | } | ||
355 | else | ||
356 | { | ||
357 | return FALSE; | ||
358 | } | ||
359 | |||
360 | cur_pos++; | ||
361 | |||
362 | if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9')) | ||
363 | { | ||
364 | } | ||
365 | else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f')) | ||
366 | { | ||
367 | } | ||
368 | else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F')) | ||
369 | { | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | return FALSE; | ||
374 | } | ||
375 | cur_pos++; | ||
376 | } | ||
377 | return TRUE; | ||
378 | } | ||
379 | |||
380 | const LLUUID& LLUUID::operator^=(const LLUUID& rhs) | ||
381 | { | ||
382 | U32* me = (U32*)&(mData[0]); | ||
383 | const U32* other = (U32*)&(rhs.mData[0]); | ||
384 | for(S32 i = 0; i < 4; ++i) | ||
385 | { | ||
386 | me[i] = me[i] ^ other[i]; | ||
387 | } | ||
388 | return *this; | ||
389 | } | ||
390 | |||
391 | LLUUID LLUUID::operator^(const LLUUID& rhs) const | ||
392 | { | ||
393 | LLUUID id(*this); | ||
394 | id ^= rhs; | ||
395 | return id; | ||
396 | } | ||
397 | |||
398 | void LLUUID::combine(const LLUUID& other, LLUUID& result) const | ||
399 | { | ||
400 | LLMD5 md5_uuid; | ||
401 | md5_uuid.update((unsigned char*)mData, 16); | ||
402 | md5_uuid.update((unsigned char*)other.mData, 16); | ||
403 | md5_uuid.finalize(); | ||
404 | md5_uuid.raw_digest(result.mData); | ||
405 | } | ||
406 | |||
407 | LLUUID LLUUID::combine(const LLUUID &other) const | ||
408 | { | ||
409 | LLUUID combination; | ||
410 | combine(other, combination); | ||
411 | return combination; | ||
412 | } | ||
413 | |||
414 | std::ostream& operator<<(std::ostream& s, const LLUUID &uuid) | ||
415 | { | ||
416 | std::string uuid_str; | ||
417 | uuid.toString(uuid_str); | ||
418 | s << uuid_str; | ||
419 | return s; | ||
420 | } | ||
421 | |||
422 | std::istream& operator>>(std::istream &s, LLUUID &uuid) | ||
423 | { | ||
424 | U32 i; | ||
425 | char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */ | ||
426 | for (i = 0; i < UUID_STR_LENGTH-1; i++) | ||
427 | { | ||
428 | s >> uuid_str[i]; | ||
429 | } | ||
430 | uuid_str[i] = '\0'; | ||
431 | uuid.set(std::string(uuid_str)); | ||
432 | return s; | ||
433 | } | ||
434 | |||
435 | static void get_random_bytes(void *buf, int nbytes) | ||
436 | { | ||
437 | int i; | ||
438 | char *cp = (char *) buf; | ||
439 | |||
440 | // *NOTE: If we are not using the janky generator ll_rand() | ||
441 | // generates at least 3 good bytes of data since it is 0 to | ||
442 | // RAND_MAX. This could be made more efficient by copying all the | ||
443 | // bytes. | ||
444 | for (i=0; i < nbytes; i++) | ||
445 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR | ||
446 | *cp++ = janky_fast_random_bytes() & 0xFF; | ||
447 | #else | ||
448 | *cp++ = ll_rand() & 0xFF; | ||
449 | #endif | ||
450 | return; | ||
451 | } | ||
452 | |||
453 | #if LL_WINDOWS | ||
454 | typedef struct _ASTAT_ | ||
455 | { | ||
456 | ADAPTER_STATUS adapt; | ||
457 | NAME_BUFFER NameBuff [30]; | ||
458 | }ASTAT, * PASTAT; | ||
459 | |||
460 | // static | ||
461 | S32 LLUUID::getNodeID(unsigned char * node_id) | ||
462 | { | ||
463 | ASTAT Adapter; | ||
464 | NCB Ncb; | ||
465 | UCHAR uRetCode; | ||
466 | LANA_ENUM lenum; | ||
467 | int i; | ||
468 | int retval = 0; | ||
469 | |||
470 | memset( &Ncb, 0, sizeof(Ncb) ); | ||
471 | Ncb.ncb_command = NCBENUM; | ||
472 | Ncb.ncb_buffer = (UCHAR *)&lenum; | ||
473 | Ncb.ncb_length = sizeof(lenum); | ||
474 | uRetCode = Netbios( &Ncb ); | ||
475 | // printf( "The NCBENUM return code is: 0x%x \n", uRetCode ); | ||
476 | |||
477 | for(i=0; i < lenum.length ;i++) | ||
478 | { | ||
479 | memset( &Ncb, 0, sizeof(Ncb) ); | ||
480 | Ncb.ncb_command = NCBRESET; | ||
481 | Ncb.ncb_lana_num = lenum.lana[i]; | ||
482 | |||
483 | uRetCode = Netbios( &Ncb ); | ||
484 | // printf( "The NCBRESET on LANA %d return code is: 0x%x \n", | ||
485 | // lenum.lana[i], uRetCode ); | ||
486 | |||
487 | memset( &Ncb, 0, sizeof (Ncb) ); | ||
488 | Ncb.ncb_command = NCBASTAT; | ||
489 | Ncb.ncb_lana_num = lenum.lana[i]; | ||
490 | |||
491 | strcpy( (char *)Ncb.ncb_callname, "* " ); /* Flawfinder: ignore */ | ||
492 | Ncb.ncb_buffer = (unsigned char *)&Adapter; | ||
493 | Ncb.ncb_length = sizeof(Adapter); | ||
494 | |||
495 | uRetCode = Netbios( &Ncb ); | ||
496 | // printf( "The NCBASTAT on LANA %d return code is: 0x%x \n", | ||
497 | // lenum.lana[i], uRetCode ); | ||
498 | if ( uRetCode == 0 ) | ||
499 | { | ||
500 | // printf( "The Ethernet Number on LANA %d is: %02x%02x%02x%02x%02x%02x\n", | ||
501 | // lenum.lana[i], | ||
502 | // Adapter.adapt.adapter_address[0], | ||
503 | // Adapter.adapt.adapter_address[1], | ||
504 | // Adapter.adapt.adapter_address[2], | ||
505 | // Adapter.adapt.adapter_address[3], | ||
506 | // Adapter.adapt.adapter_address[4], | ||
507 | // Adapter.adapt.adapter_address[5] ); | ||
508 | memcpy(node_id,Adapter.adapt.adapter_address,6); /* Flawfinder: ignore */ | ||
509 | retval = 1; | ||
510 | |||
511 | } | ||
512 | } | ||
513 | return retval; | ||
514 | } | ||
515 | |||
516 | #elif LL_DARWIN | ||
517 | // Mac OS X version of the UUID generation code... | ||
518 | /* | ||
519 | * Get an ethernet hardware address, if we can find it... | ||
520 | */ | ||
521 | #include <unistd.h> | ||
522 | #include <sys/types.h> | ||
523 | #include <sys/time.h> | ||
524 | #include <sys/socket.h> | ||
525 | #include <sys/ioctl.h> | ||
526 | #include <net/if.h> | ||
527 | #include <net/if_types.h> | ||
528 | #include <net/if_dl.h> | ||
529 | #include <net/route.h> | ||
530 | #include <ifaddrs.h> | ||
531 | |||
532 | // static | ||
533 | S32 LLUUID::getNodeID(unsigned char *node_id) | ||
534 | { | ||
535 | int i; | ||
536 | unsigned char *a = NULL; | ||
537 | struct ifaddrs *ifap, *ifa; | ||
538 | int rv; | ||
539 | S32 result = 0; | ||
540 | |||
541 | if ((rv=getifaddrs(&ifap))==-1) | ||
542 | { | ||
543 | return -1; | ||
544 | } | ||
545 | if (ifap == NULL) | ||
546 | { | ||
547 | return -1; | ||
548 | } | ||
549 | |||
550 | for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) | ||
551 | { | ||
552 | // printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family); | ||
553 | for(i=0; i< ifa->ifa_addr->sa_len; i++) | ||
554 | { | ||
555 | // printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]); | ||
556 | } | ||
557 | // printf("\n"); | ||
558 | |||
559 | if(ifa->ifa_addr->sa_family == AF_LINK) | ||
560 | { | ||
561 | // This is a link-level address | ||
562 | struct sockaddr_dl *lla = (struct sockaddr_dl *)ifa->ifa_addr; | ||
563 | |||
564 | // printf("\tLink level address, type %02X\n", lla->sdl_type); | ||
565 | |||
566 | if(lla->sdl_type == IFT_ETHER) | ||
567 | { | ||
568 | // Use the first ethernet MAC in the list. | ||
569 | // For some reason, the macro LLADDR() defined in net/if_dl.h doesn't expand correctly. This is what it would do. | ||
570 | a = (unsigned char *)&((lla)->sdl_data); | ||
571 | a += (lla)->sdl_nlen; | ||
572 | |||
573 | if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) | ||
574 | { | ||
575 | continue; | ||
576 | } | ||
577 | |||
578 | if (node_id) | ||
579 | { | ||
580 | memcpy(node_id, a, 6); | ||
581 | result = 1; | ||
582 | } | ||
583 | |||
584 | // We found one. | ||
585 | break; | ||
586 | } | ||
587 | } | ||
588 | } | ||
589 | freeifaddrs(ifap); | ||
590 | |||
591 | return result; | ||
592 | } | ||
593 | |||
594 | #else | ||
595 | |||
596 | // Linux version of the UUID generation code... | ||
597 | /* | ||
598 | * Get the ethernet hardware address, if we can find it... | ||
599 | */ | ||
600 | #include <unistd.h> | ||
601 | #include <fcntl.h> | ||
602 | #include <errno.h> | ||
603 | #include <sys/types.h> | ||
604 | #include <sys/time.h> | ||
605 | #include <sys/stat.h> | ||
606 | #include <sys/file.h> | ||
607 | #include <sys/ioctl.h> | ||
608 | #include <sys/socket.h> | ||
609 | #include <net/if.h> | ||
610 | #define HAVE_NETINET_IN_H | ||
611 | #ifdef HAVE_NETINET_IN_H | ||
612 | #include <netinet/in.h> | ||
613 | #if LL_SOLARIS | ||
614 | #include <sys/sockio.h> | ||
615 | #elif !LL_DARWIN | ||
616 | #include <linux/sockios.h> | ||
617 | #endif | ||
618 | #endif | ||
619 | |||
620 | // static | ||
621 | S32 LLUUID::getNodeID(unsigned char *node_id) | ||
622 | { | ||
623 | int sd; | ||
624 | struct ifreq ifr, *ifrp; | ||
625 | struct ifconf ifc; | ||
626 | char buf[1024]; | ||
627 | int n, i; | ||
628 | unsigned char *a; | ||
629 | |||
630 | /* | ||
631 | * BSD 4.4 defines the size of an ifreq to be | ||
632 | * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len | ||
633 | * However, under earlier systems, sa_len isn't present, so the size is | ||
634 | * just sizeof(struct ifreq) | ||
635 | */ | ||
636 | #ifdef HAVE_SA_LEN | ||
637 | #ifndef max | ||
638 | #define max(a,b) ((a) > (b) ? (a) : (b)) | ||
639 | #endif | ||
640 | #define ifreq_size(i) max(sizeof(struct ifreq),\ | ||
641 | sizeof((i).ifr_name)+(i).ifr_addr.sa_len) | ||
642 | #else | ||
643 | #define ifreq_size(i) sizeof(struct ifreq) | ||
644 | #endif /* HAVE_SA_LEN*/ | ||
645 | |||
646 | sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); | ||
647 | if (sd < 0) { | ||
648 | return -1; | ||
649 | } | ||
650 | memset(buf, 0, sizeof(buf)); | ||
651 | ifc.ifc_len = sizeof(buf); | ||
652 | ifc.ifc_buf = buf; | ||
653 | if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { | ||
654 | close(sd); | ||
655 | return -1; | ||
656 | } | ||
657 | n = ifc.ifc_len; | ||
658 | for (i = 0; i < n; i+= ifreq_size(*ifr) ) { | ||
659 | ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); | ||
660 | strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* Flawfinder: ignore */ | ||
661 | #ifdef SIOCGIFHWADDR | ||
662 | if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) | ||
663 | continue; | ||
664 | a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; | ||
665 | #else | ||
666 | #ifdef SIOCGENADDR | ||
667 | if (ioctl(sd, SIOCGENADDR, &ifr) < 0) | ||
668 | continue; | ||
669 | a = (unsigned char *) ifr.ifr_enaddr; | ||
670 | #else | ||
671 | /* | ||
672 | * XXX we don't have a way of getting the hardware | ||
673 | * address | ||
674 | */ | ||
675 | close(sd); | ||
676 | return 0; | ||
677 | #endif /* SIOCGENADDR */ | ||
678 | #endif /* SIOCGIFHWADDR */ | ||
679 | if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) | ||
680 | continue; | ||
681 | if (node_id) { | ||
682 | memcpy(node_id, a, 6); /* Flawfinder: ignore */ | ||
683 | close(sd); | ||
684 | return 1; | ||
685 | } | ||
686 | } | ||
687 | close(sd); | ||
688 | return 0; | ||
689 | } | ||
690 | |||
691 | #endif | ||
692 | |||
693 | S32 LLUUID::cmpTime(uuid_time_t *t1, uuid_time_t *t2) | ||
694 | { | ||
695 | // Compare two time values. | ||
696 | |||
697 | if (t1->high < t2->high) return -1; | ||
698 | if (t1->high > t2->high) return 1; | ||
699 | if (t1->low < t2->low) return -1; | ||
700 | if (t1->low > t2->low) return 1; | ||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | void LLUUID::getSystemTime(uuid_time_t *timestamp) | ||
705 | { | ||
706 | // Get system time with 100ns precision. Time is since Oct 15, 1582. | ||
707 | #if LL_WINDOWS | ||
708 | ULARGE_INTEGER time; | ||
709 | GetSystemTimeAsFileTime((FILETIME *)&time); | ||
710 | // NT keeps time in FILETIME format which is 100ns ticks since | ||
711 | // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582. | ||
712 | // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec) | ||
713 | // + 18 years and 5 leap days. | ||
714 | time.QuadPart += | ||
715 | (unsigned __int64) (1000*1000*10) // seconds | ||
716 | * (unsigned __int64) (60 * 60 * 24) // days | ||
717 | * (unsigned __int64) (17+30+31+365*18+5); // # of days | ||
718 | |||
719 | timestamp->high = time.HighPart; | ||
720 | timestamp->low = time.LowPart; | ||
721 | #else | ||
722 | struct timeval tp; | ||
723 | gettimeofday(&tp, 0); | ||
724 | |||
725 | // Offset between UUID formatted times and Unix formatted times. | ||
726 | // UUID UTC base time is October 15, 1582. | ||
727 | // Unix base time is January 1, 1970. | ||
728 | U64 uuid_time = ((U64)tp.tv_sec * 10000000) + (tp.tv_usec * 10) + | ||
729 | U64L(0x01B21DD213814000); | ||
730 | timestamp->high = (U32) (uuid_time >> 32); | ||
731 | timestamp->low = (U32) (uuid_time & 0xFFFFFFFF); | ||
732 | #endif | ||
733 | } | ||
734 | |||
735 | void LLUUID::getCurrentTime(uuid_time_t *timestamp) | ||
736 | { | ||
737 | // Get current time as 60 bit 100ns ticks since whenever. | ||
738 | // Compensate for the fact that real clock resolution is less | ||
739 | // than 100ns. | ||
740 | |||
741 | const U32 uuids_per_tick = 1024; | ||
742 | |||
743 | static uuid_time_t time_last; | ||
744 | static U32 uuids_this_tick; | ||
745 | static BOOL init = FALSE; | ||
746 | |||
747 | if (!init) { | ||
748 | getSystemTime(&time_last); | ||
749 | uuids_this_tick = uuids_per_tick; | ||
750 | init = TRUE; | ||
751 | } | ||
752 | |||
753 | uuid_time_t time_now = {0,0}; | ||
754 | |||
755 | while (1) { | ||
756 | getSystemTime(&time_now); | ||
757 | |||
758 | // if clock reading changed since last UUID generated | ||
759 | if (cmpTime(&time_last, &time_now)) { | ||
760 | // reset count of uuid's generated with this clock reading | ||
761 | uuids_this_tick = 0; | ||
762 | break; | ||
763 | } | ||
764 | if (uuids_this_tick < uuids_per_tick) { | ||
765 | uuids_this_tick++; | ||
766 | break; | ||
767 | } | ||
768 | // going too fast for our clock; spin | ||
769 | } | ||
770 | |||
771 | time_last = time_now; | ||
772 | |||
773 | if (uuids_this_tick != 0) { | ||
774 | if (time_now.low & 0x80000000) { | ||
775 | time_now.low += uuids_this_tick; | ||
776 | if (!(time_now.low & 0x80000000)) | ||
777 | time_now.high++; | ||
778 | } else | ||
779 | time_now.low += uuids_this_tick; | ||
780 | } | ||
781 | |||
782 | timestamp->high = time_now.high; | ||
783 | timestamp->low = time_now.low; | ||
784 | } | ||
785 | |||
786 | void LLUUID::generate() | ||
787 | { | ||
788 | // Create a UUID. | ||
789 | uuid_time_t timestamp; | ||
790 | |||
791 | static unsigned char node_id[6]; /* Flawfinder: ignore */ | ||
792 | static int has_init = 0; | ||
793 | |||
794 | // Create a UUID. | ||
795 | static uuid_time_t time_last = {0,0}; | ||
796 | static U16 clock_seq = 0; | ||
797 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR | ||
798 | static U32 seed = 0L; // dummy seed. reset it below | ||
799 | #endif | ||
800 | if (!has_init) | ||
801 | { | ||
802 | if (getNodeID(node_id) <= 0) | ||
803 | { | ||
804 | get_random_bytes(node_id, 6); | ||
805 | /* | ||
806 | * Set multicast bit, to prevent conflicts | ||
807 | * with IEEE 802 addresses obtained from | ||
808 | * network cards | ||
809 | */ | ||
810 | node_id[0] |= 0x80; | ||
811 | } | ||
812 | |||
813 | getCurrentTime(&time_last); | ||
814 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR | ||
815 | seed = time_last.low; | ||
816 | #endif | ||
817 | |||
818 | #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR | ||
819 | clock_seq = (U16)janky_fast_random_seeded_bytes(seed, 65536); | ||
820 | #else | ||
821 | clock_seq = (U16)ll_rand(65536); | ||
822 | #endif | ||
823 | has_init = 1; | ||
824 | } | ||
825 | |||
826 | // get current time | ||
827 | getCurrentTime(×tamp); | ||
828 | |||
829 | // if clock went backward change clockseq | ||
830 | if (cmpTime(×tamp, &time_last) == -1) { | ||
831 | clock_seq = (clock_seq + 1) & 0x3FFF; | ||
832 | if (clock_seq == 0) clock_seq++; | ||
833 | } | ||
834 | |||
835 | memcpy(mData+10, node_id, 6); /* Flawfinder: ignore */ | ||
836 | U32 tmp; | ||
837 | tmp = timestamp.low; | ||
838 | mData[3] = (unsigned char) tmp; | ||
839 | tmp >>= 8; | ||
840 | mData[2] = (unsigned char) tmp; | ||
841 | tmp >>= 8; | ||
842 | mData[1] = (unsigned char) tmp; | ||
843 | tmp >>= 8; | ||
844 | mData[0] = (unsigned char) tmp; | ||
845 | |||
846 | tmp = (U16) timestamp.high; | ||
847 | mData[5] = (unsigned char) tmp; | ||
848 | tmp >>= 8; | ||
849 | mData[4] = (unsigned char) tmp; | ||
850 | |||
851 | tmp = (timestamp.high >> 16) | 0x1000; | ||
852 | mData[7] = (unsigned char) tmp; | ||
853 | tmp >>= 8; | ||
854 | mData[6] = (unsigned char) tmp; | ||
855 | |||
856 | tmp = clock_seq; | ||
857 | mData[9] = (unsigned char) tmp; | ||
858 | tmp >>= 8; | ||
859 | mData[8] = (unsigned char) tmp; | ||
860 | |||
861 | LLMD5 md5_uuid; | ||
862 | |||
863 | md5_uuid.update(mData,16); | ||
864 | md5_uuid.finalize(); | ||
865 | md5_uuid.raw_digest(mData); | ||
866 | |||
867 | time_last = timestamp; | ||
868 | } | ||
869 | |||
870 | void LLUUID::generate(const std::string& hash_string) | ||
871 | { | ||
872 | LLMD5 md5_uuid((U8*)hash_string.c_str()); | ||
873 | md5_uuid.raw_digest(mData); | ||
874 | } | ||
875 | |||
876 | U32 LLUUID::getRandomSeed() | ||
877 | { | ||
878 | static unsigned char seed[16]; /* Flawfinder: ignore */ | ||
879 | |||
880 | getNodeID(&seed[0]); | ||
881 | seed[6]='\0'; | ||
882 | seed[7]='\0'; | ||
883 | getSystemTime((uuid_time_t *)(&seed[8])); | ||
884 | |||
885 | LLMD5 md5_seed; | ||
886 | |||
887 | md5_seed.update(seed,16); | ||
888 | md5_seed.finalize(); | ||
889 | md5_seed.raw_digest(seed); | ||
890 | |||
891 | return(*(U32 *)seed); | ||
892 | } | ||
893 | |||
894 | BOOL LLUUID::parseUUID(const std::string& buf, LLUUID* value) | ||
895 | { | ||
896 | if( buf.empty() || value == NULL) | ||
897 | { | ||
898 | return FALSE; | ||
899 | } | ||
900 | |||
901 | std::string temp( buf ); | ||
902 | LLStringUtil::trim(temp); | ||
903 | if( LLUUID::validate( temp ) ) | ||
904 | { | ||
905 | value->set( temp ); | ||
906 | return TRUE; | ||
907 | } | ||
908 | return FALSE; | ||
909 | } | ||
910 | |||
911 | LLAssetID LLTransactionID::makeAssetID(const LLUUID& session) const | ||
912 | { | ||
913 | LLAssetID result; | ||
914 | if (isNull()) | ||
915 | { | ||
916 | result.setNull(); | ||
917 | } | ||
918 | else | ||
919 | { | ||
920 | combine(session, result); | ||
921 | } | ||
922 | return result; | ||
923 | } | ||