C/400

40. 遠隔PC名の取得

ここでは IPアドレスから、そのPCの名前を取得するプログラムを紹介しよう。
IPアドレスからそのクライアントPCの名前を取得することは弊社製品 EnterpriseServer Ver5.0<
の開発にとって重要であった。
Web化、とりわけ Ver5.0 に初めて搭載された「AutoWeb」という WebFacing機能は導入するだけで
従来の5250画面が直ちに Web化されて表示されるというものである。
ここで、ただちに Web化されるというのはユーザーにとって非常に工数を少なくして容易にWebに
移行できるという画期的なものであるが問題は、その実行環境である。
5250エミュレーターを使用していても従来の適用業務では端末毎の明示的な名前が与えられて
いることが一般的である。
KEI001, KEI002, ... のような端末名に対してプリンターを割り振ったりジョブ名を識別して様々な
制御を行っているはずである。
ところが Web からとなるとクライアントの識別として IPアドレスしか取得することができないのである。
固定IPであれば IPアドレス毎に端末名のテーブルを用意しておいて変換することができるが
DHCPサーバー経由であれば IPアドレスは自動発生するので端末名を特定することができない。
この難題を解決するのが、ここに紹介する「遠隔PC名の取得」である。
原理は NetBios を使って構内LAN のPCへ直接、サーバー(System i) 側からその名前を
問い合わせるのである。
つまり Httpサーバー Alaska は、接続要求があるとその名前を本人(PC) に問い合わせて
その名前で AutoWeb の仮想端末ジョブを開始する。
このような仕組みであれば、PC の名前さえ正しく登録しておけば System i の開始CLP などを
一切変更することなく Webであっても 5250適用業務と同じようにジョブ名を使用することが
できるのである。
おまけにここに紹介する遠隔PC名の取得では PC固有の Macアドレスさえも取得することができる。
これは退職社員による「成りすまし」を防止することができることを意味している。
さて、NET コマンドなどの NetBios に関するインターネットの日本語のサイトはインターネットを
検索すればゴマンと出てくるに違いないが NetBios 問い合わせのソースはMicrosoft を初めとして、
恐らく読者は見つけることはできないと思う。
ここに紹介する「遠隔PC名の取得」のプログラム・ソースは唯一筆者が見つけた Perl のソースを
C/400 に書き直したものである。
このプログラムはクライアント/サーバー・モデルの適用業務でサーバー側で威力を発揮するにちがいない。

[ C/400 : RTVPCNAME ]
0001.00 /********************************************************************/  
0002.00 /*                                                                  */  
0003.00 /*   RTVPCNAM    :   遠隔PC名の取得                               */  
0004.00 /*                                                                  */  
0005.00 /*          Office Quattro Co,.Ltd 2007/10/16 13:35:47 created      */  
0006.00 /*                                                                  */  
0007.00 /*          このプログラムは AUTOWEB から呼び出されて               */  
0008.00 /*          NetBios によって遠隔のPCの名前を取得します。          */  
0009.00 /*                                                                  */  
0010.00 /*          CRTCMOD RTVPCNAM                                        */  
0011.00 /*          CRTPGM ASNET.COM/RTVPCNAM BNDSRVPGM(CVTMOD4)            */  
0012.00 /*                                                                  */  
0013.00 /********************************************************************/  
0014.00 #pragma comment(COPYRIGHT, "as400-net.com EnterpriseServer (C) CopyRigh 
0015.00 Office Quattro.Corp. 2007- All right reserved. Users Restricted        
0016.00 Rights - Use, duplication or disclosure restricted by Office Quattro   
0017.00 Corp. Licenced Materials-Property of Office Quattro.")                  
0018.00 #include <stdio.h>                                                      
0019.00 #include <stdlib.h>                                                     
0020.00 #include <string.h>                                                     
0021.00 #include <sys/socket.h>                                               
0022.00 #include <sys/types.h>                                                
0023.00 #include <netinet/in.h>                                               
0024.00 #include <netinet/tcp.h>                                              
0025.00 #include <arpa/inet.h>                                                
0026.00 #include <errno.h>                                                    
0027.00 #include <netdb.h>                                                    
0028.00 #include <micomput.h> /* triml */                                     
0029.00                                                                       
0030.00 #define TRUE         0                                                
0031.00 #define FALSE       -1                                                
0032.00 typedef struct {                                                      
0033.00    int  BYTESPRO;                                                     
0034.00    int  BYTESAVL;                                                     
0035.00    char MSGID[7];                                                     
0036.00    char RESRVD;                                                       
0037.00    char EXCPDATA[100];                                                
0038.00 } ERRSTRUCTURE;     /* Define the error return structure            */
0039.00 ERRSTRUCTURE  errcode;/* Error Code Structure for RCVMSG      */      
0040.00 /* char addr[13] = "192.168.1.11"; */                                 
0041.00 char* remote_addr;                                                    
0042.00 int PORT = 137;                                                         
0043.00                                                                         
0044.00 /*************************************************************/         
0045.00 /*       内 部 使 用  関  数                          */         
0046.00 /*************************************************************/         
0047.00 void  GetParam(int argc, char *argv[]);                                 
0048.00 void  INZSR(void);                                                      
0049.00 void  err_log(char* msg, int opt, char* function, int line);            
0050.00                                                                         
0051.00 /*************************************************************/         
0052.00 /*       IMPORT  関  数                            */         
0053.00 /*************************************************************/         
0054.00 int   toEBCDIC(char* ebcbuf, char* ascbuf, char table[10],char tbllib[1 
0055.00               int bSISO);                                               
0056.00 /*************************************************************/         
0057.00 /*       外 部 呼 出 し  関  数                      */         
0058.00 /*************************************************************/         
0059.00 /*************************************************************/         
0060.00 /*        グ ロ ー バ ル 変 数                         */         
0061.00 /*************************************************************/         
0062.00   /*------( 受取りパラメータ値 )----------*/                            
0063.00                                                                         
0064.00 /********************************************************************/  
0065.00 /*            m  a  i  n --- main module of this pgm                */  
0066.00 /*                                                                  */  
0067.00 /*          <PARAMETER> 1. PCNAME[10]                               */  
0068.00 /*                                                                  */  
0069.00 /*------------------------------------------------------------------*/  
0070.00                                                                         
0071.00 int  main(int argc, char *argv[]){                                      
0072.00    int i, sockfd, len, rc, addr_len;                                    
0073.00   struct sockaddr_in iaddr;                                             
0074.00    char buff[256];                                                      
0075.00    char request[] = { 0xa2, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,   
0076.00                       0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x4b, 0x41,   
0077.00                       0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,   
0078.00                       0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,   
0079.00                       0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,   
0080.00                       0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x21,   
0081.00                       0x00, 0x01};                                      
0082.00    int offset, rep, pi;                                 
0083.00    char type, class, name[17], typestr[128];            
0084.00    char ebc_name[20];                                                   
0085.00                                                                         
0086.00    GetParam(argc, argv);  /*[ パラメータの取得 ]*/                      
0087.00    INZSR();               /*[ 初期設定 ]*/                              
0088.00   /*-------------------------------------------------------*/           
0089.00   /*         socket : Get a socket descriptor              */           
0090.00   /*-------------------------------------------------------*/           
0091.00   if((sockfd = socket(PF_INET, SOCK_DGRAM, 0 )) < 0){                   
0092.00      perror("RTVPCNAM SOCKET"); getchar(); exit(0);                     
0093.00   }                                                                     
0094.00   /*-----------------------------------------------------------*/       
0095.00   /* connect: connect to the server using a set of port number */       
0096.00   /*-----------------------------------------------------------*/       
0097.00   memset(&iaddr, 0x00, sizeof(struct sockaddr_in));                     
0098.00   iaddr.sin_family = PF_INET;                                           
0099.00   iaddr.sin_port  = htons(PORT); /* PORT no set*/                       
0100.00   iaddr.sin_addr.s_addr = inet_addr(remote_addr);/* IP の設定 20071015  
0101.00                                                                         
0102.00   rc = connect(sockfd, (struct sockaddr *)&iaddr, sizeof(iaddr));       
0103.00   if(rc < 0){                                                           
0104.00      printf("%s %x-%x--", remote_addr,iaddr.sin_addr.s_addr,iaddr.sin_p 
0105.00      perror("RTVPCNAM CONNECT"); getchar(); exit(0);                 
0106.00   }                                                                  
0107.00   /*-----------------------------------------------------------*/    
0108.00   /*   send a message to the server using secure session       */    
0109.00   /*-----------------------------------------------------------*/    
0110.00   len = sizeof(request);                                             
0111.00   rc = send(sockfd, request, len, 0);                                
0112.00   if(rc != len){                                                     
0113.00      if(rc < 0){                                                     
0114.00        perror("SEND"); getchar(); exit(0);                           
0115.00      }                                                               
0116.00      else{                                                           
0117.00        printf("SEND did not all datan");                            
0118.00        getchar(); exit(0);                                           
0119.00      }                                                               
0120.00   }                                                                  
0121.00   /*-----------------------------------------------------------*/    
0122.00   /*   receive the message from the server using SOCKET        */    
0123.00   /*-----------------------------------------------------------*/    
0124.00   memset(buff, 0, sizeof(buff));                                     
0125.00   len = sizeof(buff);                  
0126.00   rc = recv(sockfd, buff, len, 0);                                 
0127.00   if(rc < 0){                                                      
0128.00        perror("RTVPCNAM RECV"); getchar(); exit(0);                
0129.00   }                                                                
0130.00    close(sockfd);                                                  
0131.00    /* 2007/10/14 NetBIOSプロパティ の出力 */                          
0132.00    offset = 57;              /*  ここから プロパティ */               
0133.00    rep = buff[offset-1];     /* プロパティ 数を取得 */                
0134.00    for(pi=0; pi<rep; pi++){/* プロパティ 数の ループ*/                  
0135.00        memcpy(name, &buff[offset],14); /*  名称を コピー */          
0136.00        name[14] = 0;                   /* Null STOP 設定 */        
0137.00        type = buff[offset+15];      /* タイプ の取得 */              
0138.00        class = buff[offset+16];     /* クラス の取得 */               
0139.00        if(class == 0xc4){/* グループ 名の取得 */                     
0140.00            switch(type){/*switch*/                                 
0141.00            case 0x00:                                              
0142.00                strcpy(typestr, "Domain Name");                     
0143.00                break;                                              
0144.00            case 0x01:                                              
0145.00                strcpy(typestr, "Master Browser");                  
0146.00                break;                                              
0147.00            case 0x1c:                                              
0148.00                strcpy(typestr, "Domain Controllers");              
0149.00                break;                                              
0150.00            case 0x1e:                                              
0151.00                strcpy(typestr, "Browser Service Elections");       
0152.00                break;                                              
0153.00            default:                                                
0154.00                strcpy(typestr, " ");                               
0155.00                break;                                              
0156.00            }/*switch*/                                             
0157.00        }/* グループ 名の取得 */                                      
0158.00        else{/* unique 名の取得 */                                  
0159.00            switch(type){/*switch*/                                 
0160.00            case 0x00:                                              
0161.00                strcpy(typestr, "Workstation Service");             
0162.00                break;                                              
0163.00            case 0x01:                                              
0164.00            case 0x03:                                              
0165.00                strcpy(typestr, "Messenger Service");               
0166.00                break;                                              
0168.00                strcpy(typestr, "RAS Server Service");                 
0169.00                break;                                                 
0170.00            case 0x1b:                                                 
0171.00                strcpy(typestr, "Domain Master Browser");              
0172.00                break;                                                 
0173.00            case 0x1d:                                                 
0174.00                strcpy(typestr, "Master Browser");                     
0175.00                break;                                                 
0176.00            case 0x1f:                                                 
0177.00                strcpy(typestr, "NetDDE Service");                     
0178.00                break;                                                 
0179.00            case 0x20:                                                 
0180.00                strcpy(typestr, "File Server Service");                
0181.00                break;                                                 
0182.00            case 0x21:                                                 
0183.00                strcpy(typestr, "RAS Client Service");                 
0184.00                break;                                                 
0185.00            case 0x22:                                                 
0186.00  strcpy(typestr, "Microsoft Exchange Interchange(MSMail Connector)"); 
0187.00                break;                                                 
0188.00            case 0x23:                                                 
0189.00                strcpy(typestr, "Microsoft Exchange Store");             
0190.00                break;                                                   
0191.00            case 0x24:                                                   
0192.00                strcpy(typestr, "Microsoft Exchange Directory");         
0193.00                break;                                                   
0194.00            case 0x30:                                                   
0195.00                strcpy(typestr, "Modem Sharing Server Service");         
0196.00                break;                                                   
0197.00            case 0x31:                                                   
0198.00                strcpy(typestr, "Modem Sharing Client Service");         
0199.00                break;                                                   
0200.00            case 0x43:                                                   
0201.00                strcpy(typestr, "SMS Clients Remote Control");           
0202.00                break;                                                   
0203.00            case 0x44:                                                   
0204.00                strcpy(typestr, "SMS Administrators Remote Control Tool" 
0205.00                break;                                                   
0206.00            case 0x45:                                                   
0207.00                strcpy(typestr, "SMS Clients Remote Chat");              
0208.00                break;                                                   
0209.00            case 0x46:                                                   
0210.00                strcpy(typestr, "SMS Clients Remote Transfer");          
0211.00                break;                                                   
0212.00            case 0x4c:                                                   
0213.00            case 0x52:                                                   
0214.00                strcpy(typestr, "DEC Pathworks TCPIP service on Windows  
0215.00                break;                                                   
0216.00            case 0x42:                                                   
0217.00                strcpy(typestr, "mccaffee anti-virus");                  
0218.00                break;                                                   
0219.00            case 0x87:                                                   
0220.00                strcpy(typestr, "Microsoft Exchange MTA");               
0221.00                break;                                                   
0222.00            case 0x6a:                                                   
0223.00                strcpy(typestr, "Microsoft Exchange IMC");               
0224.00                break;                                                   
0225.00            case 0xbe:                                                   
0226.00                strcpy(typestr, "Network Monitor Agent");                
0227.00                break;                                                   
0228.00            case 0xbf:                                                   
0229.00                strcpy(typestr, "Network Monitor Application");          
0230.00                break;                                                   
0231.00            default:                                                 
0232.00                strcpy(typestr, " ");                                
0233.00                break;                                               
0234.00            }/*switch*/                                              
0235.00        }/* unique 名の取得 */                                       
0236.00        /* name の文字列を EBCDIC に変換してください */              
0237.00        /* EBCDIC に変換できないので テスト 印刷 */                     
0238.00        memset(ebc_name, 0, sizeof(ebc_name));                       
0239.00        toEBCDIC(ebc_name, name, "EBCDIC5035", "ASNET.COM ", TRUE);  
0240.00        ebc_name[10] = 0x00;                                         
0241.00        len = triml(ebc_name, ' ');                                  
0242.00        if(len > 0) ebc_name[len] = 0x00;                            
0243.00        while(strlen(ebc_name) < 10) strcat(ebc_name, " ");          
0244.00        memcpy(argv[1], ebc_name, 10); /* 10 桁の PC 名を取得 */     
0245.00        break;                                                       
0246.00        /* テスト 印刷ここまで */                                       
0247.00        offset += 18;                                                
0248.00    }/* プロパティ 数の ループ*/                                          
0249.00    exit(0);                                                         
0250.00                                                                     
0252.00 /*************************************/                              
0253.00 void  GetParam(int argc, char *argv[])                               
0254.00 /*************************************/                              
0255.00 {                                                                    
0256.00    char env[256];                                                    
0257.00                                                                      
0258.00 }                                                                    
0259.00 /****************/                                                   
0260.00 void  INZSR(void)                                                    
0261.00 /****************/                                                   
0262.00  {                                                                   
0263.00                                                                      
0264.00     errcode.BYTESPRO = errcode.BYTESAVL = 0;                         
0265.00     remote_addr = getenv("REMOTE_ADDR");                             
0266.00  }                                                                   
0267.00 /********************************************************/           
0268.00 void  err_log(char* msg, int opt, char* err_at, int line)            
0269.00 /********************************************************/           
0270.00 {                                                                    
0271.00     fprintf(stderr, "%sn", msg);                                    
0272.00     fprintf(stderr, " ->ERR AT = %s, LINE = %dn", err_at, line);    
0273.00     if(opt == TRUE)                            
0274.00       fprintf(stderr, "%sn", strerror(errno));
0275.00 }