1/*
2
3Copyright (c) 2002, Oracle and/or its affiliates.
4
5Permission is hereby granted, free of charge, to any person obtaining a
6copy of this software and associated documentation files (the "Software"),
7to deal in the Software without restriction, including without limitation
8the rights to use, copy, modify, merge, publish, distribute, sublicense,
9and/or sell copies of the Software, and to permit persons to whom the
10Software is furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice (including the next
13paragraph) shall be included in all copies or substantial portions of the
14Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22DEALINGS IN THE SOFTWARE.
23
24*/
25/*
26
27Copyright 1993, 1998  The Open Group
28
29Permission to use, copy, modify, distribute, and sell this software and its
30documentation for any purpose is hereby granted without fee, provided that
31the above copyright notice appear in all copies and that both that
32copyright notice and this permission notice appear in supporting
33documentation.
34
35The above copyright notice and this permission notice shall be included in
36all copies or substantial portions of the Software.
37
38THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
41OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
42AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
43CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44
45Except as contained in this notice, the name of The Open Group shall not be
46used in advertising or otherwise to promote the sale, use or other dealings
47in this Software without prior written authorization from The Open Group.
48
49*/
50
51/*
52 * Author: Ralph Mor, X Consortium
53 */
54
55#ifdef WIN32
56# define _WILLWINSOCK_
57#endif
58#ifdef HAVE_CONFIG_H
59# include <config.h>
60#endif
61#include <X11/SM/SMlib.h>
62#include "SMlibint.h"
63#ifdef XTHREADS
64# include <X11/Xthreads.h>
65#endif
66#include <stdio.h>
67#include <unistd.h>
68
69#include <time.h>
70#define Time_t time_t
71
72#if defined(HAVE_UUID_CREATE)
73# include <uuid.h>
74#elif defined(HAVE_LIBUUID)
75# include <uuid/uuid.h>
76#else
77
78# ifndef WIN32
79
80#  ifdef TCPCONN
81#   include <sys/socket.h>
82#   include <netinet/in.h>
83#   include <arpa/inet.h>
84#   define XOS_USE_NO_LOCKING
85#   define X_INCLUDE_NETDB_H
86#   include <X11/Xos_r.h>
87#  endif
88
89# else /* WIN32 */
90
91#  include <X11/Xwinsock.h>
92#  include <X11/Xw32defs.h>
93#  define X_INCLUDE_NETDB_H
94#  define XOS_USE_MTSAFE_NETDBAPI
95#  include <X11/Xos_r.h>
96
97# endif /* WIN32 */
98
99# if defined(IPv6) && !defined(AF_INET6)
100#  error "Cannot build IPv6 support without AF_INET6"
101# endif
102
103#endif /* !(HAVE_UUID_CREATE || HAVE_LIBUUID) */
104
105
106char *
107SmsGenerateClientID(SmsConn smsConn)
108{
109#if defined(HAVE_UUID_CREATE)
110    char *id;
111    char *temp;
112    uuid_t uuid;
113    uint32_t status;
114    size_t len;
115
116    uuid_create(&uuid, &status);
117
118    uuid_to_string(&uuid, &temp, &status);
119
120    len = strlen(temp) + 2;
121    if ((id = malloc(len)) != NULL)
122        snprintf(id, len, "2%s", temp);
123
124    free(temp);
125
126    return id;
127#elif defined(HAVE_LIBUUID)
128    char *id;
129    char temp[256];
130    uuid_t uuid;
131
132    uuid_generate(uuid);
133
134    temp[0] = '2';
135    temp[1] = '\0';
136    uuid_unparse_lower(uuid, &temp[1]);
137
138    id = strdup (temp);
139
140    return id;
141#elif defined(TCPCONN)
142    static const char hex[] = "0123456789abcdef";
143    char hostname[256];
144    char address[64], *addr_ptr = address;
145    char temp[256];
146    char *id;
147    static int sequence = 0;
148    char* inet_addr;
149    char *ptr1;
150    unsigned char decimal[4];
151    int i;
152    struct in_addr *haddr = NULL;
153# ifdef HAVE_GETADDRINFO
154    struct addrinfo *ai, *first_ai;
155# endif
156
157    if (gethostname (hostname, sizeof (hostname)))
158	return (NULL);
159
160# ifdef HAVE_GETADDRINFO
161    if (getaddrinfo(hostname,NULL,NULL,&ai) != 0)
162	return NULL;
163
164    for (first_ai = ai; ai != NULL; ai = ai->ai_next) {
165	if (ai->ai_family == AF_INET)
166	    break;
167#  ifdef IPv6
168	if (ai->ai_family == AF_INET6)
169	    break;
170#  endif
171    }
172    if (ai == NULL) {
173	freeaddrinfo(first_ai);
174	return NULL;
175    }
176
177#  ifdef IPv6
178    if (ai->ai_family == AF_INET6) {
179	unsigned char *cp = (unsigned char *) &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr;
180
181	*addr_ptr++ = '6';	/* IPv6 address code */
182
183	for (i = 0 ; i < 16 ; i++) {
184            *addr_ptr++ = hex[cp[i] >> 4];
185            *addr_ptr++ = hex[cp[i] & 0x0f];
186	}
187
188        *addr_ptr++ = '\0';
189    } else  /* Fall through to IPv4 address handling */
190#  endif /* IPv6 */
191    {
192	haddr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr;
193# else /* !HAVE_GETADDRINFO */
194#  ifdef XTHREADS_NEEDS_BYNAMEPARAMS
195	_Xgethostbynameparams hparams;
196#  endif
197	struct hostent *hostp;
198
199	if ((hostp = _XGethostbyname (hostname,hparams)) != NULL)
200	    haddr = (struct in_addr *)(hostp->h_addr);
201	else
202	    return NULL;
203# endif /* !HAVE_GETADDRINFO */
204
205	*addr_ptr++ = '1';
206
207	{
208	    unsigned char *cp = (unsigned char *) &(haddr->s_addr);
209
210	    for (i = 0; i < 4; i++) {
211		*addr_ptr++ = hex[cp[i] >> 4];
212		*addr_ptr++ = hex[cp[i] & 0x0f];
213	    }
214	}
215
216	*addr_ptr++ = '\0';
217
218# ifdef HAVE_GETADDRINFO
219    }
220    freeaddrinfo(first_ai);
221# endif
222
223    sprintf (temp, "1%s%.13ld%.10ld%.4d", address, (long)time((Time_t*)0),
224	     (long)getpid(), sequence);
225
226    if (++sequence > 9999)
227	sequence = 0;
228
229    id = strdup (temp);
230
231    return (id);
232#else /* no supported id generation method, neither UUID nor TCPCONN */
233    return (NULL);
234#endif
235}
236