text: /**************************************************************************
   *
   * Copyright (c) 2013 Alcatel-Lucent
   *
   * Alcatel Lucent licenses this file to You under the Apache License,
   * Version 2.0 (the "License"); you may not use this file except in
   * compliance with the License.  A copy of the License is contained the
   * file LICENSE at the top level of this repository.
   * You may also obtain a copy of the License at:
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   **************************************************************************
   *
   * dhcp_01.c:
   * This is the PPA-specific code used for Videotron Market trial.
   * It was built from the dhcp_00.c DHCP-extension template file.
   *
   * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
   *
   */
  
  #include "config.h"
  #include "cpuio.h"
  #include "ether.h"
  #include "tfs.h"
  #include "tfsprivate.h"
  #include "genlib.h"
  #include "stddefs.h"
  
  /* Vendor specific option definitions: */
  #define VS_PROXYIP      1
  #define VS_PHONENUM     2
  #define VS_CODER        3
  #define VS_PPADHCPSRVR  4
  #define VS_MINNETDELAY  5
  #define VS_MAXNETDELAY  6
  #define VS_APPINFO      7
  #define VS_CODERCTL     8
  #define VS_NAMEVAL      99
  
  #define PPADHCPSRVR_STR "PPADHCPSRVR"
  
  /* ValidDHCPOffer():
   *  Target issued the DISCOVER, the incoming packet is the server's
   *  OFFER reply.  If the offer contains the vendor specific
   *  VS_PPADHCPSRVR option and the string within that
   *  option is correct, then accept the offer; by issuing a request.
   */
  ValidDHCPOffer(struct   dhcphdr *dhdr)
  {
      uchar   *op, *op1;
  
      op = op1 = 0;
      op1 = DhcpGetOption(DHCPOPT_VENDORSPECIFICINFO,dhdr+1);
      if(op1) {
          op = DhcpGetOption(VS_PPADHCPSRVR,op1+2);
      }
      if(op) {
          if(!strncmp(op+2,PPADHCPSRVR_STR,sizeof(PPADHCPSRVR_STR)-1)) {
              return(1);
          }
      }
      return(0);
  }
  
  /* buildDhcpHdr():
   *  Called by dhcpboot.c to allow application-specific header stuff to
   *  be added to header.  Return 0 if generic stuff in dhcpboot.c is to be
   *  used; else return 1 and the calling code will assume this function is
   *  dealing with it (see dhcpboot.c for basic idea).
   */
  int
  buildDhcpHdr(struct dhcphdr *dhcpdata)
  {
      return(0);
  }
  
  /* DhcpBootpDone():
   *  Called at the end of the Bootp or Dhcp transaction.
   *  Input...
   *  bootp:  1 if BOOTP; else DHCP.
   *  dhdr:   pointer to dhcp or bootp header.
   *  vsize:  size of vendor specific area (for bootp this is fixed at 64,
   *          but for dhcp it is variable).
   */
  void
  DhcpBootpDone(int bootp, struct dhcphdr *dhdr, int vsize)
  {
      return;
  }
  
  void
  SetPPAOption(type,op1,varname)
  int     type;
  uchar   *op1;
  char    *varname;
  {
      uchar   *op, tmp;
  
      op = DhcpGetOption(type,op1+2);
      if(op) {
          tmp = op[*(op+1)+2];
          op[*(op+1)+2] = 0;
          DhcpSetEnv(varname,op+2);
          op[*(op+1)+2] = tmp;
      }
  }
  
  /* DhcpVendorSpecific():
   *  Process vendor specific stuff within the incoming dhcp header.
   */
  DhcpVendorSpecific(struct   dhcphdr *dhdr)
  {
      ulong   ip;
      uchar   *op, *op1, buf[16], tmp;
  
      op = op1 = 0;
      op1 = DhcpGetOption(DHCPOPT_VENDORSPECIFICINFO,dhdr+1);
      if(op1) {
          /* Get PROXY_IP and BPROXY_IP (optionally): */
          op = DhcpGetOption(VS_PROXYIP,op1+2);
          if(op) {
              memcpy(&ip,op+2,4);
              DhcpSetEnv("PROXY_IP",IpToString(ip,buf));
              if(*(op+1) == 8) {
                  memcpy(&ip,op+6,4);
                  DhcpSetEnv("BPROXY_IP",IpToString(ip,buf));
              }
          }
  
          /* Get PPA phone numbers (1 or 2). */
          op = DhcpGetOption(VS_PHONENUM,op1+2);
          if(op) {
              char *space;
              tmp = op[*(op+1)+2];
              op[*(op+1)+2] = 0;
              space = strchr(op+2,' ');
              if(space) {
                  *space = 0;
                  DhcpSetEnv("LINE0_NUMBER",op+2);
                  DhcpSetEnv("LINE1_NUMBER",space+1);
                  *space = ' ';
              } else {
                  DhcpSetEnv("LINE0_NUMBER",op+2);
              }
              op[*(op+1)+2] = tmp;
          }
  
          /* Set Coder type: */
          SetPPAOption(VS_CODER,op1,"CODER");
  
          /* Set Coder control: */
          SetPPAOption(VS_CODERCTL,op1,"CODERCTL");
  
          /* Set minimum network delay setting: */
          SetPPAOption(VS_MINNETDELAY,op1,"MIN_NET_DELAY");
  
          /* Set maximum network delay setting: */
          SetPPAOption(VS_MAXNETDELAY,op1,"MAX_NET_DELAY");
  
          /* Set appinfo: */
          SetPPAOption(VS_APPINFO,op1,"APPINFO");
      }
  
      /* Check for VS_NAMEVAL here...
       * If the Vendor-Specific-Information is present, and within that
       * information there is a sub-option of VS_NAMEVAL,
       * then consider the content of that sub-option to be one or more
       * strings (separated by a comma) of the format "VARNAME=VALUE".
       * This is used to allow the DHCP server to configure shell variables
       * into the environment prior to the monitor turning over control to
       * the application.
       * Two examples of VS_NAMEVAL strings:
       * First, just one name-value combination...
       *  VARNAME=VALUE
       * Second, a multiple name-value combination...
       *  VARNAME=VALUE,VAR1=ABC,IP=1.2.3.4
       */
  
      op = op1 = 0;
      op1 = DhcpGetOption(DHCPOPT_VENDORSPECIFICINFO,dhdr+1);
      if(op1) {
          op = DhcpGetOption(VS_NAMEVAL,op1+2);
      }
      if(op) {
          int     len;
          uchar   *end, tmp;
          uchar   *name, *value, *eqsign, *comma, *base;
  
          op++;
          len = (int)*op++;
          base = op;
          tmp = base[len];
          base[len] = 0;
          end = base + len;
          while(op < end) {
              eqsign = (uchar *)strchr(op,'=');
              if(!eqsign) {
                  break;
              }
              name = op;
              *eqsign = 0;
              value = eqsign+1;
              comma = (uchar *)strchr(value,',');
              if(comma) {
                  *comma = 0;
                  op = comma+1;
              } else {
                  op = end;
              }
              DhcpSetEnv(name,value);
              *eqsign = '=';
              *comma = ',';
          }
          base[len] = tmp;
      }
  }
  
  int
  printDhcpVSopt(int vsopt, int vsoptlen, char *options)
  {
      switch(vsopt) {
      case VS_PROXYIP:
          for(i=0; i<vsoptlen; i++) {
              printf("%d ",(unsigned int)*options++);
          }
          break;
      case VS_CODER:
      case VS_NAMEVAL:
      case VS_MINNETDELAY:
      case VS_MAXNETDELAY:
      case VS_PPADHCPSRVR:
      case VS_PHONENUM:
      case VS_APPINFO:
          for(i=0; i<vsoptlen; i++) {
              printf("%c",*options++);
          }
          break;
      default:
          return(0);
      }
      return(1);
  }
  