Ejemplo n.º 1
0
void do_add(int cli_fd, struct be_msg *rmsg, struct ucred *cli_cred)
{
  static struct be_group *group = &group_head;
  static struct be_vc *prev_vc = NULL;
  static char curr_groupname[MAX_GROUPNAME_LEN] = {};
  static pid_t curr_cli_pid = 0;

  struct be_group *last_group = NULL, *new_group;
  struct be_vc *new_vc;
  struct be_msg smsg;
  int sock;

  /* New client instance means that we reset the current working group.
   */
  if(curr_cli_pid != cli_cred->pid) {
    curr_groupname[0] = '\0';
    group = &group_head;
    curr_cli_pid = cli_cred->pid;
  }

// brcm
  if(create_br(rmsg->nas_idx, rmsg->mode) == 0) {
//  if(create_br(rmsg->nas_idx) == 0) {

    smsg.msgtype = INTERFACE_FAILED;
    if( send(cli_fd, &smsg, sizeof(smsg), 0) < 0 )
      do_error(LOG_WARNING,"do_add() couldn't send interface creation failure message.");
    return;
  }

// brcm
  if( (sock = assign_vcc(rmsg->pvc, rmsg->nas_idx, rmsg->encap, 8192, rmsg->proto_filter, rmsg->mode)) < 0) {
//  if( (sock = assign_vcc(rmsg->pvc, rmsg->nas_idx, BR2684_ENCAPS_LLC, 8192)) < 0) {
    
    smsg.msgtype = SOCK_FAILED;
    if( send(cli_fd, &smsg, sizeof(smsg), 0) < 0 )
      do_error(LOG_WARNING,"do_add() couldn't send socket creation failure message.");
    return;
  }

  /* See if this group is different from the last one. If isn't, we simply pick up where
     we left off last time with the group and vc pointers stored in static variables.
     This is more efficient for multiple adds, because we always want go to the end of 
     the current group's VC list.
  */
  if( strncmp(rmsg->name,curr_groupname,MAX_GROUPNAME_LEN) ) {
    
    /* This groupname is different from the last one. Remember it for next time.
     */

    strncpy(curr_groupname,rmsg->name,MAX_GROUPNAME_LEN); 

    /* Does this group exist?  
     */
    for(group = &group_head; group != NULL; group = group->next) {
      last_group = group;
      if(!strncmp(rmsg->name,group->name,MAX_GROUPNAME_LEN)) 
	break;
    }

    if(!group) {

      /* Nope.  Create a new group.
       */
      if(! (new_group = (struct be_group *)malloc(sizeof(struct be_group))) ) {
	do_error(LOG_WARNING,"can't allocate memory for new group %s", rmsg->name);
	
	close(sock);
	smsg.msgtype = NOMEM;
	if( send(cli_fd, &smsg, sizeof(smsg), 0) < 0 )
	  do_error(LOG_WARNING,"do_add() couldn't send malloc failure message for new group.");
	return;
      }
  
      memstat.group_mallocs++;

      last_group->next      = new_group;
      new_group->head       = NULL;
      new_group->next       = NULL;
      strncpy(new_group->name,rmsg->name,MAX_GROUPNAME_LEN);
      
      /* set prev_vc to the VC list head.
       */
      group = new_group;
      prev_vc = group->head;
    } else

      /* Ratchet to the end of an existing group VC list.
       */
      for(prev_vc = group->head; prev_vc->next != NULL; prev_vc=prev_vc->next);
  }

  /* Create the new VC
   */
  if(! (new_vc = (struct be_vc *)malloc(sizeof(struct be_vc))) ) {
    do_error(LOG_WARNING,"can't allocate memory for new vc %d/%d on nas%d\n",
	     rmsg->pvc.sap_addr.vpi,
	     rmsg->pvc.sap_addr.vci,
	     rmsg->nas_idx
	     );

    close(sock);
    smsg.msgtype = NOMEM;
    if( send(cli_fd, &smsg, sizeof(smsg), 0) < 0 )
      do_error(LOG_WARNING,"do_add() couldn't send malloc failure message for new VC.");
    return;
  }
  
  memstat.vc_mallocs++;
  
  new_vc->nas_idx  = rmsg->nas_idx;
  memcpy(&new_vc->pvc, &rmsg->pvc, sizeof(struct sockaddr_atmpvc));
  new_vc->sock    = sock;
  new_vc->uid     = cli_cred->uid;
  new_vc->next    = NULL;

  /* Add the new VC to the end of the list and remember the
     new end for next time. This "if" block is neccessary because
     we cannot initialize prev_vc with the address of group_head.pvc,
     which is non-constant. My intent is to keep most of the state 
     variables local to this function.
  */

  if(!group->head)
    group->head = new_vc;
  else if(prev_vc) 
    prev_vc->next = new_vc;

  prev_vc       = new_vc;
  
  smsg.msgtype = OK;
  if( send(cli_fd, &smsg, sizeof(smsg), 0) < 0 )
    do_error(LOG_ERR,"do_add couldn't send OK response: %s",strerror(errno));      	
}
Ejemplo n.º 2
0
int main (int argc, char **argv)
{
  int c, background=0, encap=0, sndbuf=8192;
  struct atm_qos reqqos;
  int itfnum;
  lastsock=-1;
  lastitf=0;
  
  /* st qos to 0 */
  memset(&reqqos, 0, sizeof(reqqos));

  openlog (LOG_NAME,LOG_OPTION,LOG_FACILITY);
  if (argc>1)
    while ((c = getopt(argc, argv,"q:a:bc:e:s:?h")) !=EOF)
      switch (c) {
      case 'q':
	printf ("optarg : %s",optarg);
	if (text2qos(optarg,&reqqos,0)) fprintf(stderr,"QOS parameter invalid\n"); 
	break;
      case 'a':
	assign_vcc(optarg, encap, sndbuf, reqqos);
	break;
      case 'b':
	background=1;
	break;
      case 'c':
	create_br(optarg);
	itfnum = atoi(optarg);
	break;
      case 'e':
	encap=(atoi(optarg));
	if(encap<0){
	  syslog (LOG_ERR, "invalid encapsulation: %s:\n",optarg);
	  encap=0;
	}
	break;
      case 's':
	sndbuf=(atoi(optarg));
	if(sndbuf<0){
	  syslog(LOG_ERR, "Invalid sndbuf: %s, using size of 8192 instead\n",optarg);
	  sndbuf=8192;
	}
	break;
      case '?':
      case 'h':
      default:
	usage(argv[0]);
      }
  else
    usage(argv[0]);

  if (argc != optind) usage(argv[0]);
  
  if(lastsock>=0) close(lastsock);
  
  if (background) {
    pid_t pid;
    
    pid=fork();
    if (pid < 0) {
      fprintf(stderr,"Error detaching\n");
      exit(2);
    } else if (pid) 
      exit(0); // This is the parent
    
    // Become a process group and session group leader
    if (setsid()<0) {
      fprintf (stderr,"Could not set process group\n");
      exit(2);
    }
    
    // Fork again to let process group leader exit
    pid = fork();
    if (pid < 0) {
      fprintf(stderr,"Error detaching during second fork\n");
      exit(2);
    } else if (pid)
      exit(0); // This is the parent
    
    // Now we're ready for buisness
    chdir("/");            // Don't keep directories in use
    close(0); close(1); close(2);  // Close stdin, -out and -error
    /*
      Note that this implementation does not keep an open 
      stdout/err.
      If we need them they can be opened now
    */
    
  }
  
  create_pidfile(itfnum);

  syslog (LOG_INFO, "RFC 1483/2684 bridge daemon started\n");	
  atexit (exitFunc);
  
  while (1) sleep(30);	/* to keep the sockets... */
  return 0;
}