| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| #include <sys/ioctl.h> |
| #include <string.h> |
| #include <arpa/inet.h> |
| #include <netinet/in.h> |
| #include <netdb.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <sys/time.h> |
| |
| # include <net/if.h> |
| |
| #include "platforms/os400/axutil_uuid_gen_os400.h" |
| #include "platforms/axutil_platform_auto_sense.h" |
| |
| /* We need these static variables to track throughout the program execution */ |
| static axis2_bool_t axutil_uuid_gen_is_first = AXIS2_TRUE; |
| static struct axutil_uuid_st axutil_uuid_static; |
| |
| axutil_uuid_t *AXIS2_CALL |
| axutil_uuid_gen_v1() |
| { |
| struct timeval time_now; |
| struct timeval tv; |
| unsigned long long time_val; |
| unsigned long long time_val2; |
| unsigned short int clck = 0; |
| axutil_uuid_t *ret_uuid = NULL; |
| unsigned short int time_high_version = 0; |
| |
| if (AXIS2_TRUE == axutil_uuid_gen_is_first) |
| { |
| char *mac_addr = axutil_uuid_get_mac_addr(); |
| memcpy(axutil_uuid_static.mac, mac_addr, 6); |
| axutil_uuid_static.time_seq = 0; |
| axutil_uuid_static.clock = 0; |
| free(mac_addr); |
| axutil_uuid_gen_is_first = AXIS2_FALSE; |
| } |
| /* |
| * GENERATE TIME |
| */ |
| |
| /* determine current system time and sequence counter */ |
| if (gettimeofday(&time_now, NULL) == -1) |
| return NULL; |
| |
| /* check whether system time changed since last retrieve */ |
| if(!(time_now.tv_sec == axutil_uuid_static.time_last.tv_sec && time_now.tv_usec |
| == axutil_uuid_static.time_last.tv_usec)) |
| { |
| /* reset time sequence counter and continue */ |
| axutil_uuid_static.time_seq = 0; |
| } |
| |
| /* until we are out of UUIDs per tick, increment |
| the time/tick sequence counter and continue */ |
| while (axutil_uuid_static.time_seq < UUIDS_PER_TICK) |
| { |
| axutil_uuid_static.time_seq++; |
| } |
| /* sleep for 1000ns (1us) */ |
| tv.tv_sec = 0; |
| tv.tv_usec = 1; |
| /* |
| The following select causes severe performance problems. |
| Hence commenting out. I am not sure why this is required. - Samisa. |
| select(0, NULL, NULL, NULL, &tv); */ |
| |
| time_val = (unsigned long long) time_now.tv_sec * 10000000ull; |
| time_val += (unsigned long long) time_now.tv_usec * 10ull; |
| |
| ret_uuid = malloc(sizeof(axutil_uuid_t)); |
| |
| time_val += UUID_TIMEOFFSET; |
| /* compensate for low resolution system clock by adding |
| the time/tick sequence counter */ |
| if (axutil_uuid_static.time_seq > 0) |
| time_val += (unsigned long long) axutil_uuid_static.time_seq; |
| |
| time_val2 = time_val; |
| ret_uuid->time_low = (unsigned long) time_val2; |
| time_val2 >>= 32; |
| ret_uuid->time_mid = (unsigned short int) time_val2; |
| time_val2 >>= 16; |
| time_high_version = (unsigned short int) time_val2; |
| |
| /* store the 60 LSB of the time in the UUID and make version 1 */ |
| time_high_version <<= 4; |
| time_high_version &= 0xFFF0; |
| time_high_version |= 0x0001; |
| ret_uuid->time_high_version = time_high_version; |
| |
| /* |
| * GENERATE CLOCK |
| */ |
| |
| /* retrieve current clock sequence */ |
| clck = axutil_uuid_static.clock; |
| |
| /* generate new random clock sequence (initially or if the |
| time has stepped backwards) or else just increase it */ |
| if(clck == 0 || (time_now.tv_sec < axutil_uuid_static.time_last.tv_sec || (time_now.tv_sec |
| == axutil_uuid_static.time_last.tv_sec && time_now.tv_usec |
| < axutil_uuid_static.time_last.tv_usec))) |
| { |
| srand(time_now.tv_usec); |
| clck = rand(); |
| } |
| else |
| { |
| clck++; |
| } |
| clck %= (2 << 14); |
| |
| /* store back new clock sequence */ |
| axutil_uuid_static.clock = clck; |
| |
| clck &= 0x1FFF; |
| clck |= 0x2000; |
| |
| /* |
| * FINISH |
| */ |
| /* remember current system time for next iteration */ |
| axutil_uuid_static.time_last.tv_sec = time_now.tv_sec; |
| axutil_uuid_static.time_last.tv_usec = time_now.tv_usec; |
| |
| if (!ret_uuid) |
| { |
| return NULL; |
| } |
| ret_uuid->clock_variant = clck; |
| memcpy(ret_uuid->mac_addr, axutil_uuid_static.mac, 6); |
| return ret_uuid; |
| } |
| |
| axis2_char_t *AXIS2_CALL |
| axutil_platform_uuid_gen( |
| char *s) |
| { |
| axutil_uuid_t *uuid_struct = NULL; |
| axis2_char_t *uuid_str = NULL; |
| unsigned char mac[7]; |
| char mac_hex[13]; |
| |
| if (!s) |
| { |
| return NULL; |
| } |
| uuid_struct = axutil_uuid_gen_v1(); |
| if (!uuid_struct) |
| { |
| return NULL; |
| } |
| uuid_str = s; |
| if (!uuid_str) |
| { |
| return NULL; |
| } |
| memcpy(mac, uuid_struct->mac_addr, 6); |
| sprintf(mac_hex, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); |
| sprintf(uuid_str, "%08x-%04x-%04x-%04x-%s", uuid_struct->time_low, uuid_struct->time_mid, |
| uuid_struct->time_high_version, uuid_struct->clock_variant, mac_hex); |
| free(uuid_struct); |
| uuid_struct = NULL; |
| return uuid_str; |
| } |
| |
| char *AXIS2_CALL |
| axutil_uuid_get_mac_addr( |
| ) |
| { |
| struct ifreq ifr; |
| struct ifreq *IFR; |
| struct ifconf ifc; |
| struct sockaddr *sa; |
| int s = 0; |
| int i = 0; |
| char *buffer = NULL; |
| char buf[1024]; |
| int ok = AXIS2_FALSE; |
| |
| if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) |
| return NULL; |
| |
| ifc.ifc_len = sizeof(buf); |
| ifc.ifc_buf = buf; |
| ioctl(s, SIOCGIFCONF, &ifc); |
| IFR = ifc.ifc_req; |
| |
| for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; IFR++) |
| { |
| strcpy(ifr.ifr_name, IFR->ifr_name); |
| /*sprintf(ifr.ifr_name, "eth0"); */ |
| if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) |
| { |
| if (!(ifr.ifr_flags & IFF_LOOPBACK)) |
| { |
| |
| // TODO-AMRA if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0) |
| { |
| ok = AXIS2_TRUE; |
| break; |
| } |
| } |
| } |
| } |
| buffer = (char *) malloc(6 * sizeof(char)); |
| if (ok) |
| { |
| sa = (struct sockaddr *) &ifr.ifr_addr; |
| for (i = 0; i < 6; i++) |
| buffer[i] = (unsigned char) (sa->sa_data[i] & 0xff); |
| } |
| else |
| { |
| for (i = 0; i < 6; i++) |
| buffer[i] = (unsigned char) ((AXIS2_LOCAL_MAC_ADDR[i]) - '0'); |
| } |
| close(s); |
| return buffer; |
| } |
| |