| /* |
| * 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 <config.h> |
| |
| #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> |
| |
| #ifdef HAVE_LINUX_IF_H |
| # include <linux/if.h> |
| #else |
| # ifdef HAVE_NET_IF_H |
| # ifdef HAVE_SYS_SOCKIO_H |
| # include <sys/sockio.h> |
| # endif |
| # include <net/if.h> |
| # include <net/if_arp.h> |
| # endif |
| # ifdef HAVE_NET_IF_TYPES_H |
| # include <net/if_types.h> |
| # endif |
| # ifdef HAVE_NET_IF_DL_H |
| # include <net/if_dl.h> |
| # endif |
| #endif |
| #ifdef HAVE_GETIFADDRS |
| #include <ifaddrs.h> |
| #endif |
| #include <platforms/unix/axutil_uuid_gen_unix.h> |
| #include <platforms/axutil_platform_auto_sense.h> |
| |
| #ifdef AXIS2_SSL_ENABLED |
| #include <openssl/rand.h> |
| #endif |
| |
| |
| /* 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(); |
| if (mac_addr) { |
| memcpy(axutil_uuid_static.mac, mac_addr, 6); |
| free(mac_addr); |
| } else { |
| /* Default value, not expected to go there */ |
| #ifdef AXIS2_SSL_ENABLED |
| RAND_bytes(axutil_uuid_static.mac, 6); |
| #else |
| memset(axutil_uuid_static.mac, 0, 6); |
| #endif |
| } |
| axutil_uuid_static.time_seq = 0; |
| axutil_uuid_static.clock = 0; |
| 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; |
| } |
| |
| #ifdef HAVE_LINUX_IF_H /* Linux */ |
| |
| 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)) |
| { |
| 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; |
| } |
| |
| #else |
| |
| #ifdef HAVE_GETIFADDRS /* NetBSD, MacOSX, etc... */ |
| |
| #ifndef max |
| # define max(a,b) ((a) > (b) ? (a) : (b)) |
| #endif /* !max */ |
| |
| char *AXIS2_CALL |
| axutil_uuid_get_mac_addr( |
| ) |
| { |
| struct ifaddrs *ifap; |
| struct ifaddrs *ifap_head; |
| const struct sockaddr_dl *sdl; |
| unsigned char *ucp; |
| int i; |
| char *data_ptr; |
| |
| if (getifaddrs(&ifap_head) < 0) |
| return NULL; |
| for (ifap = ifap_head; ifap != NULL; ifap = ifap->ifa_next) |
| { |
| if (ifap->ifa_addr != NULL && ifap->ifa_addr->sa_family == AF_LINK) |
| { |
| sdl = (const struct sockaddr_dl *) (void *) ifap->ifa_addr; |
| ucp = (unsigned char *) (sdl->sdl_data + sdl->sdl_nlen); |
| if (sdl->sdl_alen > 0) |
| { |
| data_ptr = malloc(6 * sizeof(char)); |
| for (i = 0; i < 6 && i < sdl->sdl_alen; i++, ucp++) |
| data_ptr[i] = (unsigned char) (*ucp & 0xff); |
| |
| freeifaddrs(ifap_head); |
| return data_ptr; |
| } |
| } |
| } |
| freeifaddrs(ifap_head); |
| return NULL; |
| } |
| # else /* Solaris-ish */ |
| |
| /* code modified from that posted on: |
| * http://forum.sun.com/jive/thread.jspa?threadID=84804&tstart=30 |
| */ |
| |
| char *AXIS2_CALL |
| axutil_uuid_get_mac_addr() |
| { |
| char hostname[MAXHOSTNAMELEN]; |
| char *data_ptr; |
| struct hostent *he; |
| struct arpreq ar; |
| struct sockaddr_in *sa; |
| int s; |
| int i; |
| |
| if(gethostname(hostname, sizeof(hostname)) < 0) |
| return NULL; |
| if((he = gethostbyname(hostname)) == NULL) |
| return NULL; |
| if((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) |
| return NULL; |
| memset(&ar, 0, sizeof(ar)); |
| sa = (struct sockaddr_in *)((void *)&(ar.arp_pa)); |
| sa->sin_family = AF_INET; |
| memcpy(&(sa->sin_addr), *(he->h_addr_list), sizeof(struct in_addr)); |
| if(ioctl(s, SIOCGARP, &ar) < 0) |
| { |
| close(s); |
| return NULL; |
| } |
| close(s); |
| if(!(ar.arp_flags & ATF_COM)) |
| return NULL; |
| data_ptr = malloc(6 * sizeof(char)); |
| for(i = 0; i < 6; i++) |
| data_ptr[i] = (unsigned char)(ar.arp_ha.sa_data[i] & 0xff); |
| |
| return data_ptr; |
| } |
| # endif |
| #endif |