*DECK FFSUVIP 
USETEXT TEXTFFS 
      FUNC FFSUVIP(BUFF, LEN) B;
# TITLE FFSUVIP - VALIDATE IP ADDRESS.                                 #
  
      BEGIN                            # FFSUVIP                       #
  
# 
**    FFSUVIP - VALIDATE IP ADDRESS.
* 
*     A. LIM                           88/10/11 
* 
*     THIS PROCEDURE VALIDATES THAT THE IP ADDRESS IS IN THE CORRECT
*     FOLLOWING FORMAT: H1.H2.H3.H4 
*               WHERE -  H1, H2, H3, AND H4 ARE DECIMAL NUMBERS 
*                        EACH SEPARATED BY A DECIMAL POINT WITH 
*                        VALUE 0 - 255. NETWORK AND HOST NUMBERS ARE
*                        NOT ALLOWED TO HAVE VALUES OF ALL ZEROES OR
*                        ALL ONES WHEN VIEWED IN BINARY FORMAT. 
* 
*     FUNC FFSUVIP(BUFF, LEN) B 
* 
*     ENTRY   BUFF = BUFFER CONTAINING ASCII STRING.
*             LEN  = LENGTH OF *BUFF* IN OCTETS.
* 
*     EXIT    ONE OR MORE OF THE FOLLOWING: 
* 
*               FFSUVIP  = TRUE => IP ADDRESS IS IN CORRECT FORMAT
*                                  AND VALUE WITHIN RANGE.
*               PARMS[3] = IP ADDRESS IN ASCII. 
*               PARMS[4] = IP ADDRESS IN DISPLAY CODE.
*               PARMS[5] = IP ADDRESS IN BINARY INTERNET FORMAT.
* 
*               FFSUVIP = FALSE => IP ADDRESS IS INCORRECT. 
* 
*     NOTE      PARMS IS DEFINED IN *TEXTFFS*.
* 
*     METHOD    VALIDATE THAT THE IP ADDRESS IS IN CORRECT FORMAT 
*               AND THE VALUE OF THE NETWORK AND HOST PARTS OF THE
*               ADDRESS ARE VALID (SEE RFC 1123, SECTION 3.2.1.3).
* 
# 
  
# 
****  PROC FFSUVIP - XREF LIST
# 
      XREF
        BEGIN 
        PROC FFSUCIA;                  # CONVERT IP ADDRESS            #
        PROC NETUCAC;                  # COPY AN ASCII CHARACTER       #
        PROC NETUCAD;                  # CONVERT ASCII TO DISPLAY CODE #
        PROC NETUCAS;                  # COPY ASCII STRING             #
        PROC XDXB;                     # CONVERT DISPLAY CODE TO BINARY#
        END 
# 
****
# 
  
      ARRAY BUFF [00:00] S(1);         # BUFFER CONTAINING ASCII STRING#
        BEGIN 
        ITEM BUFF$WORD  U(00,00,60);
        END 
  
      ITEM LEN           I;            # LENGTH OF *BUFF* IN OCTETS    #
  
  
      ITEM DIND          I;            # DESTINATION INDEX             #
      ITEM DINDEX        I;            # DESTINATION INDEX             #
      ITEM EOS           B;            # END OF STRING INDICATOR       #
      ITEM I             I;            # LOOP INDUCTION VARIABLE       #
      ITEM J             I;            # LOOP INDUCTION VARIABLE       #
      ITEM NUM           I;            # NUMBER IN BINARY              #
      ITEM SINDEX        I;            # SOURCE INDEX                  #
      ITEM TOKENA        U;            # TOKEN IN ASCII                #
      ITEM TOKENDC       U;            # TOKEN IN DISPLAY CODE         #
  
      ARRAY THISCHAR [00:00] S(1);     # CURRENT CHARACTER             #
        BEGIN 
        ITEM THISCHR     U(00,00,08); 
        END 
  
      CONTROL EJECT;
      PROC FFS1GNC; 
      BEGIN                            # FFS1GNC                       #
# 
**    INTERNAL PROCEDURE - FFS1GNC
* 
*     THIS INTERNAL PROCEDURE GETS THE NEXT CHARACTER.
* 
# 
      DIND = 0; 
      NETUCAC(BUFF, SINDEX, 
              THISCHAR, DIND);         # GET NEXT CHARACTER            #
      SINDEX = SINDEX + 1;             # INCREMENT CHARACTER INDEX     #
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FFS1GNC                       #
  
  
      CONTROL EJECT;
      FUNC FFS1ANT B; 
      BEGIN                            # FFS1ANT                       #
# 
**    FFS1ANT - ASSEMBLE NEXT TOKEN.
* 
*     A. LIM                           88/10/12 
* 
*     THIS EMBEDDED FUNCTION ASSEMBLES AND VALIDATES A TOKEN. 
*     A TOKEN IS DEFINED TO BE A DECIMAL NUMBER WITH
*     A VALUE OF 0 - 255. 
* 
*     ENTRY  BUFF    = BUFFER CONTAINING ASCII CHARACTER STRING.
*            LEN     = LENGTH OF *BUFF* IN OCTETS.
*            SINDEX  = INDEX OF NEXT CHARACTER INTO *BUFF*. 
* 
*     EXIT   FFS1ANT = TRUE => A VALID TOKEN ASSEMBLED, AND 
*                              *SINDEX* POINTS TO THE BEGINNING 
*                              OF NEXT POSSIBLE TOKEN.
*            FFS1ANT = FALSE => TOKEN IS INVALID. 
# 
  
      FFS1ANT = FALSE;                 # DEFAULT TO INVALID TOKEN      #
      TOKENA  = 0;                     # ZERO OUT ASCII TOKEN          #
      TOKENDC = 0;                     # ZERO OUT DISPLAY CODE TOKEN   #
      DINDEX  = 0;                     # INITIALIZE INDEX TO 0         #
# 
*     TOKEN COMPRISES OF 1 TO 3 DIGITS, FROM 0 TO 9, AND SEPARATED
*     BY A PERIOD.
# 
  
      FOR J = 0 STEP 1                   # LOOP TILL                   #
        WHILE     (NOT EOS)              # END OF STRING, OR           #
              AND (J LQ 2)               # MORE THAN 3 CHARACTERS, OR  #
              AND (THISCHR GQ ASCIZERO)  # NOT 0 TO 9                  #
              AND (THISCHR LQ ASCININE) 
      DO
        BEGIN 
        NETUCAC(THISCHAR, 0,             # STORE CHARACTER INTO TOKEN  #
                TOKENA, DINDEX);
        IF SINDEX LS LEN
        THEN
          BEGIN                          # MORE CHARACTERS TO PARSE    #
          FFS1GNC;                       # GET NEXT CHARACTER          #
          END 
        ELSE
          BEGIN 
          EOS = TRUE;                    # EXIT LOOP                   #
          END 
  
        END 
  
# 
*     TOKEN INVALID IF: 
*       1) NOT END OF STRING, BUT NOT SEPARATED BY PERIOD, OR 
*       2) END OF STRING, BUT TOKEN CONTAINING NON-DIGIT CHARACTER. 
# 
  
      IF    ((SINDEX LS LEN) AND (THISCHR NQ ASCIPERIOD)) 
         OR ((SINDEX EQ LEN) AND ((THISCHR LS ASCIZERO) OR
              (THISCHR GR ASCININE))) 
      THEN
        BEGIN                          # NOT END OF STRING             #
        RETURN;                        # GET OUT OF HERE QUICKLY       #
        END 
# 
*     VALID TOKEN.
# 
  
      DINDEX = 0; 
      NETUCAD(TOKENA, 0, J,            # CONVERT TOKEN TO DISPLAY CODE #
              TOKENDC, DINDEX); 
  
      XDXB(TOKENDC, 1, NUM);           # CONVERT DISPLAY CODE TO BINARY#
      IF (NUM LS 0) OR (NUM GR 255) 
      THEN
        BEGIN                          # VALUE NOT IN RANGE            #
        RETURN;                        # GET OUT OF HERE QUICKLY       #
        END 
  
      FFS1ANT = TRUE;                  # VALID TOKEN                   #
  
  
      RETURN; 
  
      END                              # FFS1ANT                       #
      CONTROL EJECT;
# 
*     START MAIN PROCEDURE
# 
  
      FFSUVIP = FALSE;                 # DEFAULT TO INVALID IP ADDRESS #
  
      IF LEN EQ 0 
      THEN
        BEGIN 
        RETURN;                        # ZERO LENGTH, INVALID IP ADDR  #
        END 
  
      EOS    = FALSE;                  # INITIALIZE TO NOT ENDOF STRING#
      SINDEX = 0;                      # INITIALIZE SOURCE INDEX       #
      FOR I = 0 STEP 1                 # LOOP TILL                     #
        WHILE (SINDEX LS LEN) AND      # ENTIRE STRING , OR            #
              (I LQ 3)                 # 4 DECIMAL NUMBER              #
      DO
        BEGIN 
        FFS1GNC;                       # GET FIRST CHARACTER OF TOKEN  #
        IF NOT FFS1ANT
        THEN
          BEGIN                        # NOT A VALID DECIMAL NUMBER    #
          RETURN;                      # GET OUT OF HERE QUICKLY       #
          END 
        END 
  
      IF    (I LS 4)
         OR ((I EQ 4) AND (SINDEX LS LEN))
      THEN
        BEGIN                          # IP ADDRESS NOT 4 NUMBERS      #
        RETURN;                        # GET OUT OF HERE QUICKLY       #
        END 
  
# 
*     COPY VALIDATED IP ADDRESS (ASCII) INTO PARMS[3].
# 
  
      SINDEX = 0; 
      DINDEX = 0; 
      NETUCAS(BUFF, SINDEX, LEN,
              PARMS[3], DINDEX);
      PARAMSZ[3] = LEN;                # LENGTH OF IP ADDRESS          #
  
# 
*     CONVERT IP ADDRESS FROM ASCII TO DISPLAY CODE, AND STORE INTO 
*     PARMS[4]. 
# 
      SINDEX = 0; 
      DINDEX = 0; 
      NETUCAD(PARMS[3], SINDEX, PARAMSZ[3], 
              PARMS[4], DINDEX);
  
# 
*     CONVERT DISPLAY CODE FORM OF IP ADDRESS INTO INTERNET FORMAT AND
*     STORE INTO PARMS[5].
# 
      FFSUCIA(PARMS[4], PARMS[5]);     # CONVERT IP ADDRESSES ROUTINE  #
  
      P<I$DADR$REC> = LOC (PARMS[5]); 
      FFSUVIP = (I$DADR$NET NQ 0) AND  # VALIDATE IP ADDRESS           #
                (I$DADR$HST NQ 0);
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # FFSUVIP                       #
  
      TERM
