macuuid.pp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. {$mode objfpc}
  2. {$H+}
  3. unit macuuid;
  4. Interface
  5. uses SysUtils;
  6. Function CreateMacGUID(Out GUID : TGUID) : Integer;
  7. Implementation
  8. uses unixtype, sockets, baseunix, unix;
  9. Const
  10. MAX_ADJUSTMENT = 10;
  11. IPPROTO_IP = 0;
  12. // AF_INET = 2;
  13. // SOCK_DGRAM = 2;
  14. IF_NAMESIZE = 16;
  15. SIOCGIFCONF = $8912;
  16. SIOCGIFHWADDR = $8927;
  17. Type
  18. {$packrecords c}
  19. tifr_ifrn = record
  20. case integer of
  21. 0 : (ifrn_name: array [0..IF_NAMESIZE-1] of char);
  22. end;
  23. tifmap = record
  24. mem_start : cardinal;
  25. mem_end : cardinal;
  26. base_addr : word;
  27. irq : byte;
  28. dma : byte;
  29. port : byte;
  30. end;
  31. PIFrec = ^TIFrec;
  32. TIFrec = record
  33. ifr_ifrn : tifr_ifrn;
  34. case integer of
  35. 0 : (ifru_addr : TSockAddr);
  36. 1 : (ifru_dstaddr : TSockAddr);
  37. 2 : (ifru_broadaddr : TSockAddr);
  38. 3 : (ifru_netmask : TSockAddr);
  39. 4 : (ifru_hwaddr : TSockAddr);
  40. 5 : (ifru_flags : word);
  41. 6 : (ifru_ivalue : longint);
  42. 7 : (ifru_mtu : longint);
  43. 8 : (ifru_map : tifmap);
  44. 9 : (ifru_slave : Array[0..IF_NAMESIZE-1] of char);
  45. 10 : (ifru_newname : Array[0..IF_NAMESIZE-1] of char);
  46. 11 : (ifru_data : pointer);
  47. end;
  48. TIFConf = record
  49. ifc_len : longint;
  50. case integer of
  51. 0 : (ifcu_buf : pointer);
  52. 1 : (ifcu_req : ^tifrec);
  53. end;
  54. tuuid = record
  55. time_low : cardinal;
  56. time_mid : Word;
  57. time_hi_and_version : Word;
  58. clock_seq : Word;
  59. node : Array[0..5] of byte;
  60. end;
  61. Var
  62. MacAddr : Packed Array[1..6] of byte = (0,0,0,0,0,0);
  63. MacAddrTried : Byte = 0 ;
  64. Last : TTimeVal = (tv_sec:0;tv_usec:0);
  65. ClockSeq : Word = 0;
  66. AdjustMent : Integer = 0;
  67. Procedure GetRandomBytes(Var Buf; NBytes : Integer);
  68. Var
  69. I : Integer;
  70. P : PByte;
  71. begin
  72. P:=@Buf;
  73. Randomize;
  74. For I:=0 to NBytes-1 do
  75. P[i]:=Random(256);
  76. end;
  77. Function GetMacAddr : Boolean;
  78. var
  79. i,j,n,Sd : Integer;
  80. buf : Array[0..1023] of byte;
  81. ifc : TIfConf;
  82. ifr : TIFRec;
  83. ifp : PIFRec;
  84. p : PChar;
  85. begin
  86. Result:=MacAddrTried>0;
  87. If Result then
  88. Result:=MacAddrTried>1
  89. else
  90. begin
  91. MacAddrTried:=1;
  92. sd:=fpSocket(AF_INET,SOCK_DGRAM,IPPROTO_IP);
  93. if (sd<0) then
  94. exit;
  95. Try
  96. ifc.ifc_len:=Sizeof(Buf);
  97. ifc.ifcu_buf:=@buf;
  98. if fpioctl(sd, SIOCGIFCONF, @ifc)<0 then
  99. Exit;
  100. n:= ifc.ifc_len;
  101. i:=0;
  102. While (Not Result) and (I<N) do
  103. begin
  104. ifp:=PIFRec(PByte(ifc.ifcu_buf)+i);
  105. move(ifp^.ifr_ifrn.ifrn_name,ifr.ifr_ifrn.ifrn_name,IF_NAMESIZE);
  106. if (fpioctl(sd, SIOCGIFHWADDR, @ifr) >= 0) then
  107. begin
  108. P:=Pchar(@ifr.ifru_hwaddr.sa_data);
  109. Result:=(p[0]<>#0) or (p[1]<>#0) or (p[2]<>#0)
  110. or (p[3]<>#0) or (p[4]<>#0) or (p[5]<>#0);
  111. If Result Then
  112. begin
  113. Move(P^,MacAddr,SizeOf(MacAddr));
  114. MacAddrTried:=2;
  115. // DumpMacAddr;
  116. end;
  117. end;
  118. I:=I+sizeof(tifrec);
  119. end;
  120. Finally
  121. fileClose(sd);
  122. end;
  123. end;
  124. end;
  125. Function GetClock(Var ClockHigh,ClockLow : Cardinal; Var RetClockSeq : Word) : boolean;
  126. Var
  127. TV : TTImeVal;
  128. ClockReg : QWord;
  129. OK : Boolean;
  130. begin
  131. OK:=True;
  132. Repeat
  133. FPGetTimeOfDay(@Tv,Nil);
  134. If (Last.tv_sec=0) and (last.tv_sec=0) then
  135. begin
  136. GetRandomBytes(ClockSeq,SizeOf(ClockSeq));
  137. ClockSeq:=ClockSeq and $1FFF;
  138. last:=TV;
  139. Dec(last.tv_sec);
  140. end;
  141. if (tv.tv_sec<last.tv_sec) or
  142. ((tv.tv_sec=last.tv_sec) and (tv.tv_usec<last.tv_usec)) then
  143. begin
  144. ClockSeq:=(ClockSeq+1) and $1FFF;
  145. Adjustment:=0;
  146. Last:=Tv;
  147. end
  148. else if (tv.tv_sec=last.tv_sec) and (tv.tv_usec=last.tv_usec) then
  149. begin
  150. If Adjustment>=MAX_ADJUSTMENT then
  151. OK:=False
  152. else
  153. inc(AdjustMent);
  154. end
  155. else
  156. begin
  157. AdjustMent:=0;
  158. Last:=tv;
  159. end;
  160. Until OK;
  161. ClockReg:=tv.tv_usec*10+adjustment;
  162. Inc(ClockReg,tv.tv_sec*10000000);
  163. Inc(ClockReg,($01B21DD2 shl 32) + $13814000);
  164. ClockHigh :=Hi(ClockReg);
  165. ClockLow :=Lo(ClockReg);
  166. RetClockSeq :=ClockSeq;
  167. Result :=True;
  168. end;
  169. Procedure UUIDPack(Const UU : TUUID; Var GUID : TGUID);
  170. Var
  171. tmp : Cardinal;
  172. P : PByte;
  173. begin
  174. P:=PByte(@GUID);
  175. tmp:=uu.time_low;
  176. P[3]:=tmp and $FF;
  177. tmp:=tmp shr 8;
  178. P[2]:=tmp and $FF;
  179. tmp:=tmp shr 8;
  180. P[1]:=tmp and $FF;
  181. tmp:=tmp shr 8;
  182. P[0]:=tmp and $FF;
  183. tmp:=uu.time_mid;
  184. P[5]:=tmp and $FF;
  185. tmp:=tmp shr 8;
  186. P[4]:=tmp and $FF;
  187. tmp:=uu.time_hi_and_version;
  188. P[7]:=tmp and $FF;
  189. tmp:=tmp shr 8;
  190. P[6]:=tmp and $FF;
  191. tmp:=uu.clock_seq;
  192. P[9]:=tmp and $FF;
  193. tmp:=tmp shr 8;
  194. P[8]:=tmp and $FF;
  195. Move(uu.node,P[10],6);
  196. end;
  197. Procedure DumpMacAddr;
  198. var
  199. I : Integer;
  200. begin
  201. Write('Mac Addr: ');
  202. For i:=1 to 6 do
  203. write(hexstr(MacAddr[i],2),':');
  204. end;
  205. Function CreateMacGUID(Out GUID : TGUID) : Integer;
  206. Var
  207. UU : TUUId;
  208. ClockMid : Cardinal;
  209. begin
  210. Result:=Ord(not GetMacAddr);
  211. If (Result=0) then
  212. begin
  213. // DumpMacAddr;
  214. // Writeln;
  215. GetClock(ClockMid,uu.time_low,uu.clock_seq);
  216. uu.Clock_seq:=uu.Clock_seq or $8000;
  217. uu.time_mid:=lo(clockMid);
  218. uu.time_hi_and_version:=hi(ClockMid) or $1000;
  219. move(MacAddr,uu.node,sizeof(MacAddr));
  220. UUIDPack(UU,GUID);
  221. end;
  222. end;
  223. initialization
  224. OnCreateGUID:=@CreateMacGUID;
  225. end.