static int connect_pppoatm(void) { int fd; struct atm_qos qos; /* XXX: This won't work on Android */ system ("/sbin/modprobe pppoatm"); if (!device_got_set) no_device_given_pppoatm(); fd = socket(AF_ATMPVC, SOCK_DGRAM, 0); if (fd < 0) fatal("failed to create socket: %m"); memset(&qos, 0, sizeof qos); qos.txtp.traffic_class = qos.rxtp.traffic_class = ATM_UBR; /* TODO: support simplified QoS setting */ if (qosstr != NULL) if (text2qos(qosstr, &qos, 0)) fatal("Can't parse QoS: \"%s\""); qos.txtp.max_sdu = lcp_allowoptions[0].mru + pppoatm_overhead(); qos.rxtp.max_sdu = lcp_wantoptions[0].mru + pppoatm_overhead(); qos.aal = ATM_AAL5; if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) fatal("setsockopt(SO_ATMQOS): %m"); /* TODO: accept on SVCs... */ if (connect(fd, (struct sockaddr *) &pvcaddr, sizeof(struct sockaddr_atmpvc))) fatal("connect(%s): %m", devnam); pppoatm_max_mtu = lcp_allowoptions[0].mru; pppoatm_max_mru = lcp_wantoptions[0].mru; set_line_discipline_pppoatm(fd); strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); pppoa_fd = fd; return fd; }
static int connect_pppoatm_ses(void) { info("connect_pppoatm_ses...Enter"); glb.real_ttyfd = socket(AF_ATMPVC, SOCK_DGRAM, 0); if (glb.real_ttyfd < 0) fatal("failed to create socket: %m"); info("connect_pppoatm_ses: socket created fd - 0x%x.",glb.real_ttyfd); memset(&glb.qos, 0, sizeof glb.qos); glb.qos.txtp.traffic_class = glb.qos.rxtp.traffic_class = ATM_UBR; /* TODO: support simplified QoS setting */ if (glb.qosstr != NULL) { if (text2qos(glb.qosstr, &glb.qos, 0)) fatal("Can't parse QoS: \"%s\""); fprintf(stderr, "glb.qos.rxtp.traffic_class = %d\n", glb.qos.rxtp.traffic_class); glb.qos.txtp.pcr = glb.qos.rxtp.pcr = atoi(glb.qos_pcr); info("glb.qos.txtp.pcr = glb.qos.rxtp.pcr = %d", glb.qos.txtp.pcr); if ((strcmp(glb.qosstr, "VBR") == 0) || (strcmp(glb.qosstr, "NRTVBR") == 0)) { glb.qos.txtp.scr = glb.qos.rxtp.scr = atoi(glb.qos_scr); info("glb.qos.txtp.scr = glb.qos.rxtp.scr = %d", glb.qos.txtp.scr); glb.qos.txtp.mbs = glb.qos.rxtp.mbs = atoi(glb.qos_mbs); info("glb.qos.txtp.mbs = glb.qos.rxtp.mbs = %d", glb.qos.txtp.mbs); } } glb.qos.txtp.max_sdu = lcp_allowoptions[0].mru + (glb.llc_encaps ? 6 : 2); glb.qos.rxtp.max_sdu = lcp_wantoptions[0].mru + (glb.llc_encaps ? 6 : 2); glb.qos.aal = ATM_AAL5; if (setsockopt(glb.real_ttyfd, SOL_ATM, SO_ATMQOS, &glb.qos, sizeof(glb.qos)) < 0) fatal("setsockopt(SO_ATMQOS): %m"); /* TODO: accept on SVCs... */ info("connect_pppoatm_ses: setsockopt called."); if (connect(glb.real_ttyfd, (struct sockaddr *) &glb.pvcaddr, sizeof(struct sockaddr_atmpvc))) fatal("connect(%s): %m", devnam); info("connect_pppoatm_ses: connect successful."); glb.pppoatm_max_mtu = lcp_allowoptions[0].mru; glb.pppoatm_max_mru = lcp_wantoptions[0].mru; return glb.real_ttyfd; }
static int setup(char *spec,int tx) { struct sockaddr_atmpvc addr; struct atm_qos qos; char *here; int fd; if (!(here = strchr(spec,','))) { memset(&qos,0,sizeof(qos)); if (tx) qos.txtp.traffic_class = ATM_UBR; else qos.rxtp.traffic_class = ATM_UBR; } else { *here = 0; if (text2qos(here+1,&qos,0) < 0) { fprintf(stderr,"invalid QOS: %s\n",here+1); exit(1); } } if (tx) qos.rxtp.traffic_class = ATM_NONE; else qos.txtp.traffic_class = ATM_NONE; qos.aal = ATM_AAL5; if (text2atm(spec,(struct sockaddr *) &addr,sizeof(addr), T2A_PVC | T2A_NAME) < 0) { fprintf(stderr,"invalid PVC: %s\n",spec); exit(1); } if ((fd = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); exit(1); } if (setsockopt(fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); exit(1); } if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) { perror("bind"); exit(1); } return fd; }
static int open_signaling(SIG_ENTITY *sig) { struct atm_qos qos; int s; if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); return -1; } memset(&qos,0,sizeof(qos)); qos.aal = ATM_AAL5; qos.rxtp.max_sdu = qos.txtp.max_sdu = MAX_Q_MSG; if (sig->sig_qos) { if (text2qos(sig->sig_qos,&qos,T2Q_DEFAULTS) < 0) { fprintf(stderr,"invalid qos: %s\n",sig->sig_qos); return -1; } } else { if (sig->sig_pcr == -1) qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_UBR; else { qos.rxtp.traffic_class = qos.txtp.traffic_class = ATM_CBR; qos.rxtp.min_pcr = qos.txtp.min_pcr = sig->sig_pcr; } } if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return -1; } sig->signaling_pvc.sap_family = AF_ATMPVC; if (bind(s,(struct sockaddr *) &sig->signaling_pvc, sizeof(sig->signaling_pvc)) < 0) { perror("bind"); return -1; } return s; }
int main(void) { static int fd[MAX_PAR]; /* to force initialization */ struct sockaddr_atmsvc local[MAX_ADDR]; struct atmif_sioc req; struct atm_sap sap; struct atm_qos qos; int listen_fd; fd_set rset,wset; int fds,completed = 0,connects = 0,accepts = 0; FD_ZERO(&rset); FD_ZERO(&wset); if (text2sap(SAP,&sap,0) < 0) { fprintf(stderr,"text2sap\n"); return 1; } if (text2qos(QOS,&qos,0) < 0) { fprintf(stderr,"text2qos\n"); return 1; } listen_fd = socket(PF_ATMSVC,SOCK_DGRAM,0); if (listen_fd < 0) { perror("socket"); return 1; } req.number = ITF; req.arg = local; req.length = sizeof(local); if (ioctl(listen_fd,ATM_GETADDR,&req) < 0) { perror("ioctl"); return 1; } if (!req.length) { fprintf(stderr,"No local address\n"); return 1; } if (setsockopt(listen_fd,SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) { perror("setsockopt SO_ATMSAP"); return 1; } if (setsockopt(listen_fd,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (bind(listen_fd,(struct sockaddr *) local,sizeof(*local)) < 0) { perror("bind"); return 1; } if (fcntl(listen_fd,F_SETFL,O_NONBLOCK) < 0) { perror("fnctl"); return 1; } if (listen(listen_fd,5) < 0) { perror("listen"); return 1; } FD_SET(listen_fd,&rset); fds = listen_fd+1; (void) signal(SIGCHLD,SIG_IGN); while (1) { static struct timeval no_delay; fd_set _rset = rset; fd_set _wset = wset; int ret,i,empty; no_delay.tv_sec = 0; no_delay.tv_usec = 100000; ret = select(fds,&_rset,&_wset,NULL,&no_delay); if (ret < 0) { perror("select"); return 1; } if (FD_ISSET(listen_fd,&_rset)) { pid_t pid; pid = fork(); if (pid < 0) { perror("fork"); return 1; } if (!pid) { if (accept(listen_fd,NULL,NULL) >= 0) exit(0); perror("accept"); return 1; } accepts++; } empty = -1; for (i = 0; i < MAX_PAR; i++) if (!fd[i]) empty = i; else if (FD_ISSET(fd[i],&_wset)) { struct sockaddr_atmsvc dummy; if (connect(fd[i],(struct sockaddr *) &dummy,sizeof(dummy)) < 0) { perror("connect"); return 1; } FD_CLR(fd[i],&wset); fd[i] = 0; empty = i; if (++completed == EXIT_LIM) { printf("%d attempted, %d completed, %d accepts\n", connects,completed,accepts); return 0; } } if (empty != -1) { fd[empty] = socket(PF_ATMSVC,SOCK_DGRAM,0); if (fd[empty] < 0) { perror("socket"); return 1; } if (fcntl(fd[empty],F_SETFL,O_NONBLOCK) < 0) { perror("fnctl"); return 1; } if (setsockopt(fd[empty],SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) { perror("setsockopt SO_ATMSAP"); return 1; } if (setsockopt(fd[empty],SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (connect(fd[empty],(struct sockaddr *) local,sizeof(*local)) < 0 && errno != EINPROGRESS) { perror("connect"); return 1; } FD_SET(fd[empty],&wset); if (fds <= fd[empty]) fds = fd[empty]+1; connects++; } } return 0; }
int main(int argc, char **argv) { char mac_addr[ETH_ALEN]; char elan_name[32 + 1]; char preferred_les[ATM_ESA_LEN]; /* LANE2 */ char foreId[255]; /* Max size for a TLV */ char atm2textbuff[100]; char esibuff[20]; int esi_set = 0; int listen_addr_set = 0; int atm_set=0; int proxy_flag = 0; int lane_version = 0; /* LANE2 */ int max_frame_size = MTU_UNSPEC; int lecs_method = LECS_WELLKNOWN; int poll_ret = 0, itf = 0, phys_itf = 0, selector = 0; int daemon_flag = 0; pid_t pid; struct sockaddr_atmsvc manual_atm_addr; struct sockaddr_atmsvc listen_addr; char pidbuf[PATH_MAX + 1]; int fd; int retval; memset(elan_name, '\0', sizeof(elan_name)); memset(foreId, '\0', sizeof(foreId)); memset(preferred_les, 0, ATM_ESA_LEN); memset(&manual_atm_addr, 0, sizeof(struct sockaddr_atmsvc)); memset(&listen_addr, 0, sizeof(struct sockaddr_atmsvc)); listen_addr.sas_family = AF_ATMSVC; set_application("zeppelin"); /* for debug msgs */ while(poll_ret != -1) { poll_ret = getopt(argc, argv, "bc:e:n:s:m:l:i:I:q:12pf:t:F:"); switch(poll_ret) { case 'b': daemon_flag = 1; break; case 'c': if (atm_set) { usage(argv[0]); exit(-1); } if (text2atm(optarg, (struct sockaddr *)&manual_atm_addr, sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) { diag(COMPONENT, DIAG_ERROR, "Invalid LECS address"); usage(argv[0]); exit(-1); } atm2text(atm2textbuff, sizeof(atm2textbuff), (struct sockaddr *)&manual_atm_addr, 0); diag(COMPONENT, DIAG_INFO, "LECS address: %s", atm2textbuff); lecs_method = LECS_MANUAL; atm_set=1; break; case 'e': if(esi_convert(optarg, mac_addr)<0) { diag(COMPONENT, DIAG_ERROR, "Invalid ESI format"); usage(argv[0]); exit(-1); } mac2text(esibuff, mac_addr); diag(COMPONENT, DIAG_DEBUG, "LEC ESI:%s", esibuff); esi_set=1; break; case 'n': if (strlen(optarg) > 32) { diag(COMPONENT, DIAG_ERROR, "ELAN name too long"); exit(-1); } strcpy(elan_name, optarg); diag(COMPONENT, DIAG_INFO, "Vlan name :'%s'", elan_name); break; case 's': if (atm_set) { usage(argv[0]); exit(-1); } if (text2atm(optarg, (struct sockaddr *)&manual_atm_addr, sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) { diag(COMPONENT, DIAG_ERROR, "Invalid LES address"); usage(argv[0]); exit(-1); } atm2text(atm2textbuff, sizeof(atm2textbuff), (struct sockaddr *)&manual_atm_addr, 0); diag(COMPONENT, DIAG_INFO, "LES address: %s", atm2textbuff); lecs_method = LECS_NONE; atm_set=1; break; case 'm': set_verbosity(NULL, DIAG_DEBUG); break; case 'l': if (isdigit(optarg[0]) && strlen(optarg) < 4 && sscanf(optarg, "%d", &selector) && selector >=0 && selector <= 0xff) { listen_addr.sas_addr.prv[ATM_ESA_LEN - 1] = (char) selector; diag(COMPONENT, DIAG_INFO, "Selector byte set " "to %d", selector); } else { if (text2atm(optarg, (struct sockaddr *)&listen_addr, sizeof(struct sockaddr_atmsvc), T2A_NAME) < 0) { diag(COMPONENT, DIAG_ERROR, "Invalid ATM listen address"); usage(argv[0]); exit(-1); } listen_addr_set = 1; } break; case 'i': if (sscanf(optarg, "%d", &itf) <= 0 || itf >= MAX_LEC_ITF) { diag(COMPONENT, DIAG_ERROR, "Invalid interface number"); usage(argv[0]); exit(-1); } diag(COMPONENT, DIAG_INFO, "Interface number set to %d", itf); break; case 'I': if (sscanf(optarg, "%d", &phys_itf) <= 0 || phys_itf < 0) { diag(COMPONENT, DIAG_ERROR, "Invalid physical interface number"); usage(argv[0]); exit(-1); } diag(COMPONENT, DIAG_INFO, "Physical interface number set to %d", phys_itf); break; case 'q': #if 0 if (text2qos(optarg,NULL,0) < 0) { diag(COMPONENT, DIAG_ERROR, "Invalid QOS specification"); usage(argv[0]); exit(-1); } qos_spec = optarg; #endif diag(COMPONENT, DIAG_INFO, "-q is deprecated, ignoring it"); break; case '1': lane_version = 1; break; case '2': lane_version = 2; break; case 'p': proxy_flag = 1; break; case 'f': if (strlen(optarg) > 255) { diag(COMPONENT, DIAG_ERROR, "foreId too long"); exit(-1); } memcpy (foreId, optarg, strlen(optarg)); foreId[strlen(optarg)] = '\0'; diag(COMPONENT, DIAG_INFO, "foreId :'%s'", foreId); break; case 't': /* ERIC */ if( !strncmp( optarg, "1516", 4 )) max_frame_size = MTU_1516; else if( !strncmp( optarg, "1580", 4 )) max_frame_size = MTU_1580; else if( !strncmp( optarg, "4544", 4 )) max_frame_size = MTU_4544; else if( !strncmp( optarg, "9234", 4 )) max_frame_size = MTU_9234; else if( !strncmp( optarg, "18190", 5 )) max_frame_size = MTU_18190; break; case 'F': set_logfile(optarg); diag(COMPONENT, DIAG_DEBUG, "logfile set to %s", optarg); break; case -1: break; default: usage(argv[0]); exit(-1); } } if (argc != optind) { usage(argv[0]); exit(1); } if (lane_version == 1 && max_frame_size == MTU_1580) { diag(COMPONENT, DIAG_ERROR, "MTU 1580 not defined with LANEv1"); exit(-1); } /* Reserve signals */ signal(SIGHUP, sig_reset); signal(SIGPIPE, SIG_IGN); if (!esi_set) { if(addr_getesi(mac_addr, phys_itf) < 0) { diag(COMPONENT, DIAG_ERROR, "Can't get ESI from kernel!"); return -1; } mac2text(esibuff, mac_addr); diag(COMPONENT, DIAG_DEBUG, "LEC ESI:%s", esibuff); if (itf != 0) mac_addr[0] = 0x2 | ((itf - 1) << 2); } if ((itf = kernel_init(mac_addr, itf)) < 0 ) { diag(COMPONENT, DIAG_FATAL, "Kernel interface creation failed, exiting..."); return -1; } if (daemon_flag == 1) { daemon_flag = 0; pid = fork(); if (pid < 0) { diag(COMPONENT, DIAG_FATAL, "fork failed, exiting..."); return -1; } if (pid) { /* parent */ return 0; } else { /* child */ if (setsid() < 0) { diag(COMPONENT, DIAG_FATAL, "setsid failed, exiting..."); return -1; } } } sprintf(pidbuf, "/var/run/lec%d.pid", itf); fd = open(pidbuf, O_CREAT | O_WRONLY, 0600); if (fd < 0) { diag(COMPONENT, DIAG_FATAL, "open(%s, ..) failed, %s", pidbuf, strerror(errno)); return -1; } sprintf(pidbuf, "%d\n", getpid()); write(fd, pidbuf, strlen(pidbuf)); close(fd); /* Loop here until the Sun gets cold */ while (1) { if (!listen_addr_set) { char sel = listen_addr.sas_addr.prv[ATM_ESA_LEN - 1]; if (get_listenaddr(listen_addr.sas_addr.prv, phys_itf) < 0) { diag(COMPONENT, DIAG_FATAL, "Could not figure out my ATM address"); exit(-1); } listen_addr.sas_addr.prv[ATM_ESA_LEN - 1] = sel; } atm2text(atm2textbuff, sizeof(atm2textbuff), (struct sockaddr *)&listen_addr, A2T_NAME | A2T_PRETTY | A2T_LOCAL); diag(COMPONENT, DIAG_INFO, "Our ATM address: %s", atm2textbuff); diag(COMPONENT, DIAG_DEBUG, "initializing lec parameters"); init_lec_params(mac_addr, elan_name, listen_addr.sas_addr.prv, itf, foreId, max_frame_size, proxy_flag, lane_version); if (lecs_method != LECS_MANUAL && lecs_method != LECS_NONE) { diag(COMPONENT, DIAG_DEBUG, "trying to get LECS address from ILMI"); /* Not sure why this memset is necessary */ memset(&manual_atm_addr, 0, sizeof(struct sockaddr_atmsvc)); retval = get_lecsaddr(phys_itf, &manual_atm_addr); if (retval <= 0) { diag(COMPONENT, DIAG_DEBUG, "get_lecsaddr failed; not enough " "memory allocated for all addresses " "or no LECS address registered"); } else { diag(COMPONENT, DIAG_DEBUG, "obtained LECS address from ILMI"); lecs_method = LECS_FROM_ILMI; } } diag(COMPONENT, DIAG_DEBUG, "About to connect LECS"); if (lec_configure(lecs_method, &manual_atm_addr, &listen_addr) < 0) { close_connections(); random_delay(); continue; } diag(COMPONENT, DIAG_DEBUG, "About to connect LES"); if (les_connect(lecs_method, &manual_atm_addr, &listen_addr) < 0) { close_connections(); random_delay(); continue; } diag(COMPONENT, DIAG_DEBUG, "About to connect BUS"); if (bus_connect() < 0) { close_connections(); random_delay(); continue; } diag(COMPONENT, DIAG_DEBUG, "About to create data direct listen socket"); if (create_data_listen() < 0) { close_connections(); random_delay(); continue; } diag(COMPONENT, DIAG_DEBUG, "About to tell kernel our LEC_ID %d", lec_params.c14_lec_id); if (set_lec_id(lec_params.c14_lec_id) < 0) { close_connections(); continue; } diag(COMPONENT, DIAG_DEBUG, "About to tell kernel LEC parameters"); if (config_kernel() < 0) { close_connections(); continue; } diag(COMPONENT, DIAG_DEBUG, "Joined ELAN '%s' successfully", lec_params.c5_elan_name); main_loop(); diag(COMPONENT, DIAG_INFO, "Resetting..."); close_connections(); random_delay(); reset = 0; } return 0; /* not reached */ }
int main(int argc,char **argv) { struct atmarp_req req; int c,i,num; char *here,*end; req.type = 0; while ((c = getopt(argc,argv,"acdqQsV")) != EOF) switch (c) { case 'a': if (argc != optind || req.type) usage(argv[0]); req.type = art_table; /* (void) send_request(&req); @@@ fix this later */ return print_table(); case 'c': if (req.type) usage(argv[0]); req.type = art_create; break; case 'd': if (req.type) usage(argv[0]); req.type = art_delete; break; case 'q': if (req.type) usage(argv[0]); req.type = art_qos; break; case 'Q': if (req.type) usage(argv[0]); req.type = art_query; break; case 's': if (req.type) usage(argv[0]); req.type = art_set; break; case 'V': printf("%s\n",VERSION); return 0; default: usage(argv[0]); } switch (req.type) { case art_create: if (argc == optind) req.itf = -1; else { if (argc != optind+1) usage(argv[0]); here = argv[optind]; if (strlen(here) > 3 && !strncmp(here,"atm",3)) here += 3; req.itf = strtoul(here,&end,10); if (*end || (here[0] == '0' && here[1])) { usage(argv[0]); return 1; } } num = send_request(&req); if (req.itf == -1) printf("atm%d\n",num); return 0; case art_qos: if (argc < optind+1) usage(argv[0]); /* fall through */ case art_set: if (argc < optind+2) usage(argv[0]); break; case art_query: if (argc != optind+1) usage(argv[0]); break; case art_delete: if (argc < optind+1) usage(argv[0]); break; default: usage(argv[0]); } req.ip = text2ip(argv[optind],NULL,T2I_NAME | T2I_ERROR); if (req.ip == INADDR_NONE) return 1; req.flags = ATF_PERM; if (req.type == art_qos) { memset(&req.qos,0,sizeof(req.qos)); req.sndbuf = 0; for (i = optind+1; i < argc; i++) if (!strcmp(argv[i],"qos")) { if (++i >= argc) usage(argv[0]); if (text2qos(argv[i],&req.qos,0)) usage(argv[0]); } else if (!strcmp(argv[i],"sndbuf")) { if (++i >= argc) usage(argv[0]); req.sndbuf = strtol(argv[i],&end,0); if (*end) usage(argv[0]); } else if (i != optind+1 || argc != optind+2 || text2qos(argv[optind+1],&req.qos,0)) usage(argv[0]); } if (req.type == art_set) { memset(&req.qos,0,sizeof(req.qos)); req.sndbuf = 0; for (i = optind+2; i < argc; i++) if (!strcmp(argv[i],"temp")) req.flags &= ~ATF_PERM; else if (!strcmp(argv[i],"pub")) req.flags |= ATF_PUBL; else if (!strcmp(argv[i],"null")) req.flags |= ATF_NULL; else if (!strcmp(argv[i],"arpsrv")) req.flags |= ATF_ARPSRV; else if (!strcmp(argv[i],"qos")) { if (++i >= argc) usage(argv[0]); if (text2qos(argv[i],&req.qos,0)) usage(argv[0]); } else if (!strcmp(argv[i],"sndbuf")) { if (++i >= argc) usage(argv[0]); req.sndbuf = strtol(argv[i],&end,0); if (*end) usage(argv[0]); } else if (!strcmp(argv[i],"pcr")) { if (++i >= argc) usage(argv[0]); req.qos.txtp.traffic_class = req.qos.rxtp.traffic_class = ATM_CBR; req.qos.txtp.max_pcr = req.qos.rxtp.max_pcr = strtol(argv[i],&end,0); if (*end) usage(argv[0]); } else usage(argv[0]); if (text2atm(argv[optind+1],(struct sockaddr *) &req.addr, sizeof(req.addr),T2A_NAME) < 0) { fprintf(stderr,"%s: invalid ATM address\n",argv[optind+1]); return 1; } } if (req.type == art_delete && optind+1 < argc) { if (optind+2 < argc || strcmp(argv[optind+1],"arpsrv")) usage(argv[0]); req.flags |= ATF_ARPSRV; } if (!req.qos.aal) req.qos.aal = ATM_AAL5; send_request(&req); return 0; }
static int atm_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct sockaddr_atmsvc addr; struct atm_qos qos; struct atm_sap sap; unsigned char hdr[MAX_HDR_LEN]; __u32 excess = 0; struct rtattr *tail; int sndbuf = 0; int hdr_len = -1; int set_clip = 0; int s; memset(&addr,0,sizeof(addr)); (void) text2qos("aal5,ubr:sdu=9180,rx:none",&qos,0); (void) text2sap("blli:l2=iso8802",&sap,0); while (argc > 0) { if (!strcmp(*argv,"pvc")) { NEXT_ARG(); if (text2atm(*argv,(struct sockaddr *) &addr, sizeof(addr),T2A_PVC | T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"svc")) { NEXT_ARG(); if (text2atm(*argv,(struct sockaddr *) &addr, sizeof(addr),T2A_SVC | T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"qos")) { NEXT_ARG(); if (text2qos(*argv,&qos,0) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"sndbuf")) { char *end; NEXT_ARG(); sndbuf = strtol(*argv,&end,0); if (*end) { explain(); return -1; } } else if (!strcmp(*argv,"sap")) { NEXT_ARG(); if (addr.sas_family != AF_ATMSVC || text2sap(*argv,&sap,T2A_NAME) < 0) { explain(); return -1; } } else if (!strcmp(*argv,"hdr")) { unsigned char *ptr; char *walk; NEXT_ARG(); ptr = hdr; for (walk = *argv; *walk; walk++) { int tmp; if (ptr == hdr+MAX_HDR_LEN) { // fprintf(stderr,"header is too long\n"); return -1; } if (*walk == '.') continue; if (!isxdigit(walk[0]) || !walk[1] || !isxdigit(walk[1])) { explain(); return -1; } sscanf(walk,"%2x",&tmp); *ptr++ = tmp; walk++; } hdr_len = ptr-hdr; } else if (!strcmp(*argv,"excess")) { NEXT_ARG(); if (!strcmp(*argv,"clp")) excess = 0; else if (get_tc_classid(&excess,*argv)) { explain(); return -1; } } else if (!strcmp(*argv,"clip")) { set_clip = 1; } else { explain(); return 1; } argc--; argv++; } s = socket(addr.sas_family,SOCK_DGRAM,0); if (s < 0) { // perror("socket"); return -1; } if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { // perror("SO_ATMQOS"); return -1; } if (sndbuf) if (setsockopt(s,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { // perror("SO_SNDBUF"); return -1; } if (addr.sas_family == AF_ATMSVC && setsockopt(s,SOL_ATM,SO_ATMSAP, &sap,sizeof(sap)) < 0) { // perror("SO_ATMSAP"); return -1; } if (connect(s,(struct sockaddr *) &addr,addr.sas_family == AF_ATMPVC ? sizeof(struct sockaddr_atmpvc) : sizeof(addr)) < 0) { /// perror("connect"); return -1; } if (set_clip) if (ioctl(s,ATMARP_MKIP,0) < 0) { // perror("ioctl ATMARP_MKIP"); return -1; } tail = NLMSG_TAIL(n); addattr_l(n,1024,TCA_OPTIONS,NULL,0); addattr_l(n,1024,TCA_ATM_FD,&s,sizeof(s)); if (excess) addattr_l(n,1024,TCA_ATM_EXCESS,&excess,sizeof(excess)); if (hdr_len != -1) addattr_l(n,1024,TCA_ATM_HDR,hdr,hdr_len); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 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; }