xdmcp.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: xdmcp.c /main/5 1998/04/06 13:36:04 mgreess $ */
  24. /* (c) Copyright 1997 The Open Group */
  25. /* *
  26. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  27. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  28. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
  29. * (c) Copyright 1993, 1994 Novell, Inc. *
  30. */
  31. /*
  32. * @DEC_COPYRIGHT@
  33. */
  34. /*
  35. * HISTORY
  36. * $Log$
  37. * Revision 1.1.2.3 1995/06/06 20:25:54 Chris_Beute
  38. * Code snapshot merge from March 15 and SIA changes
  39. * [1995/05/31 20:17:42 Chris_Beute]
  40. *
  41. * Revision 1.1.2.2 1995/04/21 13:05:47 Peter_Derr
  42. * dtlogin auth key fixes from deltacde
  43. * [1995/04/14 18:03:44 Peter_Derr]
  44. *
  45. * Merge in dtlogin changes to WaitForSomething() to support command
  46. * line console login.
  47. * [1995/04/14 17:40:05 Peter_Derr]
  48. *
  49. * Use R6 xdm code to handle XDMCP
  50. * [1995/04/10 19:24:11 Peter_Derr]
  51. *
  52. * $EndLog$
  53. */
  54. /*
  55. Copyright (c) 1988 X Consortium
  56. Permission is hereby granted, free of charge, to any person obtaining
  57. a copy of this software and associated documentation files (the
  58. "Software"), to deal in the Software without restriction, including
  59. without limitation the rights to use, copy, modify, merge, publish,
  60. distribute, sublicense, and/or sell copies of the Software, and to
  61. permit persons to whom the Software is furnished to do so, subject to
  62. the following conditions:
  63. The above copyright notice and this permission notice shall be included
  64. in all copies or substantial portions of the Software.
  65. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  66. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  67. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  68. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
  69. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  70. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  71. OTHER DEALINGS IN THE SOFTWARE.
  72. Except as contained in this notice, the name of the X Consortium shall
  73. not be used in advertising or otherwise to promote the sale, use or
  74. other dealings in this Software without prior written authorization
  75. from the X Consortium.
  76. */
  77. /*
  78. * xdm - display manager daemon
  79. * Author: Keith Packard, MIT X Consortium
  80. *
  81. * xdmcp.c - Support for XDMCP
  82. */
  83. # include "dm.h"
  84. # include <X11/X.h>
  85. # include <X11/Xfuncs.h>
  86. # include <sys/types.h>
  87. # include <ctype.h>
  88. #include <sys/socket.h>
  89. #include <netinet/in.h>
  90. #include <sys/un.h>
  91. #include <netdb.h>
  92. #ifdef X_NOT_STDC_ENV
  93. #define Time_t long
  94. extern Time_t time ();
  95. #else
  96. #include <time.h>
  97. #define Time_t time_t
  98. #endif
  99. #define getString(name,len) ((name = malloc (len + 1)) ? 1 : 0)
  100. /*
  101. * interface to policy routines
  102. */
  103. extern ARRAY8Ptr ChooseAuthentication ();
  104. extern int SelectConnectionTypeIndex ();
  105. void query_respond (struct sockaddr *from, int fromlen, int length);
  106. void broadcast_respond (struct sockaddr *from, int fromlen, int length);
  107. void forward_respond (struct sockaddr *from, int fromlen, int length);
  108. void request_respond (struct sockaddr *from, int fromlen, int length);
  109. void send_willing (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status);
  110. void send_unwilling (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status);
  111. void send_accept (struct sockaddr *to, int tolen, CARD32 sessionID, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr authorizationName, ARRAY8Ptr authorizationData);
  112. void manage (struct sockaddr *from, int fromlen, int length);
  113. void send_decline (struct sockaddr *to, int tolen, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr status);
  114. void send_failed (struct sockaddr *from, int fromlen, char *name, CARD32 sessionID, char *reason);
  115. void send_refuse (struct sockaddr *from, int fromlen, CARD32 sessionID);
  116. void send_alive (struct sockaddr *from, int fromlen, int length);
  117. int xdmcpFd = -1;
  118. int chooserFd = -1;
  119. FD_TYPE WellKnownSocketsMask;
  120. int WellKnownSocketsMax;
  121. #define pS(s) ((s) ? ((char *) (s)) : "empty string")
  122. /* choose.c */
  123. int RememberIndirectClient(ARRAY8Ptr clientAddress, CARD16 connectionType);
  124. void ForgetIndirectClient(ARRAY8Ptr clientAddress, CARD16 connectionType);
  125. int IsIndirectClient(ARRAY8Ptr clientAddress, CARD16 connectionType);
  126. ARRAY8Ptr IndirectChoice(ARRAY8Ptr clientAddress, CARD16 connectionType);
  127. int ProcessChooserSocket(int fd);
  128. void RunChooser(struct display *d);
  129. void LoadDMResources(void); // resource.c
  130. void
  131. DestroyWellKnownSockets (void)
  132. {
  133. if (xdmcpFd != -1)
  134. {
  135. close (xdmcpFd);
  136. xdmcpFd = -1;
  137. }
  138. if (chooserFd != -1)
  139. {
  140. close (chooserFd);
  141. chooserFd = -1;
  142. }
  143. }
  144. int
  145. AnyWellKnownSockets (void)
  146. {
  147. return xdmcpFd != -1 || chooserFd != -1;
  148. }
  149. static XdmcpBuffer buffer;
  150. /*ARGSUSED*/
  151. static int
  152. sendForward (CARD16 connectionType, ARRAY8Ptr address, char *closure)
  153. {
  154. #ifdef AF_INET
  155. struct sockaddr_in in_addr;
  156. #endif
  157. #ifdef AF_DECnet
  158. #endif
  159. struct sockaddr *addr;
  160. int addrlen;
  161. switch (connectionType)
  162. {
  163. #ifdef AF_INET
  164. case FamilyInternet:
  165. addr = (struct sockaddr *) &in_addr;
  166. bzero ((char *) &in_addr, sizeof (in_addr));
  167. #ifdef BSD44SOCKETS
  168. in_addr.sin_len = sizeof(in_addr);
  169. #endif
  170. in_addr.sin_family = AF_INET;
  171. in_addr.sin_port = htons ((short) XDM_UDP_PORT);
  172. if (address->length != 4)
  173. return 0;
  174. memmove( (char *) &in_addr.sin_addr, address->data, address->length);
  175. addrlen = sizeof (struct sockaddr_in);
  176. break;
  177. #endif
  178. #ifdef AF_DECnet
  179. case FamilyDECnet:
  180. #endif
  181. default:
  182. return 0;
  183. }
  184. XdmcpFlush (xdmcpFd, &buffer, (XdmcpNetaddr)addr, addrlen);
  185. return 0;
  186. }
  187. extern char *NetaddrAddress();
  188. extern char *NetaddrPort();
  189. static void
  190. ClientAddress (struct sockaddr *from, ARRAY8Ptr addr, ARRAY8Ptr port, CARD16 *type)
  191. {
  192. int length, family;
  193. char *data;
  194. data = NetaddrPort(from, &length);
  195. XdmcpAllocARRAY8 (port, length);
  196. memmove( port->data, data, length);
  197. port->length = length;
  198. family = ConvertAddr((char *)from, &length, &data);
  199. XdmcpAllocARRAY8 (addr, length);
  200. memmove( addr->data, data, length);
  201. addr->length = length;
  202. *type = family;
  203. }
  204. static void
  205. all_query_respond (struct sockaddr *from, int fromlen, ARRAYofARRAY8Ptr authenticationNames, xdmOpCode type)
  206. {
  207. ARRAY8Ptr authenticationName;
  208. ARRAY8 status;
  209. ARRAY8 addr;
  210. CARD16 connectionType;
  211. int family;
  212. int length;
  213. family = ConvertAddr((char *)from, &length, (char **) &(addr.data));
  214. addr.length = length; /* convert int to short */
  215. Debug ("all_query_respond: conntype=%d, addr=%lx, len=%d\n",
  216. family, *(addr.data), addr.length);
  217. if (family < 0)
  218. return;
  219. connectionType = family;
  220. if (type == INDIRECT_QUERY)
  221. RememberIndirectClient (&addr, connectionType);
  222. else
  223. ForgetIndirectClient (&addr, connectionType);
  224. authenticationName = ChooseAuthentication (authenticationNames);
  225. if (Willing (&addr, connectionType, authenticationName, &status, type))
  226. send_willing (from, fromlen, authenticationName, &status);
  227. else
  228. if (type == QUERY)
  229. send_unwilling (from, fromlen, authenticationName, &status);
  230. XdmcpDisposeARRAY8 (&status);
  231. }
  232. static void
  233. indirect_respond (struct sockaddr *from, int fromlen, int length)
  234. {
  235. ARRAYofARRAY8 queryAuthenticationNames;
  236. ARRAY8 clientAddress;
  237. ARRAY8 clientPort;
  238. CARD16 connectionType;
  239. int expectedLen;
  240. int i;
  241. XdmcpHeader header;
  242. int localHostAsWell;
  243. Debug ("Indirect respond %d\n", length);
  244. if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames))
  245. return;
  246. expectedLen = 1;
  247. for (i = 0; i < (int)queryAuthenticationNames.length; i++)
  248. expectedLen += 2 + queryAuthenticationNames.data[i].length;
  249. if (length == expectedLen)
  250. {
  251. ClientAddress (from, &clientAddress, &clientPort, &connectionType);
  252. /*
  253. * set up the forward query packet
  254. */
  255. header.version = XDM_PROTOCOL_VERSION;
  256. header.opcode = (CARD16) FORWARD_QUERY;
  257. header.length = 0;
  258. header.length += 2 + clientAddress.length;
  259. header.length += 2 + clientPort.length;
  260. header.length += 1;
  261. for (i = 0; i < (int)queryAuthenticationNames.length; i++)
  262. header.length += 2 + queryAuthenticationNames.data[i].length;
  263. XdmcpWriteHeader (&buffer, &header);
  264. XdmcpWriteARRAY8 (&buffer, &clientAddress);
  265. XdmcpWriteARRAY8 (&buffer, &clientPort);
  266. XdmcpWriteARRAYofARRAY8 (&buffer, &queryAuthenticationNames);
  267. localHostAsWell = ForEachMatchingIndirectHost (&clientAddress, connectionType, sendForward, (char *) 0);
  268. XdmcpDisposeARRAY8 (&clientAddress);
  269. XdmcpDisposeARRAY8 (&clientPort);
  270. if (localHostAsWell)
  271. all_query_respond (from, fromlen, &queryAuthenticationNames,
  272. INDIRECT_QUERY);
  273. }
  274. else
  275. {
  276. Debug ("Indirect length error got %d expect %d\n", length, expectedLen);
  277. }
  278. XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames);
  279. }
  280. static void
  281. ProcessRequestSocket (void)
  282. {
  283. XdmcpHeader header;
  284. struct sockaddr_in addr;
  285. int addrlen = sizeof addr;
  286. Debug ("ProcessRequestSocket\n");
  287. bzero ((char *) &addr, sizeof (addr));
  288. if (!XdmcpFill (xdmcpFd, &buffer, (XdmcpNetaddr)&addr, &addrlen)) {
  289. Debug ("XdmcpFill failed\n");
  290. return;
  291. }
  292. if (!XdmcpReadHeader (&buffer, &header)) {
  293. Debug ("XdmcpReadHeader failed\n");
  294. return;
  295. }
  296. if (header.version != XDM_PROTOCOL_VERSION) {
  297. Debug ("XDMCP header version read was %d, expected %d\n",
  298. header.version, XDM_PROTOCOL_VERSION);
  299. return;
  300. }
  301. Debug ("header: %d %d %d\n", header.version, header.opcode, header.length);
  302. switch (header.opcode)
  303. {
  304. case BROADCAST_QUERY:
  305. broadcast_respond ((struct sockaddr *)&addr, addrlen, header.length);
  306. break;
  307. case QUERY:
  308. query_respond ((struct sockaddr *)&addr, addrlen, header.length);
  309. break;
  310. case INDIRECT_QUERY:
  311. indirect_respond ((struct sockaddr *)&addr, addrlen, header.length);
  312. break;
  313. case FORWARD_QUERY:
  314. forward_respond ((struct sockaddr *)&addr, addrlen, header.length);
  315. break;
  316. case REQUEST:
  317. request_respond ((struct sockaddr *)&addr, addrlen, header.length);
  318. break;
  319. case MANAGE:
  320. manage ((struct sockaddr *)&addr, addrlen, header.length);
  321. break;
  322. case KEEPALIVE:
  323. send_alive ((struct sockaddr *)&addr, addrlen, header.length);
  324. break;
  325. }
  326. }
  327. /*
  328. * dtlogin changes to WaitForSomething () merged in to support command line
  329. * login.
  330. */
  331. void WaitForSomething (void)
  332. {
  333. FD_TYPE reads;
  334. struct timeval timeout, *ptimeout;
  335. int nready;
  336. extern int Rescan, ChildReady, wakeupTime;
  337. Debug ("WaitForSomething\n");
  338. if (AnyWellKnownSockets () && !ChildReady || wakeupTime > 0 ) {
  339. reads = WellKnownSocketsMask;
  340. if (wakeupTime >= 0 ) {
  341. timeout.tv_sec = wakeupTime;
  342. timeout.tv_usec = 10;
  343. ptimeout = &timeout;
  344. Debug("Setting timer on select() for %d seconds.\n", wakeupTime);
  345. }
  346. else
  347. ptimeout = NULL;
  348. nready = select (WellKnownSocketsMax + 1, &reads, 0, 0, ptimeout);
  349. Debug ("select returns %d. Rescan: %d ChildReady: %d\n",
  350. nready, Rescan, ChildReady);
  351. if (nready > 0)
  352. {
  353. if (xdmcpFd >= 0 && FD_ISSET (xdmcpFd, &reads))
  354. ProcessRequestSocket ();
  355. if (chooserFd >= 0 && FD_ISSET (chooserFd, &reads))
  356. ProcessChooserSocket (chooserFd);
  357. }
  358. if (ChildReady)
  359. {
  360. WaitForChild ();
  361. }
  362. else
  363. StartDisplays();
  364. } else
  365. WaitForChild ();
  366. }
  367. /*
  368. * respond to a request on the UDP socket.
  369. */
  370. static ARRAY8 Hostname;
  371. void
  372. registerHostname (char *name, int namelen)
  373. {
  374. int i;
  375. if (!XdmcpReallocARRAY8 (&Hostname, namelen))
  376. return;
  377. for (i = 0; i < namelen; i++)
  378. Hostname.data[i] = name[i];
  379. }
  380. static void
  381. direct_query_respond (struct sockaddr *from, int fromlen, int length, xdmOpCode type)
  382. {
  383. ARRAYofARRAY8 queryAuthenticationNames;
  384. int expectedLen;
  385. int i;
  386. if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames))
  387. return;
  388. expectedLen = 1;
  389. for (i = 0; i < (int)queryAuthenticationNames.length; i++)
  390. expectedLen += 2 + queryAuthenticationNames.data[i].length;
  391. if (length == expectedLen)
  392. all_query_respond (from, fromlen, &queryAuthenticationNames, type);
  393. XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames);
  394. }
  395. void
  396. query_respond (struct sockaddr *from, int fromlen, int length)
  397. {
  398. Debug ("Query respond %d\n", length);
  399. direct_query_respond (from, fromlen, length, QUERY);
  400. }
  401. void
  402. broadcast_respond (struct sockaddr *from, int fromlen, int length)
  403. {
  404. direct_query_respond (from, fromlen, length, BROADCAST_QUERY);
  405. }
  406. /* computes an X display name */
  407. #if NeedWidePrototypes
  408. char *
  409. NetworkAddressToName(int connectionType, ARRAY8Ptr connectionAddress, int displayNumber)
  410. #else
  411. char *
  412. NetworkAddressToName(CARD16 connectionType, ARRAY8Ptr connectionAddress, CARD16 displayNumber)
  413. #endif
  414. {
  415. switch (connectionType)
  416. {
  417. case FamilyInternet:
  418. {
  419. CARD8 *data;
  420. struct hostent *hostent;
  421. char *name;
  422. char *localhost, *localHostname();
  423. data = connectionAddress->data;
  424. hostent = gethostbyaddr ((char *)data,
  425. connectionAddress->length, AF_INET);
  426. localhost = localHostname ();
  427. /*
  428. * protect against bogus host names
  429. */
  430. if (hostent && hostent->h_name && hostent->h_name[0]
  431. && (hostent->h_name[0] != '.'))
  432. {
  433. if (!strcmp (localhost, hostent->h_name))
  434. {
  435. if (!getString (name, 10))
  436. return 0;
  437. sprintf (name, ":%d", displayNumber);
  438. }
  439. else
  440. {
  441. if (removeDomainname)
  442. {
  443. char *localDot, *remoteDot;
  444. /* check for a common domain name. This
  445. * could reduce names by recognising common
  446. * super-domain names as well, but I don't think
  447. * this is as useful, and will confuse more
  448. * people
  449. */
  450. if ((localDot = strchr(localhost, '.')) &&
  451. (remoteDot = strchr(hostent->h_name, '.')))
  452. {
  453. /* smash the name in place; it won't
  454. * be needed later.
  455. */
  456. if (!strcmp (localDot+1, remoteDot+1))
  457. *remoteDot = '\0';
  458. }
  459. }
  460. if (!getString (name, strlen (hostent->h_name) + 10))
  461. return 0;
  462. sprintf (name, "%s:%d", hostent->h_name, displayNumber);
  463. }
  464. }
  465. else
  466. {
  467. if (!getString (name, 25))
  468. return 0;
  469. sprintf(name, "%d.%d.%d.%d:%d",
  470. data[0], data[1], data[2], data[3], displayNumber);
  471. }
  472. return name;
  473. }
  474. #ifdef DNET
  475. case FamilyDECnet:
  476. return NULL;
  477. #endif /* DNET */
  478. default:
  479. return NULL;
  480. }
  481. }
  482. /*ARGSUSED*/
  483. void
  484. forward_respond (struct sockaddr *from, int fromlen, int length)
  485. {
  486. ARRAY8 clientAddress;
  487. ARRAY8 clientPort;
  488. ARRAYofARRAY8 authenticationNames;
  489. struct sockaddr *client = NULL;
  490. int clientlen = 0;
  491. int expectedLen;
  492. int i;
  493. Debug ("Forward respond %d\n", length);
  494. clientAddress.length = 0;
  495. clientAddress.data = 0;
  496. clientPort.length = 0;
  497. clientPort.data = 0;
  498. authenticationNames.length = 0;
  499. authenticationNames.data = 0;
  500. if (XdmcpReadARRAY8 (&buffer, &clientAddress) &&
  501. XdmcpReadARRAY8 (&buffer, &clientPort) &&
  502. XdmcpReadARRAYofARRAY8 (&buffer, &authenticationNames))
  503. {
  504. expectedLen = 0;
  505. expectedLen += 2 + clientAddress.length;
  506. expectedLen += 2 + clientPort.length;
  507. expectedLen += 1; /* authenticationNames */
  508. for (i = 0; i < (int)authenticationNames.length; i++)
  509. expectedLen += 2 + authenticationNames.data[i].length;
  510. if (length == expectedLen)
  511. {
  512. int j;
  513. j = 0;
  514. for (i = 0; i < (int)clientPort.length; i++)
  515. j = j * 256 + clientPort.data[i];
  516. Debug ("Forward client address (port %d)", j);
  517. for (i = 0; i < (int)clientAddress.length; i++)
  518. Debug (" %d", clientAddress.data[i]);
  519. Debug ("\n");
  520. switch (from->sa_family)
  521. {
  522. #ifdef AF_INET
  523. case AF_INET:
  524. {
  525. static struct sockaddr_in in_addr;
  526. if (clientAddress.length != 4 ||
  527. clientPort.length != 2)
  528. {
  529. goto badAddress;
  530. }
  531. bzero ((char *) &in_addr, sizeof (in_addr));
  532. #ifdef BSD44SOCKETS
  533. in_addr.sin_len = sizeof(in_addr);
  534. #endif
  535. in_addr.sin_family = AF_INET;
  536. memmove( &in_addr.sin_addr, clientAddress.data, 4);
  537. memmove( (char *) &in_addr.sin_port, clientPort.data, 2);
  538. client = (struct sockaddr *) &in_addr;
  539. clientlen = sizeof (in_addr);
  540. }
  541. break;
  542. #endif
  543. #ifdef AF_UNIX
  544. case AF_UNIX:
  545. {
  546. static struct sockaddr_un un_addr;
  547. if (clientAddress.length >= sizeof (un_addr.sun_path))
  548. goto badAddress;
  549. bzero ((char *) &un_addr, sizeof (un_addr));
  550. un_addr.sun_family = AF_UNIX;
  551. memmove( un_addr.sun_path, clientAddress.data, clientAddress.length);
  552. un_addr.sun_path[clientAddress.length] = '\0';
  553. client = (struct sockaddr *) &un_addr;
  554. #ifdef BSD44SOCKETS
  555. un_addr.sun_len = strlen(un_addr.sun_path);
  556. clientlen = SUN_LEN(&un_addr);
  557. #else
  558. clientlen = sizeof (un_addr);
  559. #endif
  560. }
  561. break;
  562. #endif
  563. #ifdef AF_CHAOS
  564. case AF_CHAOS:
  565. goto badAddress;
  566. #endif
  567. #ifdef AF_DECnet
  568. case AF_DECnet:
  569. goto badAddress;
  570. #endif
  571. }
  572. all_query_respond (client, clientlen, &authenticationNames,
  573. FORWARD_QUERY);
  574. }
  575. else
  576. {
  577. Debug ("Forward length error got %d expect %d\n", length, expectedLen);
  578. }
  579. }
  580. badAddress:
  581. XdmcpDisposeARRAY8 (&clientAddress);
  582. XdmcpDisposeARRAY8 (&clientPort);
  583. XdmcpDisposeARRAYofARRAY8 (&authenticationNames);
  584. }
  585. void
  586. send_willing (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status)
  587. {
  588. XdmcpHeader header;
  589. Debug ("Send willing %*.*s %*.*s\n", authenticationName->length,
  590. authenticationName->length,
  591. pS(authenticationName->data),
  592. status->length,
  593. status->length,
  594. pS(status->data));
  595. header.version = XDM_PROTOCOL_VERSION;
  596. header.opcode = (CARD16) WILLING;
  597. header.length = 6 + authenticationName->length +
  598. Hostname.length + status->length;
  599. XdmcpWriteHeader (&buffer, &header);
  600. XdmcpWriteARRAY8 (&buffer, authenticationName);
  601. XdmcpWriteARRAY8 (&buffer, &Hostname);
  602. XdmcpWriteARRAY8 (&buffer, status);
  603. XdmcpFlush (xdmcpFd, &buffer, (XdmcpNetaddr)from, fromlen);
  604. }
  605. void
  606. send_unwilling (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status)
  607. {
  608. XdmcpHeader header;
  609. Debug ("Send unwilling %*.*s %*.*s\n", authenticationName->length,
  610. authenticationName->length,
  611. pS(authenticationName->data),
  612. status->length,
  613. status->length,
  614. pS(status->data));
  615. header.version = XDM_PROTOCOL_VERSION;
  616. header.opcode = (CARD16) UNWILLING;
  617. header.length = 4 + Hostname.length + status->length;
  618. XdmcpWriteHeader (&buffer, &header);
  619. XdmcpWriteARRAY8 (&buffer, &Hostname);
  620. XdmcpWriteARRAY8 (&buffer, status);
  621. XdmcpFlush (xdmcpFd, &buffer, (XdmcpNetaddr)from, fromlen);
  622. }
  623. static unsigned long globalSessionID;
  624. #define NextSessionID() (++globalSessionID)
  625. void
  626. init_session_id(void)
  627. {
  628. /* Set randomly so we are unlikely to reuse id's from a previous
  629. * incarnation so we don't say "Alive" to those displays.
  630. * Start with low digits 0 to make debugging easier.
  631. */
  632. globalSessionID = (time((Time_t)0)&0x7fff) * 16000;
  633. }
  634. static ARRAY8 outOfMemory = { (CARD16) 13, (CARD8Ptr) "Out of memory" };
  635. static ARRAY8 noValidAddr = { (CARD16) 16, (CARD8Ptr) "No valid address" };
  636. static ARRAY8 noValidAuth = { (CARD16) 22, (CARD8Ptr) "No valid authorization" };
  637. static ARRAY8 noAuthentic = { (CARD16) 29, (CARD8Ptr) "XDM has no authentication key" };
  638. void
  639. request_respond (struct sockaddr *from, int fromlen, int length)
  640. {
  641. CARD16 displayNumber;
  642. ARRAY16 connectionTypes;
  643. ARRAYofARRAY8 connectionAddresses;
  644. ARRAY8 authenticationName;
  645. ARRAY8 authenticationData;
  646. ARRAYofARRAY8 authorizationNames;
  647. ARRAY8 manufacturerDisplayID;
  648. ARRAY8Ptr reason;
  649. int expectlen;
  650. int i, j;
  651. struct protoDisplay *pdpy;
  652. ARRAY8 authorizationName, authorizationData;
  653. ARRAY8Ptr connectionAddress;
  654. Debug ("Request respond %d\n", length);
  655. connectionTypes.data = 0;
  656. connectionAddresses.data = 0;
  657. authenticationName.data = 0;
  658. authenticationData.data = 0;
  659. authorizationNames.data = 0;
  660. authorizationName.length = 0;
  661. authorizationData.length = 0;
  662. manufacturerDisplayID.data = 0;
  663. if (XdmcpReadCARD16 (&buffer, &displayNumber) &&
  664. XdmcpReadARRAY16 (&buffer, &connectionTypes) &&
  665. XdmcpReadARRAYofARRAY8 (&buffer, &connectionAddresses) &&
  666. XdmcpReadARRAY8 (&buffer, &authenticationName) &&
  667. XdmcpReadARRAY8 (&buffer, &authenticationData) &&
  668. XdmcpReadARRAYofARRAY8 (&buffer, &authorizationNames) &&
  669. XdmcpReadARRAY8 (&buffer, &manufacturerDisplayID))
  670. {
  671. expectlen = 0;
  672. expectlen += 2; /* displayNumber */
  673. expectlen += 1 + 2*connectionTypes.length; /* connectionTypes */
  674. expectlen += 1; /* connectionAddresses */
  675. for (i = 0; i < (int)connectionAddresses.length; i++)
  676. expectlen += 2 + connectionAddresses.data[i].length;
  677. expectlen += 2 + authenticationName.length; /* authenticationName */
  678. expectlen += 2 + authenticationData.length; /* authenticationData */
  679. expectlen += 1; /* authoriationNames */
  680. for (i = 0; i < (int)authorizationNames.length; i++)
  681. expectlen += 2 + authorizationNames.data[i].length;
  682. expectlen += 2 + manufacturerDisplayID.length; /* displayID */
  683. if (expectlen != length)
  684. {
  685. Debug ("Request length error got %d expect %d\n", length, expectlen);
  686. goto abort;
  687. }
  688. if (connectionTypes.length == 0 ||
  689. connectionAddresses.length != connectionTypes.length)
  690. {
  691. reason = &noValidAddr;
  692. pdpy = 0;
  693. goto decline;
  694. }
  695. pdpy = FindProtoDisplay (from, fromlen, displayNumber);
  696. if (!pdpy) {
  697. /* Check this Display against the Manager's policy */
  698. reason = Accept (from, fromlen, displayNumber);
  699. if (reason)
  700. goto decline;
  701. /* Check the Display's stream services against Manager's policy */
  702. i = SelectConnectionTypeIndex (&connectionTypes,
  703. &connectionAddresses);
  704. if (i < 0) {
  705. reason = &noValidAddr;
  706. goto decline;
  707. }
  708. /* The Manager considers this a new session */
  709. connectionAddress = &connectionAddresses.data[i];
  710. pdpy = NewProtoDisplay (from, fromlen, displayNumber,
  711. connectionTypes.data[i], connectionAddress,
  712. NextSessionID());
  713. Debug ("NewProtoDisplay 0x%x\n", pdpy);
  714. if (!pdpy) {
  715. reason = &outOfMemory;
  716. goto decline;
  717. }
  718. }
  719. if (authorizationNames.length == 0)
  720. j = 0;
  721. else
  722. j = SelectAuthorizationTypeIndex (&authenticationName,
  723. &authorizationNames);
  724. if (j < 0)
  725. {
  726. reason = &noValidAuth;
  727. goto decline;
  728. }
  729. if (!CheckAuthentication (pdpy,
  730. &manufacturerDisplayID,
  731. &authenticationName,
  732. &authenticationData))
  733. {
  734. reason = &noAuthentic;
  735. goto decline;
  736. }
  737. if (j < (int)authorizationNames.length)
  738. {
  739. Xauth *auth;
  740. SetProtoDisplayAuthorization (pdpy,
  741. (unsigned short) authorizationNames.data[j].length,
  742. (char *) authorizationNames.data[j].data);
  743. auth = pdpy->xdmcpAuthorization;
  744. if (!auth)
  745. auth = pdpy->fileAuthorization;
  746. if (auth)
  747. {
  748. authorizationName.length = auth->name_length;
  749. authorizationName.data = (CARD8Ptr) auth->name;
  750. authorizationData.length = auth->data_length;
  751. authorizationData.data = (CARD8Ptr) auth->data;
  752. }
  753. }
  754. if (pdpy)
  755. {
  756. send_accept (from, fromlen, pdpy->sessionID,
  757. &authenticationName,
  758. &authenticationData,
  759. &authorizationName,
  760. &authorizationData);
  761. }
  762. else
  763. {
  764. decline: ;
  765. send_decline (from, fromlen, &authenticationName,
  766. &authenticationData,
  767. reason);
  768. if (pdpy)
  769. DisposeProtoDisplay (pdpy);
  770. }
  771. }
  772. abort:
  773. XdmcpDisposeARRAY16 (&connectionTypes);
  774. XdmcpDisposeARRAYofARRAY8 (&connectionAddresses);
  775. XdmcpDisposeARRAY8 (&authenticationName);
  776. XdmcpDisposeARRAY8 (&authenticationData);
  777. XdmcpDisposeARRAYofARRAY8 (&authorizationNames);
  778. XdmcpDisposeARRAY8 (&manufacturerDisplayID);
  779. }
  780. void
  781. send_accept (struct sockaddr *to, int tolen, CARD32 sessionID, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr authorizationName, ARRAY8Ptr authorizationData)
  782. {
  783. XdmcpHeader header;
  784. Debug ("Accept Session ID %d\n", sessionID);
  785. header.version = XDM_PROTOCOL_VERSION;
  786. header.opcode = (CARD16) ACCEPT;
  787. header.length = 4; /* session ID */
  788. header.length += 2 + authenticationName->length;
  789. header.length += 2 + authenticationData->length;
  790. header.length += 2 + authorizationName->length;
  791. header.length += 2 + authorizationData->length;
  792. XdmcpWriteHeader (&buffer, &header);
  793. XdmcpWriteCARD32 (&buffer, sessionID);
  794. XdmcpWriteARRAY8 (&buffer, authenticationName);
  795. XdmcpWriteARRAY8 (&buffer, authenticationData);
  796. XdmcpWriteARRAY8 (&buffer, authorizationName);
  797. XdmcpWriteARRAY8 (&buffer, authorizationData);
  798. XdmcpFlush (xdmcpFd, &buffer, (XdmcpNetaddr)to, tolen);
  799. }
  800. void
  801. send_decline (struct sockaddr *to, int tolen, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr status)
  802. {
  803. XdmcpHeader header;
  804. Debug ("Decline %*.*s\n", status->length, status->length, pS(status->data));
  805. header.version = XDM_PROTOCOL_VERSION;
  806. header.opcode = (CARD16) DECLINE;
  807. header.length = 0;
  808. header.length += 2 + status->length;
  809. header.length += 2 + authenticationName->length;
  810. header.length += 2 + authenticationData->length;
  811. XdmcpWriteHeader (&buffer, &header);
  812. XdmcpWriteARRAY8 (&buffer, status);
  813. XdmcpWriteARRAY8 (&buffer, authenticationName);
  814. XdmcpWriteARRAY8 (&buffer, authenticationData);
  815. XdmcpFlush (xdmcpFd, &buffer, (XdmcpNetaddr)to, tolen);
  816. }
  817. void
  818. manage (struct sockaddr *from, int fromlen, int length)
  819. {
  820. CARD32 sessionID;
  821. CARD16 displayNumber;
  822. ARRAY8 displayClass;
  823. int expectlen;
  824. struct protoDisplay *pdpy;
  825. struct display *d;
  826. char *name = NULL;
  827. char *class = NULL;
  828. XdmcpNetaddr from_save;
  829. ARRAY8 clientAddress, clientPort;
  830. CARD16 connectionType;
  831. Debug ("Manage %d\n", length);
  832. displayClass.data = 0;
  833. displayClass.length = 0;
  834. if (XdmcpReadCARD32 (&buffer, &sessionID) &&
  835. XdmcpReadCARD16 (&buffer, &displayNumber) &&
  836. XdmcpReadARRAY8 (&buffer, &displayClass))
  837. {
  838. expectlen = 4 + /* session ID */
  839. 2 + /* displayNumber */
  840. 2 + displayClass.length; /* displayClass */
  841. if (expectlen != length)
  842. {
  843. Debug ("Manage length error got %d expect %d\n", length, expectlen);
  844. goto abort;
  845. }
  846. pdpy = FindProtoDisplay (from, fromlen, displayNumber);
  847. Debug ("Manage Session ID %d, pdpy 0x%x\n", sessionID, pdpy);
  848. if (!pdpy || pdpy->sessionID != sessionID)
  849. {
  850. /*
  851. * We may have already started a session for this display
  852. * but it hasn't seen the response in the form of an
  853. * XOpenDisplay() yet. So check if it is in the list of active
  854. * displays, and if so check that the session id's match.
  855. * If all this is true, then we have a duplicate request that
  856. * can be ignored.
  857. */
  858. if (!pdpy
  859. && (d = FindDisplayByAddress(from, fromlen, displayNumber))
  860. && d->sessionID == sessionID) {
  861. Debug("manage: got duplicate pkt, ignoring\n");
  862. goto abort;
  863. }
  864. Debug ("Session ID %d refused\n", sessionID);
  865. if (pdpy)
  866. Debug ("Existing Session ID %d\n", pdpy->sessionID);
  867. send_refuse (from, fromlen, sessionID);
  868. }
  869. else
  870. {
  871. name = NetworkAddressToName (pdpy->connectionType,
  872. &pdpy->connectionAddress,
  873. pdpy->displayNumber);
  874. Debug ("Computed display name: %s\n", name);
  875. if (!name)
  876. {
  877. send_failed (from, fromlen, "(no name)", sessionID, "out of memory");
  878. goto abort;
  879. }
  880. d = FindDisplayByName (name);
  881. if (d)
  882. {
  883. extern void StopDisplay ();
  884. Debug ("Terminating active session for %s\n", d->name);
  885. StopDisplay (d);
  886. }
  887. class = malloc (displayClass.length + 1);
  888. if (!class)
  889. {
  890. send_failed (from, fromlen, name, sessionID, "out of memory");
  891. goto abort;
  892. }
  893. if (displayClass.length)
  894. {
  895. memmove( class, displayClass.data, displayClass.length);
  896. class[displayClass.length] = '\0';
  897. }
  898. else
  899. {
  900. free ((char *) class);
  901. class = (char *) NULL;
  902. }
  903. from_save = (XdmcpNetaddr) malloc (fromlen);
  904. if (!from_save)
  905. {
  906. send_failed (from, fromlen, name, sessionID, "out of memory");
  907. goto abort;
  908. }
  909. memmove( from_save, from, fromlen);
  910. d = NewDisplay (name, class);
  911. if (!d)
  912. {
  913. free ((char *) from_save);
  914. send_failed (from, fromlen, name, sessionID, "out of memory");
  915. goto abort;
  916. }
  917. d->displayType.location = Foreign;
  918. d->displayType.lifetime = Transient;
  919. d->displayType.origin = FromXDMCP;
  920. d->sessionID = pdpy->sessionID;
  921. d->from = (struct sockaddr *)from_save;
  922. d->fromlen = fromlen;
  923. d->displayNumber = pdpy->displayNumber;
  924. #ifdef BYPASSLOGIN
  925. d->bypassLogin = 0;
  926. #endif /* BYPASSLOGIN */
  927. ClientAddress (from, &clientAddress, &clientPort, &connectionType);
  928. d->useChooser = 0;
  929. if (IsIndirectClient (&clientAddress, connectionType))
  930. {
  931. Debug ("IsIndirectClient\n");
  932. ForgetIndirectClient (&clientAddress, connectionType);
  933. if (UseChooser (&clientAddress, connectionType))
  934. {
  935. d->useChooser = 1;
  936. Debug ("Use chooser for %s\n", d->name);
  937. }
  938. }
  939. d->clientAddr = clientAddress;
  940. d->connectionType = connectionType;
  941. XdmcpDisposeARRAY8 (&clientPort);
  942. if (pdpy->fileAuthorization)
  943. {
  944. d->authorizations = (Xauth **) malloc (sizeof (Xauth *));
  945. if (!d->authorizations)
  946. {
  947. free ((char *) from_save);
  948. free ((char *) d);
  949. send_failed (from, fromlen, name, sessionID, "out of memory");
  950. goto abort;
  951. }
  952. d->authorizations[0] = pdpy->fileAuthorization;
  953. d->authNum = 1;
  954. pdpy->fileAuthorization = 0;
  955. }
  956. DisposeProtoDisplay (pdpy);
  957. Debug ("Starting display %s,%s\n", d->name, d->class);
  958. StartDisplay (d);
  959. }
  960. }
  961. abort:
  962. XdmcpDisposeARRAY8 (&displayClass);
  963. if (name) free ((char*) name);
  964. if (class) free ((char*) class);
  965. }
  966. void
  967. SendFailed (struct display *d, char *reason)
  968. {
  969. Debug ("Display start failed, sending Failed\n");
  970. send_failed (d->from, d->fromlen, d->name, d->sessionID, reason);
  971. }
  972. void
  973. send_failed (struct sockaddr *from, int fromlen, char *name, CARD32 sessionID, char *reason)
  974. {
  975. static char buf[256];
  976. XdmcpHeader header;
  977. ARRAY8 status;
  978. sprintf (buf, "Session %d failed for display %s: %s",
  979. sessionID, name, reason);
  980. Debug ("Send failed %d %s\n", sessionID, buf);
  981. status.length = strlen (buf);
  982. status.data = (CARD8Ptr) buf;
  983. header.version = XDM_PROTOCOL_VERSION;
  984. header.opcode = (CARD16) FAILED;
  985. header.length = 6 + status.length;
  986. XdmcpWriteHeader (&buffer, &header);
  987. XdmcpWriteCARD32 (&buffer, sessionID);
  988. XdmcpWriteARRAY8 (&buffer, &status);
  989. XdmcpFlush (xdmcpFd, &buffer, (XdmcpNetaddr)from, fromlen);
  990. }
  991. void
  992. send_refuse (struct sockaddr *from, int fromlen, CARD32 sessionID)
  993. {
  994. XdmcpHeader header;
  995. Debug ("Send refuse %d\n", sessionID);
  996. header.version = XDM_PROTOCOL_VERSION;
  997. header.opcode = (CARD16) REFUSE;
  998. header.length = 4;
  999. XdmcpWriteHeader (&buffer, &header);
  1000. XdmcpWriteCARD32 (&buffer, sessionID);
  1001. XdmcpFlush (xdmcpFd, &buffer, (XdmcpNetaddr)from, fromlen);
  1002. }
  1003. void
  1004. send_alive (struct sockaddr *from, int fromlen, int length)
  1005. {
  1006. CARD32 sessionID;
  1007. CARD16 displayNumber;
  1008. struct display *d;
  1009. XdmcpHeader header;
  1010. CARD8 sendRunning;
  1011. CARD32 sendSessionID;
  1012. Debug ("Send alive\n");
  1013. if (XdmcpReadCARD16 (&buffer, &displayNumber) &&
  1014. XdmcpReadCARD32 (&buffer, &sessionID))
  1015. {
  1016. if (length == 6)
  1017. {
  1018. d = FindDisplayBySessionID (sessionID);
  1019. if (!d) {
  1020. d = FindDisplayByAddress (from, fromlen, displayNumber);
  1021. }
  1022. sendRunning = 0;
  1023. sendSessionID = 0;
  1024. if (d && d->status == running)
  1025. {
  1026. if (d->sessionID == sessionID)
  1027. sendRunning = 1;
  1028. sendSessionID = d->sessionID;
  1029. }
  1030. header.version = XDM_PROTOCOL_VERSION;
  1031. header.opcode = (CARD16) ALIVE;
  1032. header.length = 5;
  1033. Debug ("alive: %d %d\n", sendRunning, sendSessionID);
  1034. XdmcpWriteHeader (&buffer, &header);
  1035. XdmcpWriteCARD8 (&buffer, sendRunning);
  1036. XdmcpWriteCARD32 (&buffer, sendSessionID);
  1037. XdmcpFlush (xdmcpFd, &buffer, (XdmcpNetaddr)from, fromlen);
  1038. }
  1039. }
  1040. }
  1041. #if NeedWidePrototypes
  1042. char *
  1043. NetworkAddressToHostname (int connectionType, ARRAY8Ptr connectionAddress)
  1044. #else
  1045. char *
  1046. NetworkAddressToHostname (CARD16 connectionType, ARRAY8Ptr connectionAddress)
  1047. #endif
  1048. {
  1049. char *name = 0;
  1050. switch (connectionType)
  1051. {
  1052. case FamilyInternet:
  1053. {
  1054. struct hostent *hostent;
  1055. char dotted[20];
  1056. char *local_name;
  1057. hostent = gethostbyaddr ((char *)connectionAddress->data,
  1058. connectionAddress->length, AF_INET);
  1059. if (hostent)
  1060. local_name = hostent->h_name;
  1061. else {
  1062. /* can't get name, so use emergency fallback */
  1063. sprintf(dotted, "%d.%d.%d.%d",
  1064. connectionAddress->data[0],
  1065. connectionAddress->data[1],
  1066. connectionAddress->data[2],
  1067. connectionAddress->data[3]);
  1068. local_name = dotted;
  1069. LogError ((unsigned char *)"Cannot convert Internet address %s to host name\n",
  1070. dotted);
  1071. }
  1072. if (!getString (name, strlen (local_name)))
  1073. break;
  1074. strcpy (name, local_name);
  1075. break;
  1076. }
  1077. #ifdef DNET
  1078. case FamilyDECnet:
  1079. break;
  1080. #endif /* DNET */
  1081. default:
  1082. break;
  1083. }
  1084. return name;
  1085. }
  1086. static int
  1087. HostnameToNetworkAddress (char *name, CARD16 connectionType, ARRAY8Ptr connectionAddress)
  1088. {
  1089. switch (connectionType)
  1090. {
  1091. case FamilyInternet:
  1092. {
  1093. struct hostent *hostent;
  1094. hostent = gethostbyname (name);
  1095. if (!hostent)
  1096. return FALSE;
  1097. if (!XdmcpAllocARRAY8 (connectionAddress, hostent->h_length))
  1098. return FALSE;
  1099. memmove( connectionAddress->data, hostent->h_addr, hostent->h_length);
  1100. return TRUE;
  1101. }
  1102. #ifdef DNET
  1103. case FamilyDECnet:
  1104. return FALSE;
  1105. #endif
  1106. }
  1107. return FALSE;
  1108. }
  1109. /*
  1110. * converts a display name into a network address, using
  1111. * the same rules as XOpenDisplay (algorithm cribbed from there)
  1112. */
  1113. static int
  1114. NameToNetworkAddress(char *name, CARD16Ptr connectionTypep, ARRAY8Ptr connectionAddress, CARD16Ptr displayNumber)
  1115. {
  1116. char *colon, *display_number;
  1117. char hostname[1024];
  1118. int dnet = FALSE;
  1119. CARD16 number;
  1120. CARD16 connectionType;
  1121. colon = strchr(name, ':');
  1122. if (!colon)
  1123. return FALSE;
  1124. if (colon != name)
  1125. {
  1126. if (colon - name > sizeof (hostname))
  1127. return FALSE;
  1128. strncpy (hostname, name, colon - name);
  1129. hostname[colon - name] = '\0';
  1130. }
  1131. else
  1132. {
  1133. strcpy (hostname, localHostname ());
  1134. }
  1135. if (colon[1] == ':')
  1136. {
  1137. dnet = TRUE;
  1138. colon++;
  1139. }
  1140. #ifndef DNETCONN
  1141. if (dnet)
  1142. return FALSE;
  1143. #endif
  1144. display_number = colon + 1;
  1145. while (*display_number && *display_number != '.')
  1146. {
  1147. if (!isascii (*display_number) || !isdigit(*display_number))
  1148. return FALSE;
  1149. }
  1150. if (display_number == colon + 1)
  1151. return FALSE;
  1152. number = atoi (colon + 1);
  1153. #ifdef DNETCONN
  1154. if (dnet)
  1155. connectionType = FamilyDECnet;
  1156. else
  1157. #endif
  1158. connectionType = FamilyInternet;
  1159. if (!HostnameToNetworkAddress (hostname, connectionType, connectionAddress))
  1160. return FALSE;
  1161. *displayNumber = number;
  1162. *connectionTypep = connectionType;
  1163. return TRUE;
  1164. }