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)); }
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; }